1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -basic-aa -dse -S %s | FileCheck %s
3
4target datalayout = "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"
5
6; Test case for PR16520. The store in %if.then is dead, because the same value
7; has been stored earlier to the same location.
8define void @test1_pr16520(i1 %b, i8* nocapture %r) {
9; CHECK-LABEL: @test1_pr16520(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    store i8 1, i8* [[R:%.*]], align 1
12; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
13; CHECK:       if.then:
14; CHECK-NEXT:    store i8 1, i8* [[R]], align 1
15; CHECK-NEXT:    tail call void @fn_mayread_or_clobber()
16; CHECK-NEXT:    br label [[IF_END:%.*]]
17; CHECK:       if.else:
18; CHECK-NEXT:    tail call void @fn_mayread_or_clobber()
19; CHECK-NEXT:    br label [[IF_END]]
20; CHECK:       if.end:
21; CHECK-NEXT:    ret void
22;
23entry:
24  store i8 1, i8* %r, align 1
25  br i1 %b, label %if.then, label %if.else
26
27if.then:                                          ; preds = %entry
28  store i8 1, i8* %r, align 1
29  tail call void @fn_mayread_or_clobber()
30  br label %if.end
31
32if.else:                                          ; preds = %entry
33  tail call void @fn_mayread_or_clobber()
34  br label %if.end
35
36if.end:                                           ; preds = %if.else, %if.then
37  ret void
38}
39
40declare void @fn_mayread_or_clobber()
41
42
43declare void @fn_readonly() readonly
44
45define void @test2(i1 %b, i8* nocapture %r) {
46; CHECK-LABEL: @test2(
47; CHECK-NEXT:  entry:
48; CHECK-NEXT:    store i8 1, i8* [[R:%.*]], align 1
49; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
50; CHECK:       if.then:
51; CHECK-NEXT:    tail call void @fn_readonly()
52; CHECK-NEXT:    br label [[IF_END:%.*]]
53; CHECK:       if.else:
54; CHECK-NEXT:    tail call void @fn_readonly()
55; CHECK-NEXT:    br label [[IF_END]]
56; CHECK:       if.end:
57; CHECK-NEXT:    store i8 1, i8* [[R]], align 1
58; CHECK-NEXT:    ret void
59;
60entry:
61  store i8 1, i8* %r, align 1
62  br i1 %b, label %if.then, label %if.else
63
64if.then:                                          ; preds = %entry
65  tail call void @fn_readonly()
66  br label %if.end
67
68if.else:                                          ; preds = %entry
69  tail call void @fn_readonly()
70  br label %if.end
71
72if.end:                                           ; preds = %if.else, %if.then
73  store i8 1, i8* %r, align 1
74  ret void
75}
76
77define void @test3(i1 %b, i8* nocapture %r) {
78; CHECK-LABEL: @test3(
79; CHECK-NEXT:  entry:
80; CHECK-NEXT:    store i8 1, i8* [[R:%.*]], align 1
81; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
82; CHECK:       if.then:
83; CHECK-NEXT:    tail call void @fn_mayread_or_clobber()
84; CHECK-NEXT:    br label [[IF_END:%.*]]
85; CHECK:       if.else:
86; CHECK-NEXT:    tail call void @fn_readonly()
87; CHECK-NEXT:    br label [[IF_END]]
88; CHECK:       if.end:
89; CHECK-NEXT:    store i8 1, i8* [[R]], align 1
90; CHECK-NEXT:    ret void
91;
92entry:
93  store i8 1, i8* %r, align 1
94  br i1 %b, label %if.then, label %if.else
95
96if.then:                                          ; preds = %entry
97  tail call void @fn_mayread_or_clobber()
98  br label %if.end
99
100if.else:                                          ; preds = %entry
101  tail call void @fn_readonly()
102  br label %if.end
103
104if.end:                                           ; preds = %if.else, %if.then
105  store i8 1, i8* %r, align 1
106  ret void
107}
108
109define void @test4(i1 %b, i8* nocapture %r) {
110; CHECK-LABEL: @test4(
111; CHECK-NEXT:  entry:
112; CHECK-NEXT:    store i8 1, i8* [[R:%.*]], align 1
113; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
114; CHECK:       if.then:
115; CHECK-NEXT:    tail call void @fn_readonly()
116; CHECK-NEXT:    br label [[IF_END:%.*]]
117; CHECK:       if.else:
118; CHECK-NEXT:    tail call void @fn_mayread_or_clobber()
119; CHECK-NEXT:    br label [[IF_END]]
120; CHECK:       if.end:
121; CHECK-NEXT:    store i8 1, i8* [[R]], align 1
122; CHECK-NEXT:    ret void
123;
124entry:
125  store i8 1, i8* %r, align 1
126  br i1 %b, label %if.then, label %if.else
127
128if.then:                                          ; preds = %entry
129  tail call void @fn_readonly()
130  br label %if.end
131
132if.else:                                          ; preds = %entry
133  tail call void @fn_mayread_or_clobber()
134  br label %if.end
135
136if.end:                                           ; preds = %if.else, %if.then
137  store i8 1, i8* %r, align 1
138  ret void
139}
140
141define void @test5(i1 %b, i8* nocapture %r) {
142; CHECK-LABEL: @test5(
143; CHECK-NEXT:  entry:
144; CHECK-NEXT:    store i8 1, i8* [[R:%.*]], align 1
145; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
146; CHECK:       if.then:
147; CHECK-NEXT:    tail call void @fn_readonly()
148; CHECK-NEXT:    br label [[IF_END:%.*]]
149; CHECK:       if.else:
150; CHECK-NEXT:    tail call void @fn_mayread_or_clobber()
151; CHECK-NEXT:    br label [[IF_END]]
152; CHECK:       if.end:
153; CHECK-NEXT:    store i8 1, i8* [[R]], align 1
154; CHECK-NEXT:    ret void
155;
156entry:
157  store i8 1, i8* %r, align 1
158  br i1 %b, label %if.then, label %if.else
159
160if.then:                                          ; preds = %entry
161  tail call void @fn_readonly()
162  br label %if.end
163
164if.else:                                          ; preds = %entry
165  tail call void @fn_mayread_or_clobber()
166  br label %if.end
167
168if.end:                                           ; preds = %if.else, %if.then
169  store i8 1, i8* %r, align 1
170  ret void
171}
172
173declare i1 @cond() readnone
174
175define void @test6(i32* noalias %P) {
176; CHECK-LABEL: @test6(
177; CHECK-NEXT:  entry:
178; CHECK-NEXT:    br label [[FOR_HEADER:%.*]]
179; CHECK:       for.header:
180; CHECK-NEXT:    store i32 1, i32* [[P:%.*]], align 4
181; CHECK-NEXT:    [[C1:%.*]] = call i1 @cond()
182; CHECK-NEXT:    br i1 [[C1]], label [[FOR_BODY:%.*]], label [[END:%.*]]
183; CHECK:       for.body:
184; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
185; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[P]], align 4
186; CHECK-NEXT:    br label [[FOR_HEADER]]
187; CHECK:       end:
188; CHECK-NEXT:    store i32 3, i32* [[P]], align 4
189; CHECK-NEXT:    ret void
190;
191entry:
192  br label %for.header
193
194for.header:
195  store i32 1, i32* %P, align 4
196  %c1 = call i1 @cond()
197  br i1 %c1, label %for.body, label %end
198
199for.body:
200  store i32 1, i32* %P, align 4
201  %lv = load i32, i32* %P
202  br label %for.header
203
204end:
205  store i32 3, i32* %P, align 4
206  ret void
207}
208
209; Make sure the store in %bb3 can be eliminated in the presences of early returns.
210define void @test7(i32* noalias %P) {
211; CHECK-LABEL: @test7(
212; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
213; CHECK-NEXT:    br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]
214; CHECK:       bb1:
215; CHECK-NEXT:    br label [[BB3:%.*]]
216; CHECK:       bb2:
217; CHECK-NEXT:    ret void
218; CHECK:       bb3:
219; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
220; CHECK-NEXT:    ret void
221;
222  store i32 0, i32* %P
223  br i1 true, label %bb1, label %bb2
224bb1:
225  br label %bb3
226bb2:
227  ret void
228bb3:
229  store i32 0, i32* %P
230  ret void
231}
232
233; Make sure the store in %bb3 won't be eliminated because it may be clobbered before.
234define void @test8(i32* noalias %P) {
235; CHECK-LABEL: @test8(
236; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
237; CHECK-NEXT:    br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]
238; CHECK:       bb1:
239; CHECK-NEXT:    call void @fn_mayread_or_clobber()
240; CHECK-NEXT:    br label [[BB3:%.*]]
241; CHECK:       bb2:
242; CHECK-NEXT:    ret void
243; CHECK:       bb3:
244; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
245; CHECK-NEXT:    ret void
246;
247  store i32 0, i32* %P
248  br i1 true, label %bb1, label %bb2
249bb1:
250  call void @fn_mayread_or_clobber()
251  br label %bb3
252bb2:
253  ret void
254bb3:
255  store i32 0, i32* %P
256  ret void
257}
258
259; Make sure the store in %bb3 will be eliminated because only the early exit path
260; may be clobbered.
261define void @test9(i32* noalias %P) {
262; CHECK-LABEL: @test9(
263; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
264; CHECK-NEXT:    br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]
265; CHECK:       bb1:
266; CHECK-NEXT:    br label [[BB3:%.*]]
267; CHECK:       bb2:
268; CHECK-NEXT:    call void @fn_mayread_or_clobber()
269; CHECK-NEXT:    ret void
270; CHECK:       bb3:
271; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
272; CHECK-NEXT:    ret void
273;
274  store i32 0, i32* %P
275  br i1 true, label %bb1, label %bb2
276bb1:
277  br label %bb3
278bb2:
279  call void @fn_mayread_or_clobber()
280  ret void
281bb3:
282  store i32 0, i32* %P
283  ret void
284}
285