; Test if the !invariant.load metadata is maintained by GVN. ; RUN: opt -basic-aa -gvn -S < %s | FileCheck %s define i32 @test1(i32* nocapture %p, i8* nocapture %q) { ; CHECK-LABEL: test1 ; CHECK: %x = load i32, i32* %p, align 4, !invariant.load !0 ; CHECK-NOT: %y = load entry: %x = load i32, i32* %p, align 4, !invariant.load !0 %conv = trunc i32 %x to i8 store i8 %conv, i8* %q, align 1 %y = load i32, i32* %p, align 4, !invariant.load !0 %add = add i32 %y, 1 ret i32 %add } define i32 @test2(i32* nocapture %p, i8* nocapture %q) { ; CHECK-LABEL: test2 ; CHECK-NOT: !invariant.load ; CHECK-NOT: %y = load entry: %x = load i32, i32* %p, align 4 %conv = trunc i32 %x to i8 store i8 %conv, i8* %q, align 1 %y = load i32, i32* %p, align 4, !invariant.load !0 %add = add i32 %y, 1 ret i32 %add } ; With the invariant.load metadata, what would otherwise ; be a case for PRE becomes a full redundancy. define i32 @test3(i1 %cnd, i32* %p, i32* %q) { ; CHECK-LABEL: test3 ; CHECK-NOT: load entry: %v1 = load i32, i32* %p br i1 %cnd, label %bb1, label %bb2 bb1: store i32 5, i32* %q br label %bb2 bb2: %v2 = load i32, i32* %p, !invariant.load !0 %res = sub i32 %v1, %v2 ret i32 %res } ; This test is here to document a case which doesn't optimize ; as well as it could. define i32 @test4(i1 %cnd, i32* %p, i32* %q) { ; CHECK-LABEL: test4 ; %v2 is redundant, but GVN currently doesn't catch that entry: %v1 = load i32, i32* %p, !invariant.load !0 br i1 %cnd, label %bb1, label %bb2 bb1: store i32 5, i32* %q br label %bb2 bb2: %v2 = load i32, i32* %p %res = sub i32 %v1, %v2 ret i32 %res } ; Checks that we return the mustalias store as a def ; so that it contributes to value forwarding. Note ; that we could and should remove the store too. define i32 @test5(i1 %cnd, i32* %p) { ; CHECK-LABEL: test5 ; CHECK-LABEL: entry: ; CHECK-NEXT: store i32 5, i32* %p ; CHECK-NEXT: ret i32 5 entry: %v1 = load i32, i32* %p, !invariant.load !0 store i32 5, i32* %p ;; must alias store, want to exploit %v2 = load i32, i32* %p, !invariant.load !0 ret i32 %v2 } declare void @foo() ; Clobbering (mayalias) stores, even in function calls, can be ignored define i32 @test6(i1 %cnd, i32* %p) { ; CHECK-LABEL: test6 ; CHECK-LABEL: entry: ; CHECK-NEXT: @foo ; CHECK-NEXT: ret i32 0 entry: %v1 = load i32, i32* %p, !invariant.load !0 call void @foo() %v2 = load i32, i32* %p, !invariant.load !0 %res = sub i32 %v1, %v2 ret i32 %res } declare noalias i32* @bar(...) ; Same as previous, but a function with a noalias result (since they're handled ; differently in MDA) define i32 @test7(i1 %cnd, i32* %p) { ; CHECK-LABEL: test7 ; CHECK-LABEL: entry: ; CHECK-NEXT: @bar ; CHECK-NEXT: ret i32 0 entry: %v1 = load i32, i32* %p, !invariant.load !0 call i32* (...) @bar(i32* %p) %v2 = load i32, i32* %p, !invariant.load !0 %res = sub i32 %v1, %v2 ret i32 %res } define i32 @test8(i1 %cnd, i32* %p) { ; CHECK-LABEL: test8 ; CHECK: @bar ; CHECK: load i32, i32* %p2, align 4, !invariant.load ; CHECK: br label %merge entry: %v1 = load i32, i32* %p, !invariant.load !0 br i1 %cnd, label %taken, label %merge taken: %p2 = call i32* (...) @bar(i32* %p) br label %merge merge: %p3 = phi i32* [%p, %entry], [%p2, %taken] %v2 = load i32, i32* %p3, !invariant.load !0 %res = sub i32 %v1, %v2 ret i32 %res } !0 = !{ }