Index: include/llvm/IR/Value.h =================================================================== --- include/llvm/IR/Value.h +++ include/llvm/IR/Value.h @@ -482,6 +482,17 @@ static_cast(this)->stripPointerCasts()); } + /// \brief Strip off pointer casts, all-zero GEPs, aliases and barriers. + /// + /// Returns the original uncasted value. If this is called on a non-pointer + /// value, it returns 'this'. This function should be used only in + /// Alias analysis. + const Value *stripPointerCastsWithBarriers() const; + Value *stripPointerCastsWithBarriers() { + return const_cast( + static_cast(this)->stripPointerCastsWithBarriers()); + } + /// \brief Strip off pointer casts and all-zero GEPs. /// /// Returns the original uncasted value. If this is called on a non-pointer Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -924,8 +924,8 @@ uint64_t V2Size, const DataLayout &DL) { - assert(GEP1->getPointerOperand()->stripPointerCasts() == - GEP2->getPointerOperand()->stripPointerCasts() && + assert(GEP1->getPointerOperand()->stripPointerCastsWithBarriers() == + GEP2->getPointerOperand()->stripPointerCastsWithBarriers() && GEP1->getPointerOperand()->getType() == GEP2->getPointerOperand()->getType() && "Expected GEPs with the same pointer operand"); @@ -1185,8 +1185,8 @@ // If we know the two GEPs are based off of the exact same pointer (and not // just the same underlying object), see if that tells us anything about // the resulting pointers. - if (GEP1->getPointerOperand()->stripPointerCasts() == - GEP2->getPointerOperand()->stripPointerCasts() && + if (GEP1->getPointerOperand()->stripPointerCastsWithBarriers() == + GEP2->getPointerOperand()->stripPointerCastsWithBarriers() && GEP1->getPointerOperand()->getType() == GEP2->getPointerOperand()->getType()) { AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, DL); @@ -1502,8 +1502,8 @@ return NoAlias; // Strip off any casts if they exist. - V1 = V1->stripPointerCasts(); - V2 = V2->stripPointerCasts(); + V1 = V1->stripPointerCastsWithBarriers(); + V2 = V2->stripPointerCastsWithBarriers(); // If V1 or V2 is undef, the result is NoAlias because we can always pick a // value for undef that aliases nothing in the program. Index: lib/IR/Value.cpp =================================================================== --- lib/IR/Value.cpp +++ lib/IR/Value.cpp @@ -433,7 +433,8 @@ PSK_ZeroIndices, PSK_ZeroIndicesAndAliases, PSK_InBoundsConstantIndices, - PSK_InBounds + PSK_InBounds, + PSK_ZeroIndicesAndAliasesAndBarriers }; template @@ -450,6 +451,7 @@ if (auto *GEP = dyn_cast(V)) { switch (StripKind) { case PSK_ZeroIndicesAndAliases: + case PSK_ZeroIndicesAndAliasesAndBarriers: case PSK_ZeroIndices: if (!GEP->hasAllZeroIndices()) return V; @@ -472,12 +474,20 @@ return V; V = GA->getAliasee(); } else { - if (auto CS = ImmutableCallSite(V)) + if (auto CS = ImmutableCallSite(V)) { if (const Value *RV = CS.getReturnedArgOperand()) { V = RV; continue; } - + // The result of invariant.group.barrier must alias it's argument, + // but it can't be marked with returned attribute, that's why it needs + // special case. + if (StripKind == PSK_ZeroIndicesAndAliasesAndBarriers && + CS.getIntrinsicID() == Intrinsic::invariant_group_barrier) { + V = CS.getArgOperand(0); + continue; + } + } return V; } assert(V->getType()->isPointerTy() && "Unexpected operand type!"); @@ -499,6 +509,10 @@ return stripPointerCastsAndOffsets(this); } +const Value *Value::stripPointerCastsWithBarriers() const { + return stripPointerCastsAndOffsets(this); +} + const Value * Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) const { Index: test/Transforms/GVN/invariant.group.ll =================================================================== --- test/Transforms/GVN/invariant.group.ll +++ test/Transforms/GVN/invariant.group.ll @@ -237,15 +237,16 @@ ret i8 %a } -; CHECK-LABEL: define i8 @unoptimizable4() { -define i8 @unoptimizable4() { +; CHECK-LABEL: define i8 @optimizable4() { +define i8 @optimizable4() { entry: %ptr = alloca i8 store i8 42, i8* %ptr, !invariant.group !0 %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) +; CHECK-NOT: load %a = load i8, i8* %ptr2, !invariant.group !0 -; CHECK: ret i8 %a +; CHECK: ret i8 42 ret i8 %a } @@ -314,8 +315,9 @@ store i8 %unknownValue, i8* %ptr, !invariant.group !0 %newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) - %d = load i8, i8* %newPtr2, !invariant.group !0 ; Can't step through invariant.group.barrier to get value of %ptr -; CHECK: ret i8 %d +; CHECK-NOT: load + %d = load i8, i8* %newPtr2, !invariant.group !0 +; CHECK: ret i8 %unknownValue ret i8 %d }