[llvm] r301227 - Handle invariant.group.barrier in BasicAA

Piotr Padlewski via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 24 12:37:17 PDT 2017


Author: prazek
Date: Mon Apr 24 14:37:17 2017
New Revision: 301227

URL: http://llvm.org/viewvc/llvm-project?rev=301227&view=rev
Log:
Handle invariant.group.barrier in BasicAA

Summary:
llvm.invariant.group.barrier returns pointer that mustalias
pointer it takes. It can't be marked with `returned` attribute,
because it would be remove easily. The other reason is that
only Alias Analysis can know about this, because if any other
pass would know it, then the result would be replaced with it's
argument, which would be invalid.

We can think about returned pointer as something that mustalias, but
it doesn't have to be bitwise the same as the argument.

Reviewers: dberlin, chandlerc, hfinkel, sanjoy

Subscribers: reames, nlewycky, rsmith, anna, amharc

Differential Revision: https://reviews.llvm.org/D31585

Added:
    llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll
Modified:
    llvm/trunk/include/llvm/IR/Value.h
    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
    llvm/trunk/lib/IR/Value.cpp
    llvm/trunk/test/Transforms/GVN/invariant.group.ll

Modified: llvm/trunk/include/llvm/IR/Value.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Value.h?rev=301227&r1=301226&r2=301227&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Value.h (original)
+++ llvm/trunk/include/llvm/IR/Value.h Mon Apr 24 14:37:17 2017
@@ -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

Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=301227&r1=301226&r2=301227&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Apr 24 14:37:17 2017
@@ -924,8 +924,8 @@ static AliasResult aliasSameBasePointerG
                                             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(cons
     // 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(co
     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.

Modified: llvm/trunk/lib/IR/Value.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Value.cpp?rev=301227&r1=301226&r2=301227&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Value.cpp (original)
+++ llvm/trunk/lib/IR/Value.cpp Mon Apr 24 14:37:17 2017
@@ -432,6 +432,7 @@ namespace {
 enum PointerStripKind {
   PSK_ZeroIndices,
   PSK_ZeroIndicesAndAliases,
+  PSK_ZeroIndicesAndAliasesAndBarriers,
   PSK_InBoundsConstantIndices,
   PSK_InBounds
 };
@@ -450,6 +451,7 @@ static const Value *stripPointerCastsAnd
     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 *stripPointerCastsAnd
         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::stripInBoundsConstan
   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 {

Added: llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll?rev=301227&view=auto
==============================================================================
--- llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll (added)
+++ llvm/trunk/test/Other/Inputs/invariant.group.barrier.ll Mon Apr 24 14:37:17 2017
@@ -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 *)

Modified: llvm/trunk/test/Transforms/GVN/invariant.group.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/invariant.group.ll?rev=301227&r1=301226&r2=301227&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GVN/invariant.group.ll (original)
+++ llvm/trunk/test/Transforms/GVN/invariant.group.ll Mon Apr 24 14:37:17 2017
@@ -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
 }
 




More information about the llvm-commits mailing list