[llvm] [InstCombine] Simplify fractions when there is no overflow (PR #92949)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 21 17:13:51 PDT 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/92949
>From 12efc104f971bf5781310a47ecc94b7727710daf Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 21 May 2024 14:09:05 -0400
Subject: [PATCH] [InstCombine] Simplify fractions when there is no overlap
https://alive2.llvm.org/ce/z/-36zkQ
---
.../InstCombine/InstCombineMulDivRem.cpp | 39 +++++++++++++
llvm/test/Transforms/InstCombine/div.ll | 58 ++++++++++++++++++-
2 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index ca1b1921404d8..4d554f21d77e3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1176,6 +1176,45 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
return Mul;
}
+
+ // We can reduce expressions of things like * 150 / 100 to * 3 / 2
+ if (Op0->hasOneUse() && !C2->isZero() &&
+ !(IsSigned && C1->isMinSignedValue() && C2->isAllOnes())) {
+ assert(!C2->isMinSignedValue() &&
+ "This should have been folded away by InstSimplify");
+ APInt GCD = APIntOps::GreatestCommonDivisor(C1->abs(), C2->abs());
+ if (!GCD.isOne() && !GCD.isZero()) {
+ APInt NewC1;
+ APInt NewC2;
+ if (IsSigned && C1->isNegative() && C2->isNegative()) {
+ NewC1 = C1->abs().udiv(GCD);
+ NewC2 = C2->abs().udiv(GCD);
+ } else if (IsSigned) {
+ NewC1 = C1->sdiv(GCD);
+ NewC2 = C2->sdiv(GCD);
+ } else {
+ NewC1 = C1->udiv(GCD);
+ NewC2 = C2->udiv(GCD);
+ }
+
+ auto *NewMul = Builder.CreateMul(
+ X, ConstantInt::get(Ty, NewC1), "",
+ /*NUW*/ cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap(),
+ /*NSW*/ true);
+
+ if (IsSigned) {
+ auto *NewDiv =
+ BinaryOperator::CreateSDiv(NewMul, ConstantInt::get(Ty, NewC2));
+ NewDiv->setIsExact(I.isExact());
+ return NewDiv;
+ }
+
+ auto *NewDiv =
+ BinaryOperator::CreateUDiv(NewMul, ConstantInt::get(Ty, NewC2));
+ NewDiv->setIsExact(I.isExact());
+ return NewDiv;
+ }
+ }
}
if ((IsSigned && match(Op0, m_NSWShl(m_Value(X), m_APInt(C1))) &&
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index e8a25ff44d029..2c97602e51b92 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -390,7 +390,7 @@ define i32 @test27(i32 %a) {
define i32 @test28(i32 %a) {
; CHECK-LABEL: @test28(
-; CHECK-NEXT: [[DIV:%.*]] = mul nuw i32 [[A:%.*]], 12
+; CHECK-NEXT: [[DIV:%.*]] = mul nuw nsw i32 [[A:%.*]], 12
; CHECK-NEXT: ret i32 [[DIV]]
;
%mul = mul nuw i32 %a, 36
@@ -1678,6 +1678,62 @@ define i32 @sdiv_sdiv_mul_nsw_exact_use(i32 %x, i32 %y, i32 %z) {
ret i32 %r
}
+define i32 @x_times_150_over_100(i32 %x) {
+; CHECK-LABEL: @x_times_150_over_100(
+; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i32 [[X:%.*]], 3
+; CHECK-NEXT: [[D1:%.*]] = lshr i32 [[TMP1]], 1
+; CHECK-NEXT: ret i32 [[D1]]
+;
+ %m = mul nuw nsw i32 %x, 150
+ %d = udiv i32 %m, 100
+ ret i32 %d
+}
+
+define i32 @x_times_150_over_100_sdiv(i32 %x) {
+; CHECK-LABEL: @x_times_150_over_100_sdiv(
+; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i32 [[X:%.*]], 3
+; CHECK-NEXT: [[D:%.*]] = sdiv i32 [[TMP1]], 2
+; CHECK-NEXT: ret i32 [[D]]
+;
+ %m = mul nuw nsw i32 %x, 150
+ %d = sdiv i32 %m, 100
+ ret i32 %d
+}
+
+define i32 @x_times_150_over_100_sdiv_negative(i32 %x) {
+; CHECK-LABEL: @x_times_150_over_100_sdiv_negative(
+; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i32 [[X:%.*]], -3
+; CHECK-NEXT: [[D:%.*]] = sdiv i32 [[TMP1]], 2
+; CHECK-NEXT: ret i32 [[D]]
+;
+ %m = mul nuw nsw i32 %x, -150
+ %d = sdiv i32 %m, 100
+ ret i32 %d
+}
+
+define i32 @x_times_150_over_100_sdiv_negative_2(i32 %x) {
+; CHECK-LABEL: @x_times_150_over_100_sdiv_negative_2(
+; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i32 [[X:%.*]], 3
+; CHECK-NEXT: [[D:%.*]] = sdiv i32 [[TMP1]], -2
+; CHECK-NEXT: ret i32 [[D]]
+;
+ %m = mul nuw nsw i32 %x, 150
+ %d = sdiv i32 %m, -100
+ ret i32 %d
+}
+
+define i32 @x_times_150_over_100_sdiv_double_negative(i32 %x) {
+; CHECK-LABEL: @x_times_150_over_100_sdiv_double_negative(
+; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i32 [[X:%.*]], 3
+; CHECK-NEXT: [[D:%.*]] = sdiv i32 [[TMP1]], 2
+; CHECK-NEXT: ret i32 [[D]]
+;
+ %m = mul nuw nsw i32 %x, -150
+ %d = sdiv i32 %m, -100
+ ret i32 %d
+}
+
+
; negative test - must have nsw
define i8 @sdiv_sdiv_mul_nuw(i8 %x, i8 %y, i8 %z) {
More information about the llvm-commits
mailing list