• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 -enable-mssa-loop-dependency=false %s -enable-new-pm=0 | FileCheck %s
2; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 -enable-mssa-loop-dependency=true -verify-memoryssa %s -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
3; RUN: opt -licm -basic-aa -licm-n2-threshold=200 < %s -S -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
4
5; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
6; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
7; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=200 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
8
9declare i32 @foo() readonly argmemonly nounwind
10declare i32 @foo2() readonly nounwind
11declare i32 @bar(i32* %loc2) readonly argmemonly nounwind
12
13define void @test(i32* %loc) {
14; CHECK-LABEL: @test
15; CHECK: @foo
16; CHECK-LABEL: loop:
17; ALIAS-N2-LABEL: @test
18; ALIAS-N2: @foo
19; ALIAS-N2-LABEL: loop:
20  br label %loop
21
22loop:
23  %res = call i32 @foo()
24  store i32 %res, i32* %loc
25  br label %loop
26}
27
28; Negative test: show argmemonly is required
29define void @test_neg(i32* %loc) {
30; CHECK-LABEL: @test_neg
31; CHECK-LABEL: loop:
32; CHECK: @foo
33; ALIAS-N2-LABEL: @test_neg
34; ALIAS-N2-LABEL: loop:
35; ALIAS-N2: @foo
36  br label %loop
37
38loop:
39  %res = call i32 @foo2()
40  store i32 %res, i32* %loc
41  br label %loop
42}
43
44define void @test2(i32* noalias %loc, i32* noalias %loc2) {
45; CHECK-LABEL: @test2
46; CHECK: @bar
47; CHECK-LABEL: loop:
48; ALIAS-N2-LABEL: @test2
49; ALIAS-N2: @bar
50; ALIAS-N2-LABEL: loop:
51  br label %loop
52
53loop:
54  %res = call i32 @bar(i32* %loc2)
55  store i32 %res, i32* %loc
56  br label %loop
57}
58
59; Negative test: %might clobber gep
60define void @test3(i32* %loc) {
61; CHECK-LABEL: @test3
62; CHECK-LABEL: loop:
63; CHECK: @bar
64; ALIAS-N2-LABEL: @test3
65; ALIAS-N2-LABEL: loop:
66; ALIAS-N2: @bar
67  br label %loop
68
69loop:
70  %res = call i32 @bar(i32* %loc)
71  %gep = getelementptr i32, i32 *%loc, i64 1000000
72  store i32 %res, i32* %gep
73  br label %loop
74}
75
76
77; Negative test: %loc might alias %loc2
78define void @test4(i32* %loc, i32* %loc2) {
79; CHECK-LABEL: @test4
80; CHECK-LABEL: loop:
81; CHECK: @bar
82; ALIAS-N2-LABEL: @test4
83; ALIAS-N2-LABEL: loop:
84; ALIAS-N2: @bar
85  br label %loop
86
87loop:
88  %res = call i32 @bar(i32* %loc2)
89  store i32 %res, i32* %loc
90  br label %loop
91}
92
93declare i32 @foo_new(i32*) readonly
94; With the default AST mechanism used by LICM for alias analysis,
95; we clump foo_new with bar.
96; With the N2 Alias analysis diagnostic tool, we are able to hoist the
97; argmemonly bar call out of the loop.
98; Using MemorySSA we can also hoist bar.
99
100define void @test5(i32* %loc2, i32* noalias %loc) {
101; ALIAS-N2-LABEL: @test5
102; ALIAS-N2: @bar
103; ALIAS-N2-LABEL: loop:
104
105; CHECK-LABEL: @test5
106; CHECK-LABEL: loop:
107; CHECK:  @bar
108  br label %loop
109
110loop:
111  %res1 = call i32 @bar(i32* %loc2)
112  %res = call i32 @foo_new(i32* %loc2)
113  store volatile i32 %res1, i32* %loc
114  br label %loop
115}
116
117
118; memcpy doesn't write to it's source argument, so loads to that location
119; can still be hoisted
120define void @test6(i32* noalias %loc, i32* noalias %loc2) {
121; CHECK-LABEL: @test6
122; CHECK: %val = load i32, i32* %loc2
123; CHECK-LABEL: loop:
124; CHECK: @llvm.memcpy
125; ALIAS-N2-LABEL: @test6
126; ALIAS-N2: %val = load i32, i32* %loc2
127; ALIAS-N2-LABEL: loop:
128; ALIAS-N2: @llvm.memcpy
129  br label %loop
130
131loop:
132  %val = load i32, i32* %loc2
133  store i32 %val, i32* %loc
134  %dest = bitcast i32* %loc to i8*
135  %src = bitcast i32* %loc2 to i8*
136  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src, i64 8, i1 false)
137  br label %loop
138}
139
140define void @test7(i32* noalias %loc, i32* noalias %loc2) {
141; CHECK-LABEL: @test7
142; CHECK: %val = load i32, i32* %loc2
143; CHECK-LABEL: loop:
144; CHECK: @custom_memcpy
145; ALIAS-N2-LABEL: @test7
146; ALIAS-N2: %val = load i32, i32* %loc2
147; ALIAS-N2-LABEL: loop:
148; ALIAS-N2: @custom_memcpy
149  br label %loop
150
151loop:
152  %val = load i32, i32* %loc2
153  store i32 %val, i32* %loc
154  %dest = bitcast i32* %loc to i8*
155  %src = bitcast i32* %loc2 to i8*
156  call void @custom_memcpy(i8* %dest, i8* %src)
157  br label %loop
158}
159
160declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)
161declare void @custom_memcpy(i8* nocapture writeonly, i8* nocapture readonly) argmemonly nounwind
162