Index: include/llvm/Analysis/InstructionSimplify.h =================================================================== --- include/llvm/Analysis/InstructionSimplify.h +++ include/llvm/Analysis/InstructionSimplify.h @@ -58,14 +58,18 @@ AssumptionCache *AC = nullptr; const Instruction *CxtI = nullptr; + /// If true, it is safe to use metadata during simplification. + bool UseMetadata = true; + SimplifyQuery(const DataLayout &DL, const Instruction *CXTI = nullptr) : DL(DL), CxtI(CXTI) {} SimplifyQuery(const DataLayout &DL, const TargetLibraryInfo *TLI, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, - const Instruction *CXTI = nullptr) - : DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI) {} + const Instruction *CXTI = nullptr, bool UseMetadata = true) + : DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), UseMetadata(UseMetadata) { + } SimplifyQuery getWithInstruction(Instruction *I) const { SimplifyQuery Copy(*this); Copy.CxtI = I; Index: include/llvm/Analysis/ValueTracking.h =================================================================== --- include/llvm/Analysis/ValueTracking.h +++ include/llvm/Analysis/ValueTracking.h @@ -99,7 +99,8 @@ bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + bool UseMetadata = true); /// Returns true if the give value is known to be non-negative. bool isKnownNonNegative(const Value *V, const DataLayout &DL, @@ -125,9 +126,10 @@ /// Return true if the given values are known to be non-equal when defined. /// Supports scalar integer types only. bool isKnownNonEqual(const Value *V1, const Value *V2, const DataLayout &DL, - AssumptionCache *AC = nullptr, - const Instruction *CxtI = nullptr, - const DominatorTree *DT = nullptr); + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr, + bool UseMetadata = true); /// Return true if 'V & Mask' is known to be zero. We use this predicate to /// simplify operations downstream. Mask is known to be zero for bits that V Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -2013,13 +2013,15 @@ computePointerICmp(const DataLayout &DL, const TargetLibraryInfo *TLI, const DominatorTree *DT, CmpInst::Predicate Pred, AssumptionCache *AC, const Instruction *CxtI, - Value *LHS, Value *RHS) { + bool UseMetadata, Value *LHS, Value *RHS) { // First, skip past any trivial no-ops. LHS = LHS->stripPointerCasts(); RHS = RHS->stripPointerCasts(); // A non-null pointer is not equal to a null pointer. - if (llvm::isKnownNonZero(LHS, DL) && isa(RHS) && + if (llvm::isKnownNonZero(LHS, DL, 0, nullptr, nullptr, nullptr, + UseMetadata) && + isa(RHS) && (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE)) return ConstantInt::get(GetCompareTy(LHS), !CmpInst::isTrueWhenEqual(Pred)); @@ -2281,12 +2283,12 @@ return getTrue(ITy); case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_ULE: - if (isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT, Q.UseMetadata)) return getFalse(ITy); break; case ICmpInst::ICMP_NE: case ICmpInst::ICMP_UGT: - if (isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT)) + if (isKnownNonZero(LHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT, Q.UseMetadata)) return getTrue(ITy); break; case ICmpInst::ICMP_SLT: { @@ -2486,7 +2488,7 @@ } static Value *simplifyICmpWithConstant(CmpInst::Predicate Pred, Value *LHS, - Value *RHS) { + Value *RHS, bool UseMetadata) { Type *ITy = GetCompareTy(RHS); // The return type. Value *X; @@ -2522,9 +2524,10 @@ ConstantRange LHS_CR = Lower != Upper ? ConstantRange(Lower, Upper) : ConstantRange(Width, true); - if (auto *I = dyn_cast(LHS)) - if (auto *Ranges = I->getMetadata(LLVMContext::MD_range)) - LHS_CR = LHS_CR.intersectWith(getConstantRangeFromMetadata(*Ranges)); + if (UseMetadata) + if (auto *I = dyn_cast(LHS)) + if (auto *Ranges = I->getMetadata(LLVMContext::MD_range)) + LHS_CR = LHS_CR.intersectWith(getConstantRangeFromMetadata(*Ranges)); if (!LHS_CR.isFullSet()) { if (RHS_CR.contains(LHS_CR)) @@ -3077,7 +3080,7 @@ if (Value *V = simplifyICmpWithZero(Pred, LHS, RHS, Q)) return V; - if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS)) + if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS, Q.UseMetadata)) return V; // If both operands have range metadata, use the metadata @@ -3086,7 +3089,7 @@ auto RHS_Instr = cast(RHS); auto LHS_Instr = cast(LHS); - if (RHS_Instr->getMetadata(LLVMContext::MD_range) && + if (Q.UseMetadata && RHS_Instr->getMetadata(LLVMContext::MD_range) && LHS_Instr->getMetadata(LLVMContext::MD_range)) { auto RHS_CR = getConstantRangeFromMetadata( *RHS_Instr->getMetadata(LLVMContext::MD_range)); @@ -3265,7 +3268,7 @@ // icmp eq|ne X, Y -> false|true if X != Y if (ICmpInst::isEquality(Pred) && - isKnownNonEqual(LHS, RHS, Q.DL, Q.AC, Q.CxtI, Q.DT)) { + isKnownNonEqual(LHS, RHS, Q.DL, Q.AC, Q.CxtI, Q.DT, Q.UseMetadata)) { return Pred == ICmpInst::ICMP_NE ? getTrue(ITy) : getFalse(ITy); } @@ -3278,8 +3281,8 @@ // Simplify comparisons of related pointers using a powerful, recursive // GEP-walk when we have target data available.. if (LHS->getType()->isPointerTy()) - if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.AC, Q.CxtI, LHS, - RHS)) + if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.AC, Q.CxtI, + Q.UseMetadata, LHS, RHS)) return C; if (auto *CLHS = dyn_cast(LHS)) if (auto *CRHS = dyn_cast(RHS)) @@ -3287,9 +3290,9 @@ Q.DL.getTypeSizeInBits(CLHS->getType()) && Q.DL.getTypeSizeInBits(CRHS->getPointerOperandType()) == Q.DL.getTypeSizeInBits(CRHS->getType())) - if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.AC, Q.CxtI, - CLHS->getPointerOperand(), - CRHS->getPointerOperand())) + if (auto *C = computePointerICmp( + Q.DL, Q.TLI, Q.DT, Pred, Q.AC, Q.CxtI, Q.UseMetadata, + CLHS->getPointerOperand(), CRHS->getPointerOperand())) return C; if (GetElementPtrInst *GLHS = dyn_cast(LHS)) { Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -118,15 +118,20 @@ /// (all of which can call computeKnownBits), and so on. std::array Excluded; + /// If true, it is safe to use metadata during simplification. + bool UseMetadata; + unsigned NumExcluded = 0; Query(const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, - const DominatorTree *DT, OptimizationRemarkEmitter *ORE = nullptr) - : DL(DL), AC(AC), CxtI(CxtI), DT(DT), ORE(ORE) {} + const DominatorTree *DT, OptimizationRemarkEmitter *ORE = nullptr, + bool UseMetadata = true) + : DL(DL), AC(AC), CxtI(CxtI), DT(DT), ORE(ORE), UseMetadata(UseMetadata) { + } Query(const Query &Q, const Value *NewExcl) : DL(Q.DL), AC(Q.AC), CxtI(Q.CxtI), DT(Q.DT), ORE(Q.ORE), - NumExcluded(Q.NumExcluded) { + UseMetadata(Q.UseMetadata), NumExcluded(Q.NumExcluded) { Excluded = Q.Excluded; Excluded[NumExcluded++] = NewExcl; assert(NumExcluded <= Excluded.size()); @@ -234,8 +239,9 @@ bool llvm::isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth, AssumptionCache *AC, const Instruction *CxtI, - const DominatorTree *DT) { - return ::isKnownNonZero(V, Depth, Query(DL, AC, safeCxtI(V, CxtI), DT)); + const DominatorTree *DT, bool UseMetadata) { + return ::isKnownNonZero( + V, Depth, Query(DL, AC, safeCxtI(V, CxtI), DT, nullptr, UseMetadata)); } bool llvm::isKnownNonNegative(const Value *V, const DataLayout &DL, @@ -268,12 +274,12 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, const Query &Q); bool llvm::isKnownNonEqual(const Value *V1, const Value *V2, - const DataLayout &DL, - AssumptionCache *AC, const Instruction *CxtI, - const DominatorTree *DT) { - return ::isKnownNonEqual(V1, V2, Query(DL, AC, - safeCxtI(V1, safeCxtI(V2, CxtI)), - DT)); + const DataLayout &DL, AssumptionCache *AC, + const Instruction *CxtI, const DominatorTree *DT, + bool UseMetadata) { + return ::isKnownNonEqual(V1, V2, + Query(DL, AC, safeCxtI(V1, safeCxtI(V2, CxtI)), DT, + /*ORE=*/nullptr, /*UseMetadata=*/UseMetadata)); } static bool MaskedValueIsZero(const Value *V, const APInt &Mask, unsigned Depth, @@ -965,8 +971,9 @@ switch (I->getOpcode()) { default: break; case Instruction::Load: - if (MDNode *MD = cast(I)->getMetadata(LLVMContext::MD_range)) - computeKnownBitsFromRangeMetadata(*MD, Known); + if (Q.UseMetadata) + if (MDNode *MD = cast(I)->getMetadata(LLVMContext::MD_range)) + computeKnownBitsFromRangeMetadata(*MD, Known); break; case Instruction::And: { // If either the LHS or the RHS are Zero, the result is zero. @@ -1442,8 +1449,9 @@ // If range metadata is attached to this call, set known bits from that, // and then intersect with known bits based on other properties of the // function. - if (MDNode *MD = cast(I)->getMetadata(LLVMContext::MD_range)) - computeKnownBitsFromRangeMetadata(*MD, Known); + if (Q.UseMetadata) + if (MDNode *MD = cast(I)->getMetadata(LLVMContext::MD_range)) + computeKnownBitsFromRangeMetadata(*MD, Known); if (const Value *RV = ImmutableCallSite(I).getReturnedArgOperand()) { computeKnownBits(RV, Known2, Depth + 1, Q); Known.Zero |= Known2.Zero; @@ -1931,14 +1939,16 @@ return false; } - if (auto *I = dyn_cast(V)) { - if (MDNode *Ranges = I->getMetadata(LLVMContext::MD_range)) { - // If the possible ranges don't contain zero, then the value is - // definitely non-zero. - if (auto *Ty = dyn_cast(V->getType())) { - const APInt ZeroValue(Ty->getBitWidth(), 0); - if (rangeMetadataExcludesValue(Ranges, ZeroValue)) - return true; + if (Q.UseMetadata) { + if (auto *I = dyn_cast(V)) { + if (MDNode *Ranges = I->getMetadata(LLVMContext::MD_range)) { + // If the possible ranges don't contain zero, then the value is + // definitely non-zero. + if (auto *Ty = dyn_cast(V->getType())) { + const APInt ZeroValue(Ty->getBitWidth(), 0); + if (rangeMetadataExcludesValue(Ranges, ZeroValue)) + return true; + } } } } @@ -1953,15 +1963,17 @@ if (isa(V) && Q.DL.getAllocaAddrSpace() == 0) return true; - // A byval, inalloca, or nonnull argument is never null. - if (const Argument *A = dyn_cast(V)) - if (A->hasByValOrInAllocaAttr() || A->hasNonNullAttr()) - return true; + if (Q.UseMetadata) { + // A byval, inalloca, or nonnull argument is never null. + if (const Argument *A = dyn_cast(V)) + if (A->hasByValOrInAllocaAttr() || A->hasNonNullAttr()) + return true; - // A Load tagged with nonnull metadata is never null. - if (const LoadInst *LI = dyn_cast(V)) - if (LI->getMetadata(LLVMContext::MD_nonnull)) - return true; + // A Load tagged with nonnull metadata is never null. + if (const LoadInst *LI = dyn_cast(V)) + if (LI->getMetadata(LLVMContext::MD_nonnull)) + return true; + } if (auto CS = ImmutableCallSite(V)) { if (CS.isReturnNonNull()) Index: lib/Transforms/Scalar/NewGVN.cpp =================================================================== --- lib/Transforms/Scalar/NewGVN.cpp +++ lib/Transforms/Scalar/NewGVN.cpp @@ -657,8 +657,8 @@ TargetLibraryInfo *TLI, AliasAnalysis *AA, MemorySSA *MSSA, const DataLayout &DL) : F(F), DT(DT), TLI(TLI), AA(AA), MSSA(MSSA), DL(DL), - PredInfo(make_unique(F, *DT, *AC)), SQ(DL, TLI, DT, AC) { - } + PredInfo(make_unique(F, *DT, *AC)), + SQ(DL, TLI, DT, AC, /*CtxI=*/nullptr, /*UseMetadata=*/false) {} bool runGVN(); Index: test/Transforms/NewGVN/metadata-simplify.ll =================================================================== --- /dev/null +++ test/Transforms/NewGVN/metadata-simplify.ll @@ -0,0 +1,160 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py + +; The tests in this file check that we do not simplify based on metadata that is +; not available on all code paths. + +; RUN: opt < %s -S -newgvn | FileCheck %s + +define i1 @test1(i32** %arg, i1 %arg2) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOAD1:%.*]] = load i32*, i32** [[ARG:%.*]], !nonnull !0 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32* [[LOAD1]], null +; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK: bb2: +; CHECK-NEXT: [[LOAD2:%.*]] = load i32*, i32** [[ARG]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32* [[LOAD2]], null +; CHECK-NEXT: ret i1 [[CMP2]] +; + br i1 %arg2, label %bb1, label %bb2 + +bb1: + %load1 = load i32*, i32** %arg, !nonnull !0 + %cmp1 = icmp eq i32* %load1, null + ret i1 %cmp1 + +bb2: + %load2 = load i32*, i32** %arg + %cmp2 = icmp eq i32* %load2, null + ret i1 %cmp2 +} + +define i1 @test2(i32** %arg, i1 %arg2) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOAD1:%.*]] = load i32*, i32** [[ARG:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32* [[LOAD1]], null +; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK: bb2: +; CHECK-NEXT: [[LOAD2:%.*]] = load i32*, i32** [[ARG]], !nonnull !0 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32* [[LOAD2]], null +; CHECK-NEXT: ret i1 [[CMP2]] +; + br i1 %arg2, label %bb1, label %bb2 + +bb1: + %load1 = load i32*, i32** %arg + %cmp1 = icmp eq i32* %load1, null + ret i1 %cmp1 + +bb2: + %load2 = load i32*, i32** %arg, !nonnull !0 + %cmp2 = icmp eq i32* %load2, null + ret i1 %cmp2 +} + + +define i1 @test3(i32* %ptr, i1 %arg2) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]], !range !1 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[LOAD1]], 999 +; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK: bb2: +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, i32* [[PTR]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[LOAD2]], 999 +; CHECK-NEXT: ret i1 [[CMP2]] +; + br i1 %arg2, label %bb1, label %bb2 + +bb1: + %load1 = load i32, i32* %ptr, !range !1 + %cmp1 = icmp ne i32 %load1, 999 + ret i1 %cmp1 + +bb2: + %load2 = load i32, i32* %ptr + %cmp2 = icmp ne i32 %load2, 999 + ret i1 %cmp2 +} + +define i1 @test4(i32* %ptr, i1 %arg2) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[LOAD1]], 999 +; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK: bb2: +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, i32* [[PTR]], !range !1 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[LOAD2]], 999 +; CHECK-NEXT: ret i1 [[CMP2]] +; + br i1 %arg2, label %bb1, label %bb2 + +bb1: + %load1 = load i32, i32* %ptr + %cmp1 = icmp ne i32 %load1, 999 + ret i1 %cmp1 + +bb2: + %load2 = load i32, i32* %ptr, !range !1 + %cmp2 = icmp ne i32 %load2, 999 + ret i1 %cmp2 +} + +define i1 @test5(i32* %ptr, i1 %arg2) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]], !range !1 +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[LOAD1]], 999 +; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK: bb2: +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, i32* [[PTR]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[LOAD2]], 999 +; CHECK-NEXT: ret i1 [[CMP2]] +; + br i1 %arg2, label %bb1, label %bb2 + +bb1: + %load1 = load i32, i32* %ptr, !range !1 + %cmp1 = icmp slt i32 %load1, 999 + ret i1 %cmp1 + +bb2: + %load2 = load i32, i32* %ptr + %cmp2 = icmp slt i32 %load2, 999 + ret i1 %cmp2 +} + +define i1 @test6(i32* %ptr, i1 %arg2) { +; CHECK-LABEL: @test6( +; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[LOAD1]], 999 +; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK: bb2: +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, i32* [[PTR]], !range !1 +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[LOAD2]], 999 +; CHECK-NEXT: ret i1 [[CMP2]] +; + br i1 %arg2, label %bb1, label %bb2 + +bb1: + %load1 = load i32, i32* %ptr + %cmp1 = icmp slt i32 %load1, 999 + ret i1 %cmp1 + +bb2: + %load2 = load i32, i32* %ptr, !range !1 + %cmp2 = icmp slt i32 %load2, 999 + ret i1 %cmp2 +} + +!0 = !{} +!1 = !{ i32 10, i32 20 }