[llvm] [InstCombine] Teach tryFactorization to treat a disjoint Or like an Add. (PR #75691)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 15 22:20:20 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Craig Topper (topperc)
<details>
<summary>Changes</summary>
If the InnerOpcode is a Mul. This replaces a combine in visitOr that was not handling all commuted cases.
This does change one of the negative cases for the original combine. We now introduce a second Mul, but the same thing already happens if the Or was an Add.
---
Full diff: https://github.com/llvm/llvm-project/pull/75691.diff
3 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (-8)
- (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+5)
- (modified) llvm/test/Transforms/InstCombine/or.ll (+4-4)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 31db1d3164b772..3ba2f19f010f97 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3391,14 +3391,6 @@ 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_DisjointOr(m_OneUse(m_Mul(m_Value(X), m_Value(Y))),
- m_Deferred(X)))) {
- Value *IncrementY = Builder.CreateAdd(Y, ConstantInt::get(Ty, 1));
- return BinaryOperator::CreateMul(X, IncrementY);
- }
-
// X | (X ^ Y) --> X | Y (4 commuted patterns)
if (match(&I, m_c_Or(m_Value(X), m_c_Xor(m_Deferred(X), m_Value(Y)))))
return BinaryOperator::CreateOr(X, Y);
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index a7ddadc25de43c..a5f4b8e40622cd 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -646,6 +646,11 @@ static Value *tryFactorization(BinaryOperator &I, const SimplifyQuery &SQ,
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
Instruction::BinaryOps TopLevelOpcode = I.getOpcode();
+ // Treat a disjoint Or like an Add if the inner opcode is a Mul.
+ if (I.getOpcode() == Instruction::Or && InnerOpcode == Instruction::Mul &&
+ cast<PossiblyDisjointInst>(I).isDisjoint())
+ TopLevelOpcode = Instruction::Add;
+
// Does "X op' Y" always equal "Y op' X"?
bool InnerCommutative = Instruction::isCommutative(InnerOpcode);
diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index 805546099398b4..757f8b965ea68d 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -1515,8 +1515,8 @@ define i32 @mul_no_common_bits_commute2(i32 %p1, i32 %p2) {
; CHECK-LABEL: @mul_no_common_bits_commute2(
; CHECK-NEXT: [[X:%.*]] = and i32 [[P1:%.*]], 7
; CHECK-NEXT: [[Y:%.*]] = shl i32 [[P2:%.*]], 3
-; CHECK-NEXT: [[M:%.*]] = mul i32 [[Y]], [[X]]
-; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[M]], [[X]]
+; CHECK-NEXT: [[M1:%.*]] = or disjoint i32 [[Y]], 1
+; CHECK-NEXT: [[R:%.*]] = mul i32 [[M1]], [[X]]
; CHECK-NEXT: ret i32 [[R]]
;
%x = and i32 %p1, 7
@@ -1566,14 +1566,14 @@ define i32 @mul_no_common_bits_uses(i32 %p1, i32 %p2) {
ret i32 %r
}
-; negative test - probably not good to create an extra mul
+; TODO: is it 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]])
-; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[M]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i32 [[X]], 25
; CHECK-NEXT: ret i32 [[R]]
;
%x = and i32 %p, 7
``````````
</details>
https://github.com/llvm/llvm-project/pull/75691
More information about the llvm-commits
mailing list