Index: llvm/trunk/include/llvm/IR/Value.h =================================================================== --- llvm/trunk/include/llvm/IR/Value.h +++ llvm/trunk/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 *stripPointerCastsAndBarriers() const; + Value *stripPointerCastsAndBarriers() { + return const_cast( + static_cast(this)->stripPointerCastsAndBarriers()); + } + /// \brief Strip off pointer casts and all-zero GEPs. /// /// Returns the original uncasted value. If this is called on a non-pointer Index: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp @@ -924,8 +924,8 @@ uint64_t V2Size, const DataLayout &DL) { - assert(GEP1->getPointerOperand()->stripPointerCasts() == - GEP2->getPointerOperand()->stripPointerCasts() && + assert(GEP1->getPointerOperand()->stripPointerCastsAndBarriers() == + GEP2->getPointerOperand()->stripPointerCastsAndBarriers() && GEP1->getPointerOperandType() == GEP2->getPointerOperandType() && "Expected GEPs with the same pointer operand"); @@ -1184,8 +1184,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()->stripPointerCastsAndBarriers() == + GEP2->getPointerOperand()->stripPointerCastsAndBarriers() && GEP1->getPointerOperandType() == GEP2->getPointerOperandType()) { AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, DL); // If we couldn't find anything interesting, don't abandon just yet. @@ -1500,8 +1500,8 @@ return NoAlias; // Strip off any casts if they exist. - V1 = V1->stripPointerCasts(); - V2 = V2->stripPointerCasts(); + V1 = V1->stripPointerCastsAndBarriers(); + V2 = V2->stripPointerCastsAndBarriers(); // 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: llvm/trunk/lib/IR/Value.cpp =================================================================== --- llvm/trunk/lib/IR/Value.cpp +++ llvm/trunk/lib/IR/Value.cpp @@ -432,6 +432,7 @@ enum PointerStripKind { PSK_ZeroIndices, PSK_ZeroIndicesAndAliases, + PSK_ZeroIndicesAndAliasesAndBarriers, PSK_InBoundsConstantIndices, PSK_InBounds }; @@ -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,11 @@ return stripPointerCastsAndOffsets(this); } +const Value *Value::stripPointerCastsAndBarriers() const { + return stripPointerCastsAndOffsets( + this); +} + const Value * Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) const { Index: llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll =================================================================== --- llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll +++ llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll @@ -0,0 +1,15 @@ +; RUN: opt -S -gvn < %s | FileCheck %s +; RUN: opt -S -newgvn < %s | FileCheck %s +; RUN: opt -S -O3 < %s | FileCheck %s + +; This test check if optimizer is not proving equality based on mustalias +; CHECK-LABEL: define void @dontProveEquality(i8* %a) +define void @dontProveEquality(i8* %a) { + %b = call i8* @llvm.invariant.group.barrier(i8* %a) + %r = i1 icmp eq i8* %b, i8* %a +;CHECK: call void @use(%r) + call void @use(%r) +} + +declare void @use(i1) +declare i8* @llvm.invariant.group.barrier(i8 *) Index: llvm/trunk/test/Transforms/GVN/invariant.group.ll =================================================================== --- llvm/trunk/test/Transforms/GVN/invariant.group.ll +++ llvm/trunk/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 }