-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[VPlan] Simplify branch on False in VPlan transform (NFC). #140409
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
063d70f
f5ee27b
74eddb5
61779cf
801b98d
069767b
d3df2c3
3f3f002
69ad1de
9233672
6ced27d
2b76566
5797781
761d4ca
ff89acf
fa0eab1
57652c7
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 |
---|---|---|
|
@@ -1841,40 +1841,37 @@ void VPlanTransforms::truncateToMinimalBitwidths( | |
} | ||
} | ||
|
||
/// Remove BranchOnCond recipes with true conditions together with removing | ||
/// dead edges to their successors. | ||
static void removeBranchOnCondTrue(VPlan &Plan) { | ||
/// Remove BranchOnCond recipes with true or false conditions together with | ||
/// removing dead edges to their successors. | ||
static void removeBranchOnConst(VPlan &Plan) { | ||
using namespace llvm::VPlanPatternMatch; | ||
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. Name of 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. updated, thanks |
||
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>( | ||
vp_depth_first_shallow(Plan.getEntry()))) { | ||
VPValue *Cond; | ||
if (VPBB->getNumSuccessors() != 2 || VPBB == Plan.getEntry() || | ||
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. Independent: why is the entry block excluded? 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. Entry will have 2 successors w/o branch. Will be fixed by introducing a branch recipe, possibly on an opaque condition, when connecting entry to vector.ph/scalar.ph. 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. Ah, right, perhaps worth a clarifying TODO. |
||
!match(&VPBB->back(), m_BranchOnCond(m_True()))) | ||
!match(&VPBB->back(), m_BranchOnCond(m_VPValue(Cond)))) | ||
continue; | ||
|
||
VPBasicBlock *RemovedSucc = cast<VPBasicBlock>(VPBB->getSuccessors()[1]); | ||
unsigned DeadIdx = RemovedSucc->getIndexForPredecessor(VPBB); | ||
|
||
// Values coming from VPBB into ResumePhi recipes of RemoveSucc are removed | ||
// from these recipes. | ||
for (VPRecipeBase &R : make_early_inc_range(*RemovedSucc)) { | ||
assert((!isa<VPIRInstruction>(&R) || | ||
!isa<PHINode>(cast<VPIRInstruction>(&R)->getInstruction())) && | ||
!isa<VPHeaderPHIRecipe>(&R) && | ||
"Cannot update VPIRInstructions wrapping phis or header phis yet"); | ||
auto *VPI = dyn_cast<VPPhi>(&R); | ||
if (!VPI) | ||
break; | ||
VPBuilder B(VPI); | ||
SmallVector<VPValue *> NewOperands; | ||
// Create new operand list, with the dead incoming value filtered out. | ||
for (const auto &[Idx, Op] : enumerate(VPI->operands())) { | ||
if (Idx == DeadIdx) | ||
continue; | ||
NewOperands.push_back(Op); | ||
} | ||
VPI->replaceAllUsesWith( | ||
B.createScalarPhi(NewOperands, VPI->getDebugLoc(), VPI->getName())); | ||
VPI->eraseFromParent(); | ||
unsigned RemovedIdx; | ||
if (match(Cond, m_True())) | ||
RemovedIdx = 1; | ||
else if (match(Cond, m_False())) | ||
RemovedIdx = 0; | ||
else | ||
continue; | ||
|
||
VPBasicBlock *RemovedSucc = | ||
cast<VPBasicBlock>(VPBB->getSuccessors()[RemovedIdx]); | ||
const auto &Preds = RemovedSucc->getPredecessors(); | ||
assert(count(Preds, VPBB) == 1 && | ||
"There must be a single edge between VPBB and its successor"); | ||
// Values coming from VPBB into phi recipes of RemoveSucc are removed from | ||
// these recipes. | ||
for (VPRecipeBase &R : RemovedSucc->phis()) { | ||
auto *Phi = cast<VPPhiAccessors>(&R); | ||
assert((!isa<VPIRPhi>(&R) || RemovedSucc->getNumPredecessors() == 1) && | ||
"VPIRPhis must have a single predecessor"); | ||
Phi->removeIncomingValueFor(VPBB); | ||
} | ||
// Disconnect blocks and remove the terminator. RemovedSucc will be deleted | ||
// automatically on VPlan destruction if it becomes unreachable. | ||
|
@@ -1894,7 +1891,7 @@ void VPlanTransforms::optimize(VPlan &Plan) { | |
runPass(legalizeAndOptimizeInductions, Plan); | ||
runPass(removeRedundantExpandSCEVRecipes, Plan); | ||
runPass(simplifyRecipes, Plan, *Plan.getCanonicalIV()->getScalarType()); | ||
runPass(removeBranchOnCondTrue, Plan); | ||
runPass(removeBranchOnConst, Plan); | ||
runPass(removeDeadRecipes, Plan); | ||
|
||
runPass(createAndOptimizeReplicateRegions, Plan); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ class VPSlotTracker; | |
class VPUser; | ||
class VPRecipeBase; | ||
class VPInterleaveRecipe; | ||
class VPPhiAccessors; | ||
|
||
// This is the base class of the VPlan Def/Use graph, used for modeling the data | ||
// flow into, within and out of the VPlan. VPValues can stand for live-ins | ||
|
@@ -199,8 +200,18 @@ raw_ostream &operator<<(raw_ostream &OS, const VPRecipeBase &R); | |
/// This class augments VPValue with operands which provide the inverse def-use | ||
/// edges from VPValue's users to their defs. | ||
class VPUser { | ||
/// Grant access to removeOperand for VPPhiAccessors, the only supported user. | ||
friend class VPPhiAccessors; | ||
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. Why/is this befriending needed? 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. removeOperand is added as private, to discourage its used unless really necessary, hence befriending. Could also expose as protected or public instead 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. Worth clarifying this discouraging motivation for Currently 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. current VPPhiAccessors::removeIncomingValueFor supports any phi-like recipe, and is used for VPPhi and VPIRPhi. Updated the code in |
||
|
||
SmallVector<VPValue *, 2> Operands; | ||
|
||
/// Removes the operand at index \p Idx. This also removes the VPUser from the | ||
/// use-list of the operand. | ||
void removeOperand(unsigned Idx) { | ||
getOperand(Idx)->removeUser(*this); | ||
Operands.erase(Operands.begin() + Idx); | ||
} | ||
|
||
protected: | ||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||
/// Print the operands to \p O. | ||
|
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: take the number of ScalarPH predecessors once, here, reuse it repeatedly inside the loop, asserting it is one more than the number of ResumePhi's operands.
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.
Updated, thanks