]> granicus.if.org Git - clang/commitdiff
Make skipping of vardecls more precise: it's ok to skip a decl if the entire
authorChris Lattner <sabre@nondot.org>
Mon, 28 Feb 2011 07:22:44 +0000 (07:22 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 28 Feb 2011 07:22:44 +0000 (07:22 +0000)
compound stmt containing the decl is skipped.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126639 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGStmt.cpp
test/CodeGen/switch-dce.c

index 21fb36a72d646bc7f7ca4356045cf3484535f926..24acf65739805a2f1c29cefaa4f0bef237639dc7 100644 (file)
@@ -887,9 +887,16 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
     // the skipped statements must be skippable) or we might already have it.
     CompoundStmt::const_body_iterator I = CS->body_begin(), E = CS->body_end();
     if (Case) {
+      // Keep track of whether we see a skipped declaration.  The code could be
+      // using the declaration even if it is skipped, so we can't optimize out
+      // the decl if the kept statements might refer to it.
+      bool HadSkippedDecl = false;
+      
       // If we're looking for the case, just see if we can skip each of the
       // substatements.
       for (; Case && I != E; ++I) {
+        HadSkippedDecl |= isa<DeclStmt>(I);
+        
         switch (CollectStatementsForCase(*I, Case, FoundCase, ResultStmts)) {
         case CSFC_Failure: return CSFC_Failure;
         case CSFC_Success:
@@ -898,6 +905,11 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
           // and also contains the break to exit the switch.  In the later case,
           // we just verify the rest of the statements are elidable.
           if (FoundCase) {
+            // If we found the case and skipped declarations, we can't do the
+            // optimization.
+            if (HadSkippedDecl)
+              return CSFC_Failure;
+            
             for (++I; I != E; ++I)
               if (CodeGenFunction::ContainsLabel(*I, true))
                 return CSFC_Failure;
@@ -911,6 +923,11 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
           assert(FoundCase && "Didn't find case but returned fallthrough?");
           // We recursively found Case, so we're not looking for it anymore.
           Case = 0;
+            
+          // If we found the case and skipped declarations, we can't do the
+          // optimization.
+          if (HadSkippedDecl)
+            return CSFC_Failure;
           break;
         }
       }
@@ -943,9 +960,7 @@ static CSFC_Result CollectStatementsForCase(const Stmt *S,
   // for statement or increment etc.  If we are skipping over this statement,
   // just verify it doesn't have labels, which would make it invalid to elide.
   if (Case) {
-    if (CodeGenFunction::ContainsLabel(S, true) ||
-        // Don't skip over DeclStmts, which can be used even if skipped over.
-        isa<DeclStmt>(S))
+    if (CodeGenFunction::ContainsLabel(S, true))
       return CSFC_Failure;
     return CSFC_Success;
   }
index 82b206149b9e13a27f13cf9dc0fd568028629b54..a03c4001d3d54208413caed6dc55f87b9c62de5d 100644 (file)
@@ -87,6 +87,7 @@ void test5() {
     int x;  // eliding var decl?
     case 1:
       x = 4;
+      i = x;
       break;
   } 
 }
@@ -196,3 +197,22 @@ void test11() {
       break;
   }
 }
+
+// CHECK: @test12
+// CHECK-NOT: switch
+// CHECK: ret void
+void test12() {
+  switch (1) {
+  case 2: {
+     int a;   // Ok to skip this vardecl.
+     a = 42;
+   }
+  case 1:
+    break;
+  case 42: ;
+    int x;  // eliding var decl?
+    x = 4;
+    break;
+  }
+}
+