1 ; RUN: opt -S -basicaa -gvn < %s | FileCheck %s 2 3 declare void @argmemonly_function(i32 *) argmemonly 4 5 define i32 @test0(i32* %P, i32* noalias %P2) { 6 ; CHECK-LABEL: @test0( 7 %v1 = load i32, i32* %P 8 ; CHECK: %v1 = load i32, i32* %P 9 call void @argmemonly_function(i32* %P2) [ "tag"() ] 10 ; CHECK: call void @argmemonly_function( 11 %v2 = load i32, i32* %P 12 ; CHECK: %v2 = load i32, i32* %P 13 %diff = sub i32 %v1, %v2 14 ; CHECK: %diff = sub i32 %v1, %v2 15 ret i32 %diff 16 ; CHECK: ret i32 %diff 17 } 18 19 define i32 @test1(i32* %P, i32* noalias %P2) { 20 ; CHECK-LABEL: @test1( 21 %v1 = load i32, i32* %P 22 call void @argmemonly_function(i32* %P2) argmemonly [ "tag"() ] 23 ; CHECK: call void @argmemonly_function( 24 %v2 = load i32, i32* %P 25 %diff = sub i32 %v1, %v2 26 ret i32 %diff 27 ; CHECK: ret i32 0 28 } 29 30 define i32 @test2(i32* %P, i32* noalias %P2) { 31 ; Note: in this test we //can// GVN %v1 and %v2 into one value in theory. Calls 32 ; with deopt operand bundles are not argmemonly because they *read* the entire 33 ; heap, but they don't write to any location in the heap if the callee does not 34 ; deoptimize the caller. This fact, combined with the fact that 35 ; @argmemonly_function is, well, an argmemonly function, can be used to conclude 36 ; that %P is not written to at the callsite. However LLVM currently cannot 37 ; describe the "does not write to non-args, and reads the entire heap" effect on 38 ; a callsite. 39 40 ; CHECK-LABEL: @test2( 41 %v1 = load i32, i32* %P 42 ; CHECK: %v1 = load i32, i32* %P 43 call void @argmemonly_function(i32* %P2) [ "deopt"() ] 44 ; CHECK: call void @argmemonly_function( 45 %v2 = load i32, i32* %P 46 ; CHECK: %v2 = load i32, i32* %P 47 %diff = sub i32 %v1, %v2 48 ; CHECK: %diff = sub i32 %v1, %v2 49 ret i32 %diff 50 ; CHECK: ret i32 %diff 51 } 52