Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3135,46 +3135,56 @@ isa(Op1)) { Constant *Op1C = cast(Op1); Type *Op1Type = Op1->getType(); - unsigned NumElts = Op1Type->getVectorNumElements(); + + // Check if all elements of the constant can be safely + // incremented/decremented without overflowing/underflowing. + auto allElementsValid = [](Constant *C, bool IsLT, bool IsSigned) { + unsigned NumElts = C->getType()->getVectorNumElements(); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *Elt = C->getAggregateElement(i); + if (isa(Elt)) + continue; + // Bail out if we can't determine if this constant is min/max or if we + // know that this constant is min/max. + auto *CI = dyn_cast(Elt); + if (!CI || (IsLT ? CI->isMaxValue(IsSigned) : CI->isMinValue(IsSigned))) + return false; + } + return true; + }; // Set the new comparison predicate and splat a vector of 1 or -1 to - // increment or decrement the vector constants. But first, check that no - // elements of the constant vector would overflow/underflow when we - // increment/decrement the constants. + // increment or decrement the vector constants. // // TODO? If the edge cases for vectors were guaranteed to be handled as they // are for scalar, we could remove the min/max checks here. However, to do // that, we would have to use insertelement/shufflevector to replace edge // values. - + CmpInst::Predicate NewPred; Constant *OneOrNegOne = nullptr; switch (I.getPredicate()) { case ICmpInst::ICMP_ULE: - for (unsigned i = 0; i != NumElts; ++i) - if (cast(Op1C->getAggregateElement(i))->isMaxValue(false)) - return nullptr; + if (!allElementsValid(Op1C, true, false)) + return nullptr; NewPred = ICmpInst::ICMP_ULT; OneOrNegOne = ConstantInt::get(Op1Type, 1); break; case ICmpInst::ICMP_SLE: - for (unsigned i = 0; i != NumElts; ++i) - if (cast(Op1C->getAggregateElement(i))->isMaxValue(true)) - return nullptr; + if (!allElementsValid(Op1C, true, true)) + return nullptr; NewPred = ICmpInst::ICMP_SLT; OneOrNegOne = ConstantInt::get(Op1Type, 1); break; case ICmpInst::ICMP_UGE: - for (unsigned i = 0; i != NumElts; ++i) - if (cast(Op1C->getAggregateElement(i))->isMinValue(false)) - return nullptr; + if (!allElementsValid(Op1C, false, false)) + return nullptr; NewPred = ICmpInst::ICMP_UGT; OneOrNegOne = ConstantInt::get(Op1Type, -1); break; case ICmpInst::ICMP_SGE: - for (unsigned i = 0; i != NumElts; ++i) - if (cast(Op1C->getAggregateElement(i))->isMinValue(true)) - return nullptr; + if (!allElementsValid(Op1C, false, true)) + return nullptr; NewPred = ICmpInst::ICMP_SGT; OneOrNegOne = ConstantInt::get(Op1Type, -1); break; Index: test/Transforms/InstCombine/icmp-vec.ll =================================================================== --- test/Transforms/InstCombine/icmp-vec.ll +++ test/Transforms/InstCombine/icmp-vec.ll @@ -159,3 +159,25 @@ ret <2 x i1> %cmp } +; If we can't determine if a constant element is min/max (eg, it's a ConstantExpr), do nothing. + +define <2 x i1> @PR27756_1(<2 x i8> %a) { +; CHECK-LABEL: @PR27756_1( +; CHECK-NEXT: [[CMP:%.*]] = icmp sle <2 x i8> %a, to i8), i8 0> +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %cmp = icmp sle <2 x i8> %a, to i8), i8 0> + ret <2 x i1> %cmp +} + +; Undef elements don't prevent the transform of the comparison. + +define <2 x i1> @PR27756_2(<2 x i8> %a) { +; CHECK-LABEL: @PR27756_2( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> %a, +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %cmp = icmp sle <2 x i8> %a, + ret <2 x i1> %cmp +} +