1 ; RUN: opt -S -aa-pipeline=basic-aa -passes=gvn < %s | FileCheck %s
3 declare void @argmemonly_function(ptr) argmemonly
5 define i32 @test0(ptr %P, ptr noalias %P2) {
8 ; CHECK: %v1 = load i32, ptr %P
9 call void @argmemonly_function(ptr %P2) [ "tag"() ]
10 ; CHECK: call void @argmemonly_function(
11 %v2 = load i32, ptr %P
12 ; CHECK: %v2 = load i32, ptr %P
13 %diff = sub i32 %v1, %v2
14 ; CHECK: %diff = sub i32 %v1, %v2
16 ; CHECK: ret i32 %diff
19 define i32 @test1(ptr %P, ptr noalias %P2) {
20 ; CHECK-LABEL: @test1(
21 %v1 = load i32, ptr %P
22 call void @argmemonly_function(ptr %P2) argmemonly [ "tag"() ]
23 ; CHECK: call void @argmemonly_function(
24 %v2 = load i32, ptr %P
25 %diff = sub i32 %v1, %v2
30 define i32 @test2(ptr %P, ptr 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.
38 ; CHECK-LABEL: @test2(
39 %v1 = load i32, ptr %P
40 call void @argmemonly_function(ptr %P2) [ "deopt"() ]
41 ; CHECK: call void @argmemonly_function(
42 %v2 = load i32, ptr %P
43 %diff = sub i32 %v1, %v2