summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/Value.h11
-rw-r--r--llvm/lib/Analysis/BasicAliasAnalysis.cpp12
-rw-r--r--llvm/lib/IR/Value.cpp19
-rw-r--r--llvm/test/Other/Inputs/invariant.group.barrier.ll15
-rw-r--r--llvm/test/Transforms/GVN/invariant.group.ll12
5 files changed, 56 insertions, 13 deletions
diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h
index a4b48d7f353..00f82139925 100644
--- a/llvm/include/llvm/IR/Value.h
+++ b/llvm/include/llvm/IR/Value.h
@@ -482,6 +482,17 @@ public:
static_cast<const Value *>(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<Value *>(
+ static_cast<const Value *>(this)->stripPointerCastsAndBarriers());
+ }
+
/// \brief Strip off pointer casts and all-zero GEPs.
///
/// Returns the original uncasted value. If this is called on a non-pointer
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 3db041cc0fa..53782302030 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -924,8 +924,8 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
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 @@ AliasResult BasicAAResult::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size,
// 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 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, uint64_t V1Size,
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.
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index b07c57685a2..d83bdf2acd4 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -432,6 +432,7 @@ namespace {
enum PointerStripKind {
PSK_ZeroIndices,
PSK_ZeroIndicesAndAliases,
+ PSK_ZeroIndicesAndAliasesAndBarriers,
PSK_InBoundsConstantIndices,
PSK_InBounds
};
@@ -450,6 +451,7 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) {
if (auto *GEP = dyn_cast<GEPOperator>(V)) {
switch (StripKind) {
case PSK_ZeroIndicesAndAliases:
+ case PSK_ZeroIndicesAndAliasesAndBarriers:
case PSK_ZeroIndices:
if (!GEP->hasAllZeroIndices())
return V;
@@ -472,12 +474,20 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) {
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 @@ const Value *Value::stripInBoundsConstantOffsets() const {
return stripPointerCastsAndOffsets<PSK_InBoundsConstantIndices>(this);
}
+const Value *Value::stripPointerCastsAndBarriers() const {
+ return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliasesAndBarriers>(
+ this);
+}
+
const Value *
Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
APInt &Offset) const {
diff --git a/llvm/test/Other/Inputs/invariant.group.barrier.ll b/llvm/test/Other/Inputs/invariant.group.barrier.ll
new file mode 100644
index 00000000000..565b0989ecb
--- /dev/null
+++ b/llvm/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 *)
diff --git a/llvm/test/Transforms/GVN/invariant.group.ll b/llvm/test/Transforms/GVN/invariant.group.ll
index 570519bec52..787a1035d9c 100644
--- a/llvm/test/Transforms/GVN/invariant.group.ll
+++ b/llvm/test/Transforms/GVN/invariant.group.ll
@@ -237,15 +237,16 @@ entry:
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 @@ entry:
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
}
OpenPOWER on IntegriCloud