[llvm] 99f8b79 - [InstCombine] try to fold 'or' into 'mul' operand

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 29 14:07:01 PST 2021


Author: Sanjay Patel
Date: 2021-11-29T17:03:08-05:00
New Revision: 99f8b795cc03f9bcda7f9cbd9625c2976ae62bd5

URL: https://github.com/llvm/llvm-project/commit/99f8b795cc03f9bcda7f9cbd9625c2976ae62bd5
DIFF: https://github.com/llvm/llvm-project/commit/99f8b795cc03f9bcda7f9cbd9625c2976ae62bd5.diff

LOG: [InstCombine] try to fold 'or' into 'mul' operand

or (mul X, Y), X --> mul X, (add Y, 1) (when the multiply has no common bits with X)

We already have this fold if the pattern ends in 'add', but we can miss it if the
'add' becomes 'or' via another no-common-bits transform.

This is part of fixing:
http://llvm.org/PR49055
...but it won't make a difference on that example yet.

https://alive2.llvm.org/ce/z/Vrmoeb

Differential Revision: https://reviews.llvm.org/D114729

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 6d3b228e7d7f3..dc55b5a31596b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2639,6 +2639,15 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
     return BinaryOperator::CreateXor(Or, ConstantInt::get(Ty, *CV));
   }
 
+  // If the operands have no common bits set:
+  // or (mul X, Y), X --> add (mul X, Y), X --> mul X, (Y + 1)
+  if (match(&I,
+            m_c_Or(m_OneUse(m_Mul(m_Value(X), m_Value(Y))), m_Deferred(X))) &&
+      haveNoCommonBitsSet(Op0, Op1, DL)) {
+    Value *IncrementY = Builder.CreateAdd(Y, ConstantInt::get(Ty, 1));
+    return BinaryOperator::CreateMul(X, IncrementY);
+  }
+
   // (A & C) | (B & D)
   Value *A, *B, *C, *D;
   if (match(Op0, m_And(m_Value(A), m_Value(C))) &&

diff  --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index 962ad47d74edc..869c17a3ccf9d 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -1446,8 +1446,8 @@ define i32 @mul_no_common_bits(i32 %p1, i32 %p2) {
 ; CHECK-LABEL: @mul_no_common_bits(
 ; CHECK-NEXT:    [[X:%.*]] = and i32 [[P1:%.*]], 7
 ; CHECK-NEXT:    [[Y:%.*]] = shl i32 [[P2:%.*]], 3
-; CHECK-NEXT:    [[M:%.*]] = mul i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[R:%.*]] = or i32 [[M]], [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[Y]], 1
+; CHECK-NEXT:    [[R:%.*]] = mul i32 [[X]], [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %x = and i32 %p1, 7
@@ -1460,8 +1460,7 @@ define i32 @mul_no_common_bits(i32 %p1, i32 %p2) {
 define i32 @mul_no_common_bits_const_op(i32 %p) {
 ; CHECK-LABEL: @mul_no_common_bits_const_op(
 ; CHECK-NEXT:    [[X:%.*]] = and i32 [[P:%.*]], 7
-; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[X]], 24
-; CHECK-NEXT:    [[R:%.*]] = or i32 [[M]], [[X]]
+; CHECK-NEXT:    [[R:%.*]] = mul nuw nsw i32 [[X]], 25
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %x = and i32 %p, 7
@@ -1473,8 +1472,7 @@ define i32 @mul_no_common_bits_const_op(i32 %p) {
 define <2 x i12> @mul_no_common_bits_commute(<2 x i12> %p) {
 ; CHECK-LABEL: @mul_no_common_bits_commute(
 ; CHECK-NEXT:    [[X:%.*]] = and <2 x i12> [[P:%.*]], <i12 1, i12 1>
-; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw <2 x i12> [[X]], <i12 14, i12 16>
-; CHECK-NEXT:    [[R:%.*]] = or <2 x i12> [[X]], [[M]]
+; CHECK-NEXT:    [[R:%.*]] = mul nuw nsw <2 x i12> [[X]], <i12 15, i12 17>
 ; CHECK-NEXT:    ret <2 x i12> [[R]]
 ;
   %x = and <2 x i12> %p, <i12 1, i12 1>
@@ -1483,8 +1481,29 @@ define <2 x i12> @mul_no_common_bits_commute(<2 x i12> %p) {
   ret <2 x i12> %r
 }
 
-define i32 @mul_no_common_bits_uses(i32 %p) {
+; negative test - extra use requires extra instructions
+
+define i32 @mul_no_common_bits_uses(i32 %p1, i32 %p2) {
 ; CHECK-LABEL: @mul_no_common_bits_uses(
+; CHECK-NEXT:    [[X:%.*]] = and i32 [[P1:%.*]], 7
+; CHECK-NEXT:    [[Y:%.*]] = shl i32 [[P2:%.*]], 3
+; CHECK-NEXT:    [[M:%.*]] = mul i32 [[X]], [[Y]]
+; CHECK-NEXT:    call void @use(i32 [[M]])
+; CHECK-NEXT:    [[R:%.*]] = or i32 [[M]], [[X]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %x = and i32 %p1, 7
+  %y = shl i32 %p2, 3
+  %m = mul i32 %x, %y
+  call void @use(i32 %m)
+  %r = or i32 %m, %x
+  ret i32 %r
+}
+
+; negative test - probably not good to create an extra mul
+
+define i32 @mul_no_common_bits_const_op_uses(i32 %p) {
+; CHECK-LABEL: @mul_no_common_bits_const_op_uses(
 ; CHECK-NEXT:    [[X:%.*]] = and i32 [[P:%.*]], 7
 ; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[X]], 24
 ; CHECK-NEXT:    call void @use(i32 [[M]])
@@ -1498,6 +1517,8 @@ define i32 @mul_no_common_bits_uses(i32 %p) {
   ret i32 %r
 }
 
+; negative test - %x and %m may have set 3rd bit
+
 define i32 @mul_common_bits(i32 %p) {
 ; CHECK-LABEL: @mul_common_bits(
 ; CHECK-NEXT:    [[X:%.*]] = and i32 [[P:%.*]], 7


        


More information about the llvm-commits mailing list