// Statically, we can see that the base objects are the same, but the
// pointers have dynamic offsets which we can't resolve. And none of our
// little tricks above worked.
- //
- // TODO: Returning PartialAlias instead of MayAlias is a mild hack; the
- // practical effect of this is protecting TBAA in the case of dynamic
- // indices into arrays of unions or malloc'd memory.
- return PartialAlias;
+ return MayAlias;
}
static AliasResult MergeAliasResults(AliasResult A, AliasResult B) {
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; CHECK: Function: foo
-; CHECK: PartialAlias: i32* %Ipointer, i32* %Jpointer
+; CHECK: MayAlias: i32* %Ipointer, i32* %Jpointer
; CHECK: 9 no alias responses
-; CHECK: 6 partial alias responses
+; CHECK: 6 may alias responses
define void @foo(i32* noalias %p, i32* noalias %q, i32 %i, i32 %j) {
%Ipointer = getelementptr i32, i32* %p, i32 %i
target datalayout = "e-p:32:32:32"
-; CHECK: 1 partial alias response
+; CHECK: 1 may alias responses
define i32 @test(i32* %tab, i32 %indvar) nounwind {
%tmp31 = mul i32 %indvar, -2
@c = external global i32
; CHECK-LABEL: f
-; CHECK: PartialAlias: i32* %arrayidx, i32* %arrayidx6
+; CHECK: MayAlias: i32* %arrayidx, i32* %arrayidx6
define void @f() {
%idxprom = zext i32 undef to i64
%add4 = add i32 0, 1
target triple = "x86_64-apple-darwin13.4.0"
; CHECK-LABEL: compute1
-; CHECK: PartialAlias: i32* %arrayidx8, i32* %out
-; CHECK: PartialAlias: i32* %arrayidx11, i32* %out
-; CHECK: PartialAlias: i32* %arrayidx11, i32* %arrayidx8
-; CHECK: PartialAlias: i32* %arrayidx14, i32* %out
-; CHECK: PartialAlias: i32* %arrayidx14, i32* %arrayidx8
-; CHECK: PartialAlias: i32* %arrayidx11, i32* %arrayidx14
+; CHECK: MayAlias: i32* %arrayidx8, i32* %out
+; CHECK: MayAlias: i32* %arrayidx11, i32* %out
+; CHECK: MayAlias: i32* %arrayidx11, i32* %arrayidx8
+; CHECK: MayAlias: i32* %arrayidx14, i32* %out
+; CHECK: MayAlias: i32* %arrayidx14, i32* %arrayidx8
+; CHECK: MayAlias: i32* %arrayidx11, i32* %arrayidx14
define void @compute1(i32 %num.0.lcssa, i32* %out) {
%idxprom = zext i32 %num.0.lcssa to i64
%arrayidx8 = getelementptr inbounds i32, i32* %out, i64 %idxprom
}
; CHECK-LABEL: compute2
-; CHECK: PartialAlias: i32* %arrayidx11, i32* %out.addr
+; CHECK: MayAlias: i32* %arrayidx11, i32* %out.addr
define void @compute2(i32 %num, i32* %out.addr) {
%add9 = add i32 %num, 1
%idxprom10 = zext i32 %add9 to i64
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-; CHECK: PartialAlias: double* %p.0.i.0, double* %p3
+; CHECK: MayAlias: double* %p.0.i.0, double* %p3
; %p3 is equal to %p.0.i.0 on the second iteration of the loop,
; so MayAlias is needed. In practice, basicaa returns PartialAlias
--- /dev/null
+; RUN: opt -basicaa -aa-eval -print-all-alias-modref-info -disable-output < %s 2>&1 | FileCheck %s
+
+; Check that BasicAA falls back to MayAlias (instead of PartialAlias) when none
+; of its little tricks are applicable.
+
+; CHECK: MayAlias: float* %arrayidxA, float* %arrayidxB
+
+define void @fallback_mayalias(float* noalias nocapture %C, i64 %i, i64 %j) local_unnamed_addr {
+entry:
+ %shl = shl i64 %i, 3
+ %mul = shl nsw i64 %j, 4
+ %addA = add nsw i64 %mul, %shl
+ %orB = or i64 %shl, 1
+ %addB = add nsw i64 %mul, %orB
+
+ %arrayidxA = getelementptr inbounds float, float* %C, i64 %addA
+ store float undef, float* %arrayidxA, align 4
+
+ %arrayidxB = getelementptr inbounds float, float* %C, i64 %addB
+ store float undef, float* %arrayidxB, align 4
+
+ ret void
+}
}
; CHECK-LABEL: test_zext_sext_amounts
-; CHECK: PartialAlias: i8* %a, i8* %b
+; CHECK: MayAlias: i8* %a, i8* %b
; %a and %b only PartialAlias as, although they're both zext(sext(%num)) they'll extend the sign by a different
; number of bits before zext-ing the remainder.
define void @test_zext_sext_amounts(i8* %mem, i8 %num) {
}
; CHECK-LABEL: test_path_dependence
-; CHECK: PartialAlias: i8* %a, i8* %b
+; CHECK: MayAlias: i8* %a, i8* %b
; CHECK: MustAlias: i8* %a, i8* %c
-; CHECK: PartialAlias: i8* %a, i8* %d
+; CHECK: MayAlias: i8* %a, i8* %d
define void @test_path_dependence(i32 %p, i8* %mem) {
%p.minus1 = add i32 %p, -1 ; this will always unsigned-wrap, unless %p == 0
%p.minus1.64 = zext i32 %p.minus1 to i64
}
; CHECK-LABEL: test_zext_sext_num
-; CHECK: PartialAlias: i8* %a, i8* %b
+; CHECK: MayAlias: i8* %a, i8* %b
; %a and %b NoAlias if %num == 255 (see @test_zext_sext_255), but %a and %b NoAlias for other values of %num (e.g. 0)
define void @test_zext_sext_num(i8* %mem, i8 %num) {
%zext.num = zext i8 %num to i16
}
; CHECK-LABEL: constantOffsetHeuristic_i3_i8
-; CHECK: PartialAlias: i32* %a, i32* %b
+; CHECK: MayAlias: i32* %a, i32* %b
; CHECK: NoAlias: i32* %a, i32* %c
-; CHECK: PartialAlias: i32* %b, i32* %c
+; CHECK: MayAlias: i32* %b, i32* %c
define void @constantOffsetHeuristic_i3_i8(i8* %mem, i3 %val) {
%zext.plus.7 = add nsw i3 %val, 7
%zext.plus.4 = add nsw i3 %val, 4
}
; CHECK-LABEL: constantOffsetHeuristic_i8_i8
-; CHECK: PartialAlias: i32* %a, i32* %b
+; CHECK: MayAlias: i32* %a, i32* %b
; CHECK: NoAlias: i32* %a, i32* %c
; CHECK: NoAlias: i32* %b, i32* %c
define void @constantOffsetHeuristic_i8_i8(i8* %mem, i8 %val) {
; CHECK-DAG: MustAlias: %struct* %st, %struct* %sta
-; CHECK-DAG: PartialAlias: %struct* %st, i32* %x
-; CHECK-DAG: PartialAlias: %struct* %st, i32* %y
-; CHECK-DAG: PartialAlias: %struct* %st, i32* %z
+; CHECK-DAG: MayAlias: %struct* %st, i32* %x
+; CHECK-DAG: MayAlias: %struct* %st, i32* %y
+; CHECK-DAG: MayAlias: %struct* %st, i32* %z
; CHECK-DAG: NoAlias: i32* %x, i32* %y
; CHECK-DAG: NoAlias: i32* %x, i32* %z
; CHECK-DAG: NoAlias: i32* %y, i32* %z
-; CHECK-DAG: PartialAlias: %struct* %st, %struct* %y_12
-; CHECK-DAG: PartialAlias: %struct* %y_12, i32* %x
-; CHECK-DAG: PartialAlias: i32* %x, i80* %y_10
+; CHECK-DAG: MayAlias: %struct* %st, %struct* %y_12
+; CHECK-DAG: MayAlias: %struct* %y_12, i32* %x
+; CHECK-DAG: MayAlias: i32* %x, i80* %y_10
-; CHECK-DAG: PartialAlias: %struct* %st, i64* %y_8
-; CHECK-DAG: PartialAlias: i32* %z, i64* %y_8
+; CHECK-DAG: MayAlias: %struct* %st, i64* %y_8
+; CHECK-DAG: MayAlias: i32* %z, i64* %y_8
; CHECK-DAG: NoAlias: i32* %x, i64* %y_8
; CHECK-DAG: MustAlias: %struct* %y_12, i32* %y
}
; CHECK: Function: t2
-; CHECK: PartialAlias: i32* %gep1, i32* %gep2
+; CHECK: MayAlias: i32* %gep1, i32* %gep2
define void @t2([8 x i32]* %p, i32 %addend, i32* %q) {
%knownnonzero = load i32, i32* %q, !range !0
%add = add nsw nuw i32 %addend, %knownnonzero
}
; CHECK: Function: t4
-; CHECK: PartialAlias: i32* %gep1, i32* %gep2
+; CHECK: MayAlias: i32* %gep1, i32* %gep2
define void @t4([8 x i32]* %p, i32 %addend, i32* %q) {
%knownnonzero = load i32, i32* %q, !range !0
%add = add nsw nuw i32 %addend, %knownnonzero
}
; CHECK: Function: t5
-; CHECK: PartialAlias: i32* %gep2, i64* %bc
+; CHECK: MayAlias: i32* %gep2, i64* %bc
define void @t5([8 x i32]* %p, i32 %addend, i32* %q) {
%knownnonzero = load i32, i32* %q, !range !0
%add = add nsw nuw i32 %addend, %knownnonzero
; CHECK-LABEL: test_simple
-; CHECK-DAG: PartialAlias: %struct* %st, i32* %x
-; CHECK-DAG: PartialAlias: %struct* %st, i32* %y
-; CHECK-DAG: PartialAlias: %struct* %st, i32* %z
+; CHECK-DAG: MayAlias: %struct* %st, i32* %x
+; CHECK-DAG: MayAlias: %struct* %st, i32* %y
+; CHECK-DAG: MayAlias: %struct* %st, i32* %z
; CHECK-DAG: NoAlias: i32* %x, i32* %y
; CHECK-DAG: NoAlias: i32* %x, i32* %z
; CHECK-DAG: NoAlias: i32* %y, i32* %z
-; CHECK-DAG: PartialAlias: %struct* %st, %struct* %y_12
-; CHECK-DAG: PartialAlias: %struct* %y_12, i32* %x
-; CHECK-DAG: PartialAlias: i32* %x, i80* %y_10
+; CHECK-DAG: MayAlias: %struct* %st, %struct* %y_12
+; CHECK-DAG: MayAlias: %struct* %y_12, i32* %x
+; CHECK-DAG: MayAlias: i32* %x, i80* %y_10
-; CHECK-DAG: PartialAlias: %struct* %st, i64* %y_8
-; CHECK-DAG: PartialAlias: i32* %z, i64* %y_8
+; CHECK-DAG: MayAlias: %struct* %st, i64* %y_8
+; CHECK-DAG: MayAlias: i32* %z, i64* %y_8
; CHECK-DAG: NoAlias: i32* %x, i64* %y_8
; CHECK-DAG: MustAlias: %struct* %y_12, i32* %y
; CHECK-LABEL: test_in_array
-; CHECK-DAG: PartialAlias: [1 x %struct]* %st, i32* %x
-; CHECK-DAG: PartialAlias: [1 x %struct]* %st, i32* %y
-; CHECK-DAG: PartialAlias: [1 x %struct]* %st, i32* %z
+; CHECK-DAG: MayAlias: [1 x %struct]* %st, i32* %x
+; CHECK-DAG: MayAlias: [1 x %struct]* %st, i32* %y
+; CHECK-DAG: MayAlias: [1 x %struct]* %st, i32* %z
; CHECK-DAG: NoAlias: i32* %x, i32* %y
; CHECK-DAG: NoAlias: i32* %x, i32* %z
; CHECK-DAG: NoAlias: i32* %y, i32* %z
-; CHECK-DAG: PartialAlias: %struct* %y_12, [1 x %struct]* %st
-; CHECK-DAG: PartialAlias: %struct* %y_12, i32* %x
-; CHECK-DAG: PartialAlias: i32* %x, i80* %y_10
+; CHECK-DAG: MayAlias: %struct* %y_12, [1 x %struct]* %st
+; CHECK-DAG: MayAlias: %struct* %y_12, i32* %x
+; CHECK-DAG: MayAlias: i32* %x, i80* %y_10
-; CHECK-DAG: PartialAlias: [1 x %struct]* %st, i64* %y_8
-; CHECK-DAG: PartialAlias: i32* %z, i64* %y_8
+; CHECK-DAG: MayAlias: [1 x %struct]* %st, i64* %y_8
+; CHECK-DAG: MayAlias: i32* %z, i64* %y_8
; CHECK-DAG: NoAlias: i32* %x, i64* %y_8
; CHECK-DAG: MustAlias: %struct* %y_12, i32* %y
; CHECK-LABEL: test_in_3d_array
-; CHECK-DAG: PartialAlias: [1 x [1 x [1 x %struct]]]* %st, i32* %x
-; CHECK-DAG: PartialAlias: [1 x [1 x [1 x %struct]]]* %st, i32* %y
-; CHECK-DAG: PartialAlias: [1 x [1 x [1 x %struct]]]* %st, i32* %z
+; CHECK-DAG: MayAlias: [1 x [1 x [1 x %struct]]]* %st, i32* %x
+; CHECK-DAG: MayAlias: [1 x [1 x [1 x %struct]]]* %st, i32* %y
+; CHECK-DAG: MayAlias: [1 x [1 x [1 x %struct]]]* %st, i32* %z
; CHECK-DAG: NoAlias: i32* %x, i32* %y
; CHECK-DAG: NoAlias: i32* %x, i32* %z
; CHECK-DAG: NoAlias: i32* %y, i32* %z
-; CHECK-DAG: PartialAlias: %struct* %y_12, [1 x [1 x [1 x %struct]]]* %st
-; CHECK-DAG: PartialAlias: %struct* %y_12, i32* %x
-; CHECK-DAG: PartialAlias: i32* %x, i80* %y_10
+; CHECK-DAG: MayAlias: %struct* %y_12, [1 x [1 x [1 x %struct]]]* %st
+; CHECK-DAG: MayAlias: %struct* %y_12, i32* %x
+; CHECK-DAG: MayAlias: i32* %x, i80* %y_10
-; CHECK-DAG: PartialAlias: [1 x [1 x [1 x %struct]]]* %st, i64* %y_8
-; CHECK-DAG: PartialAlias: i32* %z, i64* %y_8
+; CHECK-DAG: MayAlias: [1 x [1 x [1 x %struct]]]* %st, i64* %y_8
+; CHECK-DAG: MayAlias: i32* %z, i64* %y_8
; CHECK-DAG: NoAlias: i32* %x, i64* %y_8
; CHECK-DAG: MustAlias: %struct* %y_12, i32* %y
; CHECK-DAG: NoAlias: i32* %y, i32* %y2
; CHECK-DAG: NoAlias: i32* %z, i32* %z2
-; CHECK-DAG: PartialAlias: i32* %x, i32* %y2
-; CHECK-DAG: PartialAlias: i32* %x, i32* %z2
+; CHECK-DAG: MayAlias: i32* %x, i32* %y2
+; CHECK-DAG: MayAlias: i32* %x, i32* %z2
-; CHECK-DAG: PartialAlias: i32* %x2, i32* %y
-; CHECK-DAG: PartialAlias: i32* %y, i32* %z2
+; CHECK-DAG: MayAlias: i32* %x2, i32* %y
+; CHECK-DAG: MayAlias: i32* %y, i32* %z2
-; CHECK-DAG: PartialAlias: i32* %x2, i32* %z
-; CHECK-DAG: PartialAlias: i32* %y2, i32* %z
+; CHECK-DAG: MayAlias: i32* %x2, i32* %z
+; CHECK-DAG: MayAlias: i32* %y2, i32* %z
define void @test_same_underlying_object_same_indices(%struct* %st, i64 %i, i64 %j, i64 %k) {
%st2 = getelementptr %struct, %struct* %st, i32 10
; CHECK-LABEL: test_same_underlying_object_different_indices
-; CHECK-DAG: PartialAlias: i32* %x, i32* %x2
-; CHECK-DAG: PartialAlias: i32* %y, i32* %y2
-; CHECK-DAG: PartialAlias: i32* %z, i32* %z2
+; CHECK-DAG: MayAlias: i32* %x, i32* %x2
+; CHECK-DAG: MayAlias: i32* %y, i32* %y2
+; CHECK-DAG: MayAlias: i32* %z, i32* %z2
-; CHECK-DAG: PartialAlias: i32* %x, i32* %y2
-; CHECK-DAG: PartialAlias: i32* %x, i32* %z2
+; CHECK-DAG: MayAlias: i32* %x, i32* %y2
+; CHECK-DAG: MayAlias: i32* %x, i32* %z2
-; CHECK-DAG: PartialAlias: i32* %x2, i32* %y
-; CHECK-DAG: PartialAlias: i32* %y, i32* %z2
+; CHECK-DAG: MayAlias: i32* %x2, i32* %y
+; CHECK-DAG: MayAlias: i32* %y, i32* %z2
-; CHECK-DAG: PartialAlias: i32* %x2, i32* %z
-; CHECK-DAG: PartialAlias: i32* %y2, i32* %z
+; CHECK-DAG: MayAlias: i32* %x2, i32* %z
+; CHECK-DAG: MayAlias: i32* %y2, i32* %z
define void @test_same_underlying_object_different_indices(%struct* %st, i64 %i1, i64 %j1, i64 %k1, i64 %i2, i64 %k2, i64 %j2) {
%st2 = getelementptr %struct, %struct* %st, i32 10
}
; CHECK-LABEL: test_sign_extension
-; CHECK: PartialAlias: i64* %b.i64, i8* %a
+; CHECK: MayAlias: i64* %b.i64, i8* %a
define void @test_sign_extension(i32 %p) {
%1 = tail call i8* @malloc(i64 120)
}
; CHECK-LABEL: test_fe_tools
-; CHECK: PartialAlias: i32* %a, i32* %b
+; CHECK: MayAlias: i32* %a, i32* %b
define void @test_fe_tools([8 x i32]* %values) {
br label %reorder
@d = global i32 0, align 4
; CHECK-LABEL: test_spec2006
-; CHECK: PartialAlias: i32** %x, i32** %y
+; CHECK: MayAlias: i32** %x, i32** %y
define void @test_spec2006() {
%h = alloca [1 x [2 x i32*]], align 16
}
; CHECK-LABEL: test_modulo_analysis_with_global
-; CHECK: PartialAlias: i32** %x, i32** %y
+; CHECK: MayAlias: i32** %x, i32** %y
define void @test_modulo_analysis_with_global() {
%h = alloca [1 x [2 x i32*]], align 16
%idxprom = sext i32 %sub to i64
%half = bitcast %union.vector_t* %vb to [8 x i16]*
%arrayidx = getelementptr inbounds [8 x i16], [8 x i16]* %half, i64 0, i64 %idxprom
- %tmp4 = load i16, i16* %arrayidx, align 2, !tbaa !0
+ %tmp4 = load i16, i16* %arrayidx, align 2, !tbaa !10
%conv = zext i16 %tmp4 to i32
%and = and i32 %conv, 15
%sub6 = sub nsw i32 7, %i.01
%idxprom7 = sext i32 %sub6 to i64
%half9 = bitcast %union.vector_t* %va to [8 x i16]*
%arrayidx10 = getelementptr inbounds [8 x i16], [8 x i16]* %half9, i64 0, i64 %idxprom7
- %tmp11 = load i16, i16* %arrayidx10, align 2, !tbaa !0
+ %tmp11 = load i16, i16* %arrayidx10, align 2, !tbaa !10
%conv12 = zext i16 %tmp11 to i32
%shl = shl i32 %conv12, %and
%sub15 = sub nsw i32 7, %i.01
%idxprom16 = sext i32 %sub15 to i64
%half18 = bitcast %union.vector_t* %va to [8 x i16]*
%arrayidx19 = getelementptr inbounds [8 x i16], [8 x i16]* %half18, i64 0, i64 %idxprom16
- %tmp20 = load i16, i16* %arrayidx19, align 2, !tbaa !0
+ %tmp20 = load i16, i16* %arrayidx19, align 2, !tbaa !10
%conv21 = zext i16 %tmp20 to i32
%sub23 = sub nsw i32 16, %and
%shr = lshr i32 %conv21, %sub23
%idxprom27 = sext i32 %sub26 to i64
%half28 = bitcast %union.vector_t* %t to [8 x i16]*
%arrayidx29 = getelementptr inbounds [8 x i16], [8 x i16]* %half28, i64 0, i64 %idxprom27
- store i16 %conv24, i16* %arrayidx29, align 2, !tbaa !0
+ store i16 %conv24, i16* %arrayidx29, align 2, !tbaa !10
%inc = add nsw i32 %i.01, 1
%cmp = icmp slt i32 %inc, 8
br i1 %cmp, label %for.body, label %for.end
for.end: ; preds = %for.body
%arrayidx31 = getelementptr inbounds %union.vector_t, %union.vector_t* %t, i64 0, i32 0, i64 1
- %tmp32 = load i64, i64* %arrayidx31, align 8, !tbaa !3
+ %tmp32 = load i64, i64* %arrayidx31, align 8, !tbaa !10
%arrayidx35 = getelementptr inbounds %union.vector_t, %union.vector_t* %vd, i64 0, i32 0, i64 1
- store i64 %tmp32, i64* %arrayidx35, align 8, !tbaa !3
+ store i64 %tmp32, i64* %arrayidx35, align 8, !tbaa !10
%arrayidx37 = getelementptr inbounds %union.vector_t, %union.vector_t* %t, i64 0, i32 0, i64 0
- %tmp38 = load i64, i64* %arrayidx37, align 8, !tbaa !3
+ %tmp38 = load i64, i64* %arrayidx37, align 8, !tbaa !10
%arrayidx41 = getelementptr inbounds %union.vector_t, %union.vector_t* %vd, i64 0, i32 0, i64 0
- store i64 %tmp38, i64* %arrayidx41, align 8, !tbaa !3
+ store i64 %tmp38, i64* %arrayidx41, align 8, !tbaa !10
ret void
}
}
; CHECK: [[TAG]] = !{[[TYPE_LL:!.*]], [[TYPE_LL]], i64 0}
-; CHECK: [[TYPE_LL]] = !{!"long long", {{!.*}}}
+; CHECK: [[TYPE_LL]] = !{!"omnipotent char", {{!.*}}}
!0 = !{!6, !6, i64 0}
!1 = !{!"omnipotent char", !2}
!2 = !{!"Simple C/C++ TBAA"}
!7 = !{!"long long", !1}
!8 = !{!"int", !1}
!9 = !{!"float", !1}
+!10 = !{!1, !1, i64 0}