1; RUN: opt < %s -aa-pipeline=tbaa,basic-aa -passes=aa-eval -evaluate-aa-metadata \ 2; RUN: -print-no-aliases -print-may-aliases -disable-output 2>&1 | \ 3; RUN: FileCheck %s 4; RUN: opt < %s -aa-pipeline=tbaa,basic-aa -passes=gvn -S | FileCheck %s --check-prefix=OPT 5; 6; Check that TBAA handles access tags with aggregate final access types 7; correctly. 8 9%A = type { i32, i32 } ; struct A { int i, j; }; 10%B = type { %A } ; struct B { A a; }; 11%C = type { %B } ; struct C { B b; }; 12%D = type { i16 } ; struct D { short s; }; 13 14; int vs. A::i => MayAlias. 15define i32 @f1(ptr %i, ptr %a) { 16entry: 17; CHECK-LABEL: f1 18; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 19; OPT-LABEL: f1 20; OPT: store i32 5, 21; OPT: store i32 7, 22; OPT: %[[RET:.*]] = load i32, 23; OPT: ret i32 %[[RET]] 24 store i32 5, ptr %i, align 4, !tbaa !3 ; TAG_int 25 store i32 7, ptr %a, align 4, !tbaa !5 ; TAG_A_i 26 %0 = load i32, ptr %i, align 4, !tbaa !3 ; TAG_int 27 ret i32 %0 28} 29 30; int vs. B::a => MayAlias. 31define i32 @f2(ptr %i, ptr %b) { 32entry: 33; CHECK-LABEL: f2 34; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 35; OPT-LABEL: f2 36; OPT: store i32 5, 37; OPT: store i32 7, 38; OPT: %[[RET:.*]] = load i32, 39; OPT: ret i32 %[[RET]] 40 store i32 5, ptr %i, align 4, !tbaa !3 ; TAG_int 41 store i32 7, ptr %b, align 4, !tbaa !7 ; TAG_B_a 42 %0 = load i32, ptr %i, align 4, !tbaa !3 ; TAG_int 43 ret i32 %0 44} 45 46; int vs. C::b => MayAlias. 47define i32 @f3(ptr %i, ptr %c) { 48entry: 49; CHECK-LABEL: f3 50; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 51; OPT-LABEL: f3 52; OPT: store i32 5, 53; OPT: store i32 7, 54; OPT: %[[RET:.*]] = load i32, 55; OPT: ret i32 %[[RET]] 56 store i32 5, ptr %i, align 4, !tbaa !3 ; TAG_int 57 store i32 7, ptr %c, align 4, !tbaa !9 ; TAG_C_b 58 %0 = load i32, ptr %i, align 4, !tbaa !3 ; TAG_int 59 ret i32 %0 60} 61 62; A vs. C::b => MayAlias. 63define i32 @f4(ptr %a, ptr %c) { 64entry: 65; CHECK-LABEL: f4 66; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 67; OPT-LABEL: f4 68; OPT: store i32 5, 69; OPT: store i32 7, 70; OPT: %[[RET:.*]] = load i32, 71; OPT: ret i32 %[[RET]] 72 store i32 5, ptr %a, align 4, !tbaa !10 ; TAG_A 73 store i32 7, ptr %c, align 4, !tbaa !9 ; TAG_C_b 74 %0 = load i32, ptr %a, align 4, !tbaa !10 ; TAG_A 75 ret i32 %0 76} 77 78; short vs. C::b => NoAlias. 79define i32 @f5(ptr %i, ptr %c) { 80entry: 81; CHECK-LABEL: f5 82; CHECK: NoAlias: store i32 7, {{.*}} <-> store i32 5, 83; OPT-LABEL: f5 84; OPT: store i32 5, 85; OPT: store i32 7, 86; OPT: ret i32 5 87 store i32 5, ptr %i, align 4, !tbaa !12 ; TAG_short 88 store i32 7, ptr %c, align 4, !tbaa !9 ; TAG_C_b 89 %0 = load i32, ptr %i, align 4, !tbaa !12 ; TAG_short 90 ret i32 %0 91} 92 93; C vs. D => NoAlias. 94define i32 @f6(ptr %c, ptr %d) { 95entry: 96; CHECK-LABEL: f6 97; CHECK: NoAlias: store i16 7, {{.*}} <-> store i32 5, 98; OPT-LABEL: f6 99; OPT: store i32 5, 100; OPT: store i16 7, 101; OPT: ret i32 5 102 store i32 5, ptr %c, align 4, !tbaa !13 ; TAG_C 103 store i16 7, ptr %d, align 4, !tbaa !15 ; TAG_D 104 %0 = load i32, ptr %c, align 4, !tbaa !13 ; TAG_C 105 ret i32 %0 106} 107 108; A vs. A::j => MayAlias. 109; This differs from A vs. A::i case in that the offsets of the final 110; accessed objects in A do not match. 111define i32 @f7(ptr %i, ptr %a) { 112entry: 113; CHECK-LABEL: f7 114; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 115; OPT-LABEL: f7 116; OPT: store i32 5, 117; OPT: store i32 7, 118; OPT: %[[RET:.*]] = load i32, 119; OPT: ret i32 %[[RET]] 120 store i32 5, ptr %i, align 4, !tbaa !10 ; TAG_A 121 store i32 7, ptr %a, align 4, !tbaa !16 ; TAG_A_j 122 %0 = load i32, ptr %i, align 4, !tbaa !10 ; TAG_A 123 ret i32 %0 124} 125 126!0 = !{!"root"} 127!1 = !{!0, i64 1, !"char"} 128!2 = !{!1, i64 4, !"int"} 129!3 = !{!2, !2, i64 0, i64 4} ; TAG_int 130 131!4 = !{!1, i64 4, !"A", !2, i64 0, i64 4, !2, i64 4, i64 4} 132!5 = !{!4, !2, i64 0, i64 4} ; TAG_A_i 133!16 = !{!4, !2, i64 4, i64 4} ; TAG_A_j 134 135!6 = !{!1, i64 4, !"B", !4, i64 0, i64 4} 136!7 = !{!6, !4, i64 0, i64 4} ; TAG_B_a 137 138!8 = !{!1, i64 4, !"C", !6, i64 0, i64 4} 139!9 = !{!8, !6, i64 0, i64 4} ; TAG_C_b 140 141!10 = !{!4, !4, i64 0, i64 4} ; TAG_A 142 143!11 = !{!1, i64 2, !"short"} 144!12 = !{!11, !11, i64 0, i64 2} ; TAG_short 145 146!13 = !{!8, !8, i64 0, i64 4} ; TAG_C 147 148!14 = !{!4, i64 2, !"D", !11, i64 0, i64 2} 149!15 = !{!14, !14, i64 0, i64 2} ; TAG_D 150