#include "llvm/CodeGen/Passes.h"
#include "BranchFolding.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LivePhysRegs.h"
cl::init(false), cl::Hidden);
static cl::opt<bool> DisableDiamond("disable-ifcvt-diamond",
cl::init(false), cl::Hidden);
-static cl::opt<bool> DisableForkedDiamond("disable-ifcvt-forked-diamond",
- cl::init(false), cl::Hidden);
static cl::opt<bool> IfCvtBranchFold("ifcvt-branch-fold",
cl::init(true), cl::Hidden);
STATISTIC(NumTriangleFalse,"Number of triangle (F) if-conversions performed");
STATISTIC(NumTriangleFRev, "Number of triangle (F/R) if-conversions performed");
STATISTIC(NumDiamonds, "Number of diamond if-conversions performed");
-STATISTIC(NumForkedDiamonds, "Number of forked-diamond if-conversions performed");
STATISTIC(NumIfConvBBs, "Number of if-converted blocks");
STATISTIC(NumDupBBs, "Number of duplicated blocks");
STATISTIC(NumUnpred, "Number of true blocks of diamonds unpredicated");
ICTriangleRev, // Same as ICTriangle, but true path rev condition.
ICTriangleFalse, // Same as ICTriangle, but on the false path.
ICTriangle, // BB is entry of a triangle sub-CFG.
- ICDiamond, // BB is entry of a diamond sub-CFG.
- ICForkedDiamond // BB is entry of an almost diamond sub-CFG, with a
- // common tail that can be shared.
+ ICDiamond // BB is entry of a diamond sub-CFG.
};
/// BBInfo - One per MachineBasicBlock, this is used to cache the result
bool IsAnalyzed : 1;
bool IsEnqueued : 1;
bool IsBrAnalyzable : 1;
- bool IsBrReversible : 1;
bool HasFallThrough : 1;
bool IsUnpredicable : 1;
bool CannotBeCopied : 1;
SmallVector<MachineOperand, 4> Predicate;
BBInfo() : IsDone(false), IsBeingAnalyzed(false),
IsAnalyzed(false), IsEnqueued(false), IsBrAnalyzable(false),
- IsBrReversible(false), HasFallThrough(false),
- IsUnpredicable(false), CannotBeCopied(false),
- ClobbersPred(false), NonPredSize(0), ExtraCost(0),
- ExtraCost2(0), BB(nullptr), TrueBB(nullptr),
+ HasFallThrough(false), IsUnpredicable(false),
+ CannotBeCopied(false), ClobbersPred(false), NonPredSize(0),
+ ExtraCost(0), ExtraCost2(0), BB(nullptr), TrueBB(nullptr),
FalseBB(nullptr) {}
};
struct IfcvtToken {
BBInfo &BBI;
IfcvtKind Kind;
+ bool NeedSubsumption;
unsigned NumDups;
unsigned NumDups2;
- bool NeedSubsumption : 1;
- bool TClobbersPred : 1;
- bool FClobbersPred : 1;
- IfcvtToken(BBInfo &b, IfcvtKind k, bool s, unsigned d, unsigned d2 = 0,
- bool tc = false, bool fc = false)
- : BBI(b), Kind(k), NumDups(d), NumDups2(d2), NeedSubsumption(s),
- TClobbersPred(tc), FClobbersPred(fc) {}
+ IfcvtToken(BBInfo &b, IfcvtKind k, bool s, unsigned d, unsigned d2 = 0)
+ : BBI(b), Kind(k), NeedSubsumption(s), NumDups(d), NumDups2(d2) {}
};
/// BBAnalysis - Results of if-conversion feasibility analysis indexed by
bool FalseBranch, unsigned &Dups,
BranchProbability Prediction) const;
bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
- unsigned &Dups1, unsigned &Dups2,
- BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const;
- bool ValidForkedDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
- unsigned &Dups1, unsigned &Dups2,
- BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const;
+ unsigned &Dups1, unsigned &Dups2) const;
void AnalyzeBranches(BBInfo &BBI);
void ScanInstructions(BBInfo &BBI,
MachineBasicBlock::iterator &Begin,
MachineBasicBlock::iterator &End) const;
- bool RescanInstructions(
- MachineBasicBlock::iterator &TIB, MachineBasicBlock::iterator &FIB,
- MachineBasicBlock::iterator &TIE, MachineBasicBlock::iterator &FIE,
- BBInfo &TrueBBI, BBInfo &FalseBBI) const;
void AnalyzeBlock(MachineBasicBlock *MBB,
std::vector<std::unique_ptr<IfcvtToken>> &Tokens);
bool FeasibilityAnalysis(BBInfo &BBI, SmallVectorImpl<MachineOperand> &Cond,
- bool isTriangle = false, bool RevBranch = false,
- bool hasCommonTail = false);
+ bool isTriangle = false, bool RevBranch = false);
void AnalyzeBlocks(MachineFunction &MF,
std::vector<std::unique_ptr<IfcvtToken>> &Tokens);
void InvalidatePreds(MachineBasicBlock *BB);
void RemoveExtraEdges(BBInfo &BBI);
bool IfConvertSimple(BBInfo &BBI, IfcvtKind Kind);
bool IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind);
- bool IfConvertDiamondCommon(BBInfo &BBI, BBInfo &TrueBBI, BBInfo &FalseBBI,
- unsigned NumDups1, unsigned NumDups2,
- bool TClobbersPred, bool FClobbersPred,
- bool RemoveTrueBranch, bool RemoveFalseBranch,
- bool MergeAddEdges);
bool IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
unsigned NumDups1, unsigned NumDups2);
- bool IfConvertForkedDiamond(BBInfo &BBI, IfcvtKind Kind,
- unsigned NumDups1, unsigned NumDups2,
- bool TClobbers, bool FClobbers);
void PredicateBlock(BBInfo &BBI,
MachineBasicBlock::iterator E,
SmallVectorImpl<MachineOperand> &Cond,
if (RetVal) ++NumDiamonds;
break;
}
- case ICForkedDiamond: {
- if (DisableForkedDiamond) break;
- DEBUG(dbgs() << "Ifcvt (Forked Diamond): BB#"
- << BBI.BB->getNumber() << " (T:"
- << BBI.TrueBB->getNumber() << ",F:"
- << BBI.FalseBB->getNumber() << ") ");
- RetVal = IfConvertForkedDiamond(BBI, Kind, NumDups, NumDups2,
- Token->TClobbersPred,
- Token->FClobbersPred);
- DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n");
- if (RetVal) ++NumForkedDiamonds;
- break;
- }
}
Change |= RetVal;
return;
--TIE;
--FIE;
- // Upon exit TIE and FIE will both point at the last non-shared instruction,
- // they need to be moved forward to point past the last non-shared
- // instruction.
- auto IncrementEndIteratorsOnExit = make_scope_exit([&]() {
- ++TIE; ++FIE;
- });
-
if (!TBB.succ_empty() || !FBB.succ_empty()) {
if (SkipConditionalBranches) {
while (TIE != TIB && TIE->isBranch())
}
}
-/// RescanInstructions - Run ScanInstructions on a pair of blocks.
-/// @param TIB - True Iterator Begin, points to first non-shared instruction
-/// @param FIB - False Iterator Begin, points to first non-shared instruction
-/// @param TIE - True Iterator End, points past last non-shared instruction
-/// @param FIE - False Iterator End, points past last non-shared instruction
-/// @param TrueBBI - BBInfo to update for the true block.
-/// @param FalseBBI - BBInfo to update for the false block.
-/// @returns - false if either block cannot be predicated or if both blocks end
-/// with a predicate-clobbering instruction.
-bool IfConverter::RescanInstructions(
- MachineBasicBlock::iterator &TIB, MachineBasicBlock::iterator &FIB,
- MachineBasicBlock::iterator &TIE, MachineBasicBlock::iterator &FIE,
- BBInfo &TrueBBI, BBInfo &FalseBBI) const {
- ScanInstructions(TrueBBI, TIB, TIE);
- if (TrueBBI.IsUnpredicable)
- return false;
- ScanInstructions(FalseBBI, FIB, FIE);
- if (FalseBBI.IsUnpredicable)
- return false;
- if (TrueBBI.ClobbersPred && FalseBBI.ClobbersPred)
- return false;
- return true;
-}
-
-/// ValidForkedDiamond - Returns true if the 'true' and 'false' blocks (along
-/// with their common predecessor) form a diamond if a common tail block is
-/// extracted.
-/// While not strictly a diamond, this pattern would form a diamond if
-/// tail-merging had merged the shared tails.
-/// EBB
-/// _/ \_
-/// | |
-/// TBB FBB
-/// / \ / \
-/// FalseBB TrueBB FalseBB
-/// Currently only handles analyzable branches.
-/// Specifically excludes actual diamonds to avoid overlap.
-bool IfConverter::ValidForkedDiamond(
- BBInfo &TrueBBI, BBInfo &FalseBBI,
- unsigned &Dups1, unsigned &Dups2,
- BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const {
- Dups1 = Dups2 = 0;
- if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone ||
- FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone)
- return false;
-
- if (!TrueBBI.IsBrAnalyzable || !FalseBBI.IsBrAnalyzable)
- return false;
- // Don't IfConvert blocks that can't be folded into their predecessor.
- if (TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1)
- return false;
-
- // This function is specifically looking for conditional tails, as
- // unconditional tails are already handled by the standard diamond case.
- if (TrueBBI.BrCond.size() == 0 ||
- FalseBBI.BrCond.size() == 0)
- return false;
-
- MachineBasicBlock *TT = TrueBBI.TrueBB;
- MachineBasicBlock *TF = TrueBBI.FalseBB;
- MachineBasicBlock *FT = FalseBBI.TrueBB;
- MachineBasicBlock *FF = FalseBBI.FalseBB;
-
- if (!TT)
- TT = getNextBlock(TrueBBI.BB);
- if (!TF)
- TF = getNextBlock(TrueBBI.BB);
- if (!FT)
- FT = getNextBlock(FalseBBI.BB);
- if (!FF)
- FF = getNextBlock(FalseBBI.BB);
-
- if (!TT || !TF)
- return false;
-
- // Check successors. If they don't match, bail.
- if (!((TT == FT && TF == FF) || (TF == FT && TT == FF)))
- return false;
-
- bool FalseReversed = false;
- if (TF == FT && TT == FF) {
- // If the branches are opposing, but we can't reverse, don't do it.
- if (!FalseBBI.IsBrReversible)
- return false;
- FalseReversed = true;
- ReverseBranchCondition(FalseBBI);
- }
- auto UnReverseOnExit = make_scope_exit([&]() {
- if (FalseReversed)
- ReverseBranchCondition(FalseBBI);
- });
-
- // Count duplicate instructions at the beginning of the true and false blocks.
- MachineBasicBlock::iterator TIB = TrueBBI.BB->begin();
- MachineBasicBlock::iterator FIB = FalseBBI.BB->begin();
- MachineBasicBlock::iterator TIE = TrueBBI.BB->end();
- MachineBasicBlock::iterator FIE = FalseBBI.BB->end();
- countDuplicatedInstructions(TIB, FIB, TIE, FIE, Dups1, Dups2,
- *TrueBBI.BB, *FalseBBI.BB,
- /* SkipConditionalBranches */ false);
-
- TrueBBICalc.BB = TrueBBI.BB;
- FalseBBICalc.BB = FalseBBI.BB;
- if (!RescanInstructions(TIB, FIB, TIE, FIE, TrueBBICalc, FalseBBICalc))
- return false;
- // The size is used to decide whether to if-convert, and the shared portions
- // are subtracted off. Because of the subtraction, we just use the size that
- // was calculated by the original ScanInstructions, as it is correct.
- TrueBBICalc.NonPredSize = TrueBBI.NonPredSize;
- FalseBBICalc.NonPredSize = FalseBBI.NonPredSize;
- return true;
-}
-
/// ValidDiamond - Returns true if the 'true' and 'false' blocks (along
/// with their common predecessor) forms a valid diamond shape for ifcvt.
-bool IfConverter::ValidDiamond(
- BBInfo &TrueBBI, BBInfo &FalseBBI,
- unsigned &Dups1, unsigned &Dups2,
- BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const {
+bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
+ unsigned &Dups1, unsigned &Dups2) const {
Dups1 = Dups2 = 0;
if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone ||
FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone)
return false;
// FIXME: Allow true block to have an early exit?
- if (TrueBBI.FalseBB || FalseBBI.FalseBB)
+ if (TrueBBI.FalseBB || FalseBBI.FalseBB ||
+ (TrueBBI.ClobbersPred && FalseBBI.ClobbersPred))
return false;
// Count duplicate instructions at the beginning and end of the true and
countDuplicatedInstructions(TIB, FIB, TIE, FIE, Dups1, Dups2,
*TrueBBI.BB, *FalseBBI.BB,
/* SkipConditionalBranches */ true);
-
- TrueBBICalc.BB = TrueBBI.BB;
- FalseBBICalc.BB = FalseBBI.BB;
- if (!RescanInstructions(TIB, FIB, TIE, FIE, TrueBBICalc, FalseBBICalc))
- return false;
- // The size is used to decide whether to if-convert, and the shared portions
- // are subtracted off. Because of the subtraction, we just use the size that
- // was calculated by the original ScanInstructions, as it is correct.
- TrueBBICalc.NonPredSize = TrueBBI.NonPredSize;
- FalseBBICalc.NonPredSize = FalseBBI.NonPredSize;
return true;
}
BBI.BrCond.clear();
BBI.IsBrAnalyzable =
!TII->analyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond);
- SmallVector<MachineOperand, 4> RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
- BBI.IsBrReversible = (RevCond.size() == 0) ||
- !TII->ReverseBranchCondition(RevCond);
BBI.HasFallThrough = BBI.IsBrAnalyzable && BBI.FalseBB == nullptr;
if (BBI.BrCond.size()) {
/// FeasibilityAnalysis - Determine if the block is a suitable candidate to be
/// predicated by the specified predicate.
-/// @param BBI BBInfo for the block to check
-/// @param Pred Predicate array for the branch that leads to BBI
-/// @param isTriangle true if the Analysis is for a triangle
-/// @param RevBranch true if Reverse(Pred) leads to BBI (e.g. BBI is the false
-/// case
-/// @param hasCommonTail true if BBI shares a tail with a sibling block that
-/// contains any instruction that would make the block unpredicable.
bool IfConverter::FeasibilityAnalysis(BBInfo &BBI,
SmallVectorImpl<MachineOperand> &Pred,
- bool isTriangle, bool RevBranch,
- bool hasCommonTail) {
+ bool isTriangle, bool RevBranch) {
// If the block is dead or unpredicable, then it cannot be predicated.
- // Two blocks may share a common unpredicable tail, but this doesn't prevent
- // them from being if-converted. The non-shared portion is assumed to have
- // been checked
- if (BBI.IsDone || (BBI.IsUnpredicable && !hasCommonTail))
+ if (BBI.IsDone || BBI.IsUnpredicable)
return false;
// If it is already predicated but we couldn't analyze its terminator, the
if (BBI.Predicate.size() && !TII->SubsumesPredicate(Pred, BBI.Predicate))
return false;
- if (!hasCommonTail && BBI.BrCond.size()) {
+ if (BBI.BrCond.size()) {
if (!isTriangle)
return false;
BranchProbability Prediction = MBPI->getEdgeProbability(BB, TrueBBI.BB);
- if (CanRevCond) {
- BBInfo TrueBBICalc, FalseBBICalc;
- auto feasibleDiamond = [&]() {
- return (
- MeetIfcvtSizeLimit(
- *TrueBBI.BB, (TrueBBICalc.NonPredSize - (Dups + Dups2) +
- TrueBBICalc.ExtraCost), TrueBBICalc.ExtraCost2,
- *FalseBBI.BB, (FalseBBICalc.NonPredSize - (Dups + Dups2) +
- FalseBBICalc.ExtraCost), FalseBBICalc.ExtraCost2,
- Prediction) &&
- FeasibilityAnalysis(TrueBBI, BBI.BrCond,
- /* IsTriangle */ false, /* RevCond */ false,
- /* hasCommonTail */ true) &&
- FeasibilityAnalysis(FalseBBI, RevCond,
- /* IsTriangle */ false, /* RevCond */ false,
- /* hasCommonTail */ true));
- };
-
- if (ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2,
- TrueBBICalc, FalseBBICalc)) {
- if (feasibleDiamond()) {
- // Diamond:
- // EBB
- // / \_
- // | |
- // TBB FBB
- // \ /
- // TailBB
- // Note TailBB can be empty.
- Tokens.push_back(llvm::make_unique<IfcvtToken>(
- BBI, ICDiamond, TNeedSub | FNeedSub, Dups, Dups2));
- Enqueued = true;
- }
- } else if (ValidForkedDiamond(TrueBBI, FalseBBI, Dups, Dups2,
- TrueBBICalc, FalseBBICalc)) {
- if (feasibleDiamond()) {
- // ForkedDiamond:
- // if TBB and FBB have a common tail that includes their conditional
- // branch instructions, then we can If Convert this pattern.
- // EBB
- // _/ \_
- // | |
- // TBB FBB
- // / \ / \
- // FalseBB TrueBB FalseBB
- //
- Tokens.push_back(llvm::make_unique<IfcvtToken>(
- BBI, ICForkedDiamond, TNeedSub | FNeedSub, Dups, Dups2,
- (bool) TrueBBICalc.ClobbersPred, (bool) FalseBBICalc.ClobbersPred));
- Enqueued = true;
- }
- }
+ if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2) &&
+ MeetIfcvtSizeLimit(*TrueBBI.BB, (TrueBBI.NonPredSize - (Dups + Dups2) +
+ TrueBBI.ExtraCost), TrueBBI.ExtraCost2,
+ *FalseBBI.BB, (FalseBBI.NonPredSize - (Dups + Dups2) +
+ FalseBBI.ExtraCost),FalseBBI.ExtraCost2,
+ Prediction) &&
+ FeasibilityAnalysis(TrueBBI, BBI.BrCond) &&
+ FeasibilityAnalysis(FalseBBI, RevCond)) {
+ // Diamond:
+ // EBB
+ // / \_
+ // | |
+ // TBB FBB
+ // \ /
+ // TailBB
+ // Note TailBB can be empty.
+ Tokens.push_back(llvm::make_unique<IfcvtToken>(
+ BBI, ICDiamond, TNeedSub | FNeedSub, Dups, Dups2));
+ Enqueued = true;
}
if (ValidTriangle(TrueBBI, FalseBBI, false, Dups, Prediction) &&
return true;
}
-/// IfConvertDiamondCommon - Common code shared between diamond conversions.
-/// BBI, TrueBBI, and FalseBBI form the diamond shape.
-/// NumDups1 - number of shared instructions at the beginning of TrueBBI and
-/// FalseBBI
-/// NumDups2 - number of shared instructions at the end of TrueBBI and FalseBBI
-/// RemoveTrueBranch - Remove the branch of the true block before predicating
-/// Only false for unanalyzable fallthrough cases.
-/// RemoveFalseBranch - Remove the branch of the false block before predicating
-/// Only false for unanalyzable fallthrough cases.
-/// MergeAddEdges - Add successor edges when merging blocks. Only false for
-/// unanalyzable fallthrough
-bool IfConverter::IfConvertDiamondCommon(
- BBInfo &BBI, BBInfo &TrueBBI, BBInfo &FalseBBI,
- unsigned NumDups1, unsigned NumDups2,
- bool TClobbersPred, bool FClobbersPred,
- bool RemoveTrueBranch, bool RemoveFalseBranch,
- bool MergeAddEdges) {
+/// IfConvertDiamond - If convert a diamond sub-CFG.
+///
+bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
+ unsigned NumDups1, unsigned NumDups2) {
+ BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
+ BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
+ MachineBasicBlock *TailBB = TrueBBI.TrueBB;
+ // True block must fall through or end with an unanalyzable terminator.
+ if (!TailBB) {
+ if (blockAlwaysFallThrough(TrueBBI))
+ TailBB = FalseBBI.TrueBB;
+ assert((TailBB || !TrueBBI.IsBrAnalyzable) && "Unexpected!");
+ }
if (TrueBBI.IsDone || FalseBBI.IsDone ||
- TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1) {
+ TrueBBI.BB->pred_size() > 1 ||
+ FalseBBI.BB->pred_size() > 1) {
// Something has changed. It's no longer safe to predicate these blocks.
BBI.IsAnalyzed = false;
TrueBBI.IsAnalyzed = false;
// Figure out the more profitable ordering.
bool DoSwap = false;
- if (TClobbersPred && !FClobbersPred)
+ if (TrueBBI.ClobbersPred && !FalseBBI.ClobbersPred)
DoSwap = true;
- else if (TClobbersPred == FClobbersPred) {
+ else if (TrueBBI.ClobbersPred == FalseBBI.ClobbersPred) {
if (TrueBBI.NonPredSize > FalseBBI.NonPredSize)
DoSwap = true;
}
if (DoSwap) {
std::swap(BBI1, BBI2);
std::swap(Cond1, Cond2);
- std::swap(RemoveTrueBranch, RemoveFalseBranch);
}
// Remove the conditional branch from entry to the blocks.
BBI.BB->splice(BBI.BB->end(), BBI1->BB, BBI1->BB->begin(), DI1);
BBI2->BB->erase(BBI2->BB->begin(), DI2);
- if (RemoveTrueBranch)
+ // Remove branch from the 'true' block, unless it was not analyzable.
+ // Non-analyzable branches need to be preserved, since in such cases,
+ // the CFG structure is not an actual diamond (the join block may not
+ // be present).
+ if (BBI1->IsBrAnalyzable)
BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB);
// Remove duplicated instructions.
DI1 = BBI1->BB->end();
// must be removed.
RemoveKills(BBI1->BB->begin(), BBI1->BB->end(), DontKill, *TRI);
- // Remove 'false' block branch, and find the last instruction to predicate.
- // Save the debug location.
- if (RemoveFalseBranch)
+ // Remove 'false' block branch (unless it was not analyzable), and find
+ // the last instruction to predicate.
+ if (BBI2->IsBrAnalyzable)
BBI2->NonPredSize -= TII->RemoveBranch(*BBI2->BB);
DI2 = BBI2->BB->end();
while (NumDups2 != 0) {
PredicateBlock(*BBI2, DI2, *Cond2);
// Merge the true block into the entry of the diamond.
- MergeBlocks(BBI, *BBI1, MergeAddEdges);
- MergeBlocks(BBI, *BBI2, MergeAddEdges);
- return true;
-}
-
-/// IfConvertForkedDiamond - If convert an almost-diamond sub-CFG where the true
-/// and false blocks share a common tail.
-bool IfConverter::IfConvertForkedDiamond(
- BBInfo &BBI, IfcvtKind Kind,
- unsigned NumDups1, unsigned NumDups2,
- bool TClobbersPred, bool FClobbersPred) {
- BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
- BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
-
- // Save the debug location for later.
- DebugLoc dl;
- MachineBasicBlock::iterator TIE = TrueBBI.BB->getFirstTerminator();
- if (TIE != TrueBBI.BB->end())
- dl = TIE->getDebugLoc();
- // Removing branches from both blocks is safe, because we have already
- // determined that both blocks have the same branch instructions. The branch
- // will be added back at the end, unpredicated.
- if (!IfConvertDiamondCommon(
- BBI, TrueBBI, FalseBBI,
- NumDups1, NumDups2,
- TClobbersPred, FClobbersPred,
- /* RemoveTrueBranch */ true, /* RemoveFalseBranch */ true,
- /* MergeAddEdges */ true))
- return false;
-
- // Add back the branch.
- // Debug location saved above when removing the branch from BBI2
- TII->InsertBranch(*BBI.BB, TrueBBI.TrueBB, TrueBBI.FalseBB,
- TrueBBI.BrCond, dl);
-
- RemoveExtraEdges(BBI);
-
- // Update block info.
- BBI.IsDone = TrueBBI.IsDone = FalseBBI.IsDone = true;
- InvalidatePreds(BBI.BB);
-
- // FIXME: Must maintain LiveIns.
- return true;
-}
-
-/// IfConvertDiamond - If convert a diamond sub-CFG.
-///
-bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
- unsigned NumDups1, unsigned NumDups2) {
- BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
- BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
- MachineBasicBlock *TailBB = TrueBBI.TrueBB;
-
- // True block must fall through or end with an unanalyzable terminator.
- if (!TailBB) {
- if (blockAlwaysFallThrough(TrueBBI))
- TailBB = FalseBBI.TrueBB;
- assert((TailBB || !TrueBBI.IsBrAnalyzable) && "Unexpected!");
- }
-
- if (!IfConvertDiamondCommon(
- BBI, TrueBBI, FalseBBI,
- NumDups1, NumDups2,
- TrueBBI.ClobbersPred, FalseBBI.ClobbersPred,
- /* RemoveTrueBranch */ TrueBBI.IsBrAnalyzable,
- /* RemoveFalseBranch */ FalseBBI.IsBrAnalyzable,
- /* MergeAddEdges */ TailBB == nullptr))
- return false;
+ MergeBlocks(BBI, *BBI1, TailBB == nullptr);
+ MergeBlocks(BBI, *BBI2, TailBB == nullptr);
// If the if-converted block falls through or unconditionally branches into
// the tail block, and the tail block does not have other predecessors, then
CanMergeTail = false;
else if (NumPreds == 1 && CanMergeTail) {
MachineBasicBlock::pred_iterator PI = TailBB->pred_begin();
- if (*PI != TrueBBI.BB && *PI != FalseBBI.BB)
+ if (*PI != BBI1->BB && *PI != BBI2->BB)
CanMergeTail = false;
}
if (CanMergeTail) {
// RemoveExtraEdges won't work if the block has an unanalyzable branch,
// which can happen here if TailBB is unanalyzable and is merged, so
// explicitly remove BBI1 and BBI2 as successors.
- BBI.BB->removeSuccessor(TrueBBI.BB);
- BBI.BB->removeSuccessor(FalseBBI.BB, /* NormalizeSuccessProbs */ true);
+ BBI.BB->removeSuccessor(BBI1->BB);
+ BBI.BB->removeSuccessor(BBI2->BB, true);
RemoveExtraEdges(BBI);
// Update block info.