[cfe-commits] r129652 - in /cfe/trunk: lib/CodeGen/CGCleanup.cpp lib/CodeGen/CGStmt.cpp lib/CodeGen/CodeGenFunction.h test/CodeGen/switch-dce.c

Chris Lattner sabre at nondot.org
Sat Apr 16 17:54:30 PDT 2011


Author: lattner
Date: Sat Apr 16 19:54:30 2011
New Revision: 129652

URL: http://llvm.org/viewvc/llvm-project?rev=129652&view=rev
Log:
implement rdar://9289524 - case followed immediately by break results in empty IR block,
a -O0 code quality issue.

Modified:
    cfe/trunk/lib/CodeGen/CGCleanup.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGen/switch-dce.c

Modified: cfe/trunk/lib/CodeGen/CGCleanup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCleanup.cpp?rev=129652&r1=129651&r2=129652&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCleanup.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCleanup.cpp Sat Apr 16 19:54:30 2011
@@ -870,6 +870,29 @@
   }
 }
 
+/// isObviouslyBranchWithoutCleanups - Return true if a branch to the
+/// specified destination obviously has no cleanups to run.  'false' is always
+/// a conservatively correct answer for this method.
+bool CodeGenFunction::isObviouslyBranchWithoutCleanups(JumpDest Dest) const {
+  assert(Dest.getScopeDepth().encloses(EHStack.stable_begin())
+         && "stale jump destination");
+  
+  // Calculate the innermost active normal cleanup.
+  EHScopeStack::stable_iterator TopCleanup =
+    EHStack.getInnermostActiveNormalCleanup();
+  
+  // If we're not in an active normal cleanup scope, or if the
+  // destination scope is within the innermost active normal cleanup
+  // scope, we don't need to worry about fixups.
+  if (TopCleanup == EHStack.stable_end() ||
+      TopCleanup.encloses(Dest.getScopeDepth())) // works for invalid
+    return true;
+
+  // Otherwise, we might need some cleanups.
+  return false;
+}
+
+
 /// Terminate the current block by emitting a branch which might leave
 /// the current cleanup-protected scope.  The target scope may not yet
 /// be known, in which case this will require a fixup.

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=129652&r1=129651&r2=129652&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sat Apr 16 19:54:30 2011
@@ -867,11 +867,25 @@
 }
 
 void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
+  // Handle case ranges.
   if (S.getRHS()) {
     EmitCaseStmtRange(S);
     return;
   }
 
+  // If the body of the case is just a 'break', try to not emit an empty block.
+  if (isa<BreakStmt>(S.getSubStmt())) {
+    JumpDest Block = BreakContinueStack.back().BreakBlock;
+    
+    // Only do this optimization if there are no cleanups that need emitting.
+    if (isObviouslyBranchWithoutCleanups(Block)) {
+      llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext());
+      SwitchInsn->addCase(llvm::ConstantInt::get(getLLVMContext(), CaseVal),
+                          Block.getBlock());
+      return;
+    }
+  }
+  
   EmitBlock(createBasicBlock("sw.bb"));
   llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
   llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext());

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=129652&r1=129651&r2=129652&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Apr 16 19:54:30 2011
@@ -769,6 +769,11 @@
   /// block through the normal cleanup handling code (if any) and then
   /// on to \arg Dest.
   void EmitBranchThroughCleanup(JumpDest Dest);
+  
+  /// isObviouslyBranchWithoutCleanups - Return true if a branch to the
+  /// specified destination obviously has no cleanups to run.  'false' is always
+  /// a conservatively correct answer for this method.
+  bool isObviouslyBranchWithoutCleanups(JumpDest Dest) const;
 
   /// EmitBranchThroughEHCleanup - Emit a branch from the current
   /// insert block through the EH cleanup handling code (if any) and

Modified: cfe/trunk/test/CodeGen/switch-dce.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/switch-dce.c?rev=129652&r1=129651&r2=129652&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/switch-dce.c (original)
+++ cfe/trunk/test/CodeGen/switch-dce.c Sat Apr 16 19:54:30 2011
@@ -216,3 +216,18 @@
   }
 }
 
+
+// rdar://9289524 - Check that the empty cases don't produce an empty block.
+// CHECK: @test13
+// CHECK: switch 
+// CHECK:     i32 42, label %sw.epilog
+// CHECK:     i32 11, label %sw.epilog
+// CHECK: sw.epilog:
+// CHECK: ret void
+void test13(int x) {
+  switch (x) {
+  case 42: break;  // No empty block please.
+  case 11: break;  // No empty block please.
+  default: test13(42); break;
+  }
+}





More information about the cfe-commits mailing list