[PATCH] D104193: [InstCombine] Require one user (not one use) for operands when optimize both (sext bool X) * (sext bool Y) and (zext bool X) * (zext bool Y)

Daniil Seredkin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 13 06:39:22 PDT 2021


vdsered created this revision.
vdsered added reviewers: spatel, eli.friedman.
vdsered added a project: LLVM.
Herald added a subscriber: hiraditya.
vdsered requested review of this revision.
Herald added a subscriber: llvm-commits.

It is mentioned in https://reviews.llvm.org/D102574 that we are lack of optimizations for (sext bool X) * (sext bool Y) and (zext bool X) * (zext bool Y) when operands are equal. It is required now that operands of mul have one user rather than one use (less strict constraint) for the patterns in order to allow both of them them to be transformed to zext (and X, X).

Alive says that it is a correct transformation:
https://alive2.llvm.org/ce/z/27ryac


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D104193

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


Index: llvm/test/Transforms/InstCombine/mul.ll
===================================================================
--- llvm/test/Transforms/InstCombine/mul.ll
+++ llvm/test/Transforms/InstCombine/mul.ll
@@ -247,6 +247,52 @@
   ret i32 %r
 }
 
+define i32 @mul_bool_sext_one_user(i1 %x) {
+; CHECK-LABEL: @mul_bool_sext_one_user(
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[X:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %sx = sext i1 %x to i32
+  %r = mul i32 %sx, %sx
+  ret i32 %r
+}
+
+define i32 @mul_bool_zext_one_user(i1 %x) {
+; CHECK-LABEL: @mul_bool_zext_one_user(
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[X:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %sx = zext i1 %x to i32
+  %r = mul i32 %sx, %sx
+  ret i32 %r
+}
+
+define i32 @mul_bool_sext_one_extra_user(i1 %x) {
+; CHECK-LABEL: @mul_bool_sext_one_extra_user(
+; CHECK-NEXT:    [[SX:%.*]] = sext i1 [[X:%.*]] to i32
+; CHECK-NEXT:    call void @use32(i32 [[SX]])
+; CHECK-NEXT:    [[R:%.*]] = mul nsw i32 [[SX]], [[SX]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %sx = sext i1 %x to i32
+  call void @use32(i32 %sx)
+  %r = mul i32 %sx, %sx
+  ret i32 %r
+}
+
+define i32 @mul_bool_zext_one_extra_user(i1 %x) {
+; CHECK-LABEL: @mul_bool_zext_one_extra_user(
+; CHECK-NEXT:    [[SX:%.*]] = zext i1 [[X:%.*]] to i32
+; CHECK-NEXT:    call void @use32(i32 [[SX]])
+; CHECK-NEXT:    [[R:%.*]] = zext i1 [[X]] to i32
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %sx = zext i1 %x to i32
+  call void @use32(i32 %sx)
+  %r = mul i32 %sx, %sx
+  ret i32 %r
+}
+
 define <3 x i32> @mul_bools_mixed_ext(<3 x i1> %x, <3 x i1> %y) {
 ; CHECK-LABEL: @mul_bools_mixed_ext(
 ; CHECK-NEXT:    [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]]
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -328,7 +328,7 @@
   if (((match(Op0, m_ZExt(m_Value(X))) && match(Op1, m_ZExt(m_Value(Y)))) ||
        (match(Op0, m_SExt(m_Value(X))) && match(Op1, m_SExt(m_Value(Y))))) &&
       X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() &&
-      (Op0->hasOneUse() || Op1->hasOneUse())) {
+      I.isOnlyUserOfAnyOperand()) {
     Value *And = Builder.CreateAnd(X, Y, "mulbool");
     return CastInst::Create(Instruction::ZExt, And, I.getType());
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D104193.351715.patch
Type: text/x-patch
Size: 2413 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210613/d9f5ddf0/attachment.bin>


More information about the llvm-commits mailing list