xref: /llvm-project/llvm/test/Transforms/LICM/argmemonly-call.ll (revision e390c229a438ed1eb3396df8fbeeda89c49474e6)
1; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<target-ir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
2
3declare i32 @foo() readonly argmemonly nounwind
4declare i32 @foo2() readonly nounwind
5declare i32 @bar(ptr %loc2) readonly argmemonly nounwind
6
7define void @test(ptr %loc) {
8; CHECK-LABEL: @test
9; CHECK: @foo
10; CHECK-LABEL: loop:
11  br label %loop
12
13loop:
14  %res = call i32 @foo()
15  store i32 %res, ptr %loc
16  br label %loop
17}
18
19; Negative test: show argmemonly is required
20define void @test_neg(ptr %loc) {
21; CHECK-LABEL: @test_neg
22; CHECK-LABEL: loop:
23; CHECK: @foo
24  br label %loop
25
26loop:
27  %res = call i32 @foo2()
28  store i32 %res, ptr %loc
29  br label %loop
30}
31
32define void @test2(ptr noalias %loc, ptr noalias %loc2) {
33; CHECK-LABEL: @test2
34; CHECK: @bar
35; CHECK-LABEL: loop:
36  br label %loop
37
38loop:
39  %res = call i32 @bar(ptr %loc2)
40  store i32 %res, ptr %loc
41  br label %loop
42}
43
44; Negative test: %might clobber gep
45define void @test3(ptr %loc) {
46; CHECK-LABEL: @test3
47; CHECK-LABEL: loop:
48; CHECK: @bar
49  br label %loop
50
51loop:
52  %res = call i32 @bar(ptr %loc)
53  %gep = getelementptr i32, ptr %loc, i64 1000000
54  store i32 %res, ptr %gep
55  br label %loop
56}
57
58
59; Negative test: %loc might alias %loc2
60define void @test4(ptr %loc, ptr %loc2) {
61; CHECK-LABEL: @test4
62; CHECK-LABEL: loop:
63; CHECK: @bar
64  br label %loop
65
66loop:
67  %res = call i32 @bar(ptr %loc2)
68  store i32 %res, ptr %loc
69  br label %loop
70}
71
72declare i32 @foo_new(ptr) readonly
73
74define void @test5(ptr %loc2, ptr noalias %loc) {
75; CHECK-LABEL: @test5
76; CHECK: @bar
77; CHECK-LABEL: loop:
78  br label %loop
79
80loop:
81  %res1 = call i32 @bar(ptr %loc2)
82  %res = call i32 @foo_new(ptr %loc2)
83  store volatile i32 %res1, ptr %loc
84  br label %loop
85}
86
87
88; memcpy doesn't write to it's source argument, so loads to that location
89; can still be hoisted
90define void @test6(ptr noalias %loc, ptr noalias %loc2) {
91; CHECK-LABEL: @test6
92; CHECK: %val = load i32, ptr %loc2
93; CHECK-LABEL: loop:
94; CHECK: @llvm.memcpy
95  br label %loop
96
97loop:
98  %val = load i32, ptr %loc2
99  store i32 %val, ptr %loc
100  call void @llvm.memcpy.p0.p0.i64(ptr %loc, ptr %loc2, i64 8, i1 false)
101  br label %loop
102}
103
104define void @test7(ptr noalias %loc, ptr noalias %loc2) {
105; CHECK-LABEL: @test7
106; CHECK: %val = load i32, ptr %loc2
107; CHECK-LABEL: loop:
108; CHECK: @custom_memcpy
109  br label %loop
110
111loop:
112  %val = load i32, ptr %loc2
113  store i32 %val, ptr %loc
114  call void @custom_memcpy(ptr %loc, ptr %loc2)
115  br label %loop
116}
117
118declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)
119declare void @custom_memcpy(ptr nocapture writeonly, ptr nocapture readonly) argmemonly nounwind
120