Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2662,6 +2662,51 @@ if (Instruction *I = canonicalizeScalarSelectOfVecs(SI, *this)) return I; + // If the type of select is not an integer type or if the condition and + // the selection type are not both scalar nor both vector types, there is no + // point in attempting to match these patterns. + if (!isa(CondVal) && SelType->isIntOrIntVectorTy() && + CondVal->getType()->isVectorTy() == SelType->isVectorTy()) { + auto *One = ConstantInt::get(SelType, 1); + auto *Zero = Constant::getNullValue(SelType); + auto *AllOnes = Constant::getAllOnesValue(SelType); + + // select a, a, b -> select a, 1, b + // select a, zext(a), b -> select a, 1, b + if (match(TrueVal, m_ZExtOrSelf(m_Specific(CondVal)))) + return replaceOperand(SI, 1, One); + + // select a, sext(a), b -> select a, -1, b + if (match(TrueVal, m_SExt(m_Specific(CondVal)))) + return replaceOperand(SI, 1, AllOnes); + + // select a, b, a -> select a, b, false + // select a, b, zext(a) -> select a, b, false + // select a, b, sext(a) -> select a, b, false + if (match(FalseVal, m_ZExtOrSExtOrSelf(m_Specific(CondVal)))) + return replaceOperand(SI, 2, Zero); + + Value *NotCond; + + // select a, !a, b -> select !a, b, false + // select a, sext(!a), b -> select !a, b, false + // select a, zext(!a), b -> select !a, b, false + if (match(TrueVal, m_ZExtOrSExtOrSelf(m_CombineAnd( + m_Value(NotCond), m_Not(m_Specific(CondVal)))))) + return SelectInst::Create(NotCond, FalseVal, Zero); + + // select a, b, !a -> select !a, true, b + // select a, b, zext(!a) -> select !a, true, b + if (match(FalseVal, m_ZExtOrSelf(m_CombineAnd(m_Value(NotCond), + m_Not(m_Specific(CondVal)))))) + return SelectInst::Create(NotCond, One, TrueVal); + + // select a, b, sext(!a) -> select !a, -1, b + if (match(FalseVal, m_SExt(m_CombineAnd(m_Value(NotCond), + m_Not(m_Specific(CondVal)))))) + return SelectInst::Create(NotCond, AllOnes, TrueVal); + } + // Avoid potential infinite loops by checking for non-constant condition. // TODO: Can we assert instead by improving canonicalizeSelectToShuffle()? // Scalar select must have simplified? @@ -2711,20 +2756,6 @@ return SelectInst::Create(NotCond, One, TrueVal); } - // select a, a, b -> select a, true, b - if (CondVal == TrueVal) - return replaceOperand(SI, 1, One); - // select a, b, a -> select a, b, false - if (CondVal == FalseVal) - return replaceOperand(SI, 2, Zero); - - // select a, !a, b -> select !a, b, false - if (match(TrueVal, m_Not(m_Specific(CondVal)))) - return SelectInst::Create(TrueVal, FalseVal, Zero); - // select a, b, !a -> select !a, true, b - if (match(FalseVal, m_Not(m_Specific(CondVal)))) - return SelectInst::Create(FalseVal, One, TrueVal); - Value *A, *B; // DeMorgan in select form: !a && !b --> !(a || b) Index: llvm/test/Transforms/InstCombine/select.ll =================================================================== --- llvm/test/Transforms/InstCombine/select.ll +++ llvm/test/Transforms/InstCombine/select.ll @@ -3210,3 +3210,120 @@ declare void @use_i8(i8) declare void @use_i32(i32) declare i32 @llvm.cttz.i32(i32, i1 immarg) + +define i32 @select_cond_zext_cond(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_zext_cond( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 1, i32 [[B:%.*]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %zext = zext i1 %cond to i32 + %sel = select i1 %cond, i32 %zext, i32 %b + ret i32 %sel +} + +define <2 x i32> @select_cond_zext_cond_vec(<2 x i1> %cond, <2 x i32> %b) { +; CHECK-LABEL: @select_cond_zext_cond_vec( +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> , <2 x i32> [[B:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SEL]] +; + %zext = zext <2 x i1> %cond to <2 x i32> + %sel = select <2 x i1> %cond, <2 x i32> %zext, <2 x i32> %b + ret <2 x i32> %sel +} + +define i32 @select_cond_sext_cond(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_sext_cond( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 -1, i32 [[B:%.*]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %sext = sext i1 %cond to i32 + %sel = select i1 %cond, i32 %sext, i32 %b + ret i32 %sel +} + +define <2 x i32> @select_cond_sext_cond_vec(<2 x i1> %cond, <2 x i32> %b) { +; CHECK-LABEL: @select_cond_sext_cond_vec( +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> , <2 x i32> [[B:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SEL]] +; + %sext = sext <2 x i1> %cond to <2 x i32> + %sel = select <2 x i1> %cond, <2 x i32> %sext, <2 x i32> %b + ret <2 x i32> %sel +} + +define i32 @select_cond_val_zext_cond(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_val_zext_cond( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 0 +; CHECK-NEXT: ret i32 [[SEL]] +; + %zext = zext i1 %cond to i32 + %sel = select i1 %cond, i32 %b, i32 %zext + ret i32 %sel +} + +define <2 x i32> @select_cond_val_zext_cond_vec(<2 x i1> %cond, <2 x i32> %b) { +; CHECK-LABEL: @select_cond_val_zext_cond_vec( +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> [[B:%.*]], <2 x i32> zeroinitializer +; CHECK-NEXT: ret <2 x i32> [[SEL]] +; + %zext = zext <2 x i1> %cond to <2 x i32> + %sel = select <2 x i1> %cond, <2 x i32> %b, <2 x i32> %zext + ret <2 x i32> %sel +} + +define i32 @select_cond_val_sext_cond(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_val_sext_cond( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 0 +; CHECK-NEXT: ret i32 [[SEL]] +; + %sext = sext i1 %cond to i32 + %sel = select i1 %cond, i32 %b, i32 %sext + ret i32 %sel +} + +define i32 @select_cond_zext_not_cond_val(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_zext_not_cond_val( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 0, i32 [[B:%.*]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_cond = xor i1 %cond, true + %zext = zext i1 %not_cond to i32 + %sel = select i1 %cond, i32 %zext, i32 %b + ret i32 %sel +} + +define i32 @select_cond_sext_not_cond_val(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_sext_not_cond_val( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 0, i32 [[B:%.*]] +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_cond = xor i1 %cond, true + %sext = sext i1 %not_cond to i32 + %sel = select i1 %cond, i32 %sext, i32 %b + ret i32 %sel +} + + +define i32 @select_cond_val_zext_not_cond(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_val_zext_not_cond( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 1 +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_cond = xor i1 %cond, true + %zext = zext i1 %not_cond to i32 + %sel = select i1 %cond, i32 %b, i32 %zext + ret i32 %sel +} + +define i32 @select_cond_val_sext_not_cond(i1 %cond, i32 %b) { +; CHECK-LABEL: @select_cond_val_sext_not_cond( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i32 [[B:%.*]], i32 -1 +; CHECK-NEXT: ret i32 [[SEL]] +; + %not_cond = xor i1 %cond, true + %sext = sext i1 %not_cond to i32 + %sel = select i1 %cond, i32 %b, i32 %sext + ret i32 %sel +} + +