diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2023,6 +2023,42 @@ (Mul->hasNoUnsignedWrap() || Mul->hasNoSignedWrap())) return new ICmpInst(Pred, X, ConstantInt::getNullValue(MulTy)); + { + BinaryOperator *InnerMul; + Value *X, *Y; + const APInt *MulC; + // icmp((MulC * X) * Y, C) --> icmp(X * Y, C) + if (match(Mul, m_c_Mul(m_BinOp(InnerMul), m_Value(Y))) && + match(InnerMul, m_c_Mul(m_APInt(MulC), m_Value(X)))) { + if (Mul->hasNoSignedWrap() && InnerMul->hasNoSignedWrap() && + MulC->isStrictlyPositive()) { + Value *NewMul = Builder.CreateMul(X, Y, "mul", /*HasNUW=*/false, + /*HasNSW*/ true); + // MulC * X * Y s= 1 --> X * Y s= 1 + if (C.isOne() && + (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE)) + return new ICmpInst(Pred, NewMul, ConstantInt::get(MulTy, C)); + // MulC * X * Y s>/s<= -1 --> X * Y s>/s<= -1 + if (C.isAllOnes() && + (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE)) + return new ICmpInst(Pred, NewMul, ConstantInt::get(MulTy, C)); + // icmp(MulC * X * Y, 0) --> icmp(X * Y, 0) + if (C.isZero()) { + switch (Pred) { + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SGE: + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SLE: + return new ICmpInst(Pred, NewMul, ConstantInt::get(MulTy, C)); + break; + default: + break; + } + } + } + } + } + const APInt *MulC; if (!match(Mul->getOperand(1), m_APInt(MulC))) return nullptr; diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -4968,9 +4968,8 @@ define i1 @mul_mul_sge_zero(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_sge_zero( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL2]], -1 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL1]], -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -4981,9 +4980,8 @@ define <2 x i1> @mul_mul_sge_zero_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_sge_zero_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL2]], +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL1]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a, @@ -4994,9 +4992,8 @@ define i1 @mul_mul_sge_one(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_sge_one( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL2]], 0 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL1]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -5007,9 +5004,8 @@ define <2 x i1> @mul_mul_sge_one_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_sge_one_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL2]], zeroinitializer +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a, @@ -5020,9 +5016,8 @@ define i1 @mul_mul_slt_zero(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_slt_zero( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL2]], 0 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL1]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -5033,9 +5028,8 @@ define <2 x i1> @mul_mul_slt_zero_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_slt_zero_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL2]], zeroinitializer +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a, @@ -5046,9 +5040,8 @@ define i1 @mul_mul_slt_one(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_slt_one( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL2]], 1 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL1]], 1 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -5059,9 +5052,8 @@ define <2 x i1> @mul_mul_slt_one_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_slt_one_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL2]], +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL1]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a, @@ -5072,9 +5064,8 @@ define i1 @mul_mul_sle_zero(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_sle_zero( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL2]], 1 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL1]], 1 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -5085,9 +5076,8 @@ define <2 x i1> @mul_mul_sle_zero_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_sle_zero_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL2]], +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL1]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a, @@ -5098,9 +5088,8 @@ define i1 @mul_mul_sle_negone(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_sle_negone( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL2]], 0 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[MUL1]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -5111,9 +5100,8 @@ define <2 x i1> @mul_mul_sle_negone_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_sle_negone_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL2]], zeroinitializer +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[MUL1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a, @@ -5124,9 +5112,8 @@ define i1 @mul_mul_sgt_zero(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_sgt_zero( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL2]], 0 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL1]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -5137,9 +5124,8 @@ define <2 x i1> @mul_mul_sgt_zero_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_sgt_zero_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL2]], zeroinitializer +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a, @@ -5150,9 +5136,8 @@ define i1 @mul_mul_sgt_negone(i8 %a, i8 %b) { ; CHECK-LABEL: @mul_mul_sgt_negone( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42 -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL2]], -1 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL1]], -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %mul = mul nsw i8 %a, 42 @@ -5163,9 +5148,8 @@ define <2 x i1> @mul_mul_sgt_negone_vec(<2 x i8> %a, <2 x i8> %b) { ; CHECK-LABEL: @mul_mul_sgt_negone_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL2]], +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw <2 x i8> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[MUL1]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul nsw <2 x i8> %a,