From: Chris Lattner Date: Wed, 4 Mar 2009 04:46:18 +0000 (+0000) Subject: add a special case for codegen that improves the case where we have X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5512f28fa7b26e87e613dc1558b29b2a89647809;p=clang 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 --- 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(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(CurCase->getSubStmt()); + } + + // Normal default recursion for non-cases. + EmitStmt(CurCase->getSubStmt()); } void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) {