forked from OSchip/llvm-project
[If Converter] Convert recursion to iteration.
This commit makes changes to IfConverter::AnalyzeBlock to use iteration instead of recursion. Previously, this function would get called recursively a large number of times and eventually segfault when a function with the following CFG was compiled: BB0: if (condition0) goto BB1 goto BB2 BB1: goto BB2 BB2: if (condition1) goto BB3 goto BB4 BB3: ... (repeat until BB7488) rdar://problem/21386145 Differential Revision: http://reviews.llvm.org/D10587 llvm-svn: 240589
This commit is contained in:
parent
75403d7753
commit
14348aa2c5
|
@ -197,8 +197,7 @@ namespace {
|
|||
bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI,
|
||||
unsigned &Dups1, unsigned &Dups2) const;
|
||||
void ScanInstructions(BBInfo &BBI);
|
||||
BBInfo &AnalyzeBlock(MachineBasicBlock *BB,
|
||||
std::vector<IfcvtToken*> &Tokens);
|
||||
void AnalyzeBlock(MachineBasicBlock *MBB, std::vector<IfcvtToken*> &Tokens);
|
||||
bool FeasibilityAnalysis(BBInfo &BBI, SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool isTriangle = false, bool RevBranch = false);
|
||||
void AnalyzeBlocks(MachineFunction &MF, std::vector<IfcvtToken*> &Tokens);
|
||||
|
@ -764,155 +763,185 @@ bool IfConverter::FeasibilityAnalysis(BBInfo &BBI,
|
|||
/// AnalyzeBlock - Analyze the structure of the sub-CFG starting from
|
||||
/// the specified block. Record its successors and whether it looks like an
|
||||
/// if-conversion candidate.
|
||||
IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB,
|
||||
std::vector<IfcvtToken*> &Tokens) {
|
||||
BBInfo &BBI = BBAnalysis[BB->getNumber()];
|
||||
void IfConverter::AnalyzeBlock(MachineBasicBlock *MBB,
|
||||
std::vector<IfcvtToken*> &Tokens) {
|
||||
struct BBState {
|
||||
BBState(MachineBasicBlock *BB) : MBB(BB), SuccsAnalyzed(false) {}
|
||||
MachineBasicBlock *MBB;
|
||||
|
||||
if (BBI.IsAnalyzed || BBI.IsBeingAnalyzed)
|
||||
return BBI;
|
||||
/// This flag is true if MBB's successors have been analyzed.
|
||||
bool SuccsAnalyzed;
|
||||
};
|
||||
|
||||
BBI.BB = BB;
|
||||
BBI.IsBeingAnalyzed = true;
|
||||
// Push MBB to the stack.
|
||||
SmallVector<BBState, 16> BBStack(1, MBB);
|
||||
|
||||
ScanInstructions(BBI);
|
||||
while (!BBStack.empty()) {
|
||||
BBState &State = BBStack.back();
|
||||
MachineBasicBlock *BB = State.MBB;
|
||||
BBInfo &BBI = BBAnalysis[BB->getNumber()];
|
||||
|
||||
// Unanalyzable or ends with fallthrough or unconditional branch, or if is not
|
||||
// considered for ifcvt anymore.
|
||||
if (!BBI.IsBrAnalyzable || BBI.BrCond.empty() || BBI.IsDone) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
return BBI;
|
||||
}
|
||||
if (!State.SuccsAnalyzed) {
|
||||
if (BBI.IsAnalyzed || BBI.IsBeingAnalyzed) {
|
||||
BBStack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not ifcvt if either path is a back edge to the entry block.
|
||||
if (BBI.TrueBB == BB || BBI.FalseBB == BB) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
return BBI;
|
||||
}
|
||||
BBI.BB = BB;
|
||||
BBI.IsBeingAnalyzed = true;
|
||||
|
||||
// Do not ifcvt if true and false fallthrough blocks are the same.
|
||||
if (!BBI.FalseBB) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
return BBI;
|
||||
}
|
||||
ScanInstructions(BBI);
|
||||
|
||||
BBInfo &TrueBBI = AnalyzeBlock(BBI.TrueBB, Tokens);
|
||||
BBInfo &FalseBBI = AnalyzeBlock(BBI.FalseBB, Tokens);
|
||||
// Unanalyzable or ends with fallthrough or unconditional branch, or if is
|
||||
// not considered for ifcvt anymore.
|
||||
if (!BBI.IsBrAnalyzable || BBI.BrCond.empty() || BBI.IsDone) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
BBStack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TrueBBI.IsDone && FalseBBI.IsDone) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
return BBI;
|
||||
}
|
||||
// Do not ifcvt if either path is a back edge to the entry block.
|
||||
if (BBI.TrueBB == BB || BBI.FalseBB == BB) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
BBStack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
SmallVector<MachineOperand, 4> RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
|
||||
bool CanRevCond = !TII->ReverseBranchCondition(RevCond);
|
||||
// Do not ifcvt if true and false fallthrough blocks are the same.
|
||||
if (!BBI.FalseBB) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
BBStack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned Dups = 0;
|
||||
unsigned Dups2 = 0;
|
||||
bool TNeedSub = !TrueBBI.Predicate.empty();
|
||||
bool FNeedSub = !FalseBBI.Predicate.empty();
|
||||
bool Enqueued = false;
|
||||
// Push the False and True blocks to the stack.
|
||||
State.SuccsAnalyzed = true;
|
||||
BBStack.push_back(BBI.FalseBB);
|
||||
BBStack.push_back(BBI.TrueBB);
|
||||
continue;
|
||||
}
|
||||
|
||||
BranchProbability Prediction = MBPI->getEdgeProbability(BB, TrueBBI.BB);
|
||||
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
|
||||
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
|
||||
|
||||
if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2) &&
|
||||
MeetIfcvtSizeLimit(*TrueBBI.BB, (TrueBBI.NonPredSize - (Dups + Dups2) +
|
||||
TrueBBI.ExtraCost), TrueBBI.ExtraCost2,
|
||||
*FalseBBI.BB, (FalseBBI.NonPredSize - (Dups + Dups2) +
|
||||
if (TrueBBI.IsDone && FalseBBI.IsDone) {
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
BBStack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
SmallVector<MachineOperand, 4>
|
||||
RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
|
||||
bool CanRevCond = !TII->ReverseBranchCondition(RevCond);
|
||||
|
||||
unsigned Dups = 0;
|
||||
unsigned Dups2 = 0;
|
||||
bool TNeedSub = !TrueBBI.Predicate.empty();
|
||||
bool FNeedSub = !FalseBBI.Predicate.empty();
|
||||
bool Enqueued = false;
|
||||
|
||||
BranchProbability Prediction = MBPI->getEdgeProbability(BB, TrueBBI.BB);
|
||||
|
||||
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(new IfcvtToken(BBI, ICDiamond, TNeedSub|FNeedSub, Dups,
|
||||
Dups2));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidTriangle(TrueBBI, FalseBBI, false, Dups, Prediction) &&
|
||||
MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
|
||||
TrueBBI.ExtraCost2, Prediction) &&
|
||||
FeasibilityAnalysis(TrueBBI, BBI.BrCond, true)) {
|
||||
// Triangle:
|
||||
// EBB
|
||||
// | \_
|
||||
// | |
|
||||
// | TBB
|
||||
// | /
|
||||
// FBB
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangle, TNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidTriangle(TrueBBI, FalseBBI, true, Dups, Prediction) &&
|
||||
MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
|
||||
TrueBBI.ExtraCost2, Prediction) &&
|
||||
FeasibilityAnalysis(TrueBBI, BBI.BrCond, true, true)) {
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangleRev, TNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidSimple(TrueBBI, Dups, Prediction) &&
|
||||
MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
|
||||
TrueBBI.ExtraCost2, Prediction) &&
|
||||
FeasibilityAnalysis(TrueBBI, BBI.BrCond)) {
|
||||
// Simple (split, no rejoin):
|
||||
// EBB
|
||||
// | \_
|
||||
// | |
|
||||
// | TBB---> exit
|
||||
// |
|
||||
// FBB
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICSimple, TNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (CanRevCond) {
|
||||
// Try the other path...
|
||||
if (ValidTriangle(FalseBBI, TrueBBI, false, Dups,
|
||||
Prediction.getCompl()) &&
|
||||
MeetIfcvtSizeLimit(*FalseBBI.BB,
|
||||
FalseBBI.NonPredSize + FalseBBI.ExtraCost,
|
||||
FalseBBI.ExtraCost2, Prediction.getCompl()) &&
|
||||
FeasibilityAnalysis(FalseBBI, RevCond, true)) {
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangleFalse, FNeedSub, Dups));
|
||||
FeasibilityAnalysis(TrueBBI, BBI.BrCond) &&
|
||||
FeasibilityAnalysis(FalseBBI, RevCond)) {
|
||||
// Diamond:
|
||||
// EBB
|
||||
// / \_
|
||||
// | |
|
||||
// TBB FBB
|
||||
// \ /
|
||||
// TailBB
|
||||
// Note TailBB can be empty.
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICDiamond, TNeedSub|FNeedSub, Dups,
|
||||
Dups2));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidTriangle(FalseBBI, TrueBBI, true, Dups,
|
||||
Prediction.getCompl()) &&
|
||||
MeetIfcvtSizeLimit(*FalseBBI.BB,
|
||||
FalseBBI.NonPredSize + FalseBBI.ExtraCost,
|
||||
if (ValidTriangle(TrueBBI, FalseBBI, false, Dups, Prediction) &&
|
||||
MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
|
||||
TrueBBI.ExtraCost2, Prediction) &&
|
||||
FeasibilityAnalysis(TrueBBI, BBI.BrCond, true)) {
|
||||
// Triangle:
|
||||
// EBB
|
||||
// | \_
|
||||
// | |
|
||||
// | TBB
|
||||
// | /
|
||||
// FBB
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangle, TNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidTriangle(TrueBBI, FalseBBI, true, Dups, Prediction) &&
|
||||
MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
|
||||
TrueBBI.ExtraCost2, Prediction) &&
|
||||
FeasibilityAnalysis(TrueBBI, BBI.BrCond, true, true)) {
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangleRev, TNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidSimple(TrueBBI, Dups, Prediction) &&
|
||||
MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost,
|
||||
TrueBBI.ExtraCost2, Prediction) &&
|
||||
FeasibilityAnalysis(TrueBBI, BBI.BrCond)) {
|
||||
// Simple (split, no rejoin):
|
||||
// EBB
|
||||
// | \_
|
||||
// | |
|
||||
// | TBB---> exit
|
||||
// |
|
||||
// FBB
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICSimple, TNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (CanRevCond) {
|
||||
// Try the other path...
|
||||
if (ValidTriangle(FalseBBI, TrueBBI, false, Dups,
|
||||
Prediction.getCompl()) &&
|
||||
MeetIfcvtSizeLimit(*FalseBBI.BB,
|
||||
FalseBBI.NonPredSize + FalseBBI.ExtraCost,
|
||||
FalseBBI.ExtraCost2, Prediction.getCompl()) &&
|
||||
FeasibilityAnalysis(FalseBBI, RevCond, true)) {
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangleFalse, FNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidTriangle(FalseBBI, TrueBBI, true, Dups,
|
||||
Prediction.getCompl()) &&
|
||||
MeetIfcvtSizeLimit(*FalseBBI.BB,
|
||||
FalseBBI.NonPredSize + FalseBBI.ExtraCost,
|
||||
FalseBBI.ExtraCost2, Prediction.getCompl()) &&
|
||||
FeasibilityAnalysis(FalseBBI, RevCond, true, true)) {
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangleFRev, FNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICTriangleFRev, FNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
|
||||
if (ValidSimple(FalseBBI, Dups, Prediction.getCompl()) &&
|
||||
MeetIfcvtSizeLimit(*FalseBBI.BB,
|
||||
FalseBBI.NonPredSize + FalseBBI.ExtraCost,
|
||||
FalseBBI.ExtraCost2, Prediction.getCompl()) &&
|
||||
FeasibilityAnalysis(FalseBBI, RevCond)) {
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICSimpleFalse, FNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ValidSimple(FalseBBI, Dups, Prediction.getCompl()) &&
|
||||
MeetIfcvtSizeLimit(*FalseBBI.BB,
|
||||
FalseBBI.NonPredSize + FalseBBI.ExtraCost,
|
||||
FalseBBI.ExtraCost2, Prediction.getCompl()) &&
|
||||
FeasibilityAnalysis(FalseBBI, RevCond)) {
|
||||
Tokens.push_back(new IfcvtToken(BBI, ICSimpleFalse, FNeedSub, Dups));
|
||||
Enqueued = true;
|
||||
}
|
||||
BBI.IsEnqueued = Enqueued;
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
BBStack.pop_back();
|
||||
}
|
||||
|
||||
BBI.IsEnqueued = Enqueued;
|
||||
BBI.IsBeingAnalyzed = false;
|
||||
BBI.IsAnalyzed = true;
|
||||
return BBI;
|
||||
}
|
||||
|
||||
/// AnalyzeBlocks - Analyze all blocks and find entries for all if-conversion
|
||||
|
|
Loading…
Reference in New Issue