IfConversion: Rescan diamonds.

The cost of predicating a diamond is only the instructions that are not shared
between the two branches. Additionally If a predicate clobbering instruction
occurs in the shared portion of the branches (e.g. a cond move), it may still
be possible to if convert the sub-cfg. This change handles these two facts by
rescanning the non-shared portion of a diamond sub-cfg to recalculate both the
predication cost and whether both blocks are pred-clobbering.

llvm-svn: 279167
This commit is contained in:
Kyle Butt 2016-08-18 22:09:25 +00:00
parent d76755ec95
commit 491afad8f6
1 changed files with 115 additions and 34 deletions

View File

@ -149,11 +149,15 @@ namespace {
struct IfcvtToken { struct IfcvtToken {
BBInfo &BBI; BBInfo &BBI;
IfcvtKind Kind; IfcvtKind Kind;
bool NeedSubsumption;
unsigned NumDups; unsigned NumDups;
unsigned NumDups2; unsigned NumDups2;
IfcvtToken(BBInfo &b, IfcvtKind k, bool s, unsigned d, unsigned d2 = 0) bool NeedSubsumption : 1;
: BBI(b), Kind(k), NeedSubsumption(s), NumDups(d), NumDups2(d2) {} 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) {}
}; };
/// Results of if-conversion feasibility analysis indexed by basic block /// Results of if-conversion feasibility analysis indexed by basic block
@ -203,15 +207,21 @@ namespace {
bool FalseBranch, unsigned &Dups, bool FalseBranch, unsigned &Dups,
BranchProbability Prediction) const; BranchProbability Prediction) const;
bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI, bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
unsigned &Dups1, unsigned &Dups2) const; unsigned &Dups1, unsigned &Dups2,
BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const;
void AnalyzeBranches(BBInfo &BBI); void AnalyzeBranches(BBInfo &BBI);
void ScanInstructions(BBInfo &BBI, void ScanInstructions(BBInfo &BBI,
MachineBasicBlock::iterator &Begin, MachineBasicBlock::iterator &Begin,
MachineBasicBlock::iterator &End) const; 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, void AnalyzeBlock(MachineBasicBlock &MBB,
std::vector<std::unique_ptr<IfcvtToken>> &Tokens); std::vector<std::unique_ptr<IfcvtToken>> &Tokens);
bool FeasibilityAnalysis(BBInfo &BBI, SmallVectorImpl<MachineOperand> &Cond, bool FeasibilityAnalysis(BBInfo &BBI, SmallVectorImpl<MachineOperand> &Cond,
bool isTriangle = false, bool RevBranch = false); bool isTriangle = false, bool RevBranch = false,
bool hasCommonTail = false);
void AnalyzeBlocks(MachineFunction &MF, void AnalyzeBlocks(MachineFunction &MF,
std::vector<std::unique_ptr<IfcvtToken>> &Tokens); std::vector<std::unique_ptr<IfcvtToken>> &Tokens);
void InvalidatePreds(MachineBasicBlock &MBB); void InvalidatePreds(MachineBasicBlock &MBB);
@ -219,7 +229,8 @@ namespace {
bool IfConvertSimple(BBInfo &BBI, IfcvtKind Kind); bool IfConvertSimple(BBInfo &BBI, IfcvtKind Kind);
bool IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind); bool IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind);
bool IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, bool IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
unsigned NumDups1, unsigned NumDups2); unsigned NumDups1, unsigned NumDups2,
bool TClobbers, bool FClobbers);
void PredicateBlock(BBInfo &BBI, void PredicateBlock(BBInfo &BBI,
MachineBasicBlock::iterator E, MachineBasicBlock::iterator E,
SmallVectorImpl<MachineOperand> &Cond, SmallVectorImpl<MachineOperand> &Cond,
@ -406,7 +417,9 @@ bool IfConverter::runOnMachineFunction(MachineFunction &MF) {
DEBUG(dbgs() << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " (T:" DEBUG(dbgs() << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " (T:"
<< BBI.TrueBB->getNumber() << ",F:" << BBI.TrueBB->getNumber() << ",F:"
<< BBI.FalseBB->getNumber() << ") "); << BBI.FalseBB->getNumber() << ") ");
RetVal = IfConvertDiamond(BBI, Kind, NumDups, NumDups2); RetVal = IfConvertDiamond(BBI, Kind, NumDups, NumDups2,
Token->TClobbersPred,
Token->FClobbersPred);
DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n"); DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n");
if (RetVal) ++NumDiamonds; if (RetVal) ++NumDiamonds;
break; break;
@ -677,10 +690,36 @@ static void countDuplicatedInstructions(
} }
} }
/// 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;
}
/// ValidDiamond - Returns true if the 'true' and 'false' blocks (along /// ValidDiamond - Returns true if the 'true' and 'false' blocks (along
/// with their common predecessor) forms a valid diamond shape for ifcvt. /// with their common predecessor) forms a valid diamond shape for ifcvt.
bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI, bool IfConverter::ValidDiamond(
unsigned &Dups1, unsigned &Dups2) const { BBInfo &TrueBBI, BBInfo &FalseBBI,
unsigned &Dups1, unsigned &Dups2,
BBInfo &TrueBBICalc, BBInfo &FalseBBICalc) const {
Dups1 = Dups2 = 0; Dups1 = Dups2 = 0;
if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone || if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone ||
FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone) FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone)
@ -701,8 +740,7 @@ bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
return false; return false;
// FIXME: Allow true block to have an early exit? // 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; return false;
// Count duplicate instructions at the beginning and end of the true and // Count duplicate instructions at the beginning and end of the true and
@ -714,6 +752,16 @@ bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
countDuplicatedInstructions(TIB, FIB, TIE, FIE, Dups1, Dups2, countDuplicatedInstructions(TIB, FIB, TIE, FIE, Dups1, Dups2,
*TrueBBI.BB, *FalseBBI.BB, *TrueBBI.BB, *FalseBBI.BB,
/* SkipConditionalBranches */ true); /* 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; return true;
} }
@ -841,11 +889,22 @@ void IfConverter::ScanInstructions(BBInfo &BBI,
/// Determine if the block is a suitable candidate to be predicated by the /// Determine if the block is a suitable candidate to be predicated by the
/// specified predicate. /// 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, bool IfConverter::FeasibilityAnalysis(BBInfo &BBI,
SmallVectorImpl<MachineOperand> &Pred, SmallVectorImpl<MachineOperand> &Pred,
bool isTriangle, bool RevBranch) { bool isTriangle, bool RevBranch,
bool hasCommonTail) {
// If the block is dead or unpredicable, then it cannot be predicated. // If the block is dead or unpredicable, then it cannot be predicated.
if (BBI.IsDone || BBI.IsUnpredicable) // 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))
return false; return false;
// If it is already predicated but we couldn't analyze its terminator, the // If it is already predicated but we couldn't analyze its terminator, the
@ -859,7 +918,7 @@ bool IfConverter::FeasibilityAnalysis(BBInfo &BBI,
if (BBI.Predicate.size() && !TII->SubsumesPredicate(Pred, BBI.Predicate)) if (BBI.Predicate.size() && !TII->SubsumesPredicate(Pred, BBI.Predicate))
return false; return false;
if (BBI.BrCond.size()) { if (!hasCommonTail && BBI.BrCond.size()) {
if (!isTriangle) if (!isTriangle)
return false; return false;
@ -966,14 +1025,23 @@ void IfConverter::AnalyzeBlock(
BranchProbability Prediction = MBPI->getEdgeProbability(BB, TrueBBI.BB); BranchProbability Prediction = MBPI->getEdgeProbability(BB, TrueBBI.BB);
if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2) && if (CanRevCond) {
BBInfo TrueBBICalc, FalseBBICalc;
if (ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2,
TrueBBICalc, FalseBBICalc) &&
MeetIfcvtSizeLimit(*TrueBBI.BB, (TrueBBI.NonPredSize - (Dups + Dups2) + MeetIfcvtSizeLimit(*TrueBBI.BB, (TrueBBI.NonPredSize - (Dups + Dups2) +
TrueBBI.ExtraCost), TrueBBI.ExtraCost2, TrueBBICalc.ExtraCost),
TrueBBICalc.ExtraCost2,
*FalseBBI.BB, (FalseBBI.NonPredSize - (Dups + Dups2) + *FalseBBI.BB, (FalseBBI.NonPredSize - (Dups + Dups2) +
FalseBBI.ExtraCost),FalseBBI.ExtraCost2, FalseBBICalc.ExtraCost),
FalseBBICalc.ExtraCost2,
Prediction) && Prediction) &&
FeasibilityAnalysis(TrueBBI, BBI.BrCond) && FeasibilityAnalysis(TrueBBI, BBI.BrCond,
FeasibilityAnalysis(FalseBBI, RevCond)) { /* IsTriangle */ false, /* RevCond */ false,
/* hasCommonTail */ true) &&
FeasibilityAnalysis(FalseBBI, RevCond,
/* IsTriangle */ false, /* RevCond */ false,
/* hasCommonTail */ true)) {
// Diamond: // Diamond:
// EBB // EBB
// / \_ // / \_
@ -983,9 +1051,12 @@ void IfConverter::AnalyzeBlock(
// TailBB // TailBB
// Note TailBB can be empty. // Note TailBB can be empty.
Tokens.push_back(llvm::make_unique<IfcvtToken>( Tokens.push_back(llvm::make_unique<IfcvtToken>(
BBI, ICDiamond, TNeedSub | FNeedSub, Dups, Dups2)); BBI, ICDiamond, TNeedSub | FNeedSub, Dups, Dups2,
(bool) TrueBBICalc.ClobbersPred,
(bool) FalseBBICalc.ClobbersPred));
Enqueued = true; Enqueued = true;
} }
}
if (ValidTriangle(TrueBBI, FalseBBI, false, Dups, Prediction) && if (ValidTriangle(TrueBBI, FalseBBI, false, Dups, Prediction) &&
MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost, MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
@ -1429,8 +1500,18 @@ bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) {
} }
/// If convert a diamond sub-CFG. /// If convert a diamond sub-CFG.
/// \p BBI is the head of the diamond
/// \p NumDups1 - number of shared instructions at the beginning of TrueBBI and
/// FalseBBI
/// \p NumDups2 - number of shared instructions at the end of TrueBBI and
/// FalseBBI
/// \p TClobbersPred - True if the true block clobbers the predicate in the
/// non-shared portion.
/// \p TClobbersPred - True if the false block clobbers the predicate in the
/// non-shared portion.
bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
unsigned NumDups1, unsigned NumDups2) { unsigned NumDups1, unsigned NumDups2,
bool TClobbersPred, bool FClobbersPred) {
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
MachineBasicBlock *TailBB = TrueBBI.TrueBB; MachineBasicBlock *TailBB = TrueBBI.TrueBB;
@ -1468,9 +1549,9 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
// Figure out the more profitable ordering. // Figure out the more profitable ordering.
bool DoSwap = false; bool DoSwap = false;
if (TrueBBI.ClobbersPred && !FalseBBI.ClobbersPred) if (TClobbersPred && !FClobbersPred)
DoSwap = true; DoSwap = true;
else if (TrueBBI.ClobbersPred == FalseBBI.ClobbersPred) { else if (TClobbersPred == FClobbersPred) {
if (TrueBBI.NonPredSize > FalseBBI.NonPredSize) if (TrueBBI.NonPredSize > FalseBBI.NonPredSize)
DoSwap = true; DoSwap = true;
} }