diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp --- a/llvm/lib/Transforms/Scalar/GVNSink.cpp +++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp @@ -46,6 +46,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" @@ -54,7 +55,9 @@ #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/Value.h" @@ -562,7 +565,7 @@ class GVNSink { public: - GVNSink() = default; + GVNSink(AssumptionCache *AC) : AC(AC) {} bool run(Function &F) { LLVM_DEBUG(dbgs() << "GVNSink: running on function @" << F.getName() @@ -577,6 +580,7 @@ } private: + AssumptionCache *AC; ValueTable VN; bool shouldAvoidSinkingInstruction(Instruction *I) { @@ -868,6 +872,11 @@ if (I != I0) { combineMetadataForCSE(I0, I, true); I0->andIRFlags(I); + // If assumptions are tracked we need to unregister any we will replace. + if (AC && isa(I) && + match(cast(I), + llvm::PatternMatch::m_Intrinsic())) + AC->unregisterAssumption(cast(I)); } for (auto *I : Insts) @@ -897,7 +906,10 @@ bool runOnFunction(Function &F) override { if (skipFunction(F)) return false; - GVNSink G; + AssumptionCache *AC = nullptr; + if (auto *ACT = getAnalysisIfAvailable()) + AC = &ACT->getAssumptionCache(F); + GVNSink G(AC); return G.run(F); } @@ -909,7 +921,8 @@ } // end anonymous namespace PreservedAnalyses GVNSinkPass::run(Function &F, FunctionAnalysisManager &AM) { - GVNSink G; + AssumptionCache *AC = AM.getCachedResult(F); + GVNSink G(AC); if (!G.run(F)) return PreservedAnalyses::all(); diff --git a/llvm/test/Transforms/GVNSink/assumption.ll b/llvm/test/Transforms/GVNSink/assumption.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GVNSink/assumption.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -S -passes="print,gvn-sink,loop-unroll" -unroll-count=3 | FileCheck %s +; +; This crashed because the cached assumption was replaced and the replacement +; was then in the cache twice. +; +; PR49043 + +@g = external global i32 + +define void @main() { +bb: + %i1.i = load volatile i32, i32* @g + %i32.i = icmp eq i32 %i1.i, 0 + call void @llvm.assume(i1 %i32.i) #3 + br label %bb4.i + +bb4.i: ; preds = %bb4.i, %bb + %i.i = load volatile i32, i32* @g + %i3.i = icmp eq i32 %i.i, 0 + call void @llvm.assume(i1 %i3.i) #3 + br label %bb4.i + +func_1.exit: ; No predecessors! + unreachable +} + +declare void @llvm.assume(i1) + +; CHECK: call void @llvm.assume( +; CHECK: call void @llvm.assume( +; CHECK: call void @llvm.assume( +