xref: /llvm-project/llvm/test/Transforms/SimpleLoopUnswitch/memssa-readnone-access.ll (revision a7a1b8b17e264fb0f2d2b4165cf9a7f5094b08b3)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S -passes="loop-mssa(loop-instsimplify,simple-loop-unswitch<nontrivial>)" < %s | FileCheck %s
3
4@vtable = constant ptr @foo
5
6declare void @foo() memory(none)
7declare void @bar()
8
9; The call becomes known readnone after simplification, but still have a
10; MemoryAccess. Make sure this does not lead to an assertion failure.
11define void @test(i1 %c) {
12; CHECK-LABEL: define void @test(
13; CHECK-SAME: i1 [[C:%.*]]) {
14; CHECK-NEXT:    [[C_FR:%.*]] = freeze i1 [[C]]
15; CHECK-NEXT:    br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
16; CHECK:       .split.us:
17; CHECK-NEXT:    br label [[LOOP_US:%.*]]
18; CHECK:       loop.us:
19; CHECK-NEXT:    call void @foo()
20; CHECK-NEXT:    br label [[EXIT_SPLIT_US:%.*]]
21; CHECK:       exit.split.us:
22; CHECK-NEXT:    br label [[EXIT:%.*]]
23; CHECK:       .split:
24; CHECK-NEXT:    br label [[LOOP:%.*]]
25; CHECK:       loop:
26; CHECK-NEXT:    call void @foo()
27; CHECK-NEXT:    br label [[LOOP]]
28; CHECK:       exit:
29; CHECK-NEXT:    ret void
30;
31  br label %loop
32
33loop:
34  %fn = load ptr, ptr @vtable, align 8
35  call void %fn()
36  br i1 %c, label %exit, label %loop
37
38exit:
39  ret void
40}
41
42; Variant with another access after the call.
43define void @test2(i1 %c, ptr %p) {
44; CHECK-LABEL: define void @test2(
45; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
46; CHECK-NEXT:    [[C_FR:%.*]] = freeze i1 [[C]]
47; CHECK-NEXT:    br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
48; CHECK:       .split.us:
49; CHECK-NEXT:    br label [[LOOP_US:%.*]]
50; CHECK:       loop.us:
51; CHECK-NEXT:    call void @foo()
52; CHECK-NEXT:    call void @bar()
53; CHECK-NEXT:    br label [[EXIT_SPLIT_US:%.*]]
54; CHECK:       exit.split.us:
55; CHECK-NEXT:    br label [[EXIT:%.*]]
56; CHECK:       .split:
57; CHECK-NEXT:    br label [[LOOP:%.*]]
58; CHECK:       loop:
59; CHECK-NEXT:    call void @foo()
60; CHECK-NEXT:    call void @bar()
61; CHECK-NEXT:    br label [[LOOP]]
62; CHECK:       exit:
63; CHECK-NEXT:    ret void
64;
65  br label %loop
66
67loop:
68  %fn = load ptr, ptr @vtable, align 8
69  call void %fn()
70  call void @bar()
71  br i1 %c, label %exit, label %loop
72
73exit:
74  ret void
75}
76
77; Variant with another access after the call and no access before the call.
78define void @test3(i1 %c, ptr %p) {
79; CHECK-LABEL: define void @test3(
80; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
81; CHECK-NEXT:    [[C_FR:%.*]] = freeze i1 [[C]]
82; CHECK-NEXT:    br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
83; CHECK:       .split.us:
84; CHECK-NEXT:    br label [[LOOP_US:%.*]]
85; CHECK:       loop.us:
86; CHECK-NEXT:    br label [[SPLIT_US:%.*]]
87; CHECK:       split.us:
88; CHECK-NEXT:    call void @foo()
89; CHECK-NEXT:    call void @bar()
90; CHECK-NEXT:    br label [[EXIT_SPLIT_US:%.*]]
91; CHECK:       exit.split.us:
92; CHECK-NEXT:    br label [[EXIT:%.*]]
93; CHECK:       .split:
94; CHECK-NEXT:    br label [[LOOP:%.*]]
95; CHECK:       loop:
96; CHECK-NEXT:    br label [[SPLIT:%.*]]
97; CHECK:       split:
98; CHECK-NEXT:    call void @foo()
99; CHECK-NEXT:    call void @bar()
100; CHECK-NEXT:    br label [[LOOP]]
101; CHECK:       exit:
102; CHECK-NEXT:    ret void
103;
104  br label %loop
105
106loop:
107  %fn = load ptr, ptr @vtable, align 8
108  br label %split
109
110split:
111  call void %fn()
112  call void @bar()
113  br i1 %c, label %exit, label %loop
114
115exit:
116  ret void
117}
118
119; Variants of the above test with swapped branch destinations.
120
121define void @test1_swapped(i1 %c) {
122; CHECK-LABEL: define void @test1_swapped(
123; CHECK-SAME: i1 [[C:%.*]]) {
124; CHECK-NEXT:  start:
125; CHECK-NEXT:    [[C_FR:%.*]] = freeze i1 [[C]]
126; CHECK-NEXT:    br i1 [[C_FR]], label [[START_SPLIT_US:%.*]], label [[START_SPLIT:%.*]]
127; CHECK:       start.split.us:
128; CHECK-NEXT:    br label [[LOOP_US:%.*]]
129; CHECK:       loop.us:
130; CHECK-NEXT:    call void @foo()
131; CHECK-NEXT:    br label [[LOOP_US]]
132; CHECK:       start.split:
133; CHECK-NEXT:    br label [[LOOP:%.*]]
134; CHECK:       loop:
135; CHECK-NEXT:    call void @foo()
136; CHECK-NEXT:    br label [[EXIT:%.*]]
137; CHECK:       exit:
138; CHECK-NEXT:    ret void
139;
140start:
141  br label %loop
142
143loop:
144  %fn = load ptr, ptr @vtable, align 8
145  call void %fn()
146  br i1 %c, label %loop, label %exit
147
148exit:
149  ret void
150}
151
152define void @test2_swapped(i1 %c, ptr %p) {
153; CHECK-LABEL: define void @test2_swapped(
154; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
155; CHECK-NEXT:    [[C_FR:%.*]] = freeze i1 [[C]]
156; CHECK-NEXT:    br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
157; CHECK:       .split.us:
158; CHECK-NEXT:    br label [[LOOP_US:%.*]]
159; CHECK:       loop.us:
160; CHECK-NEXT:    call void @foo()
161; CHECK-NEXT:    call void @bar()
162; CHECK-NEXT:    br label [[LOOP_US]]
163; CHECK:       .split:
164; CHECK-NEXT:    br label [[LOOP:%.*]]
165; CHECK:       loop:
166; CHECK-NEXT:    call void @foo()
167; CHECK-NEXT:    call void @bar()
168; CHECK-NEXT:    br label [[EXIT:%.*]]
169; CHECK:       exit:
170; CHECK-NEXT:    ret void
171;
172  br label %loop
173
174loop:
175  %fn = load ptr, ptr @vtable, align 8
176  call void %fn()
177  call void @bar()
178  br i1 %c, label %loop, label %exit
179
180exit:
181  ret void
182}
183
184define void @test3_swapped(i1 %c, ptr %p) {
185; CHECK-LABEL: define void @test3_swapped(
186; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
187; CHECK-NEXT:    [[C_FR:%.*]] = freeze i1 [[C]]
188; CHECK-NEXT:    br i1 [[C_FR]], label [[DOTSPLIT_US:%.*]], label [[DOTSPLIT:%.*]]
189; CHECK:       .split.us:
190; CHECK-NEXT:    br label [[LOOP_US:%.*]]
191; CHECK:       loop.us:
192; CHECK-NEXT:    br label [[SPLIT_US:%.*]]
193; CHECK:       split.us:
194; CHECK-NEXT:    call void @foo()
195; CHECK-NEXT:    call void @bar()
196; CHECK-NEXT:    br label [[LOOP_US]]
197; CHECK:       .split:
198; CHECK-NEXT:    br label [[LOOP:%.*]]
199; CHECK:       loop:
200; CHECK-NEXT:    br label [[SPLIT:%.*]]
201; CHECK:       split:
202; CHECK-NEXT:    call void @foo()
203; CHECK-NEXT:    call void @bar()
204; CHECK-NEXT:    br label [[EXIT:%.*]]
205; CHECK:       exit:
206; CHECK-NEXT:    ret void
207;
208  br label %loop
209
210loop:
211  %fn = load ptr, ptr @vtable, align 8
212  br label %split
213
214split:
215  call void %fn()
216  call void @bar()
217  br i1 %c, label %loop, label %exit
218
219exit:
220  ret void
221}
222