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*)
11 define void @test1(%C* %arg) {
12 ; CHECK-LABEL: @test1(
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: [[TMP5:%.*]] = icmp ne i64* [[M]], [[N]]
19 ; CHECK-NEXT: [[TMP71:%.*]] = icmp eq %C* [[ARG]], null
20 ; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], i1 true, i1 [[TMP71]]
21 ; CHECK-NEXT: br i1 [[TMP7]], label [[BB10:%.*]], label [[BB8:%.*]]
23 ; CHECK-NEXT: ret void
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:%.*]]
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]]
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
52 %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
53 tail call void @bar(%struct.S* %tmp9)
56 bb10: ; preds = %entry
57 %tmp11 = tail call i64 %tmp4(%C* %arg)
61 define void @test2(%C* %arg) {
62 ; CHECK-LABEL: @test2(
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:%.*]] = select i1 [[TMP5]], i1 true, i1 [[TMP71]]
71 ; CHECK-NEXT: br i1 [[TMP7]], label [[BB10:%.*]], label [[BB8:%.*]]
73 ; CHECK-NEXT: ret void
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:%.*]]
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]]
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
101 bb8: ; preds = %entry
102 %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
103 tail call void @bar(%struct.S* %tmp9)
106 bb10: ; preds = %entry
107 %tmp11 = tail call i64 %tmp4(%C* %arg)
111 define void @test3(%C* %arg) {
112 ; CHECK-LABEL: @test3(
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: [[TMP5:%.*]] = icmp ne i64* [[M]], [[N]]
119 ; CHECK-NEXT: [[TMP7_NOT1:%.*]] = icmp eq %C* [[ARG]], null
120 ; CHECK-NEXT: [[TMP7_NOT:%.*]] = select i1 [[TMP5]], i1 true, i1 [[TMP7_NOT1]]
121 ; CHECK-NEXT: br i1 [[TMP7_NOT]], label [[BB10:%.*]], label [[BB8:%.*]]
123 ; CHECK-NEXT: ret void
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:%.*]]
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]]
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
151 bb8: ; preds = %entry
152 %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
153 tail call void @bar(%struct.S* %tmp9)
156 bb10: ; preds = %entry
157 %tmp11 = tail call i64 %tmp4(%C* %arg)
161 define void @test4(%C* %arg) {
162 ; CHECK-LABEL: @test4(
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: [[TMP7_NOT1:%.*]] = icmp eq %C* [[ARG]], null
170 ; CHECK-NEXT: [[TMP7_NOT:%.*]] = select i1 [[TMP5]], i1 true, i1 [[TMP7_NOT1]]
171 ; CHECK-NEXT: br i1 [[TMP7_NOT]], label [[BB10:%.*]], label [[BB8:%.*]]
173 ; CHECK-NEXT: ret void
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:%.*]]
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]]
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
201 bb8: ; preds = %entry
202 %tmp9 = getelementptr inbounds %C, %C* %tmp6, i64 0, i32 0
203 tail call void @bar(%struct.S* %tmp9)
206 bb10: ; preds = %entry
207 %tmp11 = tail call i64 %tmp4(%C* %arg)
211 define void @test5(%C* %arg, i1 %arg1) {
212 ; CHECK-LABEL: @test5(
214 ; CHECK-NEXT: [[TMP2_NOT1:%.*]] = icmp eq %C* [[ARG:%.*]], null
215 ; CHECK-NEXT: [[TMP2_NOT:%.*]] = select i1 [[ARG1:%.*]], i1 true, i1 [[TMP2_NOT1]]
216 ; CHECK-NEXT: br i1 [[TMP2_NOT]], label [[BB5:%.*]], label [[BB3:%.*]]
218 ; CHECK-NEXT: ret void
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:%.*]]
224 ; CHECK-NEXT: tail call void @foobar()
225 ; CHECK-NEXT: br label [[BB]]
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
235 bb3: ; preds = %entry
236 %tmp4 = getelementptr inbounds %C, %C* %tmp, i64 0, i32 0
237 tail call void @bar(%struct.S* %tmp4)
240 bb5: ; preds = %entry
241 tail call void @foobar()
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(
251 ; CHECK-NEXT: br i1 false, label [[BB:%.*]], label [[BB]]
253 ; CHECK-NEXT: [[TMP:%.*]] = select i1 [[ARG1:%.*]], i32 [[ARG:%.*]], i32 0
254 ; CHECK-NEXT: ret i32 [[TMP]]
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