1 ; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
3 declare void @argmemonly_function(i32 *) argmemonly
5 define i32 @test0(i32* %P, i32* noalias %P2) {
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
16 ; CHECK: ret i32 %diff
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
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
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
50 ; CHECK: ret i32 %diff