[llvm] 35a3048 - [InstCombine] add support for multi-use Y of (X op Y) op Z --> (Y op Z) op X
Chenbing Zheng via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 30 19:55:32 PDT 2022
Author: Chenbing Zheng
Date: 2022-08-31T10:55:05+08:00
New Revision: 35a3048c2501f7e1de4f662ed402a37f4822feec
URL: https://github.com/llvm/llvm-project/commit/35a3048c2501f7e1de4f662ed402a37f4822feec
DIFF: https://github.com/llvm/llvm-project/commit/35a3048c2501f7e1de4f662ed402a37f4822feec.diff
LOG: [InstCombine] add support for multi-use Y of (X op Y) op Z --> (Y op Z) op X
For (X op Y) op Z --> (Y op Z) op X
we can still do transform when Y is multi-use. In D131356 limit it to one-use,
this patch remove this limit.
This is still not a complete solution, I add a todo test to show it.
In this case, X and Y are both multi use, we can't differentiate how to convert based on this.
But at least we don't make the code worse,and it can solve half the scenarios.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/and-or-not.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 0dac7c3da5150..b011c5f93979e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1752,15 +1752,20 @@ static Instruction *reassociateForUses(BinaryOperator &BO,
InstCombinerImpl::BuilderTy &Builder) {
Instruction::BinaryOps Opcode = BO.getOpcode();
Value *X, *Y, *Z;
- if (match(&BO, m_c_BinOp(Opcode,
- m_OneUse(m_c_BinOp(Opcode, m_Value(X),
- m_OneUse(m_Value(Y)))),
- m_OneUse(m_Value(Z))))) {
- // (X op Y) op Z --> (Y op Z) op X
- if (!isa<Constant>(X) && !isa<Constant>(Y) && !isa<Constant>(Z) &&
- !X->hasOneUse()) {
- Value *YZ = Builder.CreateBinOp(Opcode, Y, Z);
- return BinaryOperator::Create(Opcode, YZ, X);
+ if (match(&BO,
+ m_c_BinOp(Opcode, m_OneUse(m_BinOp(Opcode, m_Value(X), m_Value(Y))),
+ m_OneUse(m_Value(Z))))) {
+ if (!isa<Constant>(X) && !isa<Constant>(Y) && !isa<Constant>(Z)) {
+ // (X op Y) op Z --> (Y op Z) op X
+ if (!X->hasOneUse()) {
+ Value *YZ = Builder.CreateBinOp(Opcode, Y, Z);
+ return BinaryOperator::Create(Opcode, YZ, X);
+ }
+ // (X op Y) op Z --> (X op Z) op Y
+ if (!Y->hasOneUse()) {
+ Value *XZ = Builder.CreateBinOp(Opcode, X, Z);
+ return BinaryOperator::Create(Opcode, XZ, Y);
+ }
}
}
diff --git a/llvm/test/Transforms/InstCombine/and-or-not.ll b/llvm/test/Transforms/InstCombine/and-or-not.ll
index 73cb2f29f5dfc..362298157e032 100644
--- a/llvm/test/Transforms/InstCombine/and-or-not.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-not.ll
@@ -747,12 +747,8 @@ define <2 x i4> @simplify_and_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x
define i4 @simplify_and_common_op_use1(i4 %x, i4 %y, i4 %z) {
; CHECK-LABEL: @simplify_and_common_op_use1(
-; CHECK-NEXT: [[XY:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: call void @use(i4 [[Y]])
-; CHECK-NEXT: [[XYZ:%.*]] = or i4 [[XY]], [[Z:%.*]]
-; CHECK-NEXT: [[NOT_XYZ:%.*]] = xor i4 [[XYZ]], -1
-; CHECK-NEXT: [[R:%.*]] = and i4 [[NOT_XYZ]], [[X]]
-; CHECK-NEXT: ret i4 [[R]]
+; CHECK-NEXT: call void @use(i4 [[Y:%.*]])
+; CHECK-NEXT: ret i4 0
;
%xy = or i4 %x, %y
call void @use(i4 %y)
@@ -766,6 +762,25 @@ define i4 @simplify_and_common_op_use1(i4 %x, i4 %y, i4 %z) {
define i4 @simplify_and_common_op_use2(i4 %x, i4 %y, i4 %z) {
; CHECK-LABEL: @simplify_and_common_op_use2(
+; CHECK-NEXT: call void @use(i4 [[Y:%.*]])
+; CHECK-NEXT: [[TMP1:%.*]] = or i4 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[XYZ:%.*]] = or i4 [[TMP1]], [[Y]]
+; CHECK-NEXT: [[NOT_XYZ:%.*]] = xor i4 [[XYZ]], -1
+; CHECK-NEXT: [[R:%.*]] = and i4 [[NOT_XYZ]], [[X]]
+; CHECK-NEXT: ret i4 [[R]]
+;
+ %xy = or i4 %y, %x
+ call void @use(i4 %y)
+ %xyz = or i4 %xy, %z
+ %not_xyz = xor i4 %xyz, -1
+ %r = and i4 %not_xyz, %x
+ ret i4 %r
+}
+
+; TODO: This should simplify.
+
+define i4 @simplify_and_common_op_use3(i4 %x, i4 %y, i4 %z) {
+; CHECK-LABEL: @simplify_and_common_op_use3(
; CHECK-NEXT: [[XY:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[XYZ:%.*]] = or i4 [[XY]], [[Z:%.*]]
; CHECK-NEXT: call void @use(i4 [[Z]])
More information about the llvm-commits
mailing list