diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -557,15 +557,16 @@ 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 +1159,8 @@ // 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; @@ -1312,6 +1314,17 @@ const GEPOperator *GEP1, LocationSize V1Size, const AAMDNodes &V1AAInfo, const Value *V2, LocationSize V2Size, const AAMDNodes &V2AAInfo, const Value *UnderlyingV1, const Value *UnderlyingV2, AAQueryInfo &AAQI) { + // Don't attempt to decompose GEP for scalable type. GEP index scale is + // unknown at compile-time for scalable type. + Type *SrcEleTy1 = GEP1->getSourceElementType(); + Type *SrcEleTy2 = isa(V2) + ? cast(V2)->getSourceElementType() + : nullptr; + if ((SrcEleTy1->isVectorTy() && SrcEleTy1->getVectorIsScalable()) || + (SrcEleTy2 && SrcEleTy2->isVectorTy() && + SrcEleTy2->getVectorIsScalable())) + return MayAlias; + DecomposedGEP DecompGEP1, DecompGEP2; unsigned MaxPointerSize = getMaxPointerSize(DL); DecompGEP1.StructOffset = DecompGEP1.OtherOffset = APInt(MaxPointerSize, 0); diff --git a/llvm/test/Analysis/BasicAA/vscale.ll b/llvm/test/Analysis/BasicAA/vscale.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/BasicAA/vscale.ll @@ -0,0 +1,123 @@ +; 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: * %alloc, * %gep1 +; CHECK-DAG: MayAlias: * %alloc, * %gep2 +; CHECK-DAG: MayAlias: * %gep1, * %gep2 +define void @gep_alloca_const_offset_1() { + %alloc = alloca + %gep1 = getelementptr , * %alloc, i64 0 + %gep2 = getelementptr , * %alloc, i64 1 + ret void +} + +; CHECK-LABEL: gep_alloca_const_offset_2 +; CHECK-DAG: MayAlias: * %alloc, * %gep1 +; CHECK-DAG: MayAlias: * %alloc, * %gep2 +; TODO: AliasResult for gep1,gep2 can be improved as MustAlias +; CHECK-DAG: MayAlias: * %gep1, * %gep2 +define void @gep_alloca_const_offset_2() { + %alloc = alloca + %gep1 = getelementptr , * %alloc, i64 1 + %gep2 = getelementptr , * %alloc, i64 1 + ret void +} + +; CHECK-LABEL: gep_alloca_const_offset_3 +; CHECK-DAG: MustAlias: * %alloc, * %gep1 +; CHECK-DAG: MayAlias: * %alloc, i32* %gep2 +; CHECK-DAG: MayAlias: * %gep1, i32* %gep2 +define void @gep_alloca_const_offset_3() { + %alloc = alloca + %gep1 = getelementptr , * %alloc, i64 0 + %gep2 = getelementptr , * %alloc, i64 0, i64 1 + ret void +} + +; CHECK-LABEL: gep_alloca_const_offset_4 +; CHECK-DAG: MustAlias: * %alloc, * %gep1 +; CHECK-DAG: MustAlias: * %alloc, i32* %gep2 +; CHECK-DAG: MustAlias: * %gep1, i32* %gep2 +define void @gep_alloca_const_offset_4() { + %alloc = alloca + %gep1 = getelementptr , * %alloc, i64 0 + %gep2 = getelementptr , * %alloc, i64 0, i64 0 + ret void +} + +; CHECK-LABEL: gep_alloca_symbolic_offset +; CHECK-DAG: MayAlias: * %alloc, * %gep1 +; CHECK-DAG: MayAlias: * %alloc, * %gep2 +; CHECK-DAG: MayAlias: * %gep1, * %gep2 +define void @gep_alloca_symbolic_offset(i64 %idx1, i64 %idx2) { + %alloc = alloca + %gep1 = getelementptr , * %alloc, i64 %idx1 + %gep2 = getelementptr , * %alloc, i64 %idx2 + ret void +} + +; CHECK-LABEL: gep_same_base_const_offset +; CHECK-DAG: MayAlias: * %p, i32* %gep1 +; CHECK-DAG: MayAlias: * %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(* %p) { + %gep1 = getelementptr , * %p, i64 1, i64 0 + %gep2 = getelementptr , * %p, i64 1, i64 1 + ret void +} + +; CHECK-LABEL: gep_same_base_symbolic_offset +; CHECK-DAG: MayAlias: * %gep1, * %p +; CHECK-DAG: MayAlias: * %gep2, * %p +; CHECK-DAG: MayAlias: * %gep1, * %gep2 +define void @gep_same_base_symbolic_offset(* %p, i64 %idx1, i64 %idx2) { + %gep1 = getelementptr , * %p, i64 %idx1 + %gep2 = getelementptr , * %p, i64 %idx2 + ret void +} + +; CHECK-LABEL: gep_different_base_const_offset +; CHECK-DAG: MayAlias: * %gep1, * %p1 +; CHECK-DAG: MayAlias: * %gep2, * %p2 +; CHECK-DAG: NoAlias: * %p1, * %p2 +; CHECK-DAG: NoAlias: * %gep1, * %p2 +; CHECK-DAG: NoAlias: * %gep2, * %p1 +; CHECK-DAG: NoAlias: * %gep1, * %gep2 +define void @gep_different_base_const_offset(* noalias %p1, * noalias %p2) { + %gep1 = getelementptr , * %p1, i64 1 + %gep2 = getelementptr , * %p2, i64 1 + ret void +} + +; getelementptr + bitcast + +; CHECK-LABEL: gep_bitcast_1 +; CHECK-DAG: MustAlias: * %p, i32* %p2 +; CHECK-DAG: MayAlias: * %p, i32* %gep1 +; CHECK-DAG: MayAlias: i32* %gep1, i32* %p2 +; CHECK-DAG: MayAlias: * %p, i32* %gep2 +; CHECK-DAG: MayAlias: i32* %gep1, i32* %gep2 +; CHECK-DAG: NoAlias: i32* %gep2, i32* %p2 +define void @gep_bitcast_1(* %p) { + %gep1 = getelementptr , * %p, i64 1, i64 0 + %p2 = bitcast * %p to i32* + %gep2 = getelementptr i32, i32* %p2, i64 4 + ret void +} + +; CHECK-LABEL: gep_bitcast_2 +; CHECK-DAG: MustAlias: * %p2, * %p +; CHECK-DAG: MayAlias: * %p, i32* %gep1 +; CHECK-DAG: MayAlias: * %p2, i32* %gep1 +; CHECK-DAG: MayAlias: * %p, float* %gep2 +; CHECK-DAG: MayAlias: float* %gep2, i32* %gep1 +; CHECK-DAG: MayAlias: * %p2, float* %gep2 +define void @gep_bitcast_2(* %p) { + %gep1 = getelementptr , * %p, i64 1, i64 0 + %p2 = bitcast * %p to * + %gep2 = getelementptr , * %p2, i64 1, i64 0 + ret void +}