[cfe-commits] r66015 - /cfe/trunk/lib/CodeGen/CGStmt.cpp

Chris Lattner sabre at nondot.org
Tue Mar 3 20:46:19 PST 2009


Author: lattner
Date: Tue Mar  3 22:46:18 2009
New Revision: 66015

URL: http://llvm.org/viewvc/llvm-project?rev=66015&view=rev
Log:
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



Modified:
    cfe/trunk/lib/CodeGen/CGStmt.cpp

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=66015&r1=66014&r2=66015&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Tue Mar  3 22:46:18 2009
@@ -592,7 +592,30 @@
   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) {





More information about the cfe-commits mailing list