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 } ; struct A { int i; }; 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(i32* %i, %A* %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, i32* %i, align 4, !tbaa !3 ; TAG_int 25 %A_i = getelementptr inbounds %A, %A* %a, i64 0, i32 0 26 store i32 7, i32* %A_i, align 4, !tbaa !5 ; TAG_A_i 27 %0 = load i32, i32* %i, align 4, !tbaa !3 ; TAG_int 28 ret i32 %0 29} 30 31; int vs. B::a => MayAlias. 32define i32 @f2(i32* %i, %B* %b) { 33entry: 34; CHECK-LABEL: f2 35; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 36; OPT-LABEL: f2 37; OPT: store i32 5, 38; OPT: store i32 7, 39; OPT: %[[RET:.*]] = load i32, 40; OPT: ret i32 %[[RET]] 41 store i32 5, i32* %i, align 4, !tbaa !3 ; TAG_int 42 %B_a = getelementptr inbounds %B, %B* %b, i64 0, i32 0, i32 0 43 store i32 7, i32* %B_a, align 4, !tbaa !7 ; TAG_B_a 44 %0 = load i32, i32* %i, align 4, !tbaa !3 ; TAG_int 45 ret i32 %0 46} 47 48; int vs. C::b => MayAlias. 49define i32 @f3(i32* %i, %C* %c) { 50entry: 51; CHECK-LABEL: f3 52; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 53; OPT-LABEL: f3 54; OPT: store i32 5, 55; OPT: store i32 7, 56; OPT: %[[RET:.*]] = load i32, 57; OPT: ret i32 %[[RET]] 58 store i32 5, i32* %i, align 4, !tbaa !3 ; TAG_int 59 %C_b = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0 60 store i32 7, i32* %C_b, align 4, !tbaa !9 ; TAG_C_b 61 %0 = load i32, i32* %i, align 4, !tbaa !3 ; TAG_int 62 ret i32 %0 63} 64 65; A vs. C::b => MayAlias. 66define i32 @f4(%A* %a, %C* %c) { 67entry: 68; CHECK-LABEL: f4 69; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5, 70; OPT-LABEL: f4 71; OPT: store i32 5, 72; OPT: store i32 7, 73; OPT: %[[RET:.*]] = load i32, 74; OPT: ret i32 %[[RET]] 75 %ap = getelementptr inbounds %A, %A* %a, i64 0, i32 0 76 store i32 5, i32* %ap, align 4, !tbaa !10 ; TAG_A 77 %C_b = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0 78 store i32 7, i32* %C_b, align 4, !tbaa !9 ; TAG_C_b 79 %0 = load i32, i32* %ap, align 4, !tbaa !10 ; TAG_A 80 ret i32 %0 81} 82 83; short vs. C::b => NoAlias. 84define i32 @f5(i32* %i, %C* %c) { 85entry: 86; CHECK-LABEL: f5 87; CHECK: NoAlias: store i32 7, {{.*}} <-> store i32 5, 88; OPT-LABEL: f5 89; OPT: store i32 5, 90; OPT: store i32 7, 91; OPT: ret i32 5 92 store i32 5, i32* %i, align 4, !tbaa !12 ; TAG_short 93 %C_b = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0 94 store i32 7, i32* %C_b, align 4, !tbaa !9 ; TAG_C_b 95 %0 = load i32, i32* %i, align 4, !tbaa !12 ; TAG_short 96 ret i32 %0 97} 98 99; C vs. D => NoAlias. 100define i32 @f6(%C* %c, %D* %d) { 101entry: 102; CHECK-LABEL: f6 103; CHECK: NoAlias: store i16 7, {{.*}} <-> store i32 5, 104; OPT-LABEL: f6 105; OPT: store i32 5, 106; OPT: store i16 7, 107; OPT: ret i32 5 108 %cp = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0 109 store i32 5, i32* %cp, align 4, !tbaa !13 ; TAG_C 110 %dp = getelementptr inbounds %D, %D* %d, i64 0, i32 0 111 store i16 7, i16* %dp, align 4, !tbaa !15 ; TAG_D 112 %0 = load i32, i32* %cp, align 4, !tbaa !13 ; TAG_C 113 ret i32 %0 114} 115 116!0 = !{!"root"} 117!1 = !{!0, i64 1, !"char"} 118!2 = !{!1, i64 4, !"int"} 119!3 = !{!2, !2, i64 0, i64 4} ; TAG_int 120 121!4 = !{!1, i64 4, !"A", !2, i64 0, i64 4} 122!5 = !{!4, !2, i64 0, i64 4} ; TAG_A_i 123 124!6 = !{!1, i64 4, !"B", !4, i64 0, i64 4} 125!7 = !{!6, !4, i64 0, i64 4} ; TAG_B_a 126 127!8 = !{!1, i64 4, !"C", !6, i64 0, i64 4} 128!9 = !{!8, !6, i64 0, i64 4} ; TAG_C_b 129 130!10 = !{!4, !4, i64 0, i64 4} ; TAG_A 131 132!11 = !{!1, i64 2, !"short"} 133!12 = !{!11, !11, i64 0, i64 2} ; TAG_short 134 135!13 = !{!8, !8, i64 0, i64 4} ; TAG_C 136 137!14 = !{!4, i64 2, !"D", !11, i64 0, i64 2} 138!15 = !{!14, !14, i64 0, i64 2} ; TAG_D 139