diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -106,6 +106,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVNExpression.h" +#include "llvm/Transforms/Utils/AssumeBundleBuilder.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/PredicateInfo.h" #include "llvm/Transforms/Utils/VNCoercion.h" @@ -495,6 +496,7 @@ AliasAnalysis *AA = nullptr; MemorySSA *MSSA = nullptr; MemorySSAWalker *MSSAWalker = nullptr; + AssumptionCache *AC = nullptr; const DataLayout &DL; std::unique_ptr PredInfo; @@ -658,7 +660,7 @@ NewGVN(Function &F, DominatorTree *DT, AssumptionCache *AC, TargetLibraryInfo *TLI, AliasAnalysis *AA, MemorySSA *MSSA, const DataLayout &DL) - : F(F), DT(DT), TLI(TLI), AA(AA), MSSA(MSSA), DL(DL), + : F(F), DT(DT), TLI(TLI), AA(AA), MSSA(MSSA), AC(AC), DL(DL), PredInfo(std::make_unique(F, *DT, *AC)), SQ(DL, TLI, DT, AC, /*CtxI=*/nullptr, /*UseInstrInfo=*/false) {} @@ -3696,6 +3698,7 @@ Inst.replaceAllUsesWith(UndefValue::get(Inst.getType())); if (isa(Inst)) continue; + salvageKnowledge(&Inst, AC); Inst.eraseFromParent(); ++NumGVNInstrDeleted; diff --git a/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll b/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll --- a/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -newgvn -S | FileCheck %s +; RUN: opt < %s -newgvn -S | FileCheck %s --check-prefixes=CHECK,NO_ASSUME +; RUN: opt < %s -newgvn --enable-knowledge-retention -S | FileCheck %s --check-prefixes=CHECK,USE_ASSUME %struct..0anon = type { i32 } %struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 } @@ -9,18 +10,32 @@ @n_spills = external global i32 ; [#uses=2] define i32 @reload(%struct.rtx_def* %first, i32 %global, %struct.FILE* %dumpfile) { -; CHECK-LABEL: @reload( -; CHECK-NEXT: cond_next2835.1: -; CHECK-NEXT: br label [[BB2928:%.*]] -; CHECK: bb2928: -; CHECK-NEXT: br i1 false, label [[COND_NEXT2943:%.*]], label [[COND_TRUE2935:%.*]] -; CHECK: cond_true2935: -; CHECK-NEXT: br label [[COND_NEXT2943]] -; CHECK: cond_next2943: -; CHECK-NEXT: br i1 false, label [[BB2982_PREHEADER:%.*]], label [[BB2928]] -; CHECK: bb2982.preheader: -; CHECK-NEXT: store i8 undef, i8* null -; CHECK-NEXT: ret i32 undef +; NO_ASSUME-LABEL: @reload( +; NO_ASSUME-NEXT: cond_next2835.1: +; NO_ASSUME-NEXT: br label [[BB2928:%.*]] +; NO_ASSUME: bb2928: +; NO_ASSUME-NEXT: br i1 false, label [[COND_NEXT2943:%.*]], label [[COND_TRUE2935:%.*]] +; NO_ASSUME: cond_true2935: +; NO_ASSUME-NEXT: br label [[COND_NEXT2943]] +; NO_ASSUME: cond_next2943: +; NO_ASSUME-NEXT: br i1 false, label [[BB2982_PREHEADER:%.*]], label [[BB2928]] +; NO_ASSUME: bb2982.preheader: +; NO_ASSUME-NEXT: store i8 undef, i8* null +; NO_ASSUME-NEXT: ret i32 undef +; +; USE_ASSUME-LABEL: @reload( +; USE_ASSUME-NEXT: cond_next2835.1: +; USE_ASSUME-NEXT: br label [[BB2928:%.*]] +; USE_ASSUME: bb2928: +; USE_ASSUME-NEXT: br i1 false, label [[COND_NEXT2943:%.*]], label [[COND_TRUE2935:%.*]] +; USE_ASSUME: cond_true2935: +; USE_ASSUME-NEXT: br label [[COND_NEXT2943]] +; USE_ASSUME: cond_next2943: +; USE_ASSUME-NEXT: br i1 false, label [[BB2982_PREHEADER:%.*]], label [[BB2928]] +; USE_ASSUME: bb2982.preheader: +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* @n_spills, i64 4), "dereferenceable"(i32* @n_spills, i64 4), "nonnull"(i32* @n_spills) ] +; USE_ASSUME-NEXT: store i8 undef, i8* null +; USE_ASSUME-NEXT: ret i32 undef ; cond_next2835.1: ; preds = %cond_next2861 %tmp2922 = load i32, i32* @n_spills, align 4 ; [#uses=0]