1 //===- LowerConstantIntrinsics.cpp - Lower constant intrinsic calls -------===// 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 pass lowers all remaining 'objectsize' 'is.constant' intrinsic calls 10 // and provides constant propagation and basic CFG cleanup on the result. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h" 15 #include "llvm/ADT/PostOrderIterator.h" 16 #include "llvm/ADT/SetVector.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/Analysis/InstructionSimplify.h" 19 #include "llvm/Analysis/MemoryBuiltins.h" 20 #include "llvm/Analysis/TargetLibraryInfo.h" 21 #include "llvm/IR/BasicBlock.h" 22 #include "llvm/IR/Constants.h" 23 #include "llvm/IR/Function.h" 24 #include "llvm/IR/Instructions.h" 25 #include "llvm/IR/IntrinsicInst.h" 26 #include "llvm/IR/Intrinsics.h" 27 #include "llvm/IR/PatternMatch.h" 28 #include "llvm/InitializePasses.h" 29 #include "llvm/Pass.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Transforms/Scalar.h" 32 #include "llvm/Transforms/Utils/Local.h" 33 34 using namespace llvm; 35 using namespace llvm::PatternMatch; 36 37 #define DEBUG_TYPE "lower-is-constant-intrinsic" 38 39 STATISTIC(IsConstantIntrinsicsHandled, 40 "Number of 'is.constant' intrinsic calls handled"); 41 STATISTIC(ObjectSizeIntrinsicsHandled, 42 "Number of 'objectsize' intrinsic calls handled"); 43 44 static Value *lowerIsConstantIntrinsic(IntrinsicInst *II) { 45 Value *Op = II->getOperand(0); 46 47 return isa<Constant>(Op) ? ConstantInt::getTrue(II->getType()) 48 : ConstantInt::getFalse(II->getType()); 49 } 50 51 static bool replaceConditionalBranchesOnConstant(Instruction *II, 52 Value *NewValue) { 53 bool HasDeadBlocks = false; 54 SmallSetVector<Instruction *, 8> Worklist; 55 replaceAndRecursivelySimplify(II, NewValue, nullptr, nullptr, nullptr, 56 &Worklist); 57 for (auto I : Worklist) { 58 BranchInst *BI = dyn_cast<BranchInst>(I); 59 if (!BI) 60 continue; 61 if (BI->isUnconditional()) 62 continue; 63 64 BasicBlock *Target, *Other; 65 if (match(BI->getOperand(0), m_Zero())) { 66 Target = BI->getSuccessor(1); 67 Other = BI->getSuccessor(0); 68 } else if (match(BI->getOperand(0), m_One())) { 69 Target = BI->getSuccessor(0); 70 Other = BI->getSuccessor(1); 71 } else { 72 Target = nullptr; 73 Other = nullptr; 74 } 75 if (Target && Target != Other) { 76 BasicBlock *Source = BI->getParent(); 77 Other->removePredecessor(Source); 78 BI->eraseFromParent(); 79 BranchInst::Create(Target, Source); 80 if (pred_begin(Other) == pred_end(Other)) 81 HasDeadBlocks = true; 82 } 83 } 84 return HasDeadBlocks; 85 } 86 87 static bool lowerConstantIntrinsics(Function &F, const TargetLibraryInfo *TLI) { 88 bool HasDeadBlocks = false; 89 const auto &DL = F.getParent()->getDataLayout(); 90 SmallVector<WeakTrackingVH, 8> Worklist; 91 92 ReversePostOrderTraversal<Function *> RPOT(&F); 93 for (BasicBlock *BB : RPOT) { 94 for (Instruction &I: *BB) { 95 IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I); 96 if (!II) 97 continue; 98 switch (II->getIntrinsicID()) { 99 default: 100 break; 101 case Intrinsic::is_constant: 102 case Intrinsic::objectsize: 103 Worklist.push_back(WeakTrackingVH(&I)); 104 break; 105 } 106 } 107 } 108 for (WeakTrackingVH &VH: Worklist) { 109 // Items on the worklist can be mutated by earlier recursive replaces. 110 // This can remove the intrinsic as dead (VH == null), but also replace 111 // the intrinsic in place. 112 if (!VH) 113 continue; 114 IntrinsicInst *II = dyn_cast<IntrinsicInst>(&*VH); 115 if (!II) 116 continue; 117 Value *NewValue; 118 switch (II->getIntrinsicID()) { 119 default: 120 continue; 121 case Intrinsic::is_constant: 122 NewValue = lowerIsConstantIntrinsic(II); 123 IsConstantIntrinsicsHandled++; 124 break; 125 case Intrinsic::objectsize: 126 NewValue = lowerObjectSizeCall(II, DL, TLI, true); 127 ObjectSizeIntrinsicsHandled++; 128 break; 129 } 130 HasDeadBlocks |= replaceConditionalBranchesOnConstant(II, NewValue); 131 } 132 if (HasDeadBlocks) 133 removeUnreachableBlocks(F); 134 return !Worklist.empty(); 135 } 136 137 PreservedAnalyses 138 LowerConstantIntrinsicsPass::run(Function &F, FunctionAnalysisManager &AM) { 139 if (lowerConstantIntrinsics(F, AM.getCachedResult<TargetLibraryAnalysis>(F))) 140 return PreservedAnalyses::none(); 141 142 return PreservedAnalyses::all(); 143 } 144 145 namespace { 146 /// Legacy pass for lowering is.constant intrinsics out of the IR. 147 /// 148 /// When this pass is run over a function it converts is.constant intrinsics 149 /// into 'true' or 'false'. This complements the normal constant folding 150 /// to 'true' as part of Instruction Simplify passes. 151 class LowerConstantIntrinsics : public FunctionPass { 152 public: 153 static char ID; 154 LowerConstantIntrinsics() : FunctionPass(ID) { 155 initializeLowerConstantIntrinsicsPass(*PassRegistry::getPassRegistry()); 156 } 157 158 bool runOnFunction(Function &F) override { 159 auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>(); 160 const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI(F) : nullptr; 161 return lowerConstantIntrinsics(F, TLI); 162 } 163 }; 164 } // namespace 165 166 char LowerConstantIntrinsics::ID = 0; 167 INITIALIZE_PASS(LowerConstantIntrinsics, "lower-constant-intrinsics", 168 "Lower constant intrinsics", false, false) 169 170 FunctionPass *llvm::createLowerConstantIntrinsicsPass() { 171 return new LowerConstantIntrinsics(); 172 } 173