Currently, DecomposeGEP() bails out on the whole decomposition if it encounters a scalable GEP type anywhere. However, it is fine to still analyze other GEPs that we look through before hitting the scalable GEP. This does mean that the decomposed GEP base is no longer required to be the same as the underlying object. However, I don't believe this property is necessary for correctness anymore. This allows us to compute slightly more precise aliasing results for GEP chains containing scalable vectors, though my primary interest here is simplifying the code. Differential Revision: https://reviews.llvm.org/D110511
220 lines
11 KiB
LLVM
220 lines
11 KiB
LLVM
; RUN: opt < %s -basic-aa -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_different_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_different_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: NoAlias: 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: NoAlias: 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: NoAlias: i32* %gep, i32* %gep_rec_1
|
|
; CHECK-DAG: NoAlias: i32* %gep, i32* %gep_rec_2
|
|
; CHECK-DAG: NoAlias: 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: NoAlias: i32* %gep, i32* %gep_rec_1
|
|
; CHECK-DAG: NoAlias: i32* %gep, i32* %gep_rec_2
|
|
; CHECK-DAG: NoAlias: i32* %gep, i32* %gep_rec_3
|
|
; CHECK-DAG: NoAlias: i32* %gep, i32* %gep_rec_4
|
|
; CHECK-DAG: NoAlias: i32* %gep, i32* %gep_rec_5
|
|
; CHECK-DAG: NoAlias: i32* %gep, i32* %gep_rec_6
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_1, i32* %gep_rec_2
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_1, i32* %gep_rec_3
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_1, i32* %gep_rec_4
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_1, i32* %gep_rec_5
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_1, i32* %gep_rec_6
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_2, i32* %gep_rec_3
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_2, i32* %gep_rec_4
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_2, i32* %gep_rec_5
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_2, i32* %gep_rec_6
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_3, i32* %gep_rec_4
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_3, i32* %gep_rec_5
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_3, i32* %gep_rec_6
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_4, i32* %gep_rec_5
|
|
; CHECK-DAG: NoAlias: i32* %gep_rec_4, i32* %gep_rec_6
|
|
; CHECK-DAG: NoAlias: 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
|
|
}
|