[llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp
Evan Cheng
evan.cheng at apple.com
Mon May 21 15:23:16 PDT 2007
Changes in directory llvm/lib/CodeGen:
IfConversion.cpp updated: 1.10 -> 1.11
---
Log message:
If-convert early exit blocks (returns, etc.); bug fixes, etc.
---
Diffs of the changes: (+226 -141)
IfConversion.cpp | 367 +++++++++++++++++++++++++++++++++----------------------
1 files changed, 226 insertions(+), 141 deletions(-)
Index: llvm/lib/CodeGen/IfConversion.cpp
diff -u llvm/lib/CodeGen/IfConversion.cpp:1.10 llvm/lib/CodeGen/IfConversion.cpp:1.11
--- llvm/lib/CodeGen/IfConversion.cpp:1.10 Fri May 18 14:32:08 2007
+++ llvm/lib/CodeGen/IfConversion.cpp Mon May 21 17:22:58 2007
@@ -30,10 +30,11 @@
enum BBICKind {
ICInvalid, // BB data invalid.
ICNotClassfied, // BB data valid, but not classified.
- ICTriangle, // BB is part of a triangle sub-CFG.
- ICDiamond, // BB is part of a diamond sub-CFG.
- ICTriangleEntry, // BB is entry of a triangle sub-CFG.
- ICDiamondEntry // BB is entry of a diamond sub-CFG.
+ ICEarlyExit, // BB is entry of an early-exit sub-CFG.
+ ICTriangle, // BB is entry of a triangle sub-CFG.
+ ICDiamond, // BB is entry of a diamond sub-CFG.
+ ICChild, // BB is part of the sub-CFG that'll be predicated.
+ ICDead // BB has been converted and merged, it's now dead.
};
/// BBInfo - One per MachineBasicBlock, this is used to cache the result
@@ -47,13 +48,15 @@
unsigned Size;
bool isPredicable;
bool ClobbersPred;
+ bool hasEarlyExit;
MachineBasicBlock *BB;
MachineBasicBlock *TrueBB;
MachineBasicBlock *FalseBB;
MachineBasicBlock *TailBB;
std::vector<MachineOperand> Cond;
BBInfo() : Kind(ICInvalid), Size(0), isPredicable(false),
- ClobbersPred(false), BB(0), TrueBB(0), FalseBB(0), TailBB(0) {}
+ ClobbersPred(false), hasEarlyExit(false),
+ BB(0), TrueBB(0), FalseBB(0), TailBB(0) {}
};
/// BBAnalysis - Results of if-conversion feasibility analysis indexed by
@@ -75,6 +78,7 @@
void FeasibilityAnalysis(BBInfo &BBI);
void InitialFunctionAnalysis(MachineFunction &MF,
std::vector<BBInfo*> &Candidates);
+ bool IfConvertEarlyExit(BBInfo &BBI);
bool IfConvertTriangle(BBInfo &BBI);
bool IfConvertDiamond(BBInfo &BBI);
void PredicateBlock(MachineBasicBlock *BB,
@@ -107,10 +111,13 @@
switch (BBI.Kind) {
default: assert(false && "Unexpected!");
break;
- case ICTriangleEntry:
+ case ICEarlyExit:
+ MadeChange |= IfConvertEarlyExit(BBI);
+ break;
+ case ICTriangle:
MadeChange |= IfConvertTriangle(BBI);
break;
- case ICDiamondEntry:
+ case ICDiamond:
MadeChange |= IfConvertDiamond(BBI);
break;
}
@@ -139,19 +146,16 @@
BBInfo &BBI = BBAnalysis[BB->getNumber()];
if (BBI.Kind != ICInvalid)
- return; // Always analyzed.
+ return; // Already analyzed.
BBI.BB = BB;
BBI.Size = std::distance(BB->begin(), BB->end());
// Look for 'root' of a simple (non-nested) triangle or diamond.
BBI.Kind = ICNotClassfied;
- if (TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, BBI.Cond)
- || !BBI.TrueBB || BBI.Cond.size() == 0)
- return;
-
- // Not a candidate if 'true' block has another predecessor.
- // FIXME: Use or'd predicate or predicated cmp.
- if (BBI.TrueBB->pred_size() > 1)
+ bool CanAnalyze = !TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, BBI.Cond);
+ // Does it end with a return, indirect jump, or jumptable branch?
+ BBI.hasEarlyExit = TII->BlockHasNoFallThrough(*BB) && !BBI.TrueBB;
+ if (!CanAnalyze || !BBI.TrueBB || BBI.Cond.size() == 0)
return;
// Not a candidate if 'true' block is going to be if-converted.
@@ -170,11 +174,6 @@
BBI.FalseBB = findFalseBlock(BB, BBI.TrueBB);
assert(BBI.FalseBB && "Expected to find the fallthrough block!");
- // Not a candidate if 'false' block has another predecessor.
- // FIXME: Invert condition and swap 'true' / 'false' blocks?
- if (BBI.FalseBB->pred_size() > 1)
- return;
-
// Not a candidate if 'false' block is going to be if-converted.
StructuralAnalysis(BBI.FalseBB);
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
@@ -185,7 +184,17 @@
if (FalseBBI.FalseBB || FalseBBI.Cond.size())
return;
- if (TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB) {
+ unsigned TrueNumPreds = BBI.TrueBB->pred_size();
+ unsigned FalseNumPreds = BBI.FalseBB->pred_size();
+ if ((TrueBBI.hasEarlyExit && TrueNumPreds <= 1) &&
+ !(FalseBBI.hasEarlyExit && FalseNumPreds <=1)) {
+ BBI.Kind = ICEarlyExit;
+ TrueBBI.Kind = ICChild;
+ } else if (!(TrueBBI.hasEarlyExit && TrueNumPreds <= 1) &&
+ (FalseBBI.hasEarlyExit && FalseNumPreds <=1)) {
+ BBI.Kind = ICEarlyExit;
+ FalseBBI.Kind = ICChild;
+ } else if (TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB) {
// Triangle:
// EBB
// | \_
@@ -193,9 +202,10 @@
// | TBB
// | /
// FBB
- BBI.Kind = ICTriangleEntry;
- TrueBBI.Kind = FalseBBI.Kind = ICTriangle;
- } else if (TrueBBI.TrueBB == FalseBBI.TrueBB) {
+ BBI.Kind = ICTriangle;
+ TrueBBI.Kind = FalseBBI.Kind = ICChild;
+ } else if (TrueBBI.TrueBB == FalseBBI.TrueBB &&
+ TrueNumPreds <= 1 && FalseNumPreds <= 1) {
// Diamond:
// EBB
// / \_
@@ -204,8 +214,8 @@
// \ /
// TailBB
// Note MBB can be empty in case both TBB and FBB are return blocks.
- BBI.Kind = ICDiamondEntry;
- TrueBBI.Kind = FalseBBI.Kind = ICDiamond;
+ BBI.Kind = ICDiamond;
+ TrueBBI.Kind = FalseBBI.Kind = ICChild;
BBI.TailBB = TrueBBI.TrueBB;
}
return;
@@ -245,8 +255,14 @@
MachineBasicBlock *BB = *DFI;
StructuralAnalysis(BB);
BBInfo &BBI = BBAnalysis[BB->getNumber()];
- if (BBI.Kind == ICTriangleEntry || BBI.Kind == ICDiamondEntry)
+ switch (BBI.Kind) {
+ default: break;
+ case ICEarlyExit:
+ case ICTriangle:
+ case ICDiamond:
Candidates.push_back(&BBI);
+ break;
+ }
}
}
@@ -276,54 +292,107 @@
}
}
+/// isNextBlock - Returns true if ToBB the next basic block after BB.
+///
+static bool isNextBlock(MachineBasicBlock *BB, MachineBasicBlock *ToBB) {
+ MachineFunction::iterator Fallthrough = BB;
+ return MachineFunction::iterator(ToBB) == ++Fallthrough;
+}
+
+/// IfConvertEarlyExit - If convert a early exit sub-CFG.
+///
+bool IfConverter::IfConvertEarlyExit(BBInfo &BBI) {
+ BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
+ BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
+ BBInfo *CvtBBI = &TrueBBI;
+ BBInfo *NextBBI = &FalseBBI;
+ bool ReserveCond = false;
+ if (TrueBBI.Kind != ICChild) {
+ std::swap(CvtBBI, NextBBI);
+ ReserveCond = true;
+ }
+
+ FeasibilityAnalysis(*CvtBBI);
+ if (!CvtBBI->isPredicable) {
+ BBI.Kind = ICNotClassfied;
+ return false;
+ }
+
+ std::vector<MachineOperand> NewCond(BBI.Cond);
+ if (ReserveCond)
+ TII->ReverseBranchCondition(NewCond);
+ PredicateBlock(CvtBBI->BB, NewCond);
+
+ // Merge converted block into entry block. Also convert the end of the
+ // block conditional branch (to the non-converted block) into an
+ // unconditional one.
+ BBI.Size -= TII->RemoveBranch(*BBI.BB);
+ BBI.BB->removeSuccessor(CvtBBI->BB);
+ MergeBlocks(BBI, *CvtBBI);
+ if (!isNextBlock(BBI.BB, NextBBI->BB)) {
+ std::vector<MachineOperand> NoCond;
+ TII->InsertBranch(*BBI.BB, NextBBI->BB, NULL, NoCond);
+ }
+
+ // Update block info.
+ CvtBBI->Kind = ICDead;
+
+ // FIXME: Must maintain LiveIns.
+ NumIfConvBBs++;
+ return true;
+}
+
/// IfConvertTriangle - If convert a triangle sub-CFG.
///
bool IfConverter::IfConvertTriangle(BBInfo &BBI) {
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
FeasibilityAnalysis(TrueBBI);
- if (TrueBBI.isPredicable) {
- BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
+ if (!TrueBBI.isPredicable) {
+ BBI.Kind = ICNotClassfied;
+ return false;
+ }
- // Predicate the 'true' block after removing its branch.
- TrueBBI.Size -= TII->RemoveBranch(*BBI.TrueBB);
- PredicateBlock(BBI.TrueBB, BBI.Cond);
-
- // Join the 'true' and 'false' blocks by copying the instructions
- // from the 'false' block to the 'true' block.
- BBI.TrueBB->removeSuccessor(BBI.FalseBB);
- MergeBlocks(TrueBBI, FalseBBI);
+ // Predicate the 'true' block after removing its branch.
+ TrueBBI.Size -= TII->RemoveBranch(*BBI.TrueBB);
+ PredicateBlock(BBI.TrueBB, BBI.Cond);
+
+ // Join the 'true' and 'false' blocks by copying the instructions
+ // from the 'false' block to the 'true' block.
+ BBI.TrueBB->removeSuccessor(BBI.FalseBB);
+ BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
+ MergeBlocks(TrueBBI, FalseBBI);
- // Now merge the entry of the triangle with the true block.
- BBI.Size -= TII->RemoveBranch(*BBI.BB);
- MergeBlocks(BBI, TrueBBI);
-
- // Update block info.
- TrueBBI.Kind = ICInvalid;
- FalseBBI.Kind = ICInvalid;
-
- // FIXME: Must maintain LiveIns.
- NumIfConvBBs++;
- return true;
- }
- return false;
+ // Now merge the entry of the triangle with the true block.
+ BBI.Size -= TII->RemoveBranch(*BBI.BB);
+ MergeBlocks(BBI, TrueBBI);
+
+ // Update block info.
+ TrueBBI.Kind = ICDead;
+
+ // FIXME: Must maintain LiveIns.
+ NumIfConvBBs++;
+ return true;
}
/// IfConvertDiamond - If convert a diamond sub-CFG.
///
bool IfConverter::IfConvertDiamond(BBInfo &BBI) {
+ bool TrueNeedCBr;
+ bool FalseNeedCBr;
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
FeasibilityAnalysis(TrueBBI);
FeasibilityAnalysis(FalseBBI);
- if (TrueBBI.isPredicable && FalseBBI.isPredicable) {
+ SmallVector<MachineInstr*, 2> Dups;
+ bool Proceed = TrueBBI.isPredicable && FalseBBI.isPredicable;
+ if (Proceed) {
// Check the 'true' and 'false' blocks if either isn't ended with a branch.
// Either the block fallthrough to another block or it ends with a
// return. If it's the former, add a conditional branch to its successor.
- bool Proceed = true;
- bool TrueNeedCBr = !TrueBBI.TrueBB && BBI.TrueBB->succ_size();
- bool FalseNeedCBr = !FalseBBI.TrueBB && BBI.FalseBB->succ_size();
+ TrueNeedCBr = !TrueBBI.TrueBB && BBI.TrueBB->succ_size();
+ FalseNeedCBr = !FalseBBI.TrueBB && BBI.FalseBB->succ_size();
if (TrueNeedCBr && TrueBBI.ClobbersPred) {
TrueBBI.isPredicable = false;
Proceed = false;
@@ -332,102 +401,118 @@
FalseBBI.isPredicable = false;
Proceed = false;
}
- if (!Proceed)
- return false;
- std::vector<MachineInstr*> Dups;
- if (!BBI.TailBB) {
- // No common merge block. Check if the terminators (e.g. return) are
- // the same or predicable.
- MachineBasicBlock::iterator TT = BBI.TrueBB->getFirstTerminator();
- MachineBasicBlock::iterator FT = BBI.FalseBB->getFirstTerminator();
- while (TT != BBI.TrueBB->end() && FT != BBI.FalseBB->end()) {
- if (TT->isIdenticalTo(FT))
- Dups.push_back(TT); // Will erase these later.
- else if (!TT->isPredicable() && !FT->isPredicable())
- return false; // Can't if-convert. Abort!
- ++TT;
- ++FT;
+ if (Proceed) {
+ if (!BBI.TailBB) {
+ // No common merge block. Check if the terminators (e.g. return) are
+ // the same or predicable.
+ MachineBasicBlock::iterator TT = BBI.TrueBB->getFirstTerminator();
+ MachineBasicBlock::iterator FT = BBI.FalseBB->getFirstTerminator();
+ while (TT != BBI.TrueBB->end() && FT != BBI.FalseBB->end()) {
+ if (TT->isIdenticalTo(FT))
+ Dups.push_back(TT); // Will erase these later.
+ else if (!TT->isPredicable() && !FT->isPredicable()) {
+ Proceed = false;
+ break; // Can't if-convert. Abort!
+ }
+ ++TT;
+ ++FT;
+ }
+
+ // One of the two pathes have more terminators, make sure they are
+ // all predicable.
+ while (Proceed && TT != BBI.TrueBB->end())
+ if (!TT->isPredicable()) {
+ Proceed = false;
+ break; // Can't if-convert. Abort!
+ }
+ while (Proceed && FT != BBI.FalseBB->end())
+ if (!FT->isPredicable()) {
+ Proceed = false;
+ break; // Can't if-convert. Abort!
+ }
}
- // One of the two pathes have more terminators, make sure they are all
- // predicable.
- while (TT != BBI.TrueBB->end())
- if (!TT->isPredicable())
- return false; // Can't if-convert. Abort!
- while (FT != BBI.FalseBB->end())
- if (!FT->isPredicable())
- return false; // Can't if-convert. Abort!
}
+ }
- // Remove the duplicated instructions from the 'true' block.
- for (unsigned i = 0, e = Dups.size(); i != e; ++i) {
- Dups[i]->eraseFromParent();
- --TrueBBI.Size;
- }
-
- // Predicate the 'true' block after removing its branch.
- TrueBBI.Size -= TII->RemoveBranch(*BBI.TrueBB);
- PredicateBlock(BBI.TrueBB, BBI.Cond);
-
- // Add a conditional branch to 'true' successor if needed.
- if (TrueNeedCBr)
- TII->InsertBranch(*BBI.TrueBB, *BBI.TrueBB->succ_begin(), NULL, BBI.Cond);
-
- // Predicate the 'false' block.
- std::vector<MachineOperand> NewCond(BBI.Cond);
- TII->ReverseBranchCondition(NewCond);
- PredicateBlock(BBI.FalseBB, NewCond, true);
-
- // Add a conditional branch to 'false' successor if needed.
- if (FalseNeedCBr)
- TII->InsertBranch(*BBI.FalseBB, *BBI.FalseBB->succ_begin(), NULL,NewCond);
-
- // Merge the 'true' and 'false' blocks by copying the instructions
- // from the 'false' block to the 'true' block. That is, unless the true
- // block would clobber the predicate, in that case, do the opposite.
- BBInfo *CvtBBI;
- if (!TrueBBI.ClobbersPred) {
- MergeBlocks(TrueBBI, FalseBBI);
- CvtBBI = &TrueBBI;
- } else {
- MergeBlocks(FalseBBI, TrueBBI);
- CvtBBI = &FalseBBI;
- }
+ if (!Proceed) {
+ BBI.Kind = ICNotClassfied;
+ return false;
+ }
- // Remove the conditional branch from entry to the blocks.
- BBI.Size -= TII->RemoveBranch(*BBI.BB);
+ // Remove the duplicated instructions from the 'true' block.
+ for (unsigned i = 0, e = Dups.size(); i != e; ++i) {
+ Dups[i]->eraseFromParent();
+ --TrueBBI.Size;
+ }
+
+ // Predicate the 'true' block after removing its branch.
+ TrueBBI.Size -= TII->RemoveBranch(*BBI.TrueBB);
+ PredicateBlock(BBI.TrueBB, BBI.Cond);
+
+ // Add a conditional branch to 'true' successor if needed.
+ if (TrueNeedCBr && TrueBBI.ClobbersPred &&
+ isNextBlock(BBI.TrueBB, *BBI.TrueBB->succ_begin()))
+ TrueNeedCBr = false;
+ if (TrueNeedCBr)
+ TII->InsertBranch(*BBI.TrueBB, *BBI.TrueBB->succ_begin(), NULL, BBI.Cond);
+
+ // Predicate the 'false' block.
+ std::vector<MachineOperand> NewCond(BBI.Cond);
+ TII->ReverseBranchCondition(NewCond);
+ PredicateBlock(BBI.FalseBB, NewCond, true);
+
+ // Add a conditional branch to 'false' successor if needed.
+ if (FalseNeedCBr && !TrueBBI.ClobbersPred &&
+ isNextBlock(BBI.FalseBB, *BBI.FalseBB->succ_begin()))
+ FalseNeedCBr = false;
+ if (FalseNeedCBr)
+ TII->InsertBranch(*BBI.FalseBB, *BBI.FalseBB->succ_begin(), NULL,NewCond);
+
+ // Merge the 'true' and 'false' blocks by copying the instructions
+ // from the 'false' block to the 'true' block. That is, unless the true
+ // block would clobber the predicate, in that case, do the opposite.
+ BBInfo *CvtBBI;
+ if (!TrueBBI.ClobbersPred) {
+ MergeBlocks(TrueBBI, FalseBBI);
+ CvtBBI = &TrueBBI;
+ } else {
+ MergeBlocks(FalseBBI, TrueBBI);
+ CvtBBI = &FalseBBI;
+ }
- // Merge the combined block into the entry of the diamond if the entry
- // block is its only predecessor. Otherwise, insert an unconditional
- // branch from entry to the if-converted block.
- if (CvtBBI->BB->pred_size() == 1) {
- BBI.BB->removeSuccessor(CvtBBI->BB);
- MergeBlocks(BBI, *CvtBBI);
- CvtBBI = &BBI;
- } else {
- std::vector<MachineOperand> NoCond;
- TII->InsertBranch(*BBI.BB, CvtBBI->BB, NULL, NoCond);
- }
+ // Remove the conditional branch from entry to the blocks.
+ BBI.Size -= TII->RemoveBranch(*BBI.BB);
- // If the if-converted block fallthrough into the tail block, then
- // fold the tail block in as well.
- if (BBI.TailBB && CvtBBI->BB->succ_size() == 1) {
- CvtBBI->Size -= TII->RemoveBranch(*CvtBBI->BB);
- CvtBBI->BB->removeSuccessor(BBI.TailBB);
- BBInfo TailBBI = BBAnalysis[BBI.TailBB->getNumber()];
- MergeBlocks(*CvtBBI, TailBBI);
- TailBBI.Kind = ICInvalid;
- }
+ // Merge the combined block into the entry of the diamond if the entry
+ // block is its only predecessor. Otherwise, insert an unconditional
+ // branch from entry to the if-converted block.
+ if (CvtBBI->BB->pred_size() == 1) {
+ BBI.BB->removeSuccessor(CvtBBI->BB);
+ MergeBlocks(BBI, *CvtBBI);
+ CvtBBI = &BBI;
+ } else {
+ std::vector<MachineOperand> NoCond;
+ TII->InsertBranch(*BBI.BB, CvtBBI->BB, NULL, NoCond);
+ }
- // Update block info.
- TrueBBI.Kind = ICInvalid;
- FalseBBI.Kind = ICInvalid;
-
- // FIXME: Must maintain LiveIns.
- NumIfConvBBs += 2;
- return true;
+ // If the if-converted block fallthrough into the tail block, then
+ // fold the tail block in as well.
+ if (BBI.TailBB && CvtBBI->BB->succ_size() == 1) {
+ CvtBBI->Size -= TII->RemoveBranch(*CvtBBI->BB);
+ CvtBBI->BB->removeSuccessor(BBI.TailBB);
+ BBInfo TailBBI = BBAnalysis[BBI.TailBB->getNumber()];
+ MergeBlocks(*CvtBBI, TailBBI);
+ TailBBI.Kind = ICDead;
}
- return false;
+
+ // Update block info.
+ TrueBBI.Kind = ICDead;
+ FalseBBI.Kind = ICDead;
+
+ // FIXME: Must maintain LiveIns.
+ NumIfConvBBs += 2;
+ return true;
}
/// PredicateBlock - Predicate every instruction in the block with the specified
More information about the llvm-commits
mailing list