[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / select-cmp-br.ll
blob06f32828c96202429999f591e90bbf48b3c0cfb7
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Replace a 'select' with 'or' in 'select - cmp [eq|ne] - br' sequence
3 ; RUN: opt -instcombine -S < %s | FileCheck %s
5 %struct.S = type { i64*, i32, i32 }
6 %C = type <{ %struct.S }>
8 declare void @bar(%struct.S*)
9 declare void @foobar()
11 define void @test1(%C* %arg) {
12 ; CHECK-LABEL: @test1(
13 ; CHECK-NEXT:  entry:
14 ; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[C:%.*]], %C* [[ARG:%.*]], i64 0, i32 0, i32 0
15 ; CHECK-NEXT:    [[M:%.*]] = load i64*, i64** [[TMP]], align 8
16 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 1, i32 0, i32 0
17 ; CHECK-NEXT:    [[N:%.*]] = load i64*, i64** [[TMP1]], align 8
18 ; CHECK-NEXT:    [[NOT_TMP5:%.*]] = icmp ne i64* [[M]], [[N]]
19 ; CHECK-NEXT:    [[TMP71:%.*]] = icmp eq %C* [[ARG]], null
20 ; CHECK-NEXT:    [[TMP7:%.*]] = or i1 [[TMP71]], [[NOT_TMP5]]
21 ; CHECK-NEXT:    br i1 [[TMP7]], label [[BB10:%.*]], label [[BB8:%.*]]
22 ; CHECK:       bb:
23 ; CHECK-NEXT:    ret void
24 ; CHECK:       bb8:
25 ; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 0, i32 0
26 ; CHECK-NEXT:    tail call void @bar(%struct.S* [[TMP9]])
27 ; CHECK-NEXT:    br label [[BB:%.*]]
28 ; CHECK:       bb10:
29 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, i64* [[M]], i64 9
30 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i64* [[TMP2]] to i64 (%C*)**
31 ; CHECK-NEXT:    [[TMP4:%.*]] = load i64 (%C*)*, i64 (%C*)** [[TMP3]], align 8
32 ; CHECK-NEXT:    [[TMP11:%.*]] = tail call i64 [[TMP4]](%C* [[ARG]])
33 ; CHECK-NEXT:    br label [[BB]]
35 entry:
36   %tmp = getelementptr inbounds %C, %C* %arg, i64 0, i32 0, i32 0
37   %m = load i64*, i64** %tmp, align 8
38   %tmp1 = getelementptr inbounds %C, %C* %arg, i64 1, i32 0, i32 0
39   %n = load i64*, i64** %tmp1, align 8
40   %tmp2 = getelementptr inbounds i64, i64* %m, i64 9
41   %tmp3 = bitcast i64* %tmp2 to i64 (%C*)**
42   %tmp4 = load i64 (%C*)*, i64 (%C*)** %tmp3, align 8
43   %tmp5 = icmp eq i64* %m, %n
44   %tmp6 = select i1 %tmp5, %C* %arg, %C* null
45   %tmp7 = icmp eq %C* %tmp6, null
46   br i1 %tmp7, label %bb10, label %bb8
48 bb:                                               ; preds = %bb10, %bb8
49   ret void
51 bb8:                                              ; preds = %entry
52   %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
53   tail call void @bar(%struct.S* %tmp9)
54   br label %bb
56 bb10:                                             ; preds = %entry
57   %tmp11 = tail call i64 %tmp4(%C* %arg)
58   br label %bb
61 define void @test2(%C* %arg) {
62 ; CHECK-LABEL: @test2(
63 ; CHECK-NEXT:  entry:
64 ; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[C:%.*]], %C* [[ARG:%.*]], i64 0, i32 0, i32 0
65 ; CHECK-NEXT:    [[M:%.*]] = load i64*, i64** [[TMP]], align 8
66 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 1, i32 0, i32 0
67 ; CHECK-NEXT:    [[N:%.*]] = load i64*, i64** [[TMP1]], align 8
68 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64* [[M]], [[N]]
69 ; CHECK-NEXT:    [[TMP71:%.*]] = icmp eq %C* [[ARG]], null
70 ; CHECK-NEXT:    [[TMP7:%.*]] = or i1 [[TMP5]], [[TMP71]]
71 ; CHECK-NEXT:    br i1 [[TMP7]], label [[BB10:%.*]], label [[BB8:%.*]]
72 ; CHECK:       bb:
73 ; CHECK-NEXT:    ret void
74 ; CHECK:       bb8:
75 ; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 0, i32 0
76 ; CHECK-NEXT:    tail call void @bar(%struct.S* [[TMP9]])
77 ; CHECK-NEXT:    br label [[BB:%.*]]
78 ; CHECK:       bb10:
79 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, i64* [[M]], i64 9
80 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i64* [[TMP2]] to i64 (%C*)**
81 ; CHECK-NEXT:    [[TMP4:%.*]] = load i64 (%C*)*, i64 (%C*)** [[TMP3]], align 8
82 ; CHECK-NEXT:    [[TMP11:%.*]] = tail call i64 [[TMP4]](%C* [[ARG]])
83 ; CHECK-NEXT:    br label [[BB]]
85 entry:
86   %tmp = getelementptr inbounds %C, %C* %arg, i64 0, i32 0, i32 0
87   %m = load i64*, i64** %tmp, align 8
88   %tmp1 = getelementptr inbounds %C, %C* %arg, i64 1, i32 0, i32 0
89   %n = load i64*, i64** %tmp1, align 8
90   %tmp2 = getelementptr inbounds i64, i64* %m, i64 9
91   %tmp3 = bitcast i64* %tmp2 to i64 (%C*)**
92   %tmp4 = load i64 (%C*)*, i64 (%C*)** %tmp3, align 8
93   %tmp5 = icmp eq i64* %m, %n
94   %tmp6 = select i1 %tmp5, %C* null, %C* %arg
95   %tmp7 = icmp eq %C* %tmp6, null
96   br i1 %tmp7, label %bb10, label %bb8
98 bb:                                               ; preds = %bb10, %bb8
99   ret void
101 bb8:                                              ; preds = %entry
102   %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
103   tail call void @bar(%struct.S* %tmp9)
104   br label %bb
106 bb10:                                             ; preds = %entry
107   %tmp11 = tail call i64 %tmp4(%C* %arg)
108   br label %bb
111 define void @test3(%C* %arg) {
112 ; CHECK-LABEL: @test3(
113 ; CHECK-NEXT:  entry:
114 ; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[C:%.*]], %C* [[ARG:%.*]], i64 0, i32 0, i32 0
115 ; CHECK-NEXT:    [[M:%.*]] = load i64*, i64** [[TMP]], align 8
116 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 1, i32 0, i32 0
117 ; CHECK-NEXT:    [[N:%.*]] = load i64*, i64** [[TMP1]], align 8
118 ; CHECK-NEXT:    [[NOT_TMP5:%.*]] = icmp ne i64* [[M]], [[N]]
119 ; CHECK-NEXT:    [[TMP71:%.*]] = icmp eq %C* [[ARG]], null
120 ; CHECK-NEXT:    [[TMP7:%.*]] = or i1 [[TMP71]], [[NOT_TMP5]]
121 ; CHECK-NEXT:    br i1 [[TMP7]], label [[BB10:%.*]], label [[BB8:%.*]]
122 ; CHECK:       bb:
123 ; CHECK-NEXT:    ret void
124 ; CHECK:       bb8:
125 ; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 0, i32 0
126 ; CHECK-NEXT:    tail call void @bar(%struct.S* [[TMP9]])
127 ; CHECK-NEXT:    br label [[BB:%.*]]
128 ; CHECK:       bb10:
129 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, i64* [[M]], i64 9
130 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i64* [[TMP2]] to i64 (%C*)**
131 ; CHECK-NEXT:    [[TMP4:%.*]] = load i64 (%C*)*, i64 (%C*)** [[TMP3]], align 8
132 ; CHECK-NEXT:    [[TMP11:%.*]] = tail call i64 [[TMP4]](%C* [[ARG]])
133 ; CHECK-NEXT:    br label [[BB]]
135 entry:
136   %tmp = getelementptr inbounds %C, %C* %arg, i64 0, i32 0, i32 0
137   %m = load i64*, i64** %tmp, align 8
138   %tmp1 = getelementptr inbounds %C, %C* %arg, i64 1, i32 0, i32 0
139   %n = load i64*, i64** %tmp1, align 8
140   %tmp2 = getelementptr inbounds i64, i64* %m, i64 9
141   %tmp3 = bitcast i64* %tmp2 to i64 (%C*)**
142   %tmp4 = load i64 (%C*)*, i64 (%C*)** %tmp3, align 8
143   %tmp5 = icmp eq i64* %m, %n
144   %tmp6 = select i1 %tmp5, %C* %arg, %C* null
145   %tmp7 = icmp ne %C* %tmp6, null
146   br i1 %tmp7, label %bb8, label %bb10
148 bb:                                               ; preds = %bb10, %bb8
149   ret void
151 bb8:                                              ; preds = %entry
152   %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
153   tail call void @bar(%struct.S* %tmp9)
154   br label %bb
156 bb10:                                             ; preds = %entry
157   %tmp11 = tail call i64 %tmp4(%C* %arg)
158   br label %bb
161 define void @test4(%C* %arg) {
162 ; CHECK-LABEL: @test4(
163 ; CHECK-NEXT:  entry:
164 ; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[C:%.*]], %C* [[ARG:%.*]], i64 0, i32 0, i32 0
165 ; CHECK-NEXT:    [[M:%.*]] = load i64*, i64** [[TMP]], align 8
166 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 1, i32 0, i32 0
167 ; CHECK-NEXT:    [[N:%.*]] = load i64*, i64** [[TMP1]], align 8
168 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64* [[M]], [[N]]
169 ; CHECK-NEXT:    [[TMP71:%.*]] = icmp eq %C* [[ARG]], null
170 ; CHECK-NEXT:    [[TMP7:%.*]] = or i1 [[TMP5]], [[TMP71]]
171 ; CHECK-NEXT:    br i1 [[TMP7]], label [[BB10:%.*]], label [[BB8:%.*]]
172 ; CHECK:       bb:
173 ; CHECK-NEXT:    ret void
174 ; CHECK:       bb8:
175 ; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [[C]], %C* [[ARG]], i64 0, i32 0
176 ; CHECK-NEXT:    tail call void @bar(%struct.S* [[TMP9]])
177 ; CHECK-NEXT:    br label [[BB:%.*]]
178 ; CHECK:       bb10:
179 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, i64* [[M]], i64 9
180 ; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i64* [[TMP2]] to i64 (%C*)**
181 ; CHECK-NEXT:    [[TMP4:%.*]] = load i64 (%C*)*, i64 (%C*)** [[TMP3]], align 8
182 ; CHECK-NEXT:    [[TMP11:%.*]] = tail call i64 [[TMP4]](%C* [[ARG]])
183 ; CHECK-NEXT:    br label [[BB]]
185 entry:
186   %tmp = getelementptr inbounds %C, %C* %arg, i64 0, i32 0, i32 0
187   %m = load i64*, i64** %tmp, align 8
188   %tmp1 = getelementptr inbounds %C, %C* %arg, i64 1, i32 0, i32 0
189   %n = load i64*, i64** %tmp1, align 8
190   %tmp2 = getelementptr inbounds i64, i64* %m, i64 9
191   %tmp3 = bitcast i64* %tmp2 to i64 (%C*)**
192   %tmp4 = load i64 (%C*)*, i64 (%C*)** %tmp3, align 8
193   %tmp5 = icmp eq i64* %m, %n
194   %tmp6 = select i1 %tmp5, %C* null, %C* %arg
195   %tmp7 = icmp ne %C* %tmp6, null
196   br i1 %tmp7, label %bb8, label %bb10
198 bb:                                               ; preds = %bb10, %bb8
199   ret void
201 bb8:                                              ; preds = %entry
202   %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
203   tail call void @bar(%struct.S* %tmp9)
204   br label %bb
206 bb10:                                             ; preds = %entry
207   %tmp11 = tail call i64 %tmp4(%C* %arg)
208   br label %bb
211 define void @test5(%C* %arg, i1 %arg1) {
212 ; CHECK-LABEL: @test5(
213 ; CHECK-NEXT:  entry:
214 ; CHECK-NEXT:    [[TMP21:%.*]] = icmp eq %C* [[ARG:%.*]], null
215 ; CHECK-NEXT:    [[TMP2:%.*]] = or i1 [[TMP21]], [[ARG1:%.*]]
216 ; CHECK-NEXT:    br i1 [[TMP2]], label [[BB5:%.*]], label [[BB3:%.*]]
217 ; CHECK:       bb:
218 ; CHECK-NEXT:    ret void
219 ; CHECK:       bb3:
220 ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [[C:%.*]], %C* [[ARG]], i64 0, i32 0
221 ; CHECK-NEXT:    tail call void @bar(%struct.S* [[TMP4]])
222 ; CHECK-NEXT:    br label [[BB:%.*]]
223 ; CHECK:       bb5:
224 ; CHECK-NEXT:    tail call void @foobar()
225 ; CHECK-NEXT:    br label [[BB]]
227 entry:
228   %tmp = select i1 %arg1, %C* null, %C* %arg
229   %tmp2 = icmp ne %C* %tmp, null
230   br i1 %tmp2, label %bb3, label %bb5
232 bb:                                               ; preds = %bb5, %bb3
233   ret void
235 bb3:                                              ; preds = %entry
236   %tmp4 = getelementptr inbounds %C, %C* %tmp, i64 0, i32 0
237   tail call void @bar(%struct.S* %tmp4)
238   br label %bb
240 bb5:                                              ; preds = %entry
241   tail call void @foobar()
242   br label %bb
245 ; Negative test. Must not trigger the select-cmp-br combine because the result
246 ; of the select is used in both flows following the br (the special case where
247 ; the conditional branch has the same target for both flows).
248 define i32 @test6(i32 %arg, i1 %arg1) {
249 ; CHECK-LABEL: @test6(
250 ; CHECK-NEXT:  entry:
251 ; CHECK-NEXT:    br i1 false, label [[BB:%.*]], label [[BB]]
252 ; CHECK:       bb:
253 ; CHECK-NEXT:    [[TMP:%.*]] = select i1 [[ARG1:%.*]], i32 [[ARG:%.*]], i32 0
254 ; CHECK-NEXT:    ret i32 [[TMP]]
256 entry:
257   %tmp = select i1 %arg1, i32 %arg, i32 0
258   %tmp2 = icmp eq i32 %tmp, 0
259   br i1 %tmp2, label %bb, label %bb
261 bb:                                               ; preds = %entry, %entry
262   ret i32 %tmp