Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1698,6 +1698,86 @@ return nullptr; } +/// canonicalize all variants of strong order compare to (a > b) - (a < b) +static Instruction * +canonicalizeStrongOrderCmp(ICmpInst *ICI, Value *TrueVal, Value *FalseVal, + InstCombiner::BuilderTy &Builder) { + if (!isa(TrueVal)) + return nullptr; + + Type *Ty = TrueVal->getType(); + ICmpInst::Predicate Pred = ICI->getPredicate(); + Value *CmpLHS = ICI->getOperand(0); + Value *CmpRHS = ICI->getOperand(1); + Value *ICI2; + ICmpInst::Predicate Pred2; + Constant *InnerTC, *InnerFC; + auto SwapICmp = [&Builder, CmpLHS, CmpRHS](ICmpInst::Predicate Pred) { + return Builder.CreateICmp(ICmpInst::getSwappedPredicate(Pred), CmpLHS, + CmpRHS); + }; + + if (FalseVal->hasOneUse() && + match(FalseVal, m_Select(m_Value(ICI2), m_ImmConstant(InnerTC), + m_ImmConstant(InnerFC))) && + match(ICI2, m_ICmp(Pred2, m_Specific(CmpLHS), m_Specific(CmpRHS)))) { + if (Pred == ICmpInst::ICMP_EQ && match(TrueVal, m_Zero()) && + ICI->hasOneUse()) { + // A == B ? 0 : (A < B ? -1 : 1) --> (a > b) - (a < b) + if (match(InnerTC, m_AllOnes()) && match(InnerFC, m_One()) && + (Pred2 == ICmpInst::ICMP_SLT || Pred2 == ICmpInst::ICMP_ULT)) { + Value *ZExt = Builder.CreateZExt(SwapICmp(Pred2), Ty); + Value *SExt = Builder.CreateSExt(ICI2, Ty); + return BinaryOperator::CreateAdd(ZExt, SExt); + } + // A == B ? 0 : (A > B ? 1 : -1) --> (a > b) - (a < b) + if (match(InnerTC, m_One()) && match(InnerFC, m_AllOnes()) && + (Pred2 == ICmpInst::ICMP_SGT || Pred2 == ICmpInst::ICMP_UGT)) { + Value *ZExt = Builder.CreateZExt(ICI2, Ty); + Value *SExt = Builder.CreateSExt(SwapICmp(Pred2), Ty); + return BinaryOperator::CreateAdd(ZExt, SExt); + } + } + } + + if (match(TrueVal, m_AllOnes()) && match(FalseVal, m_ZExt(m_Value(ICI2))) && + match(ICI2, m_ICmp(Pred2, m_Specific(CmpLHS), m_Specific(CmpRHS))) && + (Pred2 != ICmpInst::ICMP_NE || + (FalseVal->hasOneUse() && ICI2->hasOneUse()))) { + // A < B ? -1 : zext (A > B) --> (a > b) - (a < b) + // A < B ? -1 : zext (A != B) --> (a > b) - (a < b) + if ((Pred == ICmpInst::ICMP_SLT && + (Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_SGT)) || + (Pred == ICmpInst::ICMP_ULT && + (Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_UGT))) { + Value *ZExt = FalseVal; + if (Pred2 == ICmpInst::ICMP_NE) + ZExt = Builder.CreateZExt(SwapICmp(Pred), Ty); + Value *SExt = Builder.CreateSExt(ICI, Ty); + return BinaryOperator::CreateAdd(ZExt, SExt); + } + } + + if (match(TrueVal, m_One()) && match(FalseVal, m_SExt(m_Value(ICI2))) && + match(ICI2, m_ICmp(Pred2, m_Specific(CmpLHS), m_Specific(CmpRHS))) && + (Pred2 != ICmpInst::ICMP_NE || + (FalseVal->hasOneUse() && ICI2->hasOneUse()))) { + // A > B ? 1 : sext (A < B) --> (a > b) - (a < b) + // A > B ? 1 : sext (A != B) --> (a > b) - (a < b) + if ((Pred == ICmpInst::ICMP_SGT && + (Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_SLT)) || + (Pred == ICmpInst::ICMP_UGT && + (Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_ULT))) { + Value *ZExt = Builder.CreateZExt(ICI, Ty); + Value *SExt = FalseVal; + if (Pred2 == ICmpInst::ICMP_NE) + SExt = Builder.CreateSExt(SwapICmp(Pred), Ty); + return BinaryOperator::CreateAdd(ZExt, SExt); + } + } + return nullptr; +} + /// Visit a SelectInst that has an ICmpInst as its first operand. Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI) { @@ -1740,6 +1820,10 @@ } } + if (Instruction *V = + canonicalizeStrongOrderCmp(ICI, TrueVal, FalseVal, Builder)) + return V; + // Canonicalize a signbit condition to use zero constant by swapping: // (CmpLHS > -1) ? TV : FV --> (CmpLHS < 0) ? FV : TV // To avoid conflicts (infinite loops) with other canonicalizations, this is Index: llvm/test/Transforms/InstCombine/select-select.ll =================================================================== --- llvm/test/Transforms/InstCombine/select-select.ll +++ llvm/test/Transforms/InstCombine/select-select.ll @@ -179,9 +179,10 @@ define i8 @strong_order_cmp_slt_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_slt_eq( ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_LT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i8 +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_EQ:%.*]] = add nsw i8 [[TMP2]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.lt = icmp slt i32 %a, %b @@ -194,9 +195,10 @@ define i8 @strong_order_cmp_ult_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_ult_eq( ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_LT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i8 +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_EQ:%.*]] = add nsw i8 [[TMP2]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.lt = icmp ult i32 %a, %b @@ -206,6 +208,8 @@ ret i8 %sel.eq } +; negative test: wrong constant, should be -1 for first select true value. + define i8 @strong_order_cmp_slt_eq_wrong_const(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_slt_eq_wrong_const( ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] @@ -221,6 +225,8 @@ ret i8 %sel.eq } +; negative test: wrong constant, should be 1 for first select false value. + define i8 @strong_order_cmp_ult_eq_wrong_const(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_ult_eq_wrong_const( ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] @@ -236,6 +242,8 @@ ret i8 %sel.eq } +; negative test: wrong predicate, should be eq. + define i8 @strong_order_cmp_slt_ult_wrong_pred(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_slt_ult_wrong_pred( ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] @@ -254,9 +262,10 @@ define i8 @strong_order_cmp_sgt_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_sgt_eq( ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 -1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_GT]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP_GT]] to i8 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[TMP2]] to i8 +; CHECK-NEXT: [[SEL_EQ:%.*]] = add nsw i8 [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.gt = icmp sgt i32 %a, %b @@ -269,9 +278,10 @@ define i8 @strong_order_cmp_ugt_eq(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_ugt_eq( ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 -1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_GT]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP_GT]] to i8 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[TMP2]] to i8 +; CHECK-NEXT: [[SEL_EQ:%.*]] = add nsw i8 [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.gt = icmp ugt i32 %a, %b @@ -283,10 +293,11 @@ define i8 @strong_order_cmp_eq_slt(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_eq_slt( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = zext i1 [[CMP_EQ]] to i8 -; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 [[SEL_EQ]] +; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i8 +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_LT:%.*]] = add nsw i8 [[TMP2]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_LT]] ; %cmp.eq = icmp eq i32 %a, %b @@ -298,10 +309,11 @@ define i8 @strong_order_cmp_eq_sgt(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_eq_sgt( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = sext i1 [[CMP_EQ]] to i8 -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 [[SEL_EQ]] +; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP_GT]] to i8 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[TMP2]] to i8 +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw i8 [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_GT]] ; %cmp.eq = icmp eq i32 %a, %b @@ -313,10 +325,11 @@ define i8 @strong_order_cmp_eq_ult(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_eq_ult( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = zext i1 [[CMP_EQ]] to i8 -; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 [[SEL_EQ]] +; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i8 +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_LT:%.*]] = add nsw i8 [[TMP2]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_LT]] ; %cmp.eq = icmp eq i32 %a, %b @@ -328,10 +341,11 @@ define i8 @strong_order_cmp_eq_ugt(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_eq_ugt( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = sext i1 [[CMP_EQ]] to i8 -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 [[SEL_EQ]] +; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP_GT]] to i8 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[TMP2]] to i8 +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw i8 [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_GT]] ; %cmp.eq = icmp eq i32 %a, %b @@ -346,7 +360,8 @@ ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[CMP_LT]] to i8 ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 [[SEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP_GT]] to i8 +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw i8 [[TMP1]], [[SEXT]] ; CHECK-NEXT: ret i8 [[SEL_GT]] ; %cmp.lt = icmp slt i32 %a, %b @@ -361,7 +376,8 @@ ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[CMP_LT]] to i8 ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 [[SEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP_GT]] to i8 +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw i8 [[TMP1]], [[SEXT]] ; CHECK-NEXT: ret i8 [[SEL_GT]] ; %cmp.lt = icmp ult i32 %a, %b @@ -376,7 +392,8 @@ ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP_GT]] to i8 ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 [[ZEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_LT:%.*]] = add nsw i8 [[ZEXT]], [[TMP1]] ; CHECK-NEXT: ret i8 [[SEL_LT]] ; %cmp.gt = icmp sgt i32 %a, %b @@ -391,7 +408,8 @@ ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP_GT]] to i8 ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 [[ZEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_LT:%.*]] = add nsw i8 [[ZEXT]], [[TMP1]] ; CHECK-NEXT: ret i8 [[SEL_LT]] ; %cmp.gt = icmp ugt i32 %a, %b @@ -401,6 +419,8 @@ ret i8 %sel.lt } +; negative test: icmp with ne must be one-use. + define i8 @strong_order_cmp_ne_ugt_ne_not_one_use(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_ne_ugt_ne_not_one_use( ; CHECK-NEXT: [[CMP_NE:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] @@ -422,9 +442,10 @@ ; CHECK-LABEL: @strong_order_cmp_slt_eq_slt_not_oneuse( ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: call void @use1(i1 [[CMP_LT]]) -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 1 -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = select i1 [[CMP_EQ]], i8 0, i8 [[SEL_LT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i8 +; CHECK-NEXT: [[TMP3:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_EQ:%.*]] = add nsw i8 [[TMP2]], [[TMP3]] ; CHECK-NEXT: ret i8 [[SEL_EQ]] ; %cmp.lt = icmp slt i32 %a, %b @@ -435,6 +456,8 @@ ret i8 %sel.eq } +; negative test: icmp with eq predicate must be one use. + define i8 @strong_order_cmp_sgt_eq_eq_not_oneuse(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_sgt_eq_eq_not_oneuse( ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] @@ -452,6 +475,8 @@ ret i8 %sel.eq } +; negative test: icmp with eq predicate must be one use. + define i8 @strong_order_cmp_eq_ugt_eq_not_oneuse(i32 %a, i32 %b) { ; CHECK-LABEL: @strong_order_cmp_eq_ugt_eq_not_oneuse( ; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] @@ -476,7 +501,8 @@ ; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP_GT]] to i8 ; CHECK-NEXT: call void @use8(i8 [[ZEXT]]) ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select i1 [[CMP_LT]], i8 -1, i8 [[ZEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = sext i1 [[CMP_LT]] to i8 +; CHECK-NEXT: [[SEL_LT:%.*]] = add nsw i8 [[ZEXT]], [[TMP1]] ; CHECK-NEXT: ret i8 [[SEL_LT]] ; %cmp.gt = icmp ugt i32 %a, %b @@ -493,7 +519,8 @@ ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[CMP_LT]] to i8 ; CHECK-NEXT: call void @use8(i8 [[SEXT]]) ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp sgt i32 [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select i1 [[CMP_GT]], i8 1, i8 [[SEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[CMP_GT]] to i8 +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw i8 [[TMP1]], [[SEXT]] ; CHECK-NEXT: ret i8 [[SEL_GT]] ; %cmp.lt = icmp slt i32 %a, %b @@ -509,7 +536,8 @@ ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i1> [[CMP_GT]] to <2 x i8> ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult <2 x i32> [[A]], [[B]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select <2 x i1> [[CMP_LT]], <2 x i8> , <2 x i8> [[ZEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i1> [[CMP_LT]] to <2 x i8> +; CHECK-NEXT: [[SEL_LT:%.*]] = add nsw <2 x i8> [[ZEXT]], [[TMP1]] ; CHECK-NEXT: ret <2 x i8> [[SEL_LT]] ; %cmp.gt = icmp ugt <2 x i32> %a, %b @@ -524,7 +552,8 @@ ; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i1> [[CMP_GT]] to <2 x i8> ; CHECK-NEXT: [[CMP_LT:%.*]] = icmp ult <2 x i32> [[A]], [[B]] -; CHECK-NEXT: [[SEL_LT:%.*]] = select <2 x i1> [[CMP_LT]], <2 x i8> , <2 x i8> [[ZEXT]] +; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i1> [[CMP_LT]] to <2 x i8> +; CHECK-NEXT: [[SEL_LT:%.*]] = add nsw <2 x i8> [[ZEXT]], [[TMP1]] ; CHECK-NEXT: ret <2 x i8> [[SEL_LT]] ; %cmp.gt = icmp ugt <2 x i32> %a, %b @@ -536,10 +565,11 @@ define <2 x i8> @strong_order_cmp_eq_ugt_vector(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @strong_order_cmp_eq_ugt_vector( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne <2 x i32> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = sext <2 x i1> [[CMP_EQ]] to <2 x i8> -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select <2 x i1> [[CMP_GT]], <2 x i8> , <2 x i8> [[SEL_EQ]] +; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> [[CMP_GT]] to <2 x i8> +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i32> [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i8> +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw <2 x i8> [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret <2 x i8> [[SEL_GT]] ; %cmp.eq = icmp eq <2 x i32> %a, %b @@ -551,10 +581,11 @@ define <2 x i8> @strong_order_cmp_eq_ugt_vector_poison1(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @strong_order_cmp_eq_ugt_vector_poison1( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne <2 x i32> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = sext <2 x i1> [[CMP_EQ]] to <2 x i8> -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select <2 x i1> [[CMP_GT]], <2 x i8> , <2 x i8> [[SEL_EQ]] +; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> [[CMP_GT]] to <2 x i8> +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i32> [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i8> +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw <2 x i8> [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret <2 x i8> [[SEL_GT]] ; %cmp.eq = icmp eq <2 x i32> %a, %b @@ -566,10 +597,11 @@ define <2 x i8> @strong_order_cmp_eq_ugt_vector_poison2(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @strong_order_cmp_eq_ugt_vector_poison2( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne <2 x i32> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = sext <2 x i1> [[CMP_EQ]] to <2 x i8> -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select <2 x i1> [[CMP_GT]], <2 x i8> , <2 x i8> [[SEL_EQ]] +; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> [[CMP_GT]] to <2 x i8> +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i32> [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i8> +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw <2 x i8> [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret <2 x i8> [[SEL_GT]] ; %cmp.eq = icmp eq <2 x i32> %a, %b @@ -581,10 +613,11 @@ define <2 x i8> @strong_order_cmp_eq_ugt_vector_poison3(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @strong_order_cmp_eq_ugt_vector_poison3( -; CHECK-NEXT: [[CMP_EQ:%.*]] = icmp ne <2 x i32> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[SEL_EQ:%.*]] = sext <2 x i1> [[CMP_EQ]] to <2 x i8> -; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A]], [[B]] -; CHECK-NEXT: [[SEL_GT:%.*]] = select <2 x i1> [[CMP_GT]], <2 x i8> , <2 x i8> [[SEL_EQ]] +; CHECK-NEXT: [[CMP_GT:%.*]] = icmp ugt <2 x i32> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> [[CMP_GT]] to <2 x i8> +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i32> [[A]], [[B]] +; CHECK-NEXT: [[TMP3:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i8> +; CHECK-NEXT: [[SEL_GT:%.*]] = add nsw <2 x i8> [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret <2 x i8> [[SEL_GT]] ; %cmp.eq = icmp eq <2 x i32> %a, %b