1414#include " llvm/CodeGen/PreISelIntrinsicLowering.h"
1515#include " llvm/Analysis/ObjCARCInstKind.h"
1616#include " llvm/Analysis/ObjCARCUtil.h"
17+ #include " llvm/Analysis/TargetLibraryInfo.h"
1718#include " llvm/Analysis/TargetTransformInfo.h"
1819#include " llvm/CodeGen/Passes.h"
1920#include " llvm/CodeGen/TargetLowering.h"
2425#include " llvm/IR/IntrinsicInst.h"
2526#include " llvm/IR/Module.h"
2627#include " llvm/IR/Type.h"
28+ #include " llvm/IR/Use.h"
2729#include " llvm/InitializePasses.h"
2830#include " llvm/Pass.h"
2931#include " llvm/Support/Casting.h"
3032#include " llvm/Target/TargetMachine.h"
33+ #include " llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
3134#include " llvm/Transforms/Utils/LowerMemIntrinsics.h"
3235
3336using namespace llvm ;
@@ -45,6 +48,7 @@ namespace {
4548struct PreISelIntrinsicLowering {
4649 const TargetMachine &TM;
4750 const function_ref<TargetTransformInfo &(Function &)> LookupTTI;
51+ const function_ref<TargetLibraryInfo &(Function &)> LookupTLI;
4852
4953 // / If this is true, assume it's preferably to leave memory intrinsic calls
5054 // / for replacement with a library call later. Otherwise this depends on
@@ -54,8 +58,9 @@ struct PreISelIntrinsicLowering {
5458 explicit PreISelIntrinsicLowering (
5559 const TargetMachine &TM_,
5660 function_ref<TargetTransformInfo &(Function &)> LookupTTI_,
61+ function_ref<TargetLibraryInfo &(Function &)> LookupTLI_,
5762 bool UseMemIntrinsicLibFunc_ = true)
58- : TM(TM_), LookupTTI(LookupTTI_),
63+ : TM(TM_), LookupTTI(LookupTTI_), LookupTLI(LookupTLI_),
5964 UseMemIntrinsicLibFunc(UseMemIntrinsicLibFunc_) {}
6065
6166 static bool shouldExpandMemIntrinsicWithSize (Value *Size,
@@ -66,6 +71,27 @@ struct PreISelIntrinsicLowering {
6671
6772} // namespace
6873
74+ template <class T > static bool forEachCall (Function &Intrin, T Callback) {
75+ // Lowering all intrinsics in a function will delete multiple uses, so we
76+ // can't use an early-inc-range. In case some remain, we don't want to look
77+ // at them again. Unfortunately, Value::UseList is private, so we can't use a
78+ // simple Use**. If LastUse is null, the next use to consider is
79+ // Intrin.use_begin(), otherwise it's LastUse->getNext().
80+ Use *LastUse = nullptr ;
81+ bool Changed = false ;
82+ while (!Intrin.use_empty () && (!LastUse || LastUse->getNext ())) {
83+ Use *U = LastUse ? LastUse->getNext () : &*Intrin.use_begin ();
84+ bool Removed = false ;
85+ // An intrinsic cannot have its address taken, so it cannot be an argument
86+ // operand. It might be used as operand in debug metadata, though.
87+ if (auto CI = dyn_cast<CallInst>(U->getUser ()))
88+ Changed |= Removed = Callback (CI);
89+ if (!Removed)
90+ LastUse = U;
91+ }
92+ return Changed;
93+ }
94+
6995static bool lowerLoadRelative (Function &F) {
7096 if (F.use_empty ())
7197 return false ;
@@ -315,6 +341,16 @@ bool PreISelIntrinsicLowering::lowerIntrinsics(Module &M) const {
315341 case Intrinsic::load_relative:
316342 Changed |= lowerLoadRelative (F);
317343 break ;
344+ case Intrinsic::is_constant:
345+ case Intrinsic::objectsize:
346+ Changed |= forEachCall (F, [&](CallInst *CI) {
347+ Function *Parent = CI->getParent ()->getParent ();
348+ TargetLibraryInfo &TLI = LookupTLI (*Parent);
349+ bool Changed = lowerConstantIntrinsics (*Parent, TLI, /* DT=*/ nullptr );
350+ assert (Changed && " lowerConstantIntrinsics did not lower intrinsic" );
351+ return Changed;
352+ });
353+ break ;
318354 case Intrinsic::objc_autorelease:
319355 Changed |= lowerObjCCall (F, " objc_autorelease" );
320356 break ;
@@ -405,16 +441,20 @@ class PreISelIntrinsicLoweringLegacyPass : public ModulePass {
405441
406442 void getAnalysisUsage (AnalysisUsage &AU) const override {
407443 AU.addRequired <TargetTransformInfoWrapperPass>();
444+ AU.addRequired <TargetLibraryInfoWrapperPass>();
408445 AU.addRequired <TargetPassConfig>();
409446 }
410447
411448 bool runOnModule (Module &M) override {
412449 auto LookupTTI = [this ](Function &F) -> TargetTransformInfo & {
413450 return this ->getAnalysis <TargetTransformInfoWrapperPass>().getTTI (F);
414451 };
452+ auto LookupTLI = [this ](Function &F) -> TargetLibraryInfo & {
453+ return this ->getAnalysis <TargetLibraryInfoWrapperPass>().getTLI (F);
454+ };
415455
416456 const auto &TM = getAnalysis<TargetPassConfig>().getTM <TargetMachine>();
417- PreISelIntrinsicLowering Lowering (TM, LookupTTI);
457+ PreISelIntrinsicLowering Lowering (TM, LookupTTI, LookupTLI );
418458 return Lowering.lowerIntrinsics (M);
419459 }
420460};
@@ -426,6 +466,7 @@ char PreISelIntrinsicLoweringLegacyPass::ID;
426466INITIALIZE_PASS_BEGIN (PreISelIntrinsicLoweringLegacyPass,
427467 " pre-isel-intrinsic-lowering" ,
428468 " Pre-ISel Intrinsic Lowering" , false , false )
469+ INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
429470INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
430471INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
431472INITIALIZE_PASS_END(PreISelIntrinsicLoweringLegacyPass,
@@ -443,8 +484,11 @@ PreservedAnalyses PreISelIntrinsicLoweringPass::run(Module &M,
443484 auto LookupTTI = [&FAM](Function &F) -> TargetTransformInfo & {
444485 return FAM.getResult <TargetIRAnalysis>(F);
445486 };
487+ auto LookupTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
488+ return FAM.getResult <TargetLibraryAnalysis>(F);
489+ };
446490
447- PreISelIntrinsicLowering Lowering (TM, LookupTTI);
491+ PreISelIntrinsicLowering Lowering (TM, LookupTTI, LookupTLI );
448492 if (!Lowering.lowerIntrinsics (M))
449493 return PreservedAnalyses::all ();
450494 else
0 commit comments