1; RUN: opt < %s -instcombine -S | FileCheck %s
2
3define void @test1(i32* %P) {
4        store i32 undef, i32* %P
5        store i32 123, i32* undef
6        store i32 124, i32* null
7        ret void
8; CHECK-LABEL: @test1(
9; CHECK-NEXT: store i32 123, i32* undef
10; CHECK-NEXT: store i32 undef, i32* null
11; CHECK-NEXT: ret void
12}
13
14define void @test2(i32* %P) {
15        %X = load i32, i32* %P               ; <i32> [#uses=1]
16        %Y = add i32 %X, 0              ; <i32> [#uses=1]
17        store i32 %Y, i32* %P
18        ret void
19; CHECK-LABEL: @test2(
20; CHECK-NEXT: ret void
21}
22
23;; Simple sinking tests
24
25; "if then else"
26define i32 @test3(i1 %C) {
27	%A = alloca i32
28        br i1 %C, label %Cond, label %Cond2
29
30Cond:
31        store i32 -987654321, i32* %A
32        br label %Cont
33
34Cond2:
35	store i32 47, i32* %A
36	br label %Cont
37
38Cont:
39	%V = load i32, i32* %A
40	ret i32 %V
41; CHECK-LABEL: @test3(
42; CHECK-NOT: alloca
43; CHECK: Cont:
44; CHECK-NEXT:  %storemerge = phi i32 [ -987654321, %Cond ], [ 47, %Cond2 ]
45; CHECK-NEXT:  ret i32 %storemerge
46}
47
48; "if then"
49define i32 @test4(i1 %C) {
50	%A = alloca i32
51	store i32 47, i32* %A
52        br i1 %C, label %Cond, label %Cont
53
54Cond:
55        store i32 -987654321, i32* %A
56        br label %Cont
57
58Cont:
59	%V = load i32, i32* %A
60	ret i32 %V
61; CHECK-LABEL: @test4(
62; CHECK-NOT: alloca
63; CHECK: Cont:
64; CHECK-NEXT:  %storemerge = phi i32 [ -987654321, %Cond ], [ 47, %0 ]
65; CHECK-NEXT:  ret i32 %storemerge
66}
67
68; "if then"
69define void @test5(i1 %C, i32* %P) {
70	store i32 47, i32* %P, align 1
71        br i1 %C, label %Cond, label %Cont
72
73Cond:
74        store i32 -987654321, i32* %P, align 1
75        br label %Cont
76
77Cont:
78	ret void
79; CHECK-LABEL: @test5(
80; CHECK: Cont:
81; CHECK-NEXT:  %storemerge = phi i32
82; CHECK-NEXT:  store i32 %storemerge, i32* %P, align 1
83; CHECK-NEXT:  ret void
84}
85
86
87; PR14753 - merging two stores should preserve the TBAA tag.
88define void @test6(i32 %n, float* %a, i32* %gi) nounwind uwtable ssp {
89entry:
90  store i32 42, i32* %gi, align 4, !tbaa !0
91  br label %for.cond
92
93for.cond:                                         ; preds = %for.body, %entry
94  %storemerge = phi i32 [ 0, %entry ], [ %inc, %for.body ]
95  %0 = load i32, i32* %gi, align 4, !tbaa !0
96  %cmp = icmp slt i32 %0, %n
97  br i1 %cmp, label %for.body, label %for.end
98
99for.body:                                         ; preds = %for.cond
100  %idxprom = sext i32 %0 to i64
101  %arrayidx = getelementptr inbounds float, float* %a, i64 %idxprom
102  store float 0.000000e+00, float* %arrayidx, align 4, !tbaa !3
103  %1 = load i32, i32* %gi, align 4, !tbaa !0
104  %inc = add nsw i32 %1, 1
105  store i32 %inc, i32* %gi, align 4, !tbaa !0
106  br label %for.cond
107
108for.end:                                          ; preds = %for.cond
109  ret void
110; CHECK-LABEL: @test6(
111; CHECK: for.cond:
112; CHECK-NEXT: phi i32 [ 42
113; CHECK-NEXT: store i32 %storemerge, i32* %gi, align 4, !tbaa !0
114}
115
116define void @dse1(i32* %p) {
117; CHECK-LABEL: dse1
118; CHECK-NEXT: store
119; CHECK-NEXT: ret
120  store i32 0, i32* %p
121  store i32 0, i32* %p
122  ret void
123}
124
125; Slightly subtle: if we're mixing atomic and non-atomic access to the
126; same location, then the contents of the location are undefined if there's
127; an actual race.  As such, we're free to pick either store under the
128; assumption that we're not racing with any other thread.
129define void @dse2(i32* %p) {
130; CHECK-LABEL: dse2
131; CHECK-NEXT: store i32 0, i32* %p
132; CHECK-NEXT: ret
133  store atomic i32 0, i32* %p unordered, align 4
134  store i32 0, i32* %p
135  ret void
136}
137
138define void @dse3(i32* %p) {
139; CHECK-LABEL: dse3
140; CHECK-NEXT: store atomic i32 0, i32* %p unordered, align 4
141; CHECK-NEXT: ret
142  store i32 0, i32* %p
143  store atomic i32 0, i32* %p unordered, align 4
144  ret void
145}
146
147define void @dse4(i32* %p) {
148; CHECK-LABEL: dse4
149; CHECK-NEXT: store atomic i32 0, i32* %p unordered, align 4
150; CHECK-NEXT: ret
151  store atomic i32 0, i32* %p unordered, align 4
152  store atomic i32 0, i32* %p unordered, align 4
153  ret void
154}
155
156; Implementation limit - could remove unordered store here, but
157; currently don't.
158define void @dse5(i32* %p) {
159; CHECK-LABEL: dse5
160; CHECK-NEXT: store
161; CHECK-NEXT: store
162; CHECK-NEXT: ret
163  store atomic i32 0, i32* %p unordered, align 4
164  store atomic i32 0, i32* %p seq_cst, align 4
165  ret void
166}
167
168define void @write_back1(i32* %p) {
169; CHECK-LABEL: write_back1
170; CHECK-NEXT: ret
171  %v = load i32, i32* %p
172  store i32 %v, i32* %p
173  ret void
174}
175
176define void @write_back2(i32* %p) {
177; CHECK-LABEL: write_back2
178; CHECK-NEXT: ret
179  %v = load atomic i32, i32* %p unordered, align 4
180  store i32 %v, i32* %p
181  ret void
182}
183
184define void @write_back3(i32* %p) {
185; CHECK-LABEL: write_back3
186; CHECK-NEXT: ret
187  %v = load i32, i32* %p
188  store atomic i32 %v, i32* %p unordered, align 4
189  ret void
190}
191
192define void @write_back4(i32* %p) {
193; CHECK-LABEL: write_back4
194; CHECK-NEXT: ret
195  %v = load atomic i32, i32* %p unordered, align 4
196  store atomic i32 %v, i32* %p unordered, align 4
197  ret void
198}
199
200; Can't remove store due to ordering side effect
201define void @write_back5(i32* %p) {
202; CHECK-LABEL: write_back5
203; CHECK-NEXT: load
204; CHECK-NEXT: store
205; CHECK-NEXT: ret
206  %v = load atomic i32, i32* %p unordered, align 4
207  store atomic i32 %v, i32* %p seq_cst, align 4
208  ret void
209}
210
211define void @write_back6(i32* %p) {
212; CHECK-LABEL: write_back6
213; CHECK-NEXT: load
214; CHECK-NEXT: ret
215  %v = load atomic i32, i32* %p seq_cst, align 4
216  store atomic i32 %v, i32* %p unordered, align 4
217  ret void
218}
219
220define void @write_back7(i32* %p) {
221; CHECK-LABEL: write_back7
222; CHECK-NEXT: load
223; CHECK-NEXT: ret
224  %v = load atomic volatile i32, i32* %p seq_cst, align 4
225  store atomic i32 %v, i32* %p unordered, align 4
226  ret void
227}
228
229!0 = !{!4, !4, i64 0}
230!1 = !{!"omnipotent char", !2}
231!2 = !{!"Simple C/C++ TBAA"}
232!3 = !{!"float", !1}
233!4 = !{!"int", !1}
234