xref: /llvm-project/llvm/test/Analysis/BasicAA/phi-speculation.ll (revision 303c308e452c703c3d47940383ded3b2d3eefd56)
1target datalayout =
2"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
3
4; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
5
6; ptr_phi and ptr2_phi do not alias.
7; CHECK: test_noalias_1
8; CHECK: NoAlias: i32* %ptr2_phi, i32* %ptr_phi
9; CHECK: NoAlias: i32* %ptr2_inc, i32* %ptr_inc
10define i32 @test_noalias_1(ptr %ptr2, i32 %count, ptr %coeff) {
11entry:
12  %ptr = getelementptr inbounds i32, ptr %ptr2, i64 1
13  br label %while.body
14
15while.body:
16  %num = phi i32 [ %count, %entry ], [ %dec, %while.body ]
17  %ptr_phi = phi ptr [ %ptr, %entry ], [ %ptr_inc, %while.body ]
18  %ptr2_phi = phi ptr [ %ptr2, %entry ], [ %ptr2_inc, %while.body ]
19  %result.09 = phi i32 [ 0 , %entry ], [ %add, %while.body ]
20  %dec = add nsw i32 %num, -1
21  %0 = load i32, ptr %ptr_phi, align 4
22  store i32 %0, ptr %ptr2_phi, align 4
23  %1 = load i32, ptr %coeff, align 4
24  %2 = load i32, ptr %ptr_phi, align 4
25  %mul = mul nsw i32 %1, %2
26  %add = add nsw i32 %mul, %result.09
27  %tobool = icmp eq i32 %dec, 0
28  %ptr_inc = getelementptr inbounds i32, ptr %ptr_phi, i64 1
29  %ptr2_inc = getelementptr inbounds i32, ptr %ptr2_phi, i64 1
30  load i32, ptr %ptr_inc
31  load i32, ptr %ptr2_inc
32  br i1 %tobool, label %the_exit, label %while.body
33
34the_exit:
35  ret i32 %add
36}
37
38; CHECK: test_noalias_2
39; CHECK-DAG: NoAlias: i32* %ptr_outer_phi, i32* %ptr_outer_phi2
40; CHECK-DAG: NoAlias: i32* %ptr2_inc_outer, i32* %ptr_inc_outer
41; CHECK-DAG: NoAlias: i32* %ptr2_phi, i32* %ptr_phi
42; CHECK-DAG: NoAlias: i32* %ptr2_inc, i32* %ptr_inc
43define i32 @test_noalias_2(ptr %ptr2, i32 %count, ptr %coeff) {
44entry:
45  %ptr = getelementptr inbounds i32, ptr %ptr2, i64 1
46  br label %outer.while.header
47
48outer.while.header:
49  %ptr_outer_phi = phi ptr [%ptr_inc_outer, %outer.while.backedge], [ %ptr, %entry]
50  %ptr_outer_phi2 = phi ptr [%ptr2_inc_outer, %outer.while.backedge], [ %ptr2, %entry]
51  %num.outer = phi i32 [ %count, %entry ], [ %dec.outer, %outer.while.backedge ]
52  %ignore1 = load i32, ptr %ptr_outer_phi
53  %ignore2 = load i32, ptr %ptr_outer_phi2
54  br label %while.body
55
56while.body:
57  %num = phi i32 [ %count, %outer.while.header ], [ %dec, %while.body ]
58  %ptr_phi = phi ptr [ %ptr_outer_phi, %outer.while.header ], [ %ptr_inc, %while.body ]
59  %ptr2_phi = phi ptr [ %ptr_outer_phi2, %outer.while.header ], [ %ptr2_inc, %while.body ]
60  %result.09 = phi i32 [ 0 , %outer.while.header ], [ %add, %while.body ]
61  %dec = add nsw i32 %num, -1
62  %0 = load i32, ptr %ptr_phi, align 4
63  store i32 %0, ptr %ptr2_phi, align 4
64  %1 = load i32, ptr %coeff, align 4
65  %2 = load i32, ptr %ptr_phi, align 4
66  %mul = mul nsw i32 %1, %2
67  %add = add nsw i32 %mul, %result.09
68  %tobool = icmp eq i32 %dec, 0
69  %ptr_inc = getelementptr inbounds i32, ptr %ptr_phi, i64 1
70  %ptr2_inc = getelementptr inbounds i32, ptr %ptr2_phi, i64 1
71  load i32, ptr %ptr_inc
72  load i32, ptr %ptr2_inc
73  br i1 %tobool, label %outer.while.backedge, label %while.body
74
75outer.while.backedge:
76  %ptr_inc_outer = getelementptr inbounds i32, ptr %ptr_phi, i64 1
77  %ptr2_inc_outer = getelementptr inbounds i32, ptr %ptr2_phi, i64 1
78  load i32, ptr %ptr_inc_outer
79  load i32, ptr %ptr2_inc_outer
80  %dec.outer = add nsw i32 %num.outer, -1
81  %br.cond = icmp eq i32 %dec.outer, 0
82  br i1 %br.cond, label %the_exit, label %outer.while.header
83
84the_exit:
85  ret i32 %add
86}
87
88; CHECK: test_noalias_3
89; CHECK: MayAlias: i8* %ptr2_phi, i8* %ptr_phi
90define i32 @test_noalias_3(ptr noalias %x, ptr noalias %y, ptr noalias %z,
91                           i32 %count) {
92entry:
93  br label %while.body
94
95while.body:
96  %num = phi i32 [ %count, %entry ], [ %dec, %while.body ]
97  %ptr_phi = phi ptr [ %x, %entry ], [ %z, %while.body ]
98  %ptr2_phi = phi ptr [ %y, %entry ], [ %ptr_phi, %while.body ]
99  load i8, ptr %ptr_phi
100  load i8, ptr %ptr2_phi
101  %dec = add nsw i32 %num, -1
102  %tobool = icmp eq i32 %dec, 0
103  br i1 %tobool, label %the_exit, label %while.body
104
105the_exit:
106  ret i32 1
107}
108
109; CHECK-LABEL: test_different_stride_noalias
110; CHECK: NoAlias: i8* %x.base, i16* %y.base
111; CHECK: NoAlias: i8* %x, i16* %y
112; CHECK: NoAlias: i8* %x.next, i16* %y.next
113define void @test_different_stride_noalias(i1 %c, ptr noalias %x.base, ptr noalias %y.base) {
114entry:
115  load i8, ptr %x.base
116  load i16, ptr %y.base
117  br label %loop
118
119loop:
120  %x = phi ptr [ %x.base, %entry ], [ %x.next, %loop ]
121  %y = phi ptr [ %y.base, %entry ], [ %y.next, %loop ]
122  load i8, ptr %x
123  load i16, ptr %y
124  %x.next = getelementptr i8, ptr %x, i64 1
125  %y.next = getelementptr i16, ptr %y, i64 1
126  load i8, ptr %x.next
127  load i16, ptr %y.next
128  br i1 %c, label %loop, label %exit
129
130exit:
131  ret void
132}
133
134; CHECK-LABEL: test_no_loop_mustalias
135; CHECK: MustAlias: i16* %z16, i8* %z8
136define void @test_no_loop_mustalias(i1 %c, ptr noalias %x8, ptr noalias %y8) {
137  br i1 %c, label %if, label %else
138
139if:
140  br label %end
141
142else:
143  br label %end
144
145end:
146  %z8 = phi ptr [ %x8, %if ], [ %y8, %else ]
147  %z16 = phi ptr [ %x8, %if ], [ %y8, %else ]
148  load i8, ptr %z8
149  load i16, ptr %z16
150  ret void
151}
152
153; CHECK-LABEL: test_same_stride_mustalias
154; CHECK: MustAlias: i4* %x.base, i8* %x.base
155; CHECK: MayAlias: i8* %x, i4* %y
156; CHECK: MayAlias: i8* %x.next, i4* %y.next
157; TODO: (x, y) could be MustAlias
158define void @test_same_stride_mustalias(i1 %c, ptr noalias %x.base) {
159entry:
160  load i8, ptr %x.base
161  load i4, ptr %x.base
162  br label %loop
163
164loop:
165  %x = phi ptr [ %x.base, %entry ], [ %x.next, %loop ]
166  %y = phi ptr [ %x.base, %entry ], [ %y.next, %loop ]
167  load i8, ptr %x
168  load i4, ptr %y
169  %x.next = getelementptr i8, ptr %x, i64 1
170  %y.next = getelementptr i4, ptr %y, i64 1
171  load i8, ptr %x.next
172  load i4, ptr %y.next
173  br i1 %c, label %loop, label %exit
174
175exit:
176  ret void
177}
178
179; CHECK-LABEL: test_different_stride_mustalias
180; CHECK: MustAlias: i16* %x.base, i8* %x.base
181; CHECK: MayAlias: i8* %x, i16* %y
182; CHECK: MayAlias: i8* %x.next, i16* %y.next
183; Even though the base pointers MustAlias, the different strides don't preserve
184; this property across iterations.
185define void @test_different_stride_mustalias(i1 %c, ptr noalias %x.base) {
186entry:
187  load i8, ptr %x.base
188  load i16, ptr %x.base
189  br label %loop
190
191loop:
192  %x = phi ptr [ %x.base, %entry ], [ %x.next, %loop ]
193  %y = phi ptr [ %x.base, %entry ], [ %y.next, %loop ]
194  load i8, ptr %x
195  load i16, ptr %y
196  %x.next = getelementptr i8, ptr %x, i64 1
197  %y.next = getelementptr i16, ptr %y, i64 1
198  load i8, ptr %x.next
199  load i16, ptr %y.next
200  br i1 %c, label %loop, label %exit
201
202exit:
203  ret void
204}
205