diff options
author | Chris Lattner <sabre@nondot.org> | 2009-03-04 04:46:18 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-03-04 04:46:18 +0000 |
commit | 5512f28fa7b26e87e613dc1558b29b2a89647809 (patch) | |
tree | de00b82ae97cd0b553496c55e68263d3467a2388 /lib/CodeGen | |
parent | 91ee0140ecb60b5c1402edc9e577257636c4ca60 (diff) |
add a special case for codegen that improves the case where we have
multiple sequential cases to a) not create tons of fall-through basic blocks
and b) not recurse deeply. This fixes codegen on 100K deep cases, and improves
codegen on moderate cases from this:
switch i32 %tmp, label %sw.epilog [
i32 1000, label %sw.bb
i32 1001, label %sw.bb1
i32 1002, label %sw.bb2
i32 1003, label %sw.bb3
i32 1004, label %sw.bb4
...
sw.bb: ; preds = %entry
br label %sw.bb1
sw.bb1: ; preds = %entry, %sw.bb
br label %sw.bb2
sw.bb2: ; preds = %entry, %sw.bb1
br label %sw.bb3
sw.bb3: ; preds = %entry, %sw.bb2
br label %sw.bb4
to:
switch i32 %tmp, label %sw.epilog [
i32 1000, label %sw.bb
i32 1001, label %sw.bb
i32 1002, label %sw.bb
i32 1003, label %sw.bb
i32 1004, label %sw.bb
sw.bb: ;; many preds
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66015 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index cbd8a897bd..839ba671b9 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -592,7 +592,30 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { llvm::BasicBlock *CaseDest = Builder.GetInsertBlock(); llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext()); SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal), CaseDest); - EmitStmt(S.getSubStmt()); + + // Recursively emitting the statement is acceptable, but is not wonderful for + // code where we have many case statements nested together, i.e.: + // case 1: + // case 2: + // case 3: etc. + // Handling this recursively will create a new block for each case statement + // that falls through to the next case which is IR intensive. It also causes + // deep recursion which can run into stack depth limitations. Handle + // sequential non-range case statements specially. + const CaseStmt *CurCase = &S; + const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt()); + + // Otherwise, iteratively add consequtive cases to this switch stmt. + while (NextCase && NextCase->getRHS() == 0) { + CurCase = NextCase; + CaseVal = CurCase->getLHS()->EvaluateAsInt(getContext()); + SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal), CaseDest); + + NextCase = dyn_cast<CaseStmt>(CurCase->getSubStmt()); + } + + // Normal default recursion for non-cases. + EmitStmt(CurCase->getSubStmt()); } void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) { |