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 -passes=instcombine -S < %s | FileCheck %s
5 %struct.S = type { ptr, i32, i32 }
6 %C = type <{ %struct.S }>
11 define void @test1(ptr %arg) {
12 ; CHECK-LABEL: @test1(
14 ; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
15 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[ARG]], i64 1, i32 0, i32 0
16 ; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
17 ; CHECK-NEXT: [[TMP5_NOT:%.*]] = icmp eq ptr [[M]], [[N]]
18 ; CHECK-NEXT: br i1 [[TMP5_NOT]], label [[BB8:%.*]], label [[BB10:%.*]]
20 ; CHECK-NEXT: ret void
22 ; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
23 ; CHECK-NEXT: br label [[BB:%.*]]
25 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[M]], i64 9
26 ; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
27 ; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
28 ; CHECK-NEXT: br label [[BB]]
31 %m = load ptr, ptr %arg, align 8
32 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0
33 %n = load ptr, ptr %tmp1, align 8
34 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9
35 %tmp4 = load ptr, ptr %tmp2, align 8
36 %tmp5 = icmp eq ptr %m, %n
37 %tmp6 = select i1 %tmp5, ptr %arg, ptr null
38 %tmp7 = icmp eq ptr %tmp6, null
39 br i1 %tmp7, label %bb10, label %bb8
41 bb: ; preds = %bb10, %bb8
45 tail call void @bar(ptr %tmp6)
48 bb10: ; preds = %entry
49 %tmp11 = tail call i64 %tmp4(ptr %arg)
53 define void @test2(ptr %arg) {
54 ; CHECK-LABEL: @test2(
56 ; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
57 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[ARG]], i64 1, i32 0, i32 0
58 ; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
59 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
60 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]]
62 ; CHECK-NEXT: ret void
64 ; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
65 ; CHECK-NEXT: br label [[BB:%.*]]
67 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[M]], i64 9
68 ; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
69 ; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
70 ; CHECK-NEXT: br label [[BB]]
73 %m = load ptr, ptr %arg, align 8
74 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0
75 %n = load ptr, ptr %tmp1, align 8
76 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9
77 %tmp4 = load ptr, ptr %tmp2, align 8
78 %tmp5 = icmp eq ptr %m, %n
79 %tmp6 = select i1 %tmp5, ptr null, ptr %arg
80 %tmp7 = icmp eq ptr %tmp6, null
81 br i1 %tmp7, label %bb10, label %bb8
83 bb: ; preds = %bb10, %bb8
87 tail call void @bar(ptr %tmp6)
90 bb10: ; preds = %entry
91 %tmp11 = tail call i64 %tmp4(ptr %arg)
95 define void @test3(ptr %arg) {
96 ; CHECK-LABEL: @test3(
98 ; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
99 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[ARG]], i64 1, i32 0, i32 0
100 ; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
101 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
102 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB8:%.*]], label [[BB10:%.*]]
104 ; CHECK-NEXT: ret void
106 ; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
107 ; CHECK-NEXT: br label [[BB:%.*]]
109 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[M]], i64 9
110 ; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
111 ; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
112 ; CHECK-NEXT: br label [[BB]]
115 %m = load ptr, ptr %arg, align 8
116 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0
117 %n = load ptr, ptr %tmp1, align 8
118 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9
119 %tmp4 = load ptr, ptr %tmp2, align 8
120 %tmp5 = icmp eq ptr %m, %n
121 %tmp6 = select i1 %tmp5, ptr %arg, ptr null
122 %tmp7 = icmp ne ptr %tmp6, null
123 br i1 %tmp7, label %bb8, label %bb10
125 bb: ; preds = %bb10, %bb8
128 bb8: ; preds = %entry
129 tail call void @bar(ptr %tmp6)
132 bb10: ; preds = %entry
133 %tmp11 = tail call i64 %tmp4(ptr %arg)
137 define void @test4(ptr %arg) {
138 ; CHECK-LABEL: @test4(
140 ; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
141 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[ARG]], i64 1, i32 0, i32 0
142 ; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8
143 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]]
144 ; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]]
146 ; CHECK-NEXT: ret void
148 ; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]])
149 ; CHECK-NEXT: br label [[BB:%.*]]
151 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[M]], i64 9
152 ; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8
153 ; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]])
154 ; CHECK-NEXT: br label [[BB]]
157 %m = load ptr, ptr %arg, align 8
158 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0
159 %n = load ptr, ptr %tmp1, align 8
160 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9
161 %tmp4 = load ptr, ptr %tmp2, align 8
162 %tmp5 = icmp eq ptr %m, %n
163 %tmp6 = select i1 %tmp5, ptr null, ptr %arg
164 %tmp7 = icmp ne ptr %tmp6, null
165 br i1 %tmp7, label %bb8, label %bb10
167 bb: ; preds = %bb10, %bb8
170 bb8: ; preds = %entry
171 tail call void @bar(ptr %tmp6)
174 bb10: ; preds = %entry
175 %tmp11 = tail call i64 %tmp4(ptr %arg)
179 define void @test5(ptr %arg, i1 %arg1) {
180 ; CHECK-LABEL: @test5(
182 ; CHECK-NEXT: [[TMP2_NOT1:%.*]] = icmp eq ptr [[ARG:%.*]], null
183 ; CHECK-NEXT: [[TMP2_NOT:%.*]] = select i1 [[ARG1:%.*]], i1 true, i1 [[TMP2_NOT1]]
184 ; CHECK-NEXT: br i1 [[TMP2_NOT]], label [[BB5:%.*]], label [[BB3:%.*]]
186 ; CHECK-NEXT: ret void
188 ; CHECK-NEXT: tail call void @bar(ptr [[ARG]])
189 ; CHECK-NEXT: br label [[BB:%.*]]
191 ; CHECK-NEXT: tail call void @foobar()
192 ; CHECK-NEXT: br label [[BB]]
195 %tmp = select i1 %arg1, ptr null, ptr %arg
196 %tmp2 = icmp ne ptr %tmp, null
197 br i1 %tmp2, label %bb3, label %bb5
199 bb: ; preds = %bb5, %bb3
202 bb3: ; preds = %entry
203 tail call void @bar(ptr %tmp)
206 bb5: ; preds = %entry
207 tail call void @foobar()
211 ; Negative test. Must not trigger the select-cmp-br combine because the result
212 ; of the select is used in both flows following the br (the special case where
213 ; the conditional branch has the same target for both flows).
214 define i32 @test6(i32 %arg, i1 %arg1) {
215 ; CHECK-LABEL: @test6(
217 ; CHECK-NEXT: br i1 false, label [[BB:%.*]], label [[BB]]
219 ; CHECK-NEXT: [[TMP:%.*]] = select i1 [[ARG1:%.*]], i32 [[ARG:%.*]], i32 0
220 ; CHECK-NEXT: ret i32 [[TMP]]
223 %tmp = select i1 %arg1, i32 %arg, i32 0
224 %tmp2 = icmp eq i32 %tmp, 0
225 br i1 %tmp2, label %bb, label %bb
227 bb: ; preds = %entry, %entry