[llvm] 6c989d0 - [BasicAA] Fix aliasGEP/DecomposeGEPExpression for scalable type.

Huihui Zhang via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 10 16:59:06 PDT 2020


Author: Huihui Zhang
Date: 2020-04-10T16:58:26-07:00
New Revision: 6c989d024862f1d0a7a7f700f94adcbab76489a2

URL: https://github.com/llvm/llvm-project/commit/6c989d024862f1d0a7a7f700f94adcbab76489a2
DIFF: https://github.com/llvm/llvm-project/commit/6c989d024862f1d0a7a7f700f94adcbab76489a2.diff

LOG: [BasicAA] Fix aliasGEP/DecomposeGEPExpression for scalable type.

Summary:
Don't attempt to analyze the decomposed GEP for scalable type.
GEP index scale is not compile-time constant for scalable type.
Be conservative, return MayAlias.

Explicitly call TypeSize::getFixedSize() to assert on places where
scalable type doesn't make sense.

Add unit tests to check functionality of -basicaa for scalable type.

This patch is needed for D76944.

Reviewers: sdesmalen, efriedma, spatel, bjope, ctetreau

Reviewed By: efriedma

Subscribers: tschuett, hiraditya, rkruppe, psnobl, llvm-commits

Tags: #llvm

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

Added: 
    llvm/test/Analysis/BasicAA/vscale.ll

Modified: 
    llvm/include/llvm/Analysis/BasicAliasAnalysis.h
    llvm/lib/Analysis/BasicAliasAnalysis.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
index 22e8c4b474cb..403510dbb3a3 100644
--- a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -142,6 +142,8 @@ class BasicAAResult : public AAResultBase<BasicAAResult> {
     APInt OtherOffset;
     // Scaled variable (non-constant) indices.
     SmallVector<VariableGEPIndex, 4> VarIndices;
+    // Is GEP index scale compile-time constant.
+    bool HasCompileTimeConstantScale;
   };
 
   /// Tracks phi nodes we have visited.

diff  --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index a8be2e388539..338e45ad4a3c 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -531,6 +531,15 @@ bool BasicAAResult::DecomposeGEPExpression(const Value *V,
       return false;
     }
 
+    // Don't attempt to analyze GEPs if index scale is not a compile-time
+    // constant.
+    Type *SrcEleTy = GEPOp->getSourceElementType();
+    if (SrcEleTy->isVectorTy() && SrcEleTy->getVectorIsScalable()) {
+      Decomposed.Base = V;
+      Decomposed.HasCompileTimeConstantScale = false;
+      return false;
+    }
+
     unsigned AS = GEPOp->getPointerAddressSpace();
     // Walk the indices of the GEP, accumulating them into BaseOff/VarIndices.
     gep_type_iterator GTI = gep_type_begin(GEPOp);
@@ -557,15 +566,16 @@ bool BasicAAResult::DecomposeGEPExpression(const Value *V,
         if (CIdx->isZero())
           continue;
         Decomposed.OtherOffset +=
-          (DL.getTypeAllocSize(GTI.getIndexedType()) *
-            CIdx->getValue().sextOrSelf(MaxPointerSize))
-              .sextOrTrunc(MaxPointerSize);
+            (DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize() *
+             CIdx->getValue().sextOrSelf(MaxPointerSize))
+                .sextOrTrunc(MaxPointerSize);
         continue;
       }
 
       GepHasConstantOffset = false;
 
-      APInt Scale(MaxPointerSize, DL.getTypeAllocSize(GTI.getIndexedType()));
+      APInt Scale(MaxPointerSize,
+                  DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize());
       unsigned ZExtBits = 0, SExtBits = 0;
 
       // If the integer type is smaller than the pointer size, it is implicitly
@@ -1158,7 +1168,8 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
     // partially overlap. We also need to check that the loaded size matches
     // the element size, otherwise we could still have overlap.
     Type *LastElementTy = GetElementPtrInst::getTypeAtIndex(Ty, (uint64_t)0);
-    const uint64_t ElementSize = DL.getTypeStoreSize(LastElementTy);
+    const uint64_t ElementSize =
+        DL.getTypeStoreSize(LastElementTy).getFixedSize();
     if (V1Size != ElementSize || V2Size != ElementSize)
       return MayAlias;
 
@@ -1316,12 +1327,20 @@ AliasResult BasicAAResult::aliasGEP(
   unsigned MaxPointerSize = getMaxPointerSize(DL);
   DecompGEP1.StructOffset = DecompGEP1.OtherOffset = APInt(MaxPointerSize, 0);
   DecompGEP2.StructOffset = DecompGEP2.OtherOffset = APInt(MaxPointerSize, 0);
+  DecompGEP1.HasCompileTimeConstantScale =
+      DecompGEP2.HasCompileTimeConstantScale = true;
 
   bool GEP1MaxLookupReached =
     DecomposeGEPExpression(GEP1, DecompGEP1, DL, &AC, DT);
   bool GEP2MaxLookupReached =
     DecomposeGEPExpression(V2, DecompGEP2, DL, &AC, DT);
 
+  // Don't attempt to analyze the decomposed GEP if index scale is not a
+  // compile-time constant.
+  if (!DecompGEP1.HasCompileTimeConstantScale ||
+      !DecompGEP2.HasCompileTimeConstantScale)
+    return MayAlias;
+
   APInt GEP1BaseOffset = DecompGEP1.StructOffset + DecompGEP1.OtherOffset;
   APInt GEP2BaseOffset = DecompGEP2.StructOffset + DecompGEP2.OtherOffset;
 

diff  --git a/llvm/test/Analysis/BasicAA/vscale.ll b/llvm/test/Analysis/BasicAA/vscale.ll
new file mode 100644
index 000000000000..e0bafbf72e85
--- /dev/null
+++ b/llvm/test/Analysis/BasicAA/vscale.ll
@@ -0,0 +1,219 @@
+; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; getelementptr
+
+; CHECK-LABEL: gep_alloca_const_offset_1
+; CHECK-DAG:  MustAlias:    <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep2
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %gep2
+define void @gep_alloca_const_offset_1() {
+  %alloc = alloca <vscale x 4 x i32>
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 0
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 1
+  ret void
+}
+
+; CHECK-LABEL: gep_alloca_const_offset_2
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep2
+; TODO: AliasResult for gep1,gep2 can be improved as MustAlias
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %gep2
+define void @gep_alloca_const_offset_2() {
+  %alloc = alloca <vscale x 4 x i32>
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 1
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 1
+  ret void
+}
+
+; CHECK-LABEL: gep_alloca_const_offset_3
+; CHECK-DAG:  MustAlias:    <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %alloc, i32* %gep2
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep1, i32* %gep2
+define void @gep_alloca_const_offset_3() {
+  %alloc = alloca <vscale x 4 x i32>
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 0
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 0, i64 1
+  ret void
+}
+
+; CHECK-LABEL: gep_alloca_const_offset_4
+; CHECK-DAG:  MustAlias:    <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep1
+; CHECK-DAG:  MustAlias:    <vscale x 4 x i32>* %alloc, i32* %gep2
+; CHECK-DAG:  MustAlias:    <vscale x 4 x i32>* %gep1, i32* %gep2
+define void @gep_alloca_const_offset_4() {
+  %alloc = alloca <vscale x 4 x i32>
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 0
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 0, i64 0
+  ret void
+}
+
+; CHECK-LABEL: gep_alloca_symbolic_offset
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %alloc, <vscale x 4 x i32>* %gep2
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %gep2
+define void @gep_alloca_symbolic_offset(i64 %idx1, i64 %idx2) {
+  %alloc = alloca <vscale x 4 x i32>
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 %idx1
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %alloc, i64 %idx2
+  ret void
+}
+
+; CHECK-LABEL: gep_same_base_const_offset
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep2
+; TODO: AliasResult for gep1,gep2 can be improved as NoAlias
+; CHECK-DAG:  MayAlias:     i32* %gep1, i32* %gep2
+define void @gep_same_base_const_offset(<vscale x 4 x i32>* %p) {
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 0
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 1
+  ret void
+}
+
+; CHECK-LABEL: gep_same_base_symbolic_offset
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %p
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep2, <vscale x 4 x i32>* %p
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %gep2
+define void @gep_same_base_symbolic_offset(<vscale x 4 x i32>* %p, i64 %idx1, i64 %idx2) {
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 %idx1
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 %idx2
+  ret void
+}
+
+; CHECK-LABEL: gep_
diff erent_base_const_offset
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %p1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %gep2, <vscale x 4 x i32>* %p2
+; CHECK-DAG:  NoAlias:      <vscale x 4 x i32>* %p1, <vscale x 4 x i32>* %p2
+; CHECK-DAG:  NoAlias:      <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %p2
+; CHECK-DAG:  NoAlias:      <vscale x 4 x i32>* %gep2, <vscale x 4 x i32>* %p1
+; CHECK-DAG:  NoAlias:      <vscale x 4 x i32>* %gep1, <vscale x 4 x i32>* %gep2
+define void @gep_
diff erent_base_const_offset(<vscale x 4 x i32>* noalias %p1, <vscale x 4 x i32>* noalias %p2) {
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p1, i64 1
+  %gep2 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p2, i64 1
+  ret void
+}
+
+; getelementptr + bitcast
+
+; CHECK-LABEL: gep_bitcast_1
+; CHECK-DAG:   MustAlias:    <vscale x 4 x i32>* %p, i32* %p2
+; CHECK-DAG:   MayAlias:     <vscale x 4 x i32>* %p, i32* %gep1
+; CHECK-DAG:   MayAlias:     i32* %gep1, i32* %p2
+; CHECK-DAG:   MayAlias:     <vscale x 4 x i32>* %p, i32* %gep2
+; CHECK-DAG:   MayAlias:     i32* %gep1, i32* %gep2
+; CHECK-DAG:   NoAlias:      i32* %gep2, i32* %p2
+define void @gep_bitcast_1(<vscale x 4 x i32>* %p) {
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 0
+  %p2 = bitcast <vscale x 4 x i32>* %p to i32*
+  %gep2 = getelementptr i32, i32* %p2, i64 4
+  ret void
+}
+
+; CHECK-LABEL: gep_bitcast_2
+; CHECK-DAG:  MustAlias:    <vscale x 4 x float>* %p2, <vscale x 4 x i32>* %p
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x float>* %p2, i32* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, float* %gep2
+; CHECK-DAG:  MayAlias:     float* %gep2, i32* %gep1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x float>* %p2, float* %gep2
+define void @gep_bitcast_2(<vscale x 4 x i32>* %p) {
+  %gep1 = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 0
+  %p2 = bitcast <vscale x 4 x i32>* %p to <vscale x 4 x float>*
+  %gep2 = getelementptr <vscale x 4 x float>, <vscale x 4 x float>* %p2, i64 1, i64 0
+  ret void
+}
+
+; getelementptr recursion
+
+; CHECK-LABEL: gep_recursion_level_1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %a
+; CHECK-DAG:  MayAlias:     i32* %a, i32* %gep
+; CHECK-DAG:  MayAlias:     i32* %a, i32* %gep_rec_1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_1
+; CHECK-DAG:  MayAlias:     i32* %gep, i32* %gep_rec_1
+define void @gep_recursion_level_1(i32* %a, <vscale x 4 x i32>* %p) {
+  %gep = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 2
+  %gep_rec_1 = getelementptr i32, i32* %gep, i64 1
+  ret void
+}
+
+; CHECK-LABEL: gep_recursion_level_1_bitcast
+; CHECK-DAG:  MustAlias:    <vscale x 4 x i32>* %p, i32* %a
+; CHECK-DAG:  MayAlias:     i32* %a, i32* %gep
+; CHECK-DAG:  MayAlias:     i32* %a, i32* %gep_rec_1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_1
+; CHECK-DAG:  MayAlias:     i32* %gep, i32* %gep_rec_1
+define void @gep_recursion_level_1_bitcast(i32* %a) {
+  %p = bitcast i32* %a to <vscale x 4 x i32>*
+  %gep = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 2
+  %gep_rec_1 = getelementptr i32, i32* %gep, i64 1
+  ret void
+}
+
+; CHECK-LABEL: gep_recursion_level_2
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %a
+; CHECK-DAG:  MayAlias:     i32* %a, i32* %gep
+; CHECK-DAG:  MayAlias:     i32* %a, i32* %gep_rec_1
+; CHECK-DAG:  MayAlias:     i32* %a, i32* %gep_rec_2
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_1
+; CHECK-DAG:  MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_2
+; CHECK-DAG:  MayAlias:     i32* %gep, i32* %gep_rec_1
+; CHECK-DAG:  MayAlias:     i32* %gep, i32* %gep_rec_2
+; CHECK-DAG:  MayAlias:     i32* %gep_rec_1, i32* %gep_rec_2
+define void @gep_recursion_level_2(i32* %a, <vscale x 4 x i32>* %p) {
+  %gep = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 2
+  %gep_rec_1 = getelementptr i32, i32* %gep, i64 1
+  %gep_rec_2 = getelementptr i32, i32* %gep_rec_1, i64 1
+  ret void
+}
+
+; CHECK-LABEL: gep_recursion_max_lookup_depth_reached
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %a
+; CHECK-DAG: MayAlias:     i32* %a, i32* %gep
+; CHECK-DAG: MayAlias:     i32* %a, i32* %gep_rec_1
+; CHECK-DAG: MayAlias:     i32* %a, i32* %gep_rec_2
+; CHECK-DAG: MayAlias:     i32* %a, i32* %gep_rec_3
+; CHECK-DAG: MayAlias:     i32* %a, i32* %gep_rec_4
+; CHECK-DAG: MayAlias:     i32* %a, i32* %gep_rec_5
+; CHECK-DAG: MayAlias:     i32* %a, i32* %gep_rec_6
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %gep
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_1
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_2
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_3
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_4
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_5
+; CHECK-DAG: MayAlias:     <vscale x 4 x i32>* %p, i32* %gep_rec_6
+; CHECK-DAG: MayAlias:     i32* %gep, i32* %gep_rec_1
+; CHECK-DAG: MayAlias:     i32* %gep, i32* %gep_rec_2
+; CHECK-DAG: MayAlias:     i32* %gep, i32* %gep_rec_3
+; CHECK-DAG: MayAlias:     i32* %gep, i32* %gep_rec_4
+; CHECK-DAG: MayAlias:     i32* %gep, i32* %gep_rec_5
+; CHECK-DAG: MayAlias:     i32* %gep, i32* %gep_rec_6
+; CHECK-DAG: MayAlias:     i32* %gep_rec_1, i32* %gep_rec_2
+; CHECK-DAG: MayAlias:     i32* %gep_rec_1, i32* %gep_rec_3
+; CHECK-DAG: MayAlias:     i32* %gep_rec_1, i32* %gep_rec_4
+; CHECK-DAG: MayAlias:     i32* %gep_rec_1, i32* %gep_rec_5
+; CHECK-DAG: MayAlias:     i32* %gep_rec_1, i32* %gep_rec_6
+; CHECK-DAG: MayAlias:     i32* %gep_rec_2, i32* %gep_rec_3
+; CHECK-DAG: MayAlias:     i32* %gep_rec_2, i32* %gep_rec_4
+; CHECK-DAG: MayAlias:     i32* %gep_rec_2, i32* %gep_rec_5
+; CHECK-DAG: MayAlias:     i32* %gep_rec_2, i32* %gep_rec_6
+; CHECK-DAG: MayAlias:     i32* %gep_rec_3, i32* %gep_rec_4
+; CHECK-DAG: MayAlias:     i32* %gep_rec_3, i32* %gep_rec_5
+; CHECK-DAG: MayAlias:     i32* %gep_rec_3, i32* %gep_rec_6
+; CHECK-DAG: MayAlias:     i32* %gep_rec_4, i32* %gep_rec_5
+; CHECK-DAG: MayAlias:     i32* %gep_rec_4, i32* %gep_rec_6
+; CHECK-DAG: MayAlias:     i32* %gep_rec_5, i32* %gep_rec_6
+; GEP max lookup depth was set to 6.
+define void @gep_recursion_max_lookup_depth_reached(i32* %a, <vscale x 4 x i32>* %p) {
+  %gep = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %p, i64 1, i64 2
+  %gep_rec_1 = getelementptr i32, i32* %gep, i64 1
+  %gep_rec_2 = getelementptr i32, i32* %gep_rec_1, i64 1
+  %gep_rec_3 = getelementptr i32, i32* %gep_rec_2, i64 1
+  %gep_rec_4 = getelementptr i32, i32* %gep_rec_3, i64 1
+  %gep_rec_5 = getelementptr i32, i32* %gep_rec_4, i64 1
+  %gep_rec_6 = getelementptr i32, i32* %gep_rec_5, i64 1
+  ret void
+}


        


More information about the llvm-commits mailing list