1; Test if the !invariant.load metadata is maintained by GVN. 2; RUN: opt -basicaa -gvn -S < %s | FileCheck %s 3 4define 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 8entry: 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 17define i32 @test2(i32* nocapture %p, i8* nocapture %q) { 18; CHECK-LABEL: test2 19; CHECK-NOT: !invariant.load 20; CHECK-NOT: %y = load 21entry: 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. 32define i32 @test3(i1 %cnd, i32* %p, i32* %q) { 33; CHECK-LABEL: test3 34; CHECK-NOT: load 35entry: 36 %v1 = load i32, i32* %p 37 br i1 %cnd, label %bb1, label %bb2 38 39bb1: 40 store i32 5, i32* %q 41 br label %bb2 42 43bb2: 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. 51define i32 @test4(i1 %cnd, i32* %p, i32* %q) { 52; CHECK-LABEL: test4 53; %v2 is redundant, but GVN currently doesn't catch that 54entry: 55 %v1 = load i32, i32* %p, !invariant.load !0 56 br i1 %cnd, label %bb1, label %bb2 57 58bb1: 59 store i32 5, i32* %q 60 br label %bb2 61 62bb2: 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. 71define 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 76entry: 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 84declare void @foo() 85 86; Clobbering (mayalias) stores, even in function calls, can be ignored 87define i32 @test6(i1 %cnd, i32* %p) { 88; CHECK-LABEL: test6 89; CHECK-LABEL: entry: 90; CHECK-NEXT: @foo 91; CHECK-NEXT: ret i32 0 92entry: 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 100declare noalias i32* @bar(...) 101 102; Same as previous, but a function with a noalias result (since they're handled 103; differently in MDA) 104define i32 @test7(i1 %cnd, i32* %p) { 105; CHECK-LABEL: test7 106; CHECK-LABEL: entry: 107; CHECK-NEXT: @bar 108; CHECK-NEXT: ret i32 0 109entry: 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 117define 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 122entry: 123 %v1 = load i32, i32* %p, !invariant.load !0 124 br i1 %cnd, label %taken, label %merge 125taken: 126 %p2 = call i32* (...) @bar(i32* %p) 127 br label %merge 128merge: 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