diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index fed21db393ed2..e31af8104e147 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -5337,6 +5337,15 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I, return new ICmpInst(Pred, X, Y); if (ZKnown.isNegative()) return new ICmpInst(ICmpInst::getSwappedPredicate(Pred), X, Y); + Value *LessThan = simplifyICmpInst(ICmpInst::ICMP_SLT, X, Y, + SQ.getWithInstruction(&I)); + if (LessThan && match(LessThan, m_One())) + return new ICmpInst(ICmpInst::getSwappedPredicate(Pred), Z, + Constant::getNullValue(Z->getType())); + Value *GreaterThan = simplifyICmpInst(ICmpInst::ICMP_SGT, X, Y, + SQ.getWithInstruction(&I)); + if (GreaterThan && match(GreaterThan, m_One())) + return new ICmpInst(Pred, Z, Constant::getNullValue(Z->getType())); } } else { bool NonZero; diff --git a/llvm/test/Transforms/InstCombine/icmp-mul.ll b/llvm/test/Transforms/InstCombine/icmp-mul.ll index c9f9b6d809e8a..49e1e11fe6c36 100644 --- a/llvm/test/Transforms/InstCombine/icmp-mul.ll +++ b/llvm/test/Transforms/InstCombine/icmp-mul.ll @@ -1464,3 +1464,107 @@ entry: %cmp = icmp slt i8 %mul1, %mul2 ret i1 %cmp } + +define i1 @test_icmp_slt_mul_known_sgt(i64 %x, i64 %z) { +; CHECK-LABEL: @test_icmp_slt_mul_known_sgt( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %y = add nsw i64 %x, 1 + %mul1 = mul nsw i64 %x, %z + %mul2 = mul nsw i64 %y, %z + %cmp = icmp slt i64 %mul1, %mul2 + ret i1 %cmp +} + +define i1 @test_icmp_sle_mul_known_sgt(i64 %x, i64 %z) { +; CHECK-LABEL: @test_icmp_sle_mul_known_sgt( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %y = add nsw i64 %x, 1 + %mul1 = mul nsw i64 %x, %z + %mul2 = mul nsw i64 %y, %z + %cmp = icmp sle i64 %mul1, %mul2 + ret i1 %cmp +} + +define i1 @test_icmp_mul_known_slt(i64 %x, i64 %z) { +; CHECK-LABEL: @test_icmp_mul_known_slt( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[Z:%.*]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %y = add nsw i64 %x, 1 + %mul1 = mul nsw i64 %x, %z + %mul2 = mul nsw i64 %y, %z + %cmp = icmp slt i64 %mul2, %mul1 + ret i1 %cmp +} + +define i1 @test_icmp_slt_mul_known_sgt_commuted1(i64 %x, i64 %z) { +; CHECK-LABEL: @test_icmp_slt_mul_known_sgt_commuted1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %y = add nsw i64 %x, 1 + %mul1 = mul nsw i64 %z, %x + %mul2 = mul nsw i64 %y, %z + %cmp = icmp slt i64 %mul1, %mul2 + ret i1 %cmp +} + +define i1 @test_icmp_slt_mul_known_sgt_commuted2(i64 %x, i64 %z) { +; CHECK-LABEL: @test_icmp_slt_mul_known_sgt_commuted2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %y = add nsw i64 %x, 1 + %mul1 = mul nsw i64 %x, %z + %mul2 = mul nsw i64 %z, %y + %cmp = icmp slt i64 %mul1, %mul2 + ret i1 %cmp +} + +define i1 @test_icmp_slt_mul_unknown(i64 %x, i64 %z) { +; CHECK-LABEL: @test_icmp_slt_mul_unknown( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[Y:%.*]] = add i64 [[X:%.*]], 1 +; CHECK-NEXT: [[MUL1:%.*]] = mul nsw i64 [[X]], [[Z:%.*]] +; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i64 [[Z]], [[Y]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[MUL1]], [[MUL2]] +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %y = add i64 %x, 1 + %mul1 = mul nsw i64 %x, %z + %mul2 = mul nsw i64 %z, %y + %cmp = icmp slt i64 %mul1, %mul2 + ret i1 %cmp +} + +define i1 @test_icmp_slt_mul_no_nsw(i64 %x, i64 %z) { +; CHECK-LABEL: @test_icmp_slt_mul_no_nsw( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[Y:%.*]] = add nsw i64 [[X:%.*]], 1 +; CHECK-NEXT: [[MUL1:%.*]] = mul i64 [[X]], [[Z:%.*]] +; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i64 [[Z]], [[Y]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[MUL1]], [[MUL2]] +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %y = add nsw i64 %x, 1 + %mul1 = mul i64 %x, %z + %mul2 = mul nsw i64 %z, %y + %cmp = icmp slt i64 %mul1, %mul2 + ret i1 %cmp +}