Newer
Older
//===-- IfConversion.cpp - Machine code if conversion pass. ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the Evan Cheng and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the machine instruction level if-conversion pass.
//
//===----------------------------------------------------------------------===//
Evan Cheng
committed
#define DEBUG_TYPE "ifcvt"
#include "llvm/Function.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
STATISTIC(NumSimple, "Number of simple if-conversions performed");
STATISTIC(NumSimpleRev, "Number of simple (reversed) if-conversions performed");
STATISTIC(NumTriangle, "Number of triangle if-conversions performed");
STATISTIC(NumDiamonds, "Number of diamond if-conversions performed");
STATISTIC(NumIfConvBBs, "Number of if-converted blocks");
namespace {
class IfConverter : public MachineFunctionPass {
enum BBICKind {
ICNotAnalyzed, // BB has not been analyzed.
ICReAnalyze, // BB must be re-analyzed.
ICNotClassfied, // BB data valid, but not classified.
ICSimple, // BB is entry of an one split, no rejoin sub-CFG.
ICSimpleFalse, // Same as ICSimple, but on the false path.
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
/// if-conversion feasibility analysis. This includes results from
/// TargetInstrInfo::AnalyzeBranch() (i.e. TBB, FBB, and Cond), and its
/// classification, and common tail block of its successors (if it's a
/// diamond shape), its size, whether it's predicable, and whether any
/// instruction can clobber the 'would-be' predicate.
///
/// Kind - Type of block. See BBICKind.
/// NonPredSize - Number of non-predicated instructions.
/// IsAnalyzable - True if AnalyzeBranch() returns false.
/// ModifyPredicate - FIXME: Not used right now. True if BB would modify
/// the predicate (e.g. has cmp, call, etc.)
/// BB - Corresponding MachineBasicBlock.
/// TrueBB / FalseBB- See AnalyzeBranch().
/// BrCond - Conditions for end of block conditional branches.
/// Predicate - Predicate used in the BB.
struct BBInfo {
BBICKind Kind;
bool IsAnalyzable;
MachineBasicBlock *BB;
MachineBasicBlock *TrueBB;
MachineBasicBlock *FalseBB;
MachineBasicBlock *TailBB;
std::vector<MachineOperand> BrCond;
std::vector<MachineOperand> Predicate;
BBInfo() : Kind(ICNotAnalyzed), NonPredSize(0),
IsAnalyzable(false), ModifyPredicate(false),
BB(0), TrueBB(0), FalseBB(0), TailBB(0) {}
Evan Cheng
committed
/// Roots - Basic blocks that do not have successors. These are the starting
/// points of Graph traversal.
std::vector<MachineBasicBlock*> Roots;
/// BBAnalysis - Results of if-conversion feasibility analysis indexed by
/// basic block number.
std::vector<BBInfo> BBAnalysis;
const TargetLowering *TLI;
const TargetInstrInfo *TII;
bool MadeChange;
public:
static char ID;
IfConverter() : MachineFunctionPass((intptr_t)&ID) {}
virtual bool runOnMachineFunction(MachineFunction &MF);
virtual const char *getPassName() const { return "If converter"; }
private:
bool ReverseBranchCondition(BBInfo &BBI);
void StructuralAnalysis(MachineBasicBlock *BB);
bool FeasibilityAnalysis(BBInfo &BBI,
std::vector<MachineOperand> &Cond,
bool IgnoreTerm = false);
Evan Cheng
committed
bool AttemptRestructuring(BBInfo &BBI);
bool AnalyzeBlocks(MachineFunction &MF,
std::vector<BBInfo*> &Candidates);
Evan Cheng
committed
void ReTryPreds(MachineBasicBlock *BB);
bool IfConvertSimple(BBInfo &BBI);
bool IfConvertTriangle(BBInfo &BBI);
bool IfConvertDiamond(BBInfo &BBI);
void PredicateBlock(BBInfo &BBI,
std::vector<MachineOperand> &Cond,
bool IgnoreTerm = false);
void MergeBlocks(BBInfo &TrueBBI, BBInfo &FalseBBI);
Evan Cheng
committed
// IfcvtCandidateCmp - Used to sort if-conversion candidates.
static bool IfcvtCandidateCmp(BBInfo* C1, BBInfo* C2){
// Favor diamond over triangle, etc.
return (unsigned)C1->Kind < (unsigned)C2->Kind;
}
};
char IfConverter::ID = 0;
}
FunctionPass *llvm::createIfConverterPass() { return new IfConverter(); }
bool IfConverter::runOnMachineFunction(MachineFunction &MF) {
TLI = MF.getTarget().getTargetLowering();
TII = MF.getTarget().getInstrInfo();
if (!TII) return false;
Evan Cheng
committed
DOUT << "\nIfcvt: function \'" << MF.getFunction()->getName() << "\'\n";
Evan Cheng
committed
BBAnalysis.resize(MF.getNumBlockIDs());
Evan Cheng
committed
// Look for root nodes, i.e. blocks without successors.
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
if (I->succ_size() == 0)
Roots.push_back(I);
Evan Cheng
committed
MadeChange = false;
while (true) {
// Do an intial analysis for each basic block and finding all the potential
// candidates to perform if-convesion.
bool Change = AnalyzeBlocks(MF, Candidates);
while (!Candidates.empty()) {
BBInfo &BBI = *Candidates.back();
Candidates.pop_back();
bool RetVal = false;
switch (BBI.Kind) {
default: assert(false && "Unexpected!");
break;
Evan Cheng
committed
case ICReAnalyze:
Evan Cheng
committed
// One or more of 'children' have been modified, abort!
case ICDead:
// Block has been already been if-converted, abort!
Evan Cheng
committed
break;
case ICSimple:
case ICSimpleFalse:
DOUT << "Ifcvt (Simple" << (BBI.Kind == ICSimpleFalse ? " false" : "")
<< "): BB#" << BBI.BB->getNumber() << " ";
RetVal = IfConvertSimple(BBI);
DOUT << (RetVal ? "succeeded!" : "failed!") << "\n";
if (RetVal)
if (BBI.Kind == ICSimple) NumSimple++;
else NumSimpleRev++;
break;
DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << " ";
RetVal = IfConvertTriangle(BBI);
DOUT << (RetVal ? "succeeded!" : "failed!") << "\n";
if (RetVal) NumTriangle++;
DOUT << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " ";
RetVal = IfConvertDiamond(BBI);
DOUT << (RetVal ? "succeeded!" : "failed!") << "\n";
if (RetVal) NumDiamonds++;
Change |= RetVal;
MadeChange |= Change;
Evan Cheng
committed
Evan Cheng
committed
Roots.clear();
Evan Cheng
committed
BBAnalysis.clear();
return MadeChange;
}
static MachineBasicBlock *findFalseBlock(MachineBasicBlock *BB,
MachineBasicBlock *TrueBB) {
for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),
E = BB->succ_end(); SI != E; ++SI) {
MachineBasicBlock *SuccBB = *SI;
if (SuccBB != TrueBB)
return SuccBB;
}
return NULL;
}
bool IfConverter::ReverseBranchCondition(BBInfo &BBI) {
if (!TII->ReverseBranchCondition(BBI.BrCond)) {
TII->RemoveBranch(*BBI.BB);
TII->InsertBranch(*BBI.BB, BBI.FalseBB, BBI.TrueBB, BBI.BrCond);
std::swap(BBI.TrueBB, BBI.FalseBB);
return true;
}
return false;
}
/// StructuralAnalysis - Analyze the structure of the sub-CFG starting from
/// the specified block. Record its successors and whether it looks like an
/// if-conversion candidate.
void IfConverter::StructuralAnalysis(MachineBasicBlock *BB) {
BBInfo &BBI = BBAnalysis[BB->getNumber()];
Evan Cheng
committed
if (BBI.Kind == ICReAnalyze) {
BBI.BrCond.clear();
Evan Cheng
committed
BBI.TrueBB = BBI.FalseBB = NULL;
} else {
if (BBI.Kind != ICNotAnalyzed)
return; // Already analyzed.
BBI.BB = BB;
BBI.NonPredSize = std::distance(BB->begin(), BB->end());
}
// Look for 'root' of a simple (non-nested) triangle or diamond.
BBI.Kind = ICNotClassfied;
BBI.IsAnalyzable =
!TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond);
if (!BBI.IsAnalyzable || BBI.BrCond.size() == 0)
Evan Cheng
committed
// Do not ifcvt if either path is a back edge to the entry block.
if (BBI.TrueBB == BB || BBI.FalseBB == BB)
return;
StructuralAnalysis(BBI.TrueBB);
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
// No false branch. This BB must end with a conditional branch and a
// fallthrough.
if (!BBI.FalseBB)
BBI.FalseBB = findFalseBlock(BB, BBI.TrueBB);
assert(BBI.FalseBB && "Expected to find the fallthrough block!");
StructuralAnalysis(BBI.FalseBB);
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
// Look for more opportunities to if-convert a triangle. Try to restructure
// the CFG to form a triangle with the 'false' path.
std::vector<MachineOperand> RevCond(BBI.BrCond);
bool CanRevCond = !TII->ReverseBranchCondition(RevCond);
if (FalseBBI.FalseBB) {
if (TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB)
return;
std::vector<MachineOperand> Cond(BBI.BrCond);
if (CanRevCond &&
FalseBBI.TrueBB && FalseBBI.BB->pred_size() == 1 &&
FeasibilityAnalysis(FalseBBI, RevCond, true)) {
std::vector<MachineOperand> FalseCond(FalseBBI.BrCond);
if (FalseBBI.TrueBB == BBI.TrueBB &&
TII->SubsumesPredicate(FalseCond, BBI.BrCond)) {
// Reverse 'true' and 'false' paths.
ReverseBranchCondition(BBI);
BBI.Kind = ICTriangle;
FalseBBI.Kind = ICChild;
} else if (FalseBBI.FalseBB == BBI.TrueBB &&
!TII->ReverseBranchCondition(FalseCond) &&
TII->SubsumesPredicate(FalseCond, BBI.BrCond)) {
// Reverse 'false' block's 'true' and 'false' paths and then
// reverse 'true' and 'false' paths.
ReverseBranchCondition(FalseBBI);
ReverseBranchCondition(BBI);
BBI.Kind = ICTriangle;
FalseBBI.Kind = ICChild;
}
}
} else if (TrueBBI.TrueBB == FalseBBI.TrueBB && CanRevCond &&
TrueBBI.BB->pred_size() == 1 &&
TrueBBI.BB->pred_size() == 1 &&
// Check the 'true' and 'false' blocks if either isn't ended with
// a branch. If the block does not fallthrough to another block
// then we need to add a branch to its successor.
!(TrueBBI.ModifyPredicate &&
!TrueBBI.TrueBB && TrueBBI.BB->succ_size()) &&
!(FalseBBI.ModifyPredicate &&
!FalseBBI.TrueBB && FalseBBI.BB->succ_size()) &&
FeasibilityAnalysis(TrueBBI, BBI.BrCond) &&
FeasibilityAnalysis(FalseBBI, RevCond)) {
// Diamond:
// EBB
// / \_
// | |
// TBB FBB
// \ /
// Note MBB can be empty in case both TBB and FBB are return blocks.
BBI.Kind = ICDiamond;
TrueBBI.Kind = FalseBBI.Kind = ICChild;
BBI.TailBB = TrueBBI.TrueBB;
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
} else {
// FIXME: Consider duplicating if BB is small.
bool TryTriangle = TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB &&
BBI.TrueBB->pred_size() == 1;
bool TrySimple = TrueBBI.BrCond.size() == 0 && BBI.TrueBB->pred_size() == 1;
if ((TryTriangle || TrySimple) &&
FeasibilityAnalysis(TrueBBI, BBI.BrCond)) {
if (TryTriangle) {
// Triangle:
// EBB
// | \_
// | |
// | TBB
// | /
// FBB
BBI.Kind = ICTriangle;
TrueBBI.Kind = ICChild;
} else {
// Simple (split, no rejoin):
// EBB
// | \_
// | |
// | TBB---> exit
// |
// FBB
BBI.Kind = ICSimple;
TrueBBI.Kind = ICChild;
}
} else if (FalseBBI.BrCond.size() == 0 && BBI.FalseBB->pred_size() == 1) {
// Try 'simple' on the other path...
std::vector<MachineOperand> RevCond(BBI.BrCond);
if (TII->ReverseBranchCondition(RevCond))
assert(false && "Unable to reverse branch condition!");
if (FeasibilityAnalysis(FalseBBI, RevCond)) {
BBI.Kind = ICSimpleFalse;
FalseBBI.Kind = ICChild;
}
}
/// FeasibilityAnalysis - Determine if the block is predicable. In most
/// cases, that means all the instructions in the block has M_PREDICABLE flag.
/// Also checks if the block contains any instruction which can clobber a
/// predicate (e.g. condition code register). If so, the block is not
/// predicable unless it's the last instruction. If IgnoreTerm is true then
/// all the terminator instructions are skipped.
bool IfConverter::FeasibilityAnalysis(BBInfo &BBI,
std::vector<MachineOperand> &Cond,
bool IgnoreTerm) {
// If the block is dead, or it is going to be the entry block of a sub-CFG
// that will be if-converted, then it cannot be predicated.
if (BBI.Kind != ICNotAnalyzed &&
BBI.Kind != ICNotClassfied &&
BBI.Kind != ICChild)
return false;
// Check predication threshold.
if (BBI.NonPredSize == 0 || BBI.NonPredSize > TLI->getIfCvtBlockSizeLimit())
return false;
// If it is already predicated, check if its predicate subsumes the new
// predicate.
if (BBI.Predicate.size() && !TII->SubsumesPredicate(BBI.Predicate, Cond))
return false;
for (MachineBasicBlock::iterator I = BBI.BB->begin(), E = BBI.BB->end();
I != E; ++I) {
if (IgnoreTerm && TII->isTerminatorInstr(I->getOpcode()))
continue;
// TODO: check if instruction clobbers predicate.
if (!I->isPredicable())
return false;
return true;
Evan Cheng
committed
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/// AttemptRestructuring - Restructure the sub-CFG rooted in the given block to
/// expose more if-conversion opportunities. e.g.
///
/// cmp
/// b le BB1
/// / \____
/// / |
/// cmp |
/// b eq BB1 |
/// / \____ |
/// / \ |
/// BB1
/// ==>
///
/// cmp
/// b eq BB1
/// / \____
/// / |
/// cmp |
/// b le BB1 |
/// / \____ |
/// / \ |
/// BB1
bool IfConverter::AttemptRestructuring(BBInfo &BBI) {
return false;
}
/// AnalyzeBlocks - Analyze all blocks and find entries for all if-conversion
/// candidates. It returns true if any CFG restructuring is done to expose more
/// if-conversion opportunities.
bool IfConverter::AnalyzeBlocks(MachineFunction &MF,
std::vector<BBInfo*> &Candidates) {
Evan Cheng
committed
bool Change = false;
Evan Cheng
committed
for (unsigned i = 0, e = Roots.size(); i != e; ++i) {
for (idf_ext_iterator<MachineBasicBlock*> I=idf_ext_begin(Roots[i],Visited),
E = idf_ext_end(Roots[i], Visited); I != E; ++I) {
MachineBasicBlock *BB = *I;
StructuralAnalysis(BB);
BBInfo &BBI = BBAnalysis[BB->getNumber()];
switch (BBI.Kind) {
case ICSimple:
case ICSimpleFalse:
Evan Cheng
committed
case ICTriangle:
case ICDiamond:
Candidates.push_back(&BBI);
break;
default:
Change |= AttemptRestructuring(BBI);
break;
}
Evan Cheng
committed
Evan Cheng
committed
// Sort to favor more complex ifcvt scheme.
std::stable_sort(Candidates.begin(), Candidates.end(), IfcvtCandidateCmp);
Evan Cheng
committed
return Change;
/// isNextBlock - Returns true either if ToBB the next block after BB or
/// that all the intervening blocks are empty.
static bool isNextBlock(MachineBasicBlock *BB, MachineBasicBlock *ToBB) {
MachineFunction::iterator I = BB;
MachineFunction::iterator TI = ToBB;
MachineFunction::iterator E = BB->getParent()->end();
while (++I != TI)
if (I == E || !I->empty())
return false;
return true;
Evan Cheng
committed
/// ReTryPreds - Invalidate predecessor BB info so it would be re-analyzed
/// to determine if it can be if-converted.
Evan Cheng
committed
void IfConverter::ReTryPreds(MachineBasicBlock *BB) {
for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(),
E = BB->pred_end(); PI != E; ++PI) {
BBInfo &PBBI = BBAnalysis[(*PI)->getNumber()];
PBBI.Kind = ICReAnalyze;
}
}
Evan Cheng
committed
/// InsertUncondBranch - Inserts an unconditional branch from BB to ToBB.
///
static void InsertUncondBranch(MachineBasicBlock *BB, MachineBasicBlock *ToBB,
const TargetInstrInfo *TII) {
std::vector<MachineOperand> NoCond;
TII->InsertBranch(*BB, ToBB, NULL, NoCond);
}
/// IfConvertSimple - If convert a simple (split, no rejoin) sub-CFG.
bool IfConverter::IfConvertSimple(BBInfo &BBI) {
bool ReverseCond = BBI.Kind == ICSimpleFalse;
BBI.Kind = ICNotClassfied;
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
BBInfo *CvtBBI = &TrueBBI;
BBInfo *NextBBI = &FalseBBI;
std::vector<MachineOperand> Cond(BBI.BrCond);
if (ReverseCond) {
std::swap(CvtBBI, NextBBI);
TII->ReverseBranchCondition(Cond);
PredicateBlock(*CvtBBI, Cond);
// If the 'true' block ends without a branch, add a conditional branch
// to its successor unless that happens to be the 'false' block.
if (CvtBBI->IsAnalyzable && CvtBBI->TrueBB == NULL) {
assert(CvtBBI->BB->succ_size() == 1 && "Unexpected!");
MachineBasicBlock *SuccBB = *CvtBBI->BB->succ_begin();
if (SuccBB != NextBBI->BB)
TII->InsertBranch(*CvtBBI->BB, SuccBB, NULL, Cond);
}
// Merge converted block into entry block. Also add an unconditional branch
// to the 'false' branch.
BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB);
MergeBlocks(BBI, *CvtBBI);
Evan Cheng
committed
if (!isNextBlock(BBI.BB, NextBBI->BB))
InsertUncondBranch(BBI.BB, NextBBI->BB, TII);
std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate));
// Update block info. BB can be iteratively if-converted.
Evan Cheng
committed
BBI.Kind = ICReAnalyze;
Evan Cheng
committed
ReTryPreds(BBI.BB);
CvtBBI->Kind = ICDead;
// FIXME: Must maintain LiveIns.
return true;
}
/// IfConvertTriangle - If convert a triangle sub-CFG.
///
bool IfConverter::IfConvertTriangle(BBInfo &BBI) {
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
// Predicate the 'true' block after removing its branch.
TrueBBI.NonPredSize -= TII->RemoveBranch(*BBI.TrueBB);
PredicateBlock(TrueBBI, BBI.BrCond);
// If 'true' block has a 'false' successor, add an exit branch to it.
Evan Cheng
committed
bool HasEarlyExit = TrueBBI.FalseBB != NULL;
if (HasEarlyExit) {
std::vector<MachineOperand> RevCond(TrueBBI.BrCond);
if (TII->ReverseBranchCondition(RevCond))
assert(false && "Unable to reverse branch condition!");
TII->InsertBranch(*BBI.TrueBB, TrueBBI.FalseBB, NULL, RevCond);
}
// Join the 'true' and 'false' blocks if the 'false' block has no other
// predecessors. Otherwise, add a unconditional branch from 'true' to 'false'.
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
Evan Cheng
committed
bool FalseBBDead = false;
Evan Cheng
committed
if (!HasEarlyExit && FalseBBI.BB->pred_size() == 2) {
MergeBlocks(TrueBBI, FalseBBI);
Evan Cheng
committed
FalseBBDead = true;
} else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB))
InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII);
// Now merge the entry of the triangle with the true block.
BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB);
MergeBlocks(BBI, TrueBBI);
std::copy(BBI.BrCond.begin(), BBI.BrCond.end(),
std::back_inserter(BBI.Predicate));
// Update block info. BB can be iteratively if-converted.
Evan Cheng
committed
BBI.Kind = ICReAnalyze;
Evan Cheng
committed
ReTryPreds(BBI.BB);
TrueBBI.Kind = ICDead;
Evan Cheng
committed
if (FalseBBDead)
FalseBBI.Kind = ICDead;
// FIXME: Must maintain LiveIns.
return true;
/// IfConvertDiamond - If convert a diamond sub-CFG.
///
bool IfConverter::IfConvertDiamond(BBInfo &BBI) {
BBI.Kind = ICNotClassfied;
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
SmallVector<MachineInstr*, 2> 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;
// 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!
++TT;
}
while (FT != BBI.FalseBB->end()) {
if (!FT->isPredicable()) {
return false; // Can't if-convert. Abort!
}
++FT;
// Remove the duplicated instructions from the 'true' block.
for (unsigned i = 0, e = Dups.size(); i != e; ++i) {
Dups[i]->eraseFromParent();
// 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 branch to its successor.
bool TrueNeedBr = !TrueBBI.TrueBB && BBI.TrueBB->succ_size();
bool FalseNeedBr = !FalseBBI.TrueBB && BBI.FalseBB->succ_size();
// 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.
std::vector<MachineOperand> RevCond(BBI.BrCond);
TII->ReverseBranchCondition(RevCond);
BBInfo *CvtBBI;
if (!TrueBBI.ModifyPredicate) {
// Predicate the 'true' block after removing its branch.
TrueBBI.NonPredSize -= TII->RemoveBranch(*BBI.TrueBB);
PredicateBlock(TrueBBI, BBI.BrCond);
// Predicate the 'false' block.
PredicateBlock(FalseBBI, RevCond, true);
Evan Cheng
committed
if (TrueNeedBr)
TII->InsertBranch(*BBI.TrueBB, *BBI.TrueBB->succ_begin(), NULL,
BBI.BrCond);
// Add an unconditional branch from 'false' to to 'false' successor if it
// will not be the fallthrough block.
if (FalseNeedBr &&
!isNextBlock(BBI.BB, *BBI.FalseBB->succ_begin()))
InsertUncondBranch(BBI.FalseBB, *BBI.FalseBB->succ_begin(), TII);
MergeBlocks(TrueBBI, FalseBBI);
CvtBBI = &TrueBBI;
} else {
// Predicate the 'false' block after removing its branch.
FalseBBI.NonPredSize -= TII->RemoveBranch(*BBI.FalseBB);
PredicateBlock(FalseBBI, RevCond);
// Predicate the 'false' block.
PredicateBlock(TrueBBI, BBI.BrCond, true);
Evan Cheng
committed
// Add a conditional branch from 'false' to 'false' successor if needed.
if (FalseNeedBr)
TII->InsertBranch(*BBI.FalseBB, *BBI.FalseBB->succ_begin(), NULL,
RevCond);
// Add an unconditional branch from 'true' to to 'true' successor if it
// will not be the fallthrough block.
if (TrueNeedBr &&
!isNextBlock(BBI.BB, *BBI.TrueBB->succ_begin()))
InsertUncondBranch(BBI.TrueBB, *BBI.TrueBB->succ_begin(), TII);
MergeBlocks(FalseBBI, TrueBBI);
CvtBBI = &FalseBBI;
}
// Remove the conditional branch from entry to the blocks.
BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB);
// 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) {
MergeBlocks(BBI, *CvtBBI);
CvtBBI = &BBI;
} else if (!isNextBlock(BBI.BB, CvtBBI->BB))
Evan Cheng
committed
InsertUncondBranch(BBI.BB, CvtBBI->BB, TII);
Evan Cheng
committed
// If the if-converted block fallthrough or unconditionally branch into the
// tail block, and the tail block does not have other predecessors, then
// fold the tail block in as well.
Evan Cheng
committed
if (BBI.TailBB &&
BBI.TailBB->pred_size() == 1 && CvtBBI->BB->succ_size() == 1) {
CvtBBI->NonPredSize -= TII->RemoveBranch(*CvtBBI->BB);
BBInfo TailBBI = BBAnalysis[BBI.TailBB->getNumber()];
MergeBlocks(*CvtBBI, TailBBI);
TailBBI.Kind = ICDead;
}
// Update block info. BB may be iteratively if-converted.
if (OkToIfcvt) {
Evan Cheng
committed
BBI.Kind = ICReAnalyze;
Evan Cheng
committed
ReTryPreds(BBI.BB);
TrueBBI.Kind = ICDead;
FalseBBI.Kind = ICDead;
// FIXME: Must maintain LiveIns.
return true;
}
/// PredicateBlock - Predicate every instruction in the block with the specified
/// condition. If IgnoreTerm is true, skip over all terminator instructions.
void IfConverter::PredicateBlock(BBInfo &BBI,
std::vector<MachineOperand> &Cond,
bool IgnoreTerm) {
for (MachineBasicBlock::iterator I = BBI.BB->begin(), E = BBI.BB->end();
if (IgnoreTerm && TII->isTerminatorInstr(I->getOpcode()))
if (TII->isPredicated(I))
if (!TII->PredicateInstruction(I, Cond)) {
cerr << "Unable to predicate " << *I << "!\n";
abort();
}
NumIfConvBBs++;
}
/// TransferPreds - Transfer all the predecessors of FromBB to ToBB.
///
static void TransferPreds(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) {
for (MachineBasicBlock::pred_iterator I = FromBB->pred_begin(),
E = FromBB->pred_end(); I != E; ++I) {
MachineBasicBlock *Pred = *I;
Pred->removeSuccessor(FromBB);
if (!Pred->isSuccessor(ToBB))
Pred->addSuccessor(ToBB);
}
}
/// TransferSuccs - Transfer all the successors of FromBB to ToBB.
///
static void TransferSuccs(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) {
for (MachineBasicBlock::succ_iterator I = FromBB->succ_begin(),
E = FromBB->succ_end(); I != E; ++I) {
Evan Cheng
committed
MachineBasicBlock *Succ = *I;
FromBB->removeSuccessor(Succ);
if (!ToBB->isSuccessor(Succ))
ToBB->addSuccessor(Succ);
}
/// MergeBlocks - Move all instructions from FromBB to the end of ToBB.
void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI) {
ToBBI.BB->splice(ToBBI.BB->end(),
FromBBI.BB, FromBBI.BB->begin(), FromBBI.BB->end());
// If FromBBI is previously a successor, remove it from ToBBI's successor
// list and update its TrueBB / FalseBB field if needed.
if (ToBBI.BB->isSuccessor(FromBBI.BB))
ToBBI.BB->removeSuccessor(FromBBI.BB);
// Redirect all branches to FromBB to ToBB.
std::vector<MachineBasicBlock *> Preds(FromBBI.BB->pred_begin(),
FromBBI.BB->pred_end());
for (unsigned i = 0, e = Preds.size(); i != e; ++i)
Preds[i]->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB);
// Transfer preds / succs and update size.
TransferPreds(ToBBI.BB, FromBBI.BB);
TransferSuccs(ToBBI.BB, FromBBI.BB);
ToBBI.NonPredSize += FromBBI.NonPredSize;
FromBBI.NonPredSize = 0;