Index: include/llvm/Transforms/IPO/PassManagerBuilder.h =================================================================== --- include/llvm/Transforms/IPO/PassManagerBuilder.h +++ include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -188,7 +188,9 @@ void addLateLTOOptimizationPasses(legacy::PassManagerBase &PM); void addPGOInstrPasses(legacy::PassManagerBase &MPM); void addFunctionSimplificationPasses(legacy::PassManagerBase &MPM); - void addInstructionCombiningPass(legacy::PassManagerBase &MPM) const; + void addInstructionCombiningPass( + legacy::PassManagerBase &MPM, + bool ForceLowerPostSimplificationIntrinsics = false) const; public: /// populateFunctionPassManager - This fills in the function pass manager, Index: include/llvm/Transforms/InstCombine/InstCombine.h =================================================================== --- include/llvm/Transforms/InstCombine/InstCombine.h +++ include/llvm/Transforms/InstCombine/InstCombine.h @@ -26,12 +26,16 @@ class InstCombinePass : public PassInfoMixin { InstCombineWorklist Worklist; bool ExpensiveCombines; + bool ForceLowerPostSimplificationIntrinsics; public: static StringRef name() { return "InstCombinePass"; } - explicit InstCombinePass(bool ExpensiveCombines = true) - : ExpensiveCombines(ExpensiveCombines) {} + explicit InstCombinePass(bool ExpensiveCombines = true, + bool ForceLowerPostSimplificationIntrinsics = false) + : ExpensiveCombines(ExpensiveCombines), + ForceLowerPostSimplificationIntrinsics( + ForceLowerPostSimplificationIntrinsics) {} PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; @@ -43,12 +47,16 @@ class InstructionCombiningPass : public FunctionPass { InstCombineWorklist Worklist; const bool ExpensiveCombines; + const bool ForceLowerPostSimplificationIntrinsics; public: static char ID; // Pass identification, replacement for typeid - InstructionCombiningPass(bool ExpensiveCombines = true) - : FunctionPass(ID), ExpensiveCombines(ExpensiveCombines) { + InstructionCombiningPass(bool ExpensiveCombines = true, + bool ForceLowerPostSimplificationIntrinsics = false) + : FunctionPass(ID), ExpensiveCombines(ExpensiveCombines), + ForceLowerPostSimplificationIntrinsics( + ForceLowerPostSimplificationIntrinsics) { initializeInstructionCombiningPassPass(*PassRegistry::getPassRegistry()); } @@ -68,7 +76,8 @@ // into: // %Z = add int 2, %X // -FunctionPass *createInstructionCombiningPass(bool ExpensiveCombines = true); +FunctionPass *createInstructionCombiningPass(bool ExpensiveCombines = true, + bool ForceLowerPostSimplificationIntrinsics = false); } #endif Index: lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- lib/CodeGen/CodeGenPrepare.cpp +++ lib/CodeGen/CodeGenPrepare.cpp @@ -1671,21 +1671,18 @@ // Lower all uses of llvm.objectsize.* ConstantInt *RetVal = lowerObjectSizeCall(II, *DL, TLInfo, /*MustSucceed=*/true); - // Substituting this can cause recursive simplifications, which can - // invalidate our iterator. Use a WeakTrackingVH to hold onto it in case - // this - // happens. - Value *CurValue = &*CurInstIterator; - WeakTrackingVH IterHandle(CurValue); - replaceAndRecursivelySimplify(CI, RetVal, TLInfo, nullptr); - - // If the iterator instruction was recursively deleted, start over at the - // start of the block. - if (IterHandle != CurValue) { - CurInstIterator = BB->begin(); - SunkAddrs.clear(); - } + // In a regular optimization pipeline, it's InstCombine's job to forcibly + // lower this intrinsic and simplify the result of that. Hence, if we've + // reached this, either: + // - the optimization pipeline is misconfigured, + // - we're just running a small set of of manually-specified passes on the + // IR, or + // - there's a bug elsewhere. + // In any case, there's probably not much reason to try to simplify users + // of `RetVal`. + II->replaceAllUsesWith(RetVal); + II->eraseFromParent(); return true; } case Intrinsic::aarch64_stlxr: Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -235,9 +235,11 @@ } void PassManagerBuilder::addInstructionCombiningPass( - legacy::PassManagerBase &PM) const { + legacy::PassManagerBase &PM, + bool ForceLowerPostSimplificationIntrinsics) const { bool ExpensiveCombines = OptLevel > 2; - PM.add(createInstructionCombiningPass(ExpensiveCombines)); + PM.add(createInstructionCombiningPass( + ExpensiveCombines, ForceLowerPostSimplificationIntrinsics)); } void PassManagerBuilder::populateFunctionPassManager( @@ -634,7 +636,8 @@ // on -O1 and no #pragma is found). Would be good to have these two passes // as function calls, so that we can only pass them when the vectorizer // changed the code. - addInstructionCombiningPass(MPM); + addInstructionCombiningPass(MPM, + /*ForceLowerPostSimplificationIntrinsics=*/true); if (OptLevel > 1 && ExtraVectorizerPasses) { // At higher optimization levels, try to clean up any runtime overlap and // alignment checks inserted by the vectorizer. We want to track correllated Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1912,8 +1912,9 @@ switch (II->getIntrinsicID()) { default: break; case Intrinsic::objectsize: - if (ConstantInt *N = - lowerObjectSizeCall(II, DL, &TLI, /*MustSucceed=*/false)) + if (ConstantInt *N = lowerObjectSizeCall( + II, DL, &TLI, + /*MustSucceed=*/ForceLowerPostSimplificationIntrinsics)) return replaceInstUsesWith(CI, N); return nullptr; case Intrinsic::bswap: { Index: lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- lib/Transforms/InstCombine/InstCombineInternal.h +++ lib/Transforms/InstCombine/InstCombineInternal.h @@ -252,6 +252,11 @@ /// Enable combines that trigger rarely but are costly in compiletime. const bool ExpensiveCombines; + /// Force InstCombine to lower calls to 'best-effort' intrinsics that may + /// technically be lowered at any time, but are best lowered after + /// simplifications. + const bool ForceLowerPostSimplificationIntrinsics; + AliasAnalysis *AA; // Required analyses. @@ -270,13 +275,17 @@ public: InstCombiner(InstCombineWorklist &Worklist, BuilderTy &Builder, - bool MinimizeSize, bool ExpensiveCombines, AliasAnalysis *AA, + bool MinimizeSize, bool ExpensiveCombines, + bool ForceLowerPostSimplificationIntrinsics, AliasAnalysis *AA, AssumptionCache &AC, TargetLibraryInfo &TLI, DominatorTree &DT, OptimizationRemarkEmitter &ORE, const DataLayout &DL, LoopInfo *LI) : Worklist(Worklist), Builder(Builder), MinimizeSize(MinimizeSize), - ExpensiveCombines(ExpensiveCombines), AA(AA), AC(AC), TLI(TLI), DT(DT), - DL(DL), SQ(DL, &TLI, &DT, &AC), ORE(ORE), LI(LI) {} + ExpensiveCombines(ExpensiveCombines), + ForceLowerPostSimplificationIntrinsics( + ForceLowerPostSimplificationIntrinsics), + AA(AA), AC(AC), TLI(TLI), DT(DT), DL(DL), SQ(DL, &TLI, &DT, &AC), + ORE(ORE), LI(LI) {} /// Run the combiner over the entire worklist until it is empty. /// Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3249,6 +3249,7 @@ Function &F, InstCombineWorklist &Worklist, AliasAnalysis *AA, AssumptionCache &AC, TargetLibraryInfo &TLI, DominatorTree &DT, OptimizationRemarkEmitter &ORE, bool ExpensiveCombines = true, + bool ForceLowerPostSimplificationIntrinsics = false, LoopInfo *LI = nullptr) { auto &DL = F.getParent()->getDataLayout(); ExpensiveCombines |= EnableExpensiveCombines; @@ -3278,8 +3279,9 @@ MadeIRChange |= prepareICWorklistFromFunction(F, DL, &TLI, Worklist); - InstCombiner IC(Worklist, Builder, F.optForMinSize(), ExpensiveCombines, AA, - AC, TLI, DT, ORE, DL, LI); + InstCombiner IC(Worklist, Builder, F.optForMinSize(), ExpensiveCombines, + ForceLowerPostSimplificationIntrinsics, AA, AC, TLI, DT, + ORE, DL, LI); IC.MaxArraySizeForCombine = MaxArraySize; if (!IC.run()) @@ -3299,8 +3301,9 @@ auto *LI = AM.getCachedResult(F); auto *AA = &AM.getResult(F); - if (!combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, DT, ORE, - ExpensiveCombines, LI)) + if (!combineInstructionsOverFunction( + F, Worklist, AA, AC, TLI, DT, ORE, ExpensiveCombines, + ForceLowerPostSimplificationIntrinsics, LI)) // No changes, all analyses are preserved. return PreservedAnalyses::all(); @@ -3341,8 +3344,9 @@ auto *LIWP = getAnalysisIfAvailable(); auto *LI = LIWP ? &LIWP->getLoopInfo() : nullptr; - return combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, DT, ORE, - ExpensiveCombines, LI); + return combineInstructionsOverFunction( + F, Worklist, AA, AC, TLI, DT, ORE, ExpensiveCombines, + ForceLowerPostSimplificationIntrinsics, LI); } char InstructionCombiningPass::ID = 0; @@ -3367,8 +3371,10 @@ initializeInstructionCombiningPassPass(*unwrap(R)); } -FunctionPass *llvm::createInstructionCombiningPass(bool ExpensiveCombines) { - return new InstructionCombiningPass(ExpensiveCombines); +FunctionPass *llvm::createInstructionCombiningPass( + bool ExpensiveCombines, bool ForceLowerPostSimplificationIntrinsics) { + return new InstructionCombiningPass(ExpensiveCombines, + ForceLowerPostSimplificationIntrinsics); } void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM) { Index: test/Transforms/InstCombine/force-lower-objectsize.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/force-lower-objectsize.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -O2 -S | FileCheck %s +; +; Hack: Use -O2 so that the instcombine iteration that's meant to force lower +; objectsize intrinsics runs + +declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1) + +; CHECK-LABEL: define i32 @unresolvable +define i32 @unresolvable(i8* %p) { + ; CHECK: ret i32 -1 + %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %p, i1 false, i1 true) + ret i32 %1 +}