Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -316,22 +316,29 @@ Value *OtherOpT, *OtherOpF; bool MatchIsOpZero; - auto getCommonOp = [&](Instruction *TI, Instruction *FI, - bool Commute) -> Value * { + auto getCommonOp = [&](Instruction *TI, Instruction *FI, bool Commute, + bool Swapped = false) -> Value * { + assert(!(Commute && Swapped) && + "Commute and Swapped can't set at the same time"); Value *CommonOp = nullptr; - if (TI->getOperand(0) == FI->getOperand(0)) { - CommonOp = TI->getOperand(0); - OtherOpT = TI->getOperand(1); - OtherOpF = FI->getOperand(1); - MatchIsOpZero = true; - } else if (TI->getOperand(1) == FI->getOperand(1)) { - CommonOp = TI->getOperand(1); - OtherOpT = TI->getOperand(0); - OtherOpF = FI->getOperand(0); - MatchIsOpZero = false; - } else if (!Commute) { + if (!Swapped) { + if (TI->getOperand(0) == FI->getOperand(0)) { + CommonOp = TI->getOperand(0); + OtherOpT = TI->getOperand(1); + OtherOpF = FI->getOperand(1); + MatchIsOpZero = true; + } else if (TI->getOperand(1) == FI->getOperand(1)) { + CommonOp = TI->getOperand(1); + OtherOpT = TI->getOperand(0); + OtherOpF = FI->getOperand(0); + MatchIsOpZero = false; + } + } + + if (!Commute && !Swapped) return nullptr; - } else if (TI->getOperand(0) == FI->getOperand(1)) { + + if (TI->getOperand(0) == FI->getOperand(1)) { CommonOp = TI->getOperand(0); OtherOpT = TI->getOperand(1); OtherOpF = FI->getOperand(0); @@ -340,7 +347,7 @@ CommonOp = TI->getOperand(1); OtherOpT = TI->getOperand(0); OtherOpF = FI->getOperand(1); - MatchIsOpZero = true; + MatchIsOpZero = false; } return CommonOp; }; @@ -379,16 +386,17 @@ } } - // icmp eq/ne with a common operand also can have the common operand + // icmp with a common operand also can have the common operand // pulled after the select. ICmpInst::Predicate TPred, FPred; if (match(TI, m_ICmp(TPred, m_Value(), m_Value())) && match(FI, m_ICmp(FPred, m_Value(), m_Value()))) { - if (TPred == FPred && ICmpInst::isEquality(TPred)) { - if (Value *MatchOp = getCommonOp(TI, FI, true)) { + if (TPred == FPred || TPred == CmpInst::getSwappedPredicate(FPred)) { + bool Swapped = TPred != FPred; + if (Value *MatchOp = getCommonOp(TI, FI, !Swapped, Swapped)) { Value *NewSel = Builder.CreateSelect(Cond, OtherOpT, OtherOpF, SI.getName() + ".v", &SI); - return new ICmpInst(TPred, NewSel, MatchOp); + return new ICmpInst(MatchIsOpZero ? TPred : FPred, MatchOp, NewSel); } } } Index: llvm/test/Transforms/InstCombine/select-cmp.ll =================================================================== --- llvm/test/Transforms/InstCombine/select-cmp.ll +++ llvm/test/Transforms/InstCombine/select-cmp.ll @@ -122,13 +122,106 @@ ret i1 %r } -; negative test: pred is not eq/ne +define i1 @icmp_slt_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_slt_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp slt i6 %x, %y + %cmp2 = icmp slt i6 %x, %z + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} -define i1 @icmp_common_pred_not_eqne(i1 %c, i8 %x, i8 %y, i8 %z) { -; CHECK-LABEL: @icmp_common_pred_not_eqne( -; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 [[Z:%.*]], [[X]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[CMP1]], i1 [[CMP2]] +define i1 @icmp_sgt_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_sgt_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp sgt i6 %x, %y + %cmp2 = icmp sgt i6 %x, %z + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_sle_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_sle_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sge i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp sle i6 %y, %x + %cmp2 = icmp sle i6 %z, %x + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_sge_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_sge_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sle i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp sge i6 %y, %x + %cmp2 = icmp sge i6 %z, %x + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_slt_sgt_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_slt_sgt_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp slt i6 %x, %y + %cmp2 = icmp sgt i6 %z, %x + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_sle_sge_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_sle_sge_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sle i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp sle i6 %y, %x + %cmp2 = icmp sge i6 %x, %z + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_ult_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_ult_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp ult i6 %x, %y + %cmp2 = icmp ult i6 %x, %z + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_ule_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_ule_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp uge i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp ule i6 %y, %x + %cmp2 = icmp ule i6 %z, %x + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_ugt_common(i1 %c, i8 %x, i8 %y, i8 %z) { +; CHECK-LABEL: @icmp_ugt_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[R_V]], [[X:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %cmp1 = icmp ugt i8 %y, %x @@ -137,6 +230,43 @@ ret i1 %r } + +define i1 @icmp_uge_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_uge_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp uge i6 %y, %x + %cmp2 = icmp uge i6 %z, %x + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_ult_ugt_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_ult_ugt_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp ult i6 %x, %y + %cmp2 = icmp ugt i6 %z, %x + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + +define i1 @icmp_ule_uge_common(i1 %c, i6 %x, i6 %y, i6 %z) { +; CHECK-LABEL: @icmp_ule_uge_common( +; CHECK-NEXT: [[R_V:%.*]] = select i1 [[C:%.*]], i6 [[Y:%.*]], i6 [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i6 [[R_V]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp ule i6 %y, %x + %cmp2 = icmp uge i6 %x, %z + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + ; negative test: pred is not the same define i1 @icmp_common_pred_different(i1 %c, i8 %x, i8 %y, i8 %z) { @@ -152,6 +282,21 @@ ret i1 %r } +; negative test: two pred is not swap + +define i1 @icmp_common_pred_not_swap(i1 %c, i8 %x, i8 %y, i8 %z) { +; CHECK-LABEL: @icmp_common_pred_not_swap( +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i8 [[Z:%.*]], [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[CMP1]], i1 [[CMP2]] +; CHECK-NEXT: ret i1 [[R]] +; + %cmp1 = icmp slt i8 %y, %x + %cmp2 = icmp sle i8 %z, %x + %r = select i1 %c, i1 %cmp1, i1 %cmp2 + ret i1 %r +} + ; negative test: both icmp is not one-use define i1 @icmp_common_one_use_0(i1 %c, i8 %x, i8 %y, i8 %z) {