-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SimplifyCFG] Add support for hoisting commutative instructions #104805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1583,6 +1583,26 @@ static void hoistLockstepIdenticalDbgVariableRecords( | |
} | ||
} | ||
|
||
static bool areIdenticalUpToCommutativity(const Instruction *I1, | ||
const Instruction *I2) { | ||
if (I1->isIdenticalToWhenDefined(I2)) | ||
return true; | ||
|
||
if (auto *Cmp1 = dyn_cast<CmpInst>(I1)) | ||
if (auto *Cmp2 = dyn_cast<CmpInst>(I2)) | ||
return Cmp1->getPredicate() == Cmp2->getSwappedPredicate() && | ||
Cmp1->getOperand(0) == Cmp2->getOperand(1) && | ||
Cmp1->getOperand(1) == Cmp2->getOperand(0); | ||
|
||
if (I1->isCommutative() && I1->isSameOperationAs(I2)) { | ||
return I1->getOperand(0) == I2->getOperand(1) && | ||
I1->getOperand(1) == I2->getOperand(0) && | ||
equal(drop_begin(I1->operands(), 2), drop_begin(I2->operands(), 2)); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the operand compares be recursive? I.e There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be handled by hoisting the two xors first, at which point the add is no longer recursive. |
||
|
||
return false; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although unrelated to the complexity canonicalization case, should we also handle There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean where the select operands are swapped with an inverted icmp? I don't think we can easily handle this here, because we hoist instructions one by one, so the icmp needs to be hoistable independently. It's not impossible, but a lot more complex than just changing the comparison logic. |
||
|
||
/// Hoist any common code in the successor blocks up into the block. This | ||
/// function guarantees that BB dominates all successors. If EqTermsOnly is | ||
/// given, only perform hoisting in case both blocks only contain a terminator. | ||
|
@@ -1676,7 +1696,7 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB, | |
for (auto &SuccIter : OtherSuccIterRange) { | ||
Instruction *I2 = &*SuccIter; | ||
HasTerminator |= I2->isTerminator(); | ||
if (AllInstsAreIdentical && (!I1->isIdenticalToWhenDefined(I2) || | ||
if (AllInstsAreIdentical && (!areIdenticalUpToCommutativity(I1, I2) || | ||
MMRAMetadata(*I1) != MMRAMetadata(*I2))) | ||
AllInstsAreIdentical = false; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Isn't the
drop_begin(..., 2)
always empty?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For intrinsics, "commutative" means that the first two operands are commutative, but there may be more after that. An example are FMA intrinsics.