[PATCH] D102864: [InstSimplify] Transform X * Y % Y --> 0.
David Goldblatt via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu May 20 12:11:25 PDT 2021
davidtgoldblatt created this revision.
Herald added a subscriber: hiraditya.
davidtgoldblatt requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
simplifyDiv already handles the case X * Y / Y --> X (barring overflow).
This adds the equivalent handling to simplifyRem.
Correctness:
https://alive2.llvm.org/ce/z/J2cUbS
https://alive2.llvm.org/ce/z/us9NUM
Extending the situations in which we apply this transform would not be
correct:
https://alive2.llvm.org/ce/z/Lf9V63
https://alive2.llvm.org/ce/z/6RPQK3
https://alive2.llvm.org/ce/z/p9UdxC
https://alive2.llvm.org/ce/z/A2zlhE
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D102864
Files:
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/test/Transforms/InstSimplify/rem.ll
Index: llvm/test/Transforms/InstSimplify/rem.ll
===================================================================
--- llvm/test/Transforms/InstSimplify/rem.ll
+++ llvm/test/Transforms/InstSimplify/rem.ll
@@ -331,3 +331,65 @@
%v = srem i8 -128, -1
ret i8 %v
}
+
+define i32 @srem_of_mul_nsw(i32 %x, i32 %y) {
+; CHECK-LABEL: @srem_of_mul_nsw(
+; CHECK-NEXT: ret i32 0
+;
+ %mul = mul nsw i32 %x, %y
+ %mod = srem i32 %mul, %y
+ ret i32 %mod
+}
+
+define i32 @srem_of_mul_nuw(i32 %x, i32 %y) {
+; CHECK-LABEL: @srem_of_mul_nuw(
+; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[MOD:%.*]] = srem i32 [[MUL]], [[Y]]
+; CHECK-NEXT: ret i32 [[MOD]]
+;
+ %mul = mul nuw i32 %x, %y
+ %mod = srem i32 %mul, %y
+ ret i32 %mod
+}
+
+define i32 @srem_of_mul(i32 %x, i32 %y) {
+; CHECK-LABEL: @srem_of_mul(
+; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[MOD:%.*]] = srem i32 [[MUL]], [[Y]]
+; CHECK-NEXT: ret i32 [[MOD]]
+;
+ %mul = mul i32 %x, %y
+ %mod = srem i32 %mul, %y
+ ret i32 %mod
+}
+
+define i32 @urem_of_mul_nsw(i32 %x, i32 %y) {
+; CHECK-LABEL: @urem_of_mul_nsw(
+; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[MOD:%.*]] = urem i32 [[MUL]], [[Y]]
+; CHECK-NEXT: ret i32 [[MOD]]
+;
+ %mul = mul nsw i32 %x, %y
+ %mod = urem i32 %mul, %y
+ ret i32 %mod
+}
+
+define i32 @urem_of_mul_nuw(i32 %x, i32 %y) {
+; CHECK-LABEL: @urem_of_mul_nuw(
+; CHECK-NEXT: ret i32 0
+;
+ %mul = mul nuw i32 %x, %y
+ %mod = urem i32 %mul, %y
+ ret i32 %mod
+}
+
+define i32 @urem_of_mul(i32 %x, i32 %y) {
+; CHECK-LABEL: @urem_of_mul(
+; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[MOD:%.*]] = urem i32 [[MUL]], [[Y]]
+; CHECK-NEXT: ret i32 [[MOD]]
+;
+ %mul = mul i32 %x, %y
+ %mod = urem i32 %mul, %y
+ ret i32 %mod
+}
Index: llvm/lib/Analysis/InstructionSimplify.cpp
===================================================================
--- llvm/lib/Analysis/InstructionSimplify.cpp
+++ llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1115,6 +1115,16 @@
match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
return Op0;
+ // (X * Y) % Y -> 0 if the multiplication does not overflow.
+ Value *X;
+ if (match(Op0, m_c_Mul(m_Value(X), m_Specific(Op1)))) {
+ bool IsSigned = Opcode == Instruction::SRem;
+ auto *Mul = cast<OverflowingBinaryOperator>(Op0);
+ if ((IsSigned && Q.IIQ.hasNoSignedWrap(Mul)) ||
+ (!IsSigned && Q.IIQ.hasNoUnsignedWrap(Mul)))
+ return Constant::getNullValue(Op0->getType());
+ }
+
// (X << Y) % X -> 0
if (Q.IIQ.UseInstrInfo &&
((Opcode == Instruction::SRem &&
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D102864.346819.patch
Type: text/x-patch
Size: 2694 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210520/a1413c36/attachment.bin>
More information about the llvm-commits
mailing list