• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4define void @test1(i32* %P) {
5; CHECK-LABEL: @test1(
6; CHECK-NEXT:    store i32 123, i32* undef, align 4
7; CHECK-NEXT:    store i32 undef, i32* null, align 536870912
8; CHECK-NEXT:    ret void
9;
10  store i32 undef, i32* %P
11  store i32 123, i32* undef
12  store i32 124, i32* null
13  ret void
14}
15
16define void @test2(i32* %P) {
17; CHECK-LABEL: @test2(
18; CHECK-NEXT:    ret void
19;
20  %X = load i32, i32* %P
21  %Y = add i32 %X, 0
22  store i32 %Y, i32* %P
23  ret void
24}
25
26define void @store_at_gep_off_null(i64 %offset) {
27; CHECK-LABEL: @store_at_gep_off_null(
28; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i32, i32* null, i64 [[OFFSET:%.*]]
29; CHECK-NEXT:    store i32 undef, i32* [[PTR]], align 4
30; CHECK-NEXT:    ret void
31;
32  %ptr = getelementptr i32, i32 *null, i64 %offset
33  store i32 24, i32* %ptr
34  ret void
35}
36
37define void @store_at_gep_off_no_null_opt(i64 %offset) #0 {
38; CHECK-LABEL: @store_at_gep_off_no_null_opt(
39; CHECK-NEXT:    [[PTR:%.*]] = getelementptr i32, i32* null, i64 [[OFFSET:%.*]]
40; CHECK-NEXT:    store i32 24, i32* [[PTR]], align 4
41; CHECK-NEXT:    ret void
42;
43  %ptr = getelementptr i32, i32 *null, i64 %offset
44  store i32 24, i32* %ptr
45  ret void
46}
47
48attributes #0 = { null_pointer_is_valid }
49
50;; Simple sinking tests
51
52; "if then else"
53define i32 @test3(i1 %C) {
54; CHECK-LABEL: @test3(
55; CHECK-NEXT:    br i1 [[C:%.*]], label [[COND:%.*]], label [[COND2:%.*]]
56; CHECK:       Cond:
57; CHECK-NEXT:    br label [[CONT:%.*]]
58; CHECK:       Cond2:
59; CHECK-NEXT:    br label [[CONT]]
60; CHECK:       Cont:
61; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 47, [[COND2]] ], [ -987654321, [[COND]] ]
62; CHECK-NEXT:    ret i32 [[STOREMERGE]]
63;
64  %A = alloca i32
65  br i1 %C, label %Cond, label %Cond2
66
67Cond:
68  store i32 -987654321, i32* %A
69  br label %Cont
70
71Cond2:
72  store i32 47, i32* %A
73  br label %Cont
74
75Cont:
76  %V = load i32, i32* %A
77  ret i32 %V
78}
79
80; "if then"
81define i32 @test4(i1 %C) {
82; CHECK-LABEL: @test4(
83; CHECK-NEXT:    br i1 [[C:%.*]], label [[COND:%.*]], label [[CONT:%.*]]
84; CHECK:       Cond:
85; CHECK-NEXT:    br label [[CONT]]
86; CHECK:       Cont:
87; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ -987654321, [[COND]] ], [ 47, [[TMP0:%.*]] ]
88; CHECK-NEXT:    ret i32 [[STOREMERGE]]
89;
90  %A = alloca i32
91  store i32 47, i32* %A
92  br i1 %C, label %Cond, label %Cont
93
94Cond:
95  store i32 -987654321, i32* %A
96  br label %Cont
97
98Cont:
99  %V = load i32, i32* %A
100  ret i32 %V
101}
102
103; "if then"
104define void @test5(i1 %C, i32* %P) {
105; CHECK-LABEL: @test5(
106; CHECK-NEXT:    br i1 [[C:%.*]], label [[COND:%.*]], label [[CONT:%.*]]
107; CHECK:       Cond:
108; CHECK-NEXT:    br label [[CONT]]
109; CHECK:       Cont:
110; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ -987654321, [[COND]] ], [ 47, [[TMP0:%.*]] ]
111; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* [[P:%.*]], align 1
112; CHECK-NEXT:    ret void
113;
114  store i32 47, i32* %P, align 1
115  br i1 %C, label %Cond, label %Cont
116
117Cond:
118  store i32 -987654321, i32* %P, align 1
119  br label %Cont
120
121Cont:
122  ret void
123}
124
125
126; PR14753 - merging two stores should preserve the TBAA tag.
127define void @test6(i32 %n, float* %a, i32* %gi) nounwind uwtable ssp {
128; CHECK-LABEL: @test6(
129; CHECK-NEXT:  entry:
130; CHECK-NEXT:    br label [[FOR_COND:%.*]]
131; CHECK:       for.cond:
132; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 42, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
133; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* [[GI:%.*]], align 4, !tbaa !0
134; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[STOREMERGE]], [[N:%.*]]
135; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
136; CHECK:       for.body:
137; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[STOREMERGE]] to i64
138; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 [[IDXPROM]]
139; CHECK-NEXT:    store float 0.000000e+00, float* [[ARRAYIDX]], align 4, !tbaa !4
140; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[GI]], align 4, !tbaa !0
141; CHECK-NEXT:    [[INC]] = add nsw i32 [[TMP0]], 1
142; CHECK-NEXT:    br label [[FOR_COND]]
143; CHECK:       for.end:
144; CHECK-NEXT:    ret void
145;
146entry:
147  store i32 42, i32* %gi, align 4, !tbaa !0
148  br label %for.cond
149
150for.cond:
151  %storemerge = phi i32 [ 0, %entry ], [ %inc, %for.body ]
152  %0 = load i32, i32* %gi, align 4, !tbaa !0
153  %cmp = icmp slt i32 %0, %n
154  br i1 %cmp, label %for.body, label %for.end
155
156for.body:
157  %idxprom = sext i32 %0 to i64
158  %arrayidx = getelementptr inbounds float, float* %a, i64 %idxprom
159  store float 0.000000e+00, float* %arrayidx, align 4, !tbaa !3
160  %1 = load i32, i32* %gi, align 4, !tbaa !0
161  %inc = add nsw i32 %1, 1
162  store i32 %inc, i32* %gi, align 4, !tbaa !0
163  br label %for.cond
164
165for.end:
166  ret void
167}
168
169define void @dse1(i32* %p) {
170; CHECK-LABEL: @dse1(
171; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
172; CHECK-NEXT:    ret void
173;
174  store i32 0, i32* %p
175  store i32 0, i32* %p
176  ret void
177}
178
179; Slightly subtle: if we're mixing atomic and non-atomic access to the
180; same location, then the contents of the location are undefined if there's
181; an actual race.  As such, we're free to pick either store under the
182; assumption that we're not racing with any other thread.
183define void @dse2(i32* %p) {
184; CHECK-LABEL: @dse2(
185; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
186; CHECK-NEXT:    ret void
187;
188  store atomic i32 0, i32* %p unordered, align 4
189  store i32 0, i32* %p
190  ret void
191}
192
193define void @dse3(i32* %p) {
194; CHECK-LABEL: @dse3(
195; CHECK-NEXT:    store atomic i32 0, i32* [[P:%.*]] unordered, align 4
196; CHECK-NEXT:    ret void
197;
198  store i32 0, i32* %p
199  store atomic i32 0, i32* %p unordered, align 4
200  ret void
201}
202
203define void @dse4(i32* %p) {
204; CHECK-LABEL: @dse4(
205; CHECK-NEXT:    store atomic i32 0, i32* [[P:%.*]] unordered, align 4
206; CHECK-NEXT:    ret void
207;
208  store atomic i32 0, i32* %p unordered, align 4
209  store atomic i32 0, i32* %p unordered, align 4
210  ret void
211}
212
213; Implementation limit - could remove unordered store here, but
214; currently don't.
215define void @dse5(i32* %p) {
216; CHECK-LABEL: @dse5(
217; CHECK-NEXT:    store atomic i32 0, i32* [[P:%.*]] unordered, align 4
218; CHECK-NEXT:    store atomic i32 0, i32* [[P]] seq_cst, align 4
219; CHECK-NEXT:    ret void
220;
221  store atomic i32 0, i32* %p unordered, align 4
222  store atomic i32 0, i32* %p seq_cst, align 4
223  ret void
224}
225
226define void @write_back1(i32* %p) {
227; CHECK-LABEL: @write_back1(
228; CHECK-NEXT:    ret void
229;
230  %v = load i32, i32* %p
231  store i32 %v, i32* %p
232  ret void
233}
234
235define void @write_back2(i32* %p) {
236; CHECK-LABEL: @write_back2(
237; CHECK-NEXT:    ret void
238;
239  %v = load atomic i32, i32* %p unordered, align 4
240  store i32 %v, i32* %p
241  ret void
242}
243
244define void @write_back3(i32* %p) {
245; CHECK-LABEL: @write_back3(
246; CHECK-NEXT:    ret void
247;
248  %v = load i32, i32* %p
249  store atomic i32 %v, i32* %p unordered, align 4
250  ret void
251}
252
253define void @write_back4(i32* %p) {
254; CHECK-LABEL: @write_back4(
255; CHECK-NEXT:    ret void
256;
257  %v = load atomic i32, i32* %p unordered, align 4
258  store atomic i32 %v, i32* %p unordered, align 4
259  ret void
260}
261
262; Can't remove store due to ordering side effect
263define void @write_back5(i32* %p) {
264; CHECK-LABEL: @write_back5(
265; CHECK-NEXT:    [[V:%.*]] = load atomic i32, i32* [[P:%.*]] unordered, align 4
266; CHECK-NEXT:    store atomic i32 [[V]], i32* [[P]] seq_cst, align 4
267; CHECK-NEXT:    ret void
268;
269  %v = load atomic i32, i32* %p unordered, align 4
270  store atomic i32 %v, i32* %p seq_cst, align 4
271  ret void
272}
273
274define void @write_back6(i32* %p) {
275; CHECK-LABEL: @write_back6(
276; CHECK-NEXT:    [[V:%.*]] = load atomic i32, i32* [[P:%.*]] seq_cst, align 4
277; CHECK-NEXT:    ret void
278;
279  %v = load atomic i32, i32* %p seq_cst, align 4
280  store atomic i32 %v, i32* %p unordered, align 4
281  ret void
282}
283
284define void @write_back7(i32* %p) {
285; CHECK-LABEL: @write_back7(
286; CHECK-NEXT:    [[V:%.*]] = load atomic volatile i32, i32* [[P:%.*]] seq_cst, align 4
287; CHECK-NEXT:    ret void
288;
289  %v = load atomic volatile i32, i32* %p seq_cst, align 4
290  store atomic i32 %v, i32* %p unordered, align 4
291  ret void
292}
293
294@Unknown = external constant i32
295
296define void @store_to_constant() {
297; CHECK-LABEL: @store_to_constant(
298; CHECK-NEXT:    ret void
299;
300  store i32 0, i32* @Unknown
301  ret void
302}
303
304!0 = !{!4, !4, i64 0}
305!1 = !{!"omnipotent char", !2}
306!2 = !{!"Simple C/C++ TBAA"}
307!3 = !{!"float", !1}
308!4 = !{!"int", !1}
309