[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:
Akira Hatanaka 2015-06-24 20:34:35 +00:00
parent 75403d7753
commit 14348aa2c5
1 changed files with 158 additions and 129 deletions

View File

@ -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,50 +763,79 @@ 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,
void IfConverter::AnalyzeBlock(MachineBasicBlock *MBB,
std::vector<IfcvtToken*> &Tokens) {
struct BBState {
BBState(MachineBasicBlock *BB) : MBB(BB), SuccsAnalyzed(false) {}
MachineBasicBlock *MBB;
/// This flag is true if MBB's successors have been analyzed.
bool SuccsAnalyzed;
};
// Push MBB to the stack.
SmallVector<BBState, 16> BBStack(1, MBB);
while (!BBStack.empty()) {
BBState &State = BBStack.back();
MachineBasicBlock *BB = State.MBB;
BBInfo &BBI = BBAnalysis[BB->getNumber()];
if (BBI.IsAnalyzed || BBI.IsBeingAnalyzed)
return BBI;
if (!State.SuccsAnalyzed) {
if (BBI.IsAnalyzed || BBI.IsBeingAnalyzed) {
BBStack.pop_back();
continue;
}
BBI.BB = BB;
BBI.IsBeingAnalyzed = true;
ScanInstructions(BBI);
// Unanalyzable or ends with fallthrough or unconditional branch, or if is not
// considered for ifcvt anymore.
// 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;
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;
BBStack.pop_back();
continue;
}
// Do not ifcvt if true and false fallthrough blocks are the same.
if (!BBI.FalseBB) {
BBI.IsBeingAnalyzed = false;
BBI.IsAnalyzed = true;
return BBI;
BBStack.pop_back();
continue;
}
BBInfo &TrueBBI = AnalyzeBlock(BBI.TrueBB, Tokens);
BBInfo &FalseBBI = AnalyzeBlock(BBI.FalseBB, Tokens);
// Push the False and True blocks to the stack.
State.SuccsAnalyzed = true;
BBStack.push_back(BBI.FalseBB);
BBStack.push_back(BBI.TrueBB);
continue;
}
BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()];
BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()];
if (TrueBBI.IsDone && FalseBBI.IsDone) {
BBI.IsBeingAnalyzed = false;
BBI.IsAnalyzed = true;
return BBI;
BBStack.pop_back();
continue;
}
SmallVector<MachineOperand, 4> RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
SmallVector<MachineOperand, 4>
RevCond(BBI.BrCond.begin(), BBI.BrCond.end());
bool CanRevCond = !TII->ReverseBranchCondition(RevCond);
unsigned Dups = 0;
@ -912,7 +940,8 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB,
BBI.IsEnqueued = Enqueued;
BBI.IsBeingAnalyzed = false;
BBI.IsAnalyzed = true;
return BBI;
BBStack.pop_back();
}
}
/// AnalyzeBlocks - Analyze all blocks and find entries for all if-conversion