1//===- Utils.cpp - llvm-reduce utility functions --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains some utility functions supporting llvm-reduce.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Utils.h"
14#include "llvm/IR/Constants.h"
15#include "llvm/IR/GlobalAlias.h"
16#include "llvm/IR/GlobalIFunc.h"
17#include "llvm/Transforms/Utils/BasicBlockUtils.h"
18#include "llvm/Transforms/Utils/Local.h"
19
20using namespace llvm;
21
22extern cl::OptionCategory LLVMReduceOptions;
23
24cl::opt<bool> llvm::Verbose("verbose",
25 cl::desc("Print extra debugging information"),
26 cl::init(Val: false), cl::cat(LLVMReduceOptions));
27
28Value *llvm::getDefaultValue(Type *T) {
29 if (T->isVoidTy())
30 return PoisonValue::get(T);
31
32 if (auto *TET = dyn_cast<TargetExtType>(Val: T)) {
33 if (TET->hasProperty(Prop: TargetExtType::HasZeroInit))
34 return ConstantTargetNone::get(T: TET);
35 return PoisonValue::get(T: TET);
36 }
37
38 return Constant::getNullValue(Ty: T);
39}
40
41bool llvm::hasAliasUse(Function &F) {
42 return any_of(Range: F.users(), P: [](User *U) {
43 return isa<GlobalAlias>(Val: U) || isa<GlobalIFunc>(Val: U);
44 });
45}
46
47void llvm::simpleSimplifyCFG(Function &F, ArrayRef<BasicBlock *> BBs,
48 bool FoldBlockIntoPredecessor) {
49
50 for (BasicBlock *BB : BBs) {
51 ConstantFoldTerminator(BB);
52 if (FoldBlockIntoPredecessor)
53 MergeBlockIntoPredecessor(BB);
54 }
55
56 // Remove unreachable blocks
57 //
58 // removeUnreachableBlocks can't be used here, it will turn various undefined
59 // behavior into unreachables, but llvm-reduce was the thing that generated
60 // the undefined behavior, and we don't want it to kill the entire program.
61 SmallPtrSet<BasicBlock *, 16> Visited(llvm::from_range,
62 depth_first(G: &F.getEntryBlock()));
63
64 SmallVector<BasicBlock *, 16> Unreachable;
65 for (BasicBlock &BB : F) {
66 if (!Visited.count(Ptr: &BB))
67 Unreachable.push_back(Elt: &BB);
68 }
69
70 // The dead BB's may be in a dead cycle or otherwise have references to each
71 // other. Because of this, we have to drop all references first, then delete
72 // them all at once.
73 for (BasicBlock *BB : Unreachable) {
74 for (BasicBlock *Successor : successors(BB: &*BB))
75 if (Visited.count(Ptr: Successor))
76 Successor->removePredecessor(Pred: &*BB, /*KeepOneInputPHIs=*/true);
77 BB->dropAllReferences();
78 }
79
80 for (BasicBlock *BB : Unreachable)
81 BB->eraseFromParent();
82}
83