mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-03 00:47:07 +00:00
[VPlan][LV] Introduce condition bit in VPBlockBase
This patch introduces a VPValue in VPBlockBase to represent the condition bit that is used as successor selector when a block has multiple successors. This information wasn't necessary until now, when we are about to introduce outer loop vectorization support in VPlan code gen. Reviewers: fhahn, rengolin, mkuper, hfinkel, mssimpso Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D48814 llvm-svn: 336554
This commit is contained in:
parent
4ccc83e13c
commit
ef55ff578f
@ -6843,7 +6843,7 @@ VPRegionBlock *VPRecipeBuilder::createReplicateRegion(Instruction *Instr,
|
||||
|
||||
// Note: first set Entry as region entry and then connect successors starting
|
||||
// from it in order, to propagate the "parent" of each VPBasicBlock.
|
||||
VPBlockUtils::insertTwoBlocksAfter(Pred, Exit, Entry);
|
||||
VPBlockUtils::insertTwoBlocksAfter(Pred, Exit, BlockInMask, Entry);
|
||||
VPBlockUtils::connectBlocks(Pred, Exit);
|
||||
|
||||
return Region;
|
||||
|
@ -457,6 +457,18 @@ void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) {
|
||||
bumpIndent(1);
|
||||
for (const VPRecipeBase &Recipe : *BasicBlock)
|
||||
Recipe.print(OS, Indent);
|
||||
|
||||
// Dump the condition bit.
|
||||
const VPValue *CBV = BasicBlock->getCondBit();
|
||||
if (CBV) {
|
||||
OS << " +\n" << Indent << " \"CondBit: ";
|
||||
if (const VPInstruction *CBI = dyn_cast<VPInstruction>(CBV)) {
|
||||
CBI->printAsOperand(OS);
|
||||
OS << " (" << DOT::EscapeString(CBI->getParent()->getName()) << ")\\l\"";
|
||||
} else
|
||||
CBV->printAsOperand(OS);
|
||||
}
|
||||
|
||||
bumpIndent(-2);
|
||||
OS << "\n" << Indent << "]\n";
|
||||
dumpEdges(BasicBlock);
|
||||
|
@ -339,6 +339,9 @@ private:
|
||||
/// List of successor blocks.
|
||||
SmallVector<VPBlockBase *, 1> Successors;
|
||||
|
||||
/// Successor selector, null for zero or single successor blocks.
|
||||
VPValue *CondBit = nullptr;
|
||||
|
||||
/// Add \p Successor as the last successor to this block.
|
||||
void appendSuccessor(VPBlockBase *Successor) {
|
||||
assert(Successor && "Cannot add nullptr successor!");
|
||||
@ -470,6 +473,13 @@ public:
|
||||
return getEnclosingBlockWithPredecessors()->getSinglePredecessor();
|
||||
}
|
||||
|
||||
/// \return the condition bit selecting the successor.
|
||||
VPValue *getCondBit() { return CondBit; }
|
||||
|
||||
const VPValue *getCondBit() const { return CondBit; }
|
||||
|
||||
void setCondBit(VPValue *CV) { CondBit = CV; }
|
||||
|
||||
/// Set a given VPBlockBase \p Successor as the single successor of this
|
||||
/// VPBlockBase. This VPBlockBase is not added as predecessor of \p Successor.
|
||||
/// This VPBlockBase must have no successors.
|
||||
@ -479,11 +489,14 @@ public:
|
||||
}
|
||||
|
||||
/// Set two given VPBlockBases \p IfTrue and \p IfFalse to be the two
|
||||
/// successors of this VPBlockBase. This VPBlockBase is not added as
|
||||
/// predecessor of \p IfTrue or \p IfFalse. This VPBlockBase must have no
|
||||
/// successors.
|
||||
void setTwoSuccessors(VPBlockBase *IfTrue, VPBlockBase *IfFalse) {
|
||||
/// successors of this VPBlockBase. \p Condition is set as the successor
|
||||
/// selector. This VPBlockBase is not added as predecessor of \p IfTrue or \p
|
||||
/// IfFalse. This VPBlockBase must have no successors.
|
||||
void setTwoSuccessors(VPBlockBase *IfTrue, VPBlockBase *IfFalse,
|
||||
VPValue *Condition) {
|
||||
assert(Successors.empty() && "Setting two successors when others exist.");
|
||||
assert(Condition && "Setting two successors without condition!");
|
||||
CondBit = Condition;
|
||||
appendSuccessor(IfTrue);
|
||||
appendSuccessor(IfFalse);
|
||||
}
|
||||
@ -1265,9 +1278,10 @@ public:
|
||||
VPBlockUtils() = delete;
|
||||
|
||||
/// Insert disconnected VPBlockBase \p NewBlock after \p BlockPtr. Add \p
|
||||
/// NewBlock as successor of \p BlockPtr and \p Block as predecessor of \p
|
||||
/// NewBlock, and propagate \p BlockPtr parent to \p NewBlock. \p NewBlock
|
||||
/// must have neither successors nor predecessors.
|
||||
/// NewBlock as successor of \p BlockPtr and \p BlockPtr as predecessor of \p
|
||||
/// NewBlock, and propagate \p BlockPtr parent to \p NewBlock. If \p BlockPtr
|
||||
/// has more than one successor, its conditional bit is propagated to \p
|
||||
/// NewBlock. \p NewBlock must have neither successors nor predecessors.
|
||||
static void insertBlockAfter(VPBlockBase *NewBlock, VPBlockBase *BlockPtr) {
|
||||
assert(NewBlock->getSuccessors().empty() &&
|
||||
"Can't insert new block with successors.");
|
||||
@ -1282,16 +1296,16 @@ public:
|
||||
/// Insert disconnected VPBlockBases \p IfTrue and \p IfFalse after \p
|
||||
/// BlockPtr. Add \p IfTrue and \p IfFalse as succesors of \p BlockPtr and \p
|
||||
/// BlockPtr as predecessor of \p IfTrue and \p IfFalse. Propagate \p BlockPtr
|
||||
/// parent to \p IfTrue and \p IfFalse. \p BlockPtr must have no successors
|
||||
/// and \p IfTrue and \p IfFalse must have neither successors nor
|
||||
/// predecessors.
|
||||
/// parent to \p IfTrue and \p IfFalse. \p Condition is set as the successor
|
||||
/// selector. \p BlockPtr must have no successors and \p IfTrue and \p IfFalse
|
||||
/// must have neither successors nor predecessors.
|
||||
static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse,
|
||||
VPBlockBase *BlockPtr) {
|
||||
VPValue *Condition, VPBlockBase *BlockPtr) {
|
||||
assert(IfTrue->getSuccessors().empty() &&
|
||||
"Can't insert IfTrue with successors.");
|
||||
assert(IfFalse->getSuccessors().empty() &&
|
||||
"Can't insert IfFalse with successors.");
|
||||
BlockPtr->setTwoSuccessors(IfTrue, IfFalse);
|
||||
BlockPtr->setTwoSuccessors(IfTrue, IfFalse, Condition);
|
||||
IfTrue->setPredecessors({BlockPtr});
|
||||
IfFalse->setPredecessors({BlockPtr});
|
||||
IfTrue->setParent(BlockPtr->getParent());
|
||||
|
@ -77,12 +77,6 @@ public:
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
// Return true if \p Inst is an incoming Instruction to be ignored in the VPlan
|
||||
// representation.
|
||||
static bool isInstructionToIgnore(Instruction *Inst) {
|
||||
return isa<BranchInst>(Inst);
|
||||
}
|
||||
|
||||
// Set predecessors of \p VPBB in the same order as they are in \p BB. \p VPBB
|
||||
// must have no predecessors.
|
||||
void PlainCFGBuilder::setVPBBPredsFromBB(VPBasicBlock *VPBB, BasicBlock *BB) {
|
||||
@ -197,16 +191,24 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
|
||||
VPIRBuilder.setInsertPoint(VPBB);
|
||||
for (Instruction &InstRef : *BB) {
|
||||
Instruction *Inst = &InstRef;
|
||||
if (isInstructionToIgnore(Inst))
|
||||
continue;
|
||||
|
||||
// There should't be any VPValue for Inst at this point. Otherwise, we
|
||||
// There shouldn't be any VPValue for Inst at this point. Otherwise, we
|
||||
// visited Inst when we shouldn't, breaking the RPO traversal order.
|
||||
assert(!IRDef2VPValue.count(Inst) &&
|
||||
"Instruction shouldn't have been visited.");
|
||||
|
||||
if (auto *Br = dyn_cast<BranchInst>(Inst)) {
|
||||
// Branch instruction is not explicitly represented in VPlan but we need
|
||||
// to represent its condition bit when it's conditional.
|
||||
if (Br->isConditional())
|
||||
getOrCreateVPOperand(Br->getCondition());
|
||||
|
||||
// Skip the rest of the Instruction processing for Branch instructions.
|
||||
continue;
|
||||
}
|
||||
|
||||
VPInstruction *NewVPInst;
|
||||
if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
|
||||
if (auto *Phi = dyn_cast<PHINode>(Inst)) {
|
||||
// Phi node's operands may have not been visited at this point. We create
|
||||
// an empty VPInstruction that we will fix once the whole plain CFG has
|
||||
// been built.
|
||||
@ -279,7 +281,19 @@ VPRegionBlock *PlainCFGBuilder::buildPlainCFG() {
|
||||
assert(SuccVPBB0 && "Successor 0 not found.");
|
||||
VPBasicBlock *SuccVPBB1 = getOrCreateVPBB(TI->getSuccessor(1));
|
||||
assert(SuccVPBB1 && "Successor 1 not found.");
|
||||
VPBB->setTwoSuccessors(SuccVPBB0, SuccVPBB1);
|
||||
|
||||
// Get VPBB's condition bit.
|
||||
assert(isa<BranchInst>(TI) && "Unsupported terminator!");
|
||||
auto *Br = cast<BranchInst>(TI);
|
||||
Value *BrCond = Br->getCondition();
|
||||
// Look up the branch condition to get the corresponding VPValue
|
||||
// representing the condition bit in VPlan (which may be in another VPBB).
|
||||
assert(IRDef2VPValue.count(BrCond) &&
|
||||
"Missing condition bit in IRDef2VPValue!");
|
||||
VPValue *VPCondBit = IRDef2VPValue[BrCond];
|
||||
|
||||
// Link successors using condition bit.
|
||||
VPBB->setTwoSuccessors(SuccVPBB0, SuccVPBB1, VPCondBit);
|
||||
} else
|
||||
llvm_unreachable("Number of successors not supported.");
|
||||
|
||||
|
@ -48,6 +48,12 @@ static void verifyBlocksInRegion(const VPRegionBlock *Region) {
|
||||
// Check block's parent.
|
||||
assert(VPB->getParent() == Region && "VPBlockBase has wrong parent");
|
||||
|
||||
// Check block's condition bit.
|
||||
if (VPB->getNumSuccessors() > 1)
|
||||
assert(VPB->getCondBit() && "Missing condition bit!");
|
||||
else
|
||||
assert(!VPB->getCondBit() && "Unexpected condition bit!");
|
||||
|
||||
// Check block's successors.
|
||||
const auto &Successors = VPB->getSuccessors();
|
||||
// There must be only one instance of a successor in block's successor list.
|
||||
|
@ -61,10 +61,11 @@ TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) {
|
||||
BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
|
||||
auto Plan = doBuildPlan(LoopHeader);
|
||||
|
||||
VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
|
||||
VPBasicBlock *Entry = Plan->getEntry()->getEntryBasicBlock();
|
||||
EXPECT_NE(nullptr, Entry->getSingleSuccessor());
|
||||
EXPECT_EQ(0u, Entry->getNumPredecessors());
|
||||
EXPECT_EQ(1u, Entry->getNumSuccessors());
|
||||
EXPECT_EQ(nullptr, Entry->getCondBit());
|
||||
|
||||
VPBasicBlock *VecBB = Entry->getSingleSuccessor()->getEntryBasicBlock();
|
||||
EXPECT_EQ(7u, VecBB->size());
|
||||
@ -105,6 +106,7 @@ TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) {
|
||||
EXPECT_EQ(Instruction::ICmp, ICmp->getOpcode());
|
||||
EXPECT_EQ(2u, ICmp->getNumOperands());
|
||||
EXPECT_EQ(IndvarAdd, ICmp->getOperand(0));
|
||||
EXPECT_EQ(VecBB->getCondBit(), ICmp);
|
||||
|
||||
LoopVectorizationLegality::InductionList Inductions;
|
||||
SmallPtrSet<Instruction *, 1> DeadInstructions;
|
||||
|
Loading…
Reference in New Issue
Block a user