From 35d3ac5e9e8ba1dad0d9d1a5132d0ab946b5e844 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 28 Feb 2011 07:22:44 +0000 Subject: [PATCH] Make skipping of vardecls more precise: it's ok to skip a decl if the entire compound stmt containing the decl is skipped. llvm-svn: 126639 --- clang/lib/CodeGen/CGStmt.cpp | 21 ++++++++++++++++++--- clang/test/CodeGen/switch-dce.c | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 21fb36a72d64..24acf6573980 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -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(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(S)) + if (CodeGenFunction::ContainsLabel(S, true)) return CSFC_Failure; return CSFC_Success; } diff --git a/clang/test/CodeGen/switch-dce.c b/clang/test/CodeGen/switch-dce.c index 82b206149b9e..a03c4001d3d5 100644 --- a/clang/test/CodeGen/switch-dce.c +++ b/clang/test/CodeGen/switch-dce.c @@ -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; + } +} +