[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