[PATCH] D126040: [InstCombine] Fold a mul with bool value into and

Allen zhong via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun May 22 19:47:28 PDT 2022


Allen updated this revision to Diff 431281.
Allen marked 2 inline comments as done.
Allen added a comment.

Thanks all. Based on the disccusion above, I roll back to the previous conservative handing method, so that further improvements can be made base on more special actual scenarious.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126040/new/

https://reviews.llvm.org/D126040

Files:
  llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
  llvm/test/Transforms/InstCombine/mul-bool.ll


Index: llvm/test/Transforms/InstCombine/mul-bool.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/InstCombine/mul-bool.ll
@@ -0,0 +1,57 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; Instcombine should be able to simplify mul operator.
+
+; Scalar tests
+define i64 @scalar_mul_bit_x0_y0(i64 %x, i64 %y) {
+; CHECK-LABEL: @scalar_mul_bit_x0_y0(
+; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[Y:%.*]], 1
+; CHECK-NEXT:    [[MUL:%.*]] = and i64 [[AND2]], [[X:%.*]]
+; CHECK-NEXT:    ret i64 [[MUL]]
+;
+  %and1 = and i64 %x, 1
+  %and2 = and i64 %y, 1
+  %mul = mul i64 %and1, %and2
+  ret i64 %mul
+}
+
+; Negative test
+define i64 @scalar_mul_bit_x0_y1(i64 %x, i64 %y) {
+; CHECK-LABEL: @scalar_mul_bit_x0_y1(
+; CHECK-NEXT:    [[AND1:%.*]] = and i64 [[X:%.*]], 1
+; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[Y:%.*]], 2
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i64 [[AND1]], [[AND2]]
+; CHECK-NEXT:    ret i64 [[MUL]]
+;
+  %and1 = and i64 %x, 1
+  %and2 = and i64 %y, 2
+  %mul = mul i64 %and1, %and2
+  ret i64 %mul
+}
+
+define i64 @scalar_mul_bit_x0_yC(i64 %x, i64 %y, i64 %c) {
+; CHECK-LABEL: @scalar_mul_bit_x0_yC(
+; CHECK-NEXT:    [[AND1:%.*]] = and i64 [[X:%.*]], 1
+; CHECK-NEXT:    [[AND2:%.*]] = and i64 [[Y:%.*]], [[C:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[AND1]], [[AND2]]
+; CHECK-NEXT:    ret i64 [[MUL]]
+;
+  %and1 = and i64 %x, 1
+  %and2 = and i64 %y, %c
+  %mul = mul i64 %and1, %and2
+  ret i64 %mul
+}
+
+; Vector tests
+define <2 x i64> @vector_mul_bit_x0_y0(<2 x i64> %x, <2 x i64> %y) {
+; CHECK-LABEL: @vector_mul_bit_x0_y0(
+; CHECK-NEXT:    [[AND2:%.*]] = and <2 x i64> [[Y:%.*]], <i64 1, i64 1>
+; CHECK-NEXT:    [[MUL:%.*]] = and <2 x i64> [[AND2]], [[X:%.*]]
+; CHECK-NEXT:    ret <2 x i64> [[MUL]]
+;
+  %and1 = and <2 x i64> %x, <i64 1, i64 1>
+  %and2 = and <2 x i64> %y, <i64 1, i64 1>
+  %mul = mul <2 x i64> %and1, %and2
+  ret <2 x i64> %mul
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -375,6 +375,14 @@
   if (match(Op1, m_LShr(m_Value(X), m_APInt(C))) && *C == C->getBitWidth() - 1)
     return BinaryOperator::CreateAnd(Builder.CreateAShr(X, *C), Op0);
 
+  // X * Y --> X & Y, iff X, Y can be only 1. Don't use known bits API as
+  // somewhat unclear from a canonicalization perspective, which may increase
+  // instruction count. (We'd probably want to represent it as trunc(X) ? Y : 0
+  // rather than -X & Y, but it's increasing the count either way.)
+  if (match(Op0, m_And(m_Value(X), m_One())) &&
+      match(Op1, m_And(m_Value(Y), m_One())))
+    return BinaryOperator::CreateAnd(Op0, Op1);
+
   // ((ashr X, 31) | 1) * X --> abs(X)
   // X * ((ashr X, 31) | 1) --> abs(X)
   if (match(&I, m_c_BinOp(m_Or(m_AShr(m_Value(X),


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D126040.431281.patch
Type: text/x-patch
Size: 3058 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220523/2e902c65/attachment.bin>


More information about the llvm-commits mailing list