; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes=instcombine < %s | FileCheck %s ; If we have an smin feeding a signed or equality icmp that shares an ; operand with the smin, the compare should always be folded. ; Test all 6 foldable predicates (eq,ne,sge,sgt,sle,slt) * 4 commutation ; possibilities for each predicate. Note that folds to true/false or ; folds to an existing instruction may be handled by InstSimplify. ; smin(X, Y) == X --> X <= Y define i1 @eq_smin1(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_smin1( ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp eq i32 %sel, %x ret i1 %cmp2 } ; Commute min operands. define i1 @eq_smin2(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_smin2( ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp eq i32 %sel, %x ret i1 %cmp2 } ; Disguise the icmp predicate by commuting the min op to the RHS. define i1 @eq_smin3(i32 %a, i32 %y) { ; CHECK-LABEL: @eq_smin3( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp eq i32 %x, %sel ret i1 %cmp2 } ; Commute min operands. define i1 @eq_smin4(i32 %a, i32 %y) { ; CHECK-LABEL: @eq_smin4( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp eq i32 %x, %sel ret i1 %cmp2 } ; smin(X, Y) >= X --> Y >= X define i1 @sge_smin1(i32 %x, i32 %y) { ; CHECK-LABEL: @sge_smin1( ; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp sge i32 %sel, %x ret i1 %cmp2 } ; Commute min operands. define i1 @sge_smin2(i32 %x, i32 %y) { ; CHECK-LABEL: @sge_smin2( ; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp sge i32 %sel, %x ret i1 %cmp2 } ; Disguise the icmp predicate by commuting the min op to the RHS. define i1 @sge_smin3(i32 %a, i32 %y) { ; CHECK-LABEL: @sge_smin3( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp sle i32 %x, %sel ret i1 %cmp2 } ; Commute min operands. define i1 @sge_smin4(i32 %a, i32 %y) { ; CHECK-LABEL: @sge_smin4( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp sle i32 %x, %sel ret i1 %cmp2 } ; smin(X, Y) != X --> X > Y define i1 @ne_smin1(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_smin1( ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp ne i32 %sel, %x ret i1 %cmp2 } ; Commute min operands. define i1 @ne_smin2(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_smin2( ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp ne i32 %sel, %x ret i1 %cmp2 } ; Disguise the icmp predicate by commuting the min op to the RHS. define i1 @ne_smin3(i32 %a, i32 %y) { ; CHECK-LABEL: @ne_smin3( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp ne i32 %x, %sel ret i1 %cmp2 } ; Commute min operands. define i1 @ne_smin4(i32 %a, i32 %y) { ; CHECK-LABEL: @ne_smin4( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp ne i32 %x, %sel ret i1 %cmp2 } ; smin(X, Y) < X --> Y < X define i1 @slt_smin1(i32 %x, i32 %y) { ; CHECK-LABEL: @slt_smin1( ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp slt i32 %sel, %x ret i1 %cmp2 } ; Commute min operands. define i1 @slt_smin2(i32 %x, i32 %y) { ; CHECK-LABEL: @slt_smin2( ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp slt i32 %sel, %x ret i1 %cmp2 } ; Disguise the icmp predicate by commuting the min op to the RHS. define i1 @slt_smin3(i32 %a, i32 %y) { ; CHECK-LABEL: @slt_smin3( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp sgt i32 %x, %sel ret i1 %cmp2 } ; Commute min operands. define i1 @slt_smin4(i32 %a, i32 %y) { ; CHECK-LABEL: @slt_smin4( ; CHECK-NEXT: [[X:%.*]] = add i32 [[A:%.*]], 3 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp sgt i32 %x, %sel ret i1 %cmp2 } ; smin(X, Y) <= X --> true define i1 @sle_smin1(i32 %x, i32 %y) { ; CHECK-LABEL: @sle_smin1( ; CHECK-NEXT: ret i1 true ; %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp sle i32 %sel, %x ret i1 %cmp2 } ; Commute min operands. define i1 @sle_smin2(i32 %x, i32 %y) { ; CHECK-LABEL: @sle_smin2( ; CHECK-NEXT: ret i1 true ; %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp sle i32 %sel, %x ret i1 %cmp2 } ; Disguise the icmp predicate by commuting the min op to the RHS. define i1 @sle_smin3(i32 %a, i32 %y) { ; CHECK-LABEL: @sle_smin3( ; CHECK-NEXT: ret i1 true ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp sge i32 %x, %sel ret i1 %cmp2 } ; Commute min operands. define i1 @sle_smin4(i32 %a, i32 %y) { ; CHECK-LABEL: @sle_smin4( ; CHECK-NEXT: ret i1 true ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp sge i32 %x, %sel ret i1 %cmp2 } ; smin(X, Y) > X --> false define i1 @sgt_smin1(i32 %x, i32 %y) { ; CHECK-LABEL: @sgt_smin1( ; CHECK-NEXT: ret i1 false ; %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp sgt i32 %sel, %x ret i1 %cmp2 } ; Commute min operands. define i1 @sgt_smin2(i32 %x, i32 %y) { ; CHECK-LABEL: @sgt_smin2( ; CHECK-NEXT: ret i1 false ; %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp sgt i32 %sel, %x ret i1 %cmp2 } ; Disguise the icmp predicate by commuting the min op to the RHS. define i1 @sgt_smin3(i32 %a, i32 %y) { ; CHECK-LABEL: @sgt_smin3( ; CHECK-NEXT: ret i1 false ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %x, %y %sel = select i1 %cmp1, i32 %x, i32 %y %cmp2 = icmp slt i32 %x, %sel ret i1 %cmp2 } ; Commute min operands. define i1 @sgt_smin4(i32 %a, i32 %y) { ; CHECK-LABEL: @sgt_smin4( ; CHECK-NEXT: ret i1 false ; %x = add i32 %a, 3 ; thwart complexity-based canonicalization %cmp1 = icmp slt i32 %y, %x %sel = select i1 %cmp1, i32 %y, i32 %x %cmp2 = icmp slt i32 %x, %sel ret i1 %cmp2 } declare void @use(i1 %c) define void @eq_smin_contextual(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @eq_smin_contextual( ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp sle i32 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp sgt i32 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp eq i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @eq_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @eq_smin_contextual_commuted( ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp sle i32 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp sgt i32 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp eq i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @slt_smin_contextual(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @slt_smin_contextual( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]]) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp slt i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @slt_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @slt_smin_contextual_commuted( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]]) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp slt i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @sle_smin_contextual(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @sle_smin_contextual( ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp sle i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @sle_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @sle_smin_contextual_commuted( ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp sle i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @sgt_smin_contextual(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @sgt_smin_contextual( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP2]]) ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP3]]) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp sgt i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @sgt_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @sgt_smin_contextual_commuted( ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP2]]) ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP3]]) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp sgt i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @sge_smin_contextual(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @sge_smin_contextual( ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y:%.*]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP2]]) ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP3]]) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp sge i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %x, i32 %y) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } define void @sge_smin_contextual_commuted(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @sge_smin_contextual_commuted( ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[END:%.*]], label [[IF:%.*]] ; CHECK: if: ; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.smin.i32(i32 [[Y:%.*]], i32 [[X]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP2]]) ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP3]]) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge i32 [[Y]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne i32 [[COND]], [[Z]] ; CHECK-NEXT: call void @use(i1 [[CMP10]]) ; CHECK-NEXT: ret void ; CHECK: end: ; CHECK-NEXT: ret void ; %cmp = icmp sge i32 %x, %z br i1 %cmp, label %if, label %end if: %cond = call i32 @llvm.smin.i32(i32 %y, i32 %x) %cmp1 = icmp slt i32 %cond, %z call void @use(i1 %cmp1) %cmp2 = icmp sle i32 %cond, %z call void @use(i1 %cmp2) %cmp3 = icmp sgt i32 %cond, %z call void @use(i1 %cmp3) %cmp4 = icmp sge i32 %cond, %z call void @use(i1 %cmp4) %cmp5 = icmp ult i32 %cond, %z call void @use(i1 %cmp5) %cmp6 = icmp ule i32 %cond, %z call void @use(i1 %cmp6) %cmp7 = icmp ugt i32 %cond, %z call void @use(i1 %cmp7) %cmp8 = icmp uge i32 %cond, %z call void @use(i1 %cmp8) %cmp9 = icmp eq i32 %cond, %z call void @use(i1 %cmp9) %cmp10 = icmp ne i32 %cond, %z call void @use(i1 %cmp10) ret void end: ret void } declare void @use_v2i1(<2 x i1> %c) ; icmp pred smin(X, Y), X define void @eq_smin_v2i32(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @eq_smin_v2i32( ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], [[X]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP1]]) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> ) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> zeroinitializer) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sge <2 x i32> [[Y]], [[X]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], [[X]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ule <2 x i32> [[COND]], [[X]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], [[X]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp uge <2 x i32> [[COND]], [[X]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp sle <2 x i32> [[X]], [[Y]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp sgt <2 x i32> [[X]], [[Y]] ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP10]]) ; CHECK-NEXT: ret void ; %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> %x, <2 x i32> %y) %cmp1 = icmp slt <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp1) %cmp2 = icmp sle <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp2) %cmp3 = icmp sgt <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp3) %cmp4 = icmp sge <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp4) %cmp5 = icmp ult <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp5) %cmp6 = icmp ule <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp6) %cmp7 = icmp ugt <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp7) %cmp8 = icmp uge <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp8) %cmp9 = icmp eq <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp9) %cmp10 = icmp ne <2 x i32> %cond, %x call void @use_v2i1(<2 x i1> %cmp10) ret void } ; icmp pred smin(C1, Y), C2 where C1 == C2 define void @eq_smin_v2i32_constant(<2 x i32> %y) { ; CHECK-LABEL: @eq_smin_v2i32_constant( ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> ) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP1]]) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> ) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> zeroinitializer) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp sgt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp slt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP10]]) ; CHECK-NEXT: ret void ; %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> , <2 x i32> %y) %cmp1 = icmp slt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp1) %cmp2 = icmp sle <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp2) %cmp3 = icmp sgt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp3) %cmp4 = icmp sge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp4) %cmp5 = icmp ult <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp5) %cmp6 = icmp ule <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp6) %cmp7 = icmp ugt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp7) %cmp8 = icmp uge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp8) %cmp9 = icmp eq <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp9) %cmp10 = icmp ne <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp10) ret void } ; icmp pred smin(C1, Y), C2 where C1 < C2 define void @slt_smin_v2i32_constant(<2 x i32> %y) { ; CHECK-LABEL: @slt_smin_v2i32_constant( ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> ) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> ) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> ) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> zeroinitializer) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> zeroinitializer) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP8]]) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> zeroinitializer) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> ) ; CHECK-NEXT: ret void ; %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> , <2 x i32> %y) %cmp1 = icmp slt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp1) %cmp2 = icmp sle <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp2) %cmp3 = icmp sgt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp3) %cmp4 = icmp sge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp4) %cmp5 = icmp ult <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp5) %cmp6 = icmp ule <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp6) %cmp7 = icmp ugt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp7) %cmp8 = icmp uge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp8) %cmp9 = icmp eq <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp9) %cmp10 = icmp ne <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp10) ret void } ; icmp pred smin(C1, Y), C2 where C1 <= C2 define void @sle_smin_v2i32_constant(<2 x i32> %y) { ; CHECK-LABEL: @sle_smin_v2i32_constant( ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> ) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP1]]) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> ) ; CHECK-NEXT: call void @use_v2i1(<2 x i1> zeroinitializer) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP10]]) ; CHECK-NEXT: ret void ; %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> , <2 x i32> %y) %cmp1 = icmp slt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp1) %cmp2 = icmp sle <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp2) %cmp3 = icmp sgt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp3) %cmp4 = icmp sge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp4) %cmp5 = icmp ult <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp5) %cmp6 = icmp ule <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp6) %cmp7 = icmp ugt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp7) %cmp8 = icmp uge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp8) %cmp9 = icmp eq <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp9) %cmp10 = icmp ne <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp10) ret void } ; icmp pred smin(C1, Y), C2 where C1 > C2 define void @sgt_smin_v2i32_constant(<2 x i32> %y) { ; CHECK-LABEL: @sgt_smin_v2i32_constant( ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> ) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP2]]) ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP3]]) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP10]]) ; CHECK-NEXT: ret void ; %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> , <2 x i32> %y) %cmp1 = icmp slt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp1) %cmp2 = icmp sle <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp2) %cmp3 = icmp sgt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp3) %cmp4 = icmp sge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp4) %cmp5 = icmp ult <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp5) %cmp6 = icmp ule <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp6) %cmp7 = icmp ugt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp7) %cmp8 = icmp uge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp8) %cmp9 = icmp eq <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp9) %cmp10 = icmp ne <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp10) ret void } ; icmp pred smin(C1, Y), C2 where C1 >= C2 define void @sge_smin_v2i32_constant(<2 x i32> %y) { ; CHECK-LABEL: @sge_smin_v2i32_constant( ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> ) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP2]]) ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP3]]) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt <2 x i32> [[Y]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP10]]) ; CHECK-NEXT: ret void ; %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> , <2 x i32> %y) %cmp1 = icmp slt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp1) %cmp2 = icmp sle <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp2) %cmp3 = icmp sgt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp3) %cmp4 = icmp sge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp4) %cmp5 = icmp ult <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp5) %cmp6 = icmp ule <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp6) %cmp7 = icmp ugt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp7) %cmp8 = icmp uge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp8) %cmp9 = icmp eq <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp9) %cmp10 = icmp ne <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp10) ret void } ; icmp pred smin(C1, Y), C2 where (icmp pred' C1, C2) is not a constant splat for all pred' define void @unknown_smin_v2i32_constant(<2 x i32> %y) { ; CHECK-LABEL: @unknown_smin_v2i32_constant( ; CHECK-NEXT: [[COND:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[Y:%.*]], <2 x i32> ) ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP1]]) ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP2]]) ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP3]]) ; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP4]]) ; CHECK-NEXT: [[CMP5:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP5]]) ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP6]]) ; CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP7]]) ; CHECK-NEXT: [[CMP8:%.*]] = icmp ugt <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP8]]) ; CHECK-NEXT: [[CMP9:%.*]] = icmp eq <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP9]]) ; CHECK-NEXT: [[CMP10:%.*]] = icmp ne <2 x i32> [[COND]], ; CHECK-NEXT: call void @use_v2i1(<2 x i1> [[CMP10]]) ; CHECK-NEXT: ret void ; %cond = call <2 x i32> @llvm.smin.v2i32(<2 x i32> , <2 x i32> %y) %cmp1 = icmp slt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp1) %cmp2 = icmp sle <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp2) %cmp3 = icmp sgt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp3) %cmp4 = icmp sge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp4) %cmp5 = icmp ult <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp5) %cmp6 = icmp ule <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp6) %cmp7 = icmp ugt <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp7) %cmp8 = icmp uge <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp8) %cmp9 = icmp eq <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp9) %cmp10 = icmp ne <2 x i32> %cond, call void @use_v2i1(<2 x i1> %cmp10) ret void } ; Test cases from PR62898 define i1 @smin_or_bitwise(i32 %x) { ; CHECK-LABEL: @smin_or_bitwise( ; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 1) ; CHECK-NEXT: [[LOBIT:%.*]] = or i32 [[COND]], [[X]] ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i32 [[LOBIT]], 0 ; CHECK-NEXT: ret i1 [[TOBOOL]] ; %cond = tail call i32 @llvm.smin.i32(i32 %x, i32 1) %lobit = or i32 %cond, %x %tobool = icmp slt i32 %lobit, 0 ret i1 %tobool } define i1 @smin_and_bitwise(i32 %x) { ; CHECK-LABEL: @smin_and_bitwise( ; CHECK-NEXT: [[COND:%.*]] = tail call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 1) ; CHECK-NEXT: [[LOBIT:%.*]] = and i32 [[COND]], [[X]] ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i32 [[LOBIT]], 0 ; CHECK-NEXT: ret i1 [[TOBOOL]] ; %cond = tail call i32 @llvm.smin.i32(i32 %x, i32 1) %lobit = and i32 %cond, %x %tobool = icmp slt i32 %lobit, 0 ret i1 %tobool } ; try to fold icmp eq smin(X, Y), Z ; pre-condition X != Z ; X < Z fail ; swap X and Y ; pre-condition Y != Z fail ; Y < Z fail define i1 @eq_smin_nofold(i32 %x) { ; CHECK-LABEL: @eq_smin_nofold( ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X:%.*]], 5 ; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) ; CHECK-NEXT: [[MINV:%.*]] = tail call i32 @llvm.smin.i32(i32 [[X]], i32 5) ; CHECK-NEXT: [[RET:%.*]] = icmp eq i32 [[MINV]], 5 ; CHECK-NEXT: ret i1 [[RET]] ; %cond = icmp ne i32 %x, 5 call void @llvm.assume(i1 %cond) %minv = tail call i32 @llvm.smin.i32(i32 %x, i32 5) %ret = icmp eq i32 %minv, 5 ret i1 %ret } declare void @llvm.assume(i1) declare i32 @llvm.smin.i32(i32, i32) declare <2 x i32> @llvm.smin.v2i32(<2 x i32>, <2 x i32>)