1; RUN: opt -S -basicaa -gvn < %s | FileCheck %s 2 3declare void @argmemonly_function(i32 *) argmemonly 4 5define 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 19define 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 30define 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