1 ; Test if the !invariant.load metadata is maintained by GVN. 2 ; RUN: opt -basicaa -gvn -S < %s | FileCheck %s 3 4 define i32 @test1(i32* nocapture %p, i8* nocapture %q) { 5 ; CHECK-LABEL: test1 6 ; CHECK: %x = load i32, i32* %p, align 4, !invariant.load !0 7 ; CHECK-NOT: %y = load 8 entry: 9 %x = load i32, i32* %p, align 4, !invariant.load !0 10 %conv = trunc i32 %x to i8 11 store i8 %conv, i8* %q, align 1 12 %y = load i32, i32* %p, align 4, !invariant.load !0 13 %add = add i32 %y, 1 14 ret i32 %add 15 } 16 17 define i32 @test2(i32* nocapture %p, i8* nocapture %q) { 18 ; CHECK-LABEL: test2 19 ; CHECK-NOT: !invariant.load 20 ; CHECK-NOT: %y = load 21 entry: 22 %x = load i32, i32* %p, align 4 23 %conv = trunc i32 %x to i8 24 store i8 %conv, i8* %q, align 1 25 %y = load i32, i32* %p, align 4, !invariant.load !0 26 %add = add i32 %y, 1 27 ret i32 %add 28 } 29 30 ; With the invariant.load metadata, what would otherwise 31 ; be a case for PRE becomes a full redundancy. 32 define i32 @test3(i1 %cnd, i32* %p, i32* %q) { 33 ; CHECK-LABEL: test3 34 ; CHECK-NOT: load 35 entry: 36 %v1 = load i32, i32* %p 37 br i1 %cnd, label %bb1, label %bb2 38 39 bb1: 40 store i32 5, i32* %q 41 br label %bb2 42 43 bb2: 44 %v2 = load i32, i32* %p, !invariant.load !0 45 %res = sub i32 %v1, %v2 46 ret i32 %res 47 } 48 49 ; This test is here to document a case which doesn't optimize 50 ; as well as it could. 51 define i32 @test4(i1 %cnd, i32* %p, i32* %q) { 52 ; CHECK-LABEL: test4 53 ; %v2 is redundant, but GVN currently doesn't catch that 54 entry: 55 %v1 = load i32, i32* %p, !invariant.load !0 56 br i1 %cnd, label %bb1, label %bb2 57 58 bb1: 59 store i32 5, i32* %q 60 br label %bb2 61 62 bb2: 63 %v2 = load i32, i32* %p 64 %res = sub i32 %v1, %v2 65 ret i32 %res 66 } 67 68 ; Checks that we return the mustalias store as a def 69 ; so that it contributes to value forwarding. Note 70 ; that we could and should remove the store too. 71 define i32 @test5(i1 %cnd, i32* %p) { 72 ; CHECK-LABEL: test5 73 ; CHECK-LABEL: entry: 74 ; CHECK-NEXT: store i32 5, i32* %p 75 ; CHECK-NEXT: ret i32 5 76 entry: 77 %v1 = load i32, i32* %p, !invariant.load !0 78 store i32 5, i32* %p ;; must alias store, want to exploit 79 %v2 = load i32, i32* %p, !invariant.load !0 80 ret i32 %v2 81 } 82 83 84 declare void @foo() 85 86 ; Clobbering (mayalias) stores, even in function calls, can be ignored 87 define i32 @test6(i1 %cnd, i32* %p) { 88 ; CHECK-LABEL: test6 89 ; CHECK-LABEL: entry: 90 ; CHECK-NEXT: @foo 91 ; CHECK-NEXT: ret i32 0 92 entry: 93 %v1 = load i32, i32* %p, !invariant.load !0 94 call void @foo() 95 %v2 = load i32, i32* %p, !invariant.load !0 96 %res = sub i32 %v1, %v2 97 ret i32 %res 98 } 99 100 declare noalias i32* @bar(...) 101 102 ; Same as previous, but a function with a noalias result (since they're handled 103 ; differently in MDA) 104 define i32 @test7(i1 %cnd, i32* %p) { 105 ; CHECK-LABEL: test7 106 ; CHECK-LABEL: entry: 107 ; CHECK-NEXT: @bar 108 ; CHECK-NEXT: ret i32 0 109 entry: 110 %v1 = load i32, i32* %p, !invariant.load !0 111 call i32* (...) @bar(i32* %p) 112 %v2 = load i32, i32* %p, !invariant.load !0 113 %res = sub i32 %v1, %v2 114 ret i32 %res 115 } 116 117 define i32 @test8(i1 %cnd, i32* %p) { 118 ; CHECK-LABEL: test8 119 ; CHECK: @bar 120 ; CHECK: load i32, i32* %p2, !invariant.load 121 ; CHECK: br label %merge 122 entry: 123 %v1 = load i32, i32* %p, !invariant.load !0 124 br i1 %cnd, label %taken, label %merge 125 taken: 126 %p2 = call i32* (...) @bar(i32* %p) 127 br label %merge 128 merge: 129 %p3 = phi i32* [%p, %entry], [%p2, %taken] 130 %v2 = load i32, i32* %p3, !invariant.load !0 131 %res = sub i32 %v1, %v2 132 ret i32 %res 133 } 134 135 !0 = !{ } 136 137