1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -passes=gvn -S < %s | FileCheck %s 3 4define i32 @test1(ptr %p, ptr %q) { 5; CHECK-LABEL: define i32 @test1( 6; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 7; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA0:![0-9]+]] 8; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 9; CHECK-NEXT: ret i32 [[C]] 10; 11 %a = call i32 @foo(ptr %p), !tbaa !0 12 %b = call i32 @foo(ptr %p) 13 %c = add i32 %a, %b 14 ret i32 %c 15} 16 17define i32 @test2(ptr %p, ptr %q) { 18; CHECK-LABEL: define i32 @test2( 19; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 20; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA0]] 21; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 22; CHECK-NEXT: ret i32 [[C]] 23; 24 %a = call i32 @foo(ptr %p), !tbaa !0 25 %b = call i32 @foo(ptr %p), !tbaa !0 26 %c = add i32 %a, %b 27 ret i32 %c 28} 29 30define i32 @test3(ptr %p, ptr %q) { 31; CHECK-LABEL: define i32 @test3( 32; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 33; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA4:![0-9]+]] 34; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 35; CHECK-NEXT: ret i32 [[C]] 36; 37 %a = call i32 @foo(ptr %p), !tbaa !3 38 %b = call i32 @foo(ptr %p), !tbaa !3 39 %c = add i32 %a, %b 40 ret i32 %c 41} 42 43define i32 @test4(ptr %p, ptr %q) { 44; CHECK-LABEL: define i32 @test4( 45; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 46; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA6:![0-9]+]] 47; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 48; CHECK-NEXT: ret i32 [[C]] 49; 50 %a = call i32 @foo(ptr %p), !tbaa !1 51 %b = call i32 @foo(ptr %p), !tbaa !0 52 %c = add i32 %a, %b 53 ret i32 %c 54} 55 56define i32 @test5(ptr %p, ptr %q) { 57; CHECK-LABEL: define i32 @test5( 58; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 59; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA0]] 60; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 61; CHECK-NEXT: ret i32 [[C]] 62; 63 %a = call i32 @foo(ptr %p), !tbaa !0 64 %b = call i32 @foo(ptr %p), !tbaa !1 65 %c = add i32 %a, %b 66 ret i32 %c 67} 68 69define i32 @test6(ptr %p, ptr %q) { 70; CHECK-LABEL: define i32 @test6( 71; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 72; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA0]] 73; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 74; CHECK-NEXT: ret i32 [[C]] 75; 76 %a = call i32 @foo(ptr %p), !tbaa !0 77 %b = call i32 @foo(ptr %p), !tbaa !3 78 %c = add i32 %a, %b 79 ret i32 %c 80} 81 82define i32 @test7(ptr %p, ptr %q) { 83; CHECK-LABEL: define i32 @test7( 84; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 85; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA7:![0-9]+]] 86; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 87; CHECK-NEXT: ret i32 [[C]] 88; 89 %a = call i32 @foo(ptr %p), !tbaa !4 90 %b = call i32 @foo(ptr %p), !tbaa !3 91 %c = add i32 %a, %b 92 ret i32 %c 93} 94 95define i32 @test8(ptr %p, ptr %q) { 96; CHECK-LABEL: define i32 @test8( 97; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 98; CHECK-NEXT: store i32 15, ptr [[P]], align 4 99; CHECK-NEXT: ret i32 0 100; 101; Since we know the location is invariant, we can forward the 102; load across the potentially aliasing store. 103 104 %a = load i32, ptr %q, !tbaa !10 105 store i32 15, ptr %p 106 %b = load i32, ptr %q, !tbaa !10 107 %c = sub i32 %a, %b 108 ret i32 %c 109} 110 111define i32 @test9(ptr %p, ptr %q) { 112; CHECK-LABEL: define i32 @test9( 113; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 114; CHECK-NEXT: call void @clobber() 115; CHECK-NEXT: ret i32 0 116; 117; Since we know the location is invariant, we can forward the 118; load across the potentially aliasing store (within the call). 119 120 %a = load i32, ptr %q, !tbaa !10 121 call void @clobber() 122 %b = load i32, ptr %q, !tbaa !10 123 %c = sub i32 %a, %b 124 ret i32 %c 125} 126 127define i32 @test10(ptr %p, ptr %q) { 128; If one access encloses the other, then the merged access is the enclosed one 129; and not just the common final access type. 130; CHECK-LABEL: define i32 @test10( 131; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { 132; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA10:![0-9]+]] 133; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] 134; CHECK-NEXT: ret i32 [[C]] 135; 136 %a = call i32 @foo(ptr %p), !tbaa !15 ; TAG_X_i 137 %b = call i32 @foo(ptr %p), !tbaa !19 ; TAG_Y_x_i 138 %c = add i32 %a, %b 139 ret i32 %c 140} 141 142declare void @clobber() 143declare i32 @foo(ptr) readonly 144 145!0 = !{!5, !5, i64 0} 146!1 = !{!6, !6, i64 0} 147!2 = !{!"tbaa root"} 148!3 = !{!7, !7, i64 0} 149!4 = !{!11, !11, i64 0} 150!5 = !{!"C", !6} 151!6 = !{!"A", !2} 152!7 = !{!"B", !6} 153!8 = !{!"another root"} 154!11 = !{!"scalar type", !8} 155 156!15 = !{!16, !17, i64 0} ; TAG_X_i 157!16 = !{!"struct X", !17, i64 0} ; struct X { int i; }; 158!17 = !{!"int", !18, i64 0} 159!18 = !{!"char", !2, i64 0} 160 161!19 = !{!20, !17, i64 0} ; TAG_Y_x_i 162!20 = !{!"struct Y", !16, i64 0} ; struct Y { struct X x; }; 163 164; A TBAA structure who's only point is to have a constant location. 165!9 = !{!"yet another root"} 166!10 = !{!"node", !9, i64 1} 167;. 168; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0} 169; CHECK: [[META1]] = !{!"C", [[META2:![0-9]+]]} 170; CHECK: [[META2]] = !{!"A", [[META3:![0-9]+]]} 171; CHECK: [[META3]] = !{!"tbaa root"} 172; CHECK: [[TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0} 173; CHECK: [[META5]] = !{!"B", [[META2]]} 174; CHECK: [[TBAA6]] = !{[[META2]], [[META2]], i64 0} 175; CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0} 176; CHECK: [[META8]] = !{!"scalar type", [[META9:![0-9]+]]} 177; CHECK: [[META9]] = !{!"another root"} 178; CHECK: [[TBAA10]] = !{[[META11:![0-9]+]], [[META12:![0-9]+]], i64 0} 179; CHECK: [[META11]] = !{!"struct X", [[META12]], i64 0} 180; CHECK: [[META12]] = !{!"int", [[META13:![0-9]+]], i64 0} 181; CHECK: [[META13]] = !{!"char", [[META3]], i64 0} 182;. 183