@@ -154,3 +154,350 @@ exit: ; preds = %bb2, %bb1, %bb0
154154 %result = phi i1 [ %0 , %bb0 ], [ %1 , %bb1 ], [ %2 , %bb2 ]
155155 ret i1 %result
156156}
157+
158+ declare void @foo ()
159+
160+ define i1 @test_icmp_simple (i1 %c , i32 %a , i32 %b ) {
161+ ; CHECK-LABEL: @test_icmp_simple(
162+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
163+ ; CHECK: common.ret:
164+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
165+ ; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
166+ ; CHECK: if:
167+ ; CHECK-NEXT: [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
168+ ; CHECK-NEXT: call void @foo()
169+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
170+ ; CHECK: else:
171+ ; CHECK-NEXT: [[CMP2]] = icmp ugt i32 [[B]], [[A]]
172+ ; CHECK-NEXT: call void @bar()
173+ ; CHECK-NEXT: br label [[COMMON_RET]]
174+ ;
175+ br i1 %c , label %if , label %else
176+
177+ if:
178+ %cmp1 = icmp ult i32 %a , %b
179+ call void @foo ()
180+ ret i1 %cmp1
181+
182+ else:
183+ %cmp2 = icmp ugt i32 %b , %a
184+ call void @bar ()
185+ ret i1 %cmp2
186+ }
187+
188+ define void @test_icmp_complex (i1 %c , i32 %a , i32 %b ) {
189+ ; CHECK-LABEL: @test_icmp_complex(
190+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
191+ ; CHECK: if:
192+ ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
193+ ; CHECK-NEXT: br i1 [[CMP1]], label [[IF2:%.*]], label [[ELSE2:%.*]]
194+ ; CHECK: else:
195+ ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[B]], [[A]]
196+ ; CHECK-NEXT: br i1 [[CMP2]], label [[IF2]], label [[ELSE2]]
197+ ; CHECK: common.ret:
198+ ; CHECK-NEXT: ret void
199+ ; CHECK: if2:
200+ ; CHECK-NEXT: call void @foo()
201+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
202+ ; CHECK: else2:
203+ ; CHECK-NEXT: call void @bar()
204+ ; CHECK-NEXT: br label [[COMMON_RET]]
205+ ;
206+ br i1 %c , label %if , label %else
207+
208+ if:
209+ %cmp1 = icmp ult i32 %a , %b
210+ br i1 %cmp1 , label %if2 , label %else2
211+
212+ else:
213+ %cmp2 = icmp ugt i32 %b , %a
214+ br i1 %cmp2 , label %if2 , label %else2
215+
216+ if2:
217+ call void @foo ()
218+ ret void
219+
220+ else2:
221+ call void @bar ()
222+ ret void
223+ }
224+
225+ define i1 @test_icmp_wrong_operands (i1 %c , i32 %a , i32 %b ) {
226+ ; CHECK-LABEL: @test_icmp_wrong_operands(
227+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
228+ ; CHECK: common.ret:
229+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
230+ ; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
231+ ; CHECK: if:
232+ ; CHECK-NEXT: [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
233+ ; CHECK-NEXT: call void @foo()
234+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
235+ ; CHECK: else:
236+ ; CHECK-NEXT: [[CMP2]] = icmp ugt i32 [[A]], [[B]]
237+ ; CHECK-NEXT: call void @bar()
238+ ; CHECK-NEXT: br label [[COMMON_RET]]
239+ ;
240+ br i1 %c , label %if , label %else
241+
242+ if:
243+ %cmp1 = icmp ult i32 %a , %b
244+ call void @foo ()
245+ ret i1 %cmp1
246+
247+ else:
248+ %cmp2 = icmp ugt i32 %a , %b
249+ call void @bar ()
250+ ret i1 %cmp2
251+ }
252+
253+ define i1 @test_icmp_wrong_pred (i1 %c , i32 %a , i32 %b ) {
254+ ; CHECK-LABEL: @test_icmp_wrong_pred(
255+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
256+ ; CHECK: common.ret:
257+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
258+ ; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
259+ ; CHECK: if:
260+ ; CHECK-NEXT: [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
261+ ; CHECK-NEXT: call void @foo()
262+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
263+ ; CHECK: else:
264+ ; CHECK-NEXT: [[CMP2]] = icmp uge i32 [[B]], [[A]]
265+ ; CHECK-NEXT: call void @bar()
266+ ; CHECK-NEXT: br label [[COMMON_RET]]
267+ ;
268+ br i1 %c , label %if , label %else
269+
270+ if:
271+ %cmp1 = icmp ult i32 %a , %b
272+ call void @foo ()
273+ ret i1 %cmp1
274+
275+ else:
276+ %cmp2 = icmp uge i32 %b , %a
277+ call void @bar ()
278+ ret i1 %cmp2
279+ }
280+
281+ define i32 @test_binop (i1 %c , i32 %a , i32 %b ) {
282+ ; CHECK-LABEL: @test_binop(
283+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
284+ ; CHECK: common.ret:
285+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
286+ ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
287+ ; CHECK: if:
288+ ; CHECK-NEXT: [[OP1]] = add i32 [[A:%.*]], [[B:%.*]]
289+ ; CHECK-NEXT: call void @foo()
290+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
291+ ; CHECK: else:
292+ ; CHECK-NEXT: [[OP2]] = add i32 [[B]], [[A]]
293+ ; CHECK-NEXT: call void @bar()
294+ ; CHECK-NEXT: br label [[COMMON_RET]]
295+ ;
296+ br i1 %c , label %if , label %else
297+
298+ if:
299+ %op1 = add i32 %a , %b
300+ call void @foo ()
301+ ret i32 %op1
302+
303+ else:
304+ %op2 = add i32 %b , %a
305+ call void @bar ()
306+ ret i32 %op2
307+ }
308+
309+ define i32 @test_binop_flags (i1 %c , i32 %a , i32 %b ) {
310+ ; CHECK-LABEL: @test_binop_flags(
311+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
312+ ; CHECK: common.ret:
313+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
314+ ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
315+ ; CHECK: if:
316+ ; CHECK-NEXT: [[OP1]] = add nuw nsw i32 [[A:%.*]], [[B:%.*]]
317+ ; CHECK-NEXT: call void @foo()
318+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
319+ ; CHECK: else:
320+ ; CHECK-NEXT: [[OP2]] = add nsw i32 [[B]], [[A]]
321+ ; CHECK-NEXT: call void @bar()
322+ ; CHECK-NEXT: br label [[COMMON_RET]]
323+ ;
324+ br i1 %c , label %if , label %else
325+
326+ if:
327+ %op1 = add nuw nsw i32 %a , %b
328+ call void @foo ()
329+ ret i32 %op1
330+
331+ else:
332+ %op2 = add nsw i32 %b , %a
333+ call void @bar ()
334+ ret i32 %op2
335+ }
336+
337+ define i32 @test_binop_not_commutative (i1 %c , i32 %a , i32 %b ) {
338+ ; CHECK-LABEL: @test_binop_not_commutative(
339+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
340+ ; CHECK: common.ret:
341+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
342+ ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
343+ ; CHECK: if:
344+ ; CHECK-NEXT: [[OP1]] = sub i32 [[A:%.*]], [[B:%.*]]
345+ ; CHECK-NEXT: call void @foo()
346+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
347+ ; CHECK: else:
348+ ; CHECK-NEXT: [[OP2]] = sub i32 [[B]], [[A]]
349+ ; CHECK-NEXT: call void @bar()
350+ ; CHECK-NEXT: br label [[COMMON_RET]]
351+ ;
352+ br i1 %c , label %if , label %else
353+
354+ if:
355+ %op1 = sub i32 %a , %b
356+ call void @foo ()
357+ ret i32 %op1
358+
359+ else:
360+ %op2 = sub i32 %b , %a
361+ call void @bar ()
362+ ret i32 %op2
363+ }
364+
365+ define i32 @test_binop_wrong_ops (i1 %c , i32 %a , i32 %b , i32 %d ) {
366+ ; CHECK-LABEL: @test_binop_wrong_ops(
367+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
368+ ; CHECK: common.ret:
369+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
370+ ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
371+ ; CHECK: if:
372+ ; CHECK-NEXT: [[OP1]] = add i32 [[A:%.*]], [[B:%.*]]
373+ ; CHECK-NEXT: call void @foo()
374+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
375+ ; CHECK: else:
376+ ; CHECK-NEXT: [[OP2]] = add i32 [[B]], [[D:%.*]]
377+ ; CHECK-NEXT: call void @bar()
378+ ; CHECK-NEXT: br label [[COMMON_RET]]
379+ ;
380+ br i1 %c , label %if , label %else
381+
382+ if:
383+ %op1 = add i32 %a , %b
384+ call void @foo ()
385+ ret i32 %op1
386+
387+ else:
388+ %op2 = add i32 %b , %d
389+ call void @bar ()
390+ ret i32 %op2
391+ }
392+
393+ define i32 @test_intrin (i1 %c , i32 %a , i32 %b ) {
394+ ; CHECK-LABEL: @test_intrin(
395+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
396+ ; CHECK: common.ret:
397+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
398+ ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
399+ ; CHECK: if:
400+ ; CHECK-NEXT: [[OP1]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 [[B:%.*]])
401+ ; CHECK-NEXT: call void @foo()
402+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
403+ ; CHECK: else:
404+ ; CHECK-NEXT: [[OP2]] = call i32 @llvm.umin.i32(i32 [[B]], i32 [[A]])
405+ ; CHECK-NEXT: call void @bar()
406+ ; CHECK-NEXT: br label [[COMMON_RET]]
407+ ;
408+ br i1 %c , label %if , label %else
409+
410+ if:
411+ %op1 = call i32 @llvm.umin (i32 %a , i32 %b )
412+ call void @foo ()
413+ ret i32 %op1
414+
415+ else:
416+ %op2 = call i32 @llvm.umin (i32 %b , i32 %a )
417+ call void @bar ()
418+ ret i32 %op2
419+ }
420+
421+ define i32 @test_intrin_not_same (i1 %c , i32 %a , i32 %b ) {
422+ ; CHECK-LABEL: @test_intrin_not_same(
423+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
424+ ; CHECK: common.ret:
425+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
426+ ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
427+ ; CHECK: if:
428+ ; CHECK-NEXT: [[OP1]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 [[B:%.*]])
429+ ; CHECK-NEXT: call void @foo()
430+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
431+ ; CHECK: else:
432+ ; CHECK-NEXT: [[OP2]] = call i32 @llvm.umax.i32(i32 [[B]], i32 [[A]])
433+ ; CHECK-NEXT: call void @bar()
434+ ; CHECK-NEXT: br label [[COMMON_RET]]
435+ ;
436+ br i1 %c , label %if , label %else
437+
438+ if:
439+ %op1 = call i32 @llvm.umin (i32 %a , i32 %b )
440+ call void @foo ()
441+ ret i32 %op1
442+
443+ else:
444+ %op2 = call i32 @llvm.umax (i32 %b , i32 %a )
445+ call void @bar ()
446+ ret i32 %op2
447+ }
448+
449+ define float @test_intrin_3arg (i1 %c , float %a , float %b , float %d ) {
450+ ; CHECK-LABEL: @test_intrin_3arg(
451+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
452+ ; CHECK: common.ret:
453+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi float [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
454+ ; CHECK-NEXT: ret float [[COMMON_RET_OP]]
455+ ; CHECK: if:
456+ ; CHECK-NEXT: [[OP1]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[D:%.*]])
457+ ; CHECK-NEXT: call void @foo()
458+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
459+ ; CHECK: else:
460+ ; CHECK-NEXT: [[OP2]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[D]])
461+ ; CHECK-NEXT: call void @bar()
462+ ; CHECK-NEXT: br label [[COMMON_RET]]
463+ ;
464+ br i1 %c , label %if , label %else
465+
466+ if:
467+ %op1 = call float @llvm.fma (float %a , float %b , float %d )
468+ call void @foo ()
469+ ret float %op1
470+
471+ else:
472+ %op2 = call float @llvm.fma (float %b , float %a , float %d )
473+ call void @bar ()
474+ ret float %op2
475+ }
476+
477+ define float @test_intrin_3arg_wrong_args_commuted (i1 %c , float %a , float %b , float %d ) {
478+ ; CHECK-LABEL: @test_intrin_3arg_wrong_args_commuted(
479+ ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
480+ ; CHECK: common.ret:
481+ ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi float [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
482+ ; CHECK-NEXT: ret float [[COMMON_RET_OP]]
483+ ; CHECK: if:
484+ ; CHECK-NEXT: [[OP1]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[D:%.*]])
485+ ; CHECK-NEXT: call void @foo()
486+ ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
487+ ; CHECK: else:
488+ ; CHECK-NEXT: [[OP2]] = call float @llvm.fma.f32(float [[A]], float [[D]], float [[B]])
489+ ; CHECK-NEXT: call void @bar()
490+ ; CHECK-NEXT: br label [[COMMON_RET]]
491+ ;
492+ br i1 %c , label %if , label %else
493+
494+ if:
495+ %op1 = call float @llvm.fma (float %a , float %b , float %d )
496+ call void @foo ()
497+ ret float %op1
498+
499+ else:
500+ %op2 = call float @llvm.fma (float %a , float %d , float %b )
501+ call void @bar ()
502+ ret float %op2
503+ }
0 commit comments