[llvm-commits] [gcc-plugin] r81675 - in /gcc-plugin/trunk: llvm-convert.cpp llvm-internal.h

Duncan Sands baldrick at free.fr
Sun Sep 13 09:49:38 PDT 2009


Author: baldrick
Date: Sun Sep 13 11:49:37 2009
New Revision: 81675

URL: http://llvm.org/viewvc/llvm-project?rev=81675&view=rev
Log:
Handle gimple switches directly, rather than going via a tree.

Modified:
    gcc-plugin/trunk/llvm-convert.cpp
    gcc-plugin/trunk/llvm-internal.h

Modified: gcc-plugin/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/llvm-convert.cpp?rev=81675&r1=81674&r2=81675&view=diff

==============================================================================
--- gcc-plugin/trunk/llvm-convert.cpp (original)
+++ gcc-plugin/trunk/llvm-convert.cpp Sun Sep 13 11:49:37 2009
@@ -952,7 +952,6 @@
     case GIMPLE_RETURN:
     case GIMPLE_ASM:
     case GIMPLE_CALL:
-    case GIMPLE_SWITCH:
     case GIMPLE_RESX: {
       // TODO Handle gimple directly, rather than converting to a tree.
       tree stmt = gimple_to_tree(gimple_stmt);
@@ -984,6 +983,10 @@
     case GIMPLE_PREDICT:
       break;
 
+    case GIMPLE_SWITCH:
+      RenderGIMPLE_SWITCH(gimple_stmt);
+      break;
+
     default:
       dump(gimple_stmt);
       llvm_unreachable("Unhandled GIMPLE statement during LLVM emission!");
@@ -1048,9 +1051,8 @@
     llvm_unreachable("Unhandled expression!");
 
   // Control flow
-  case LABEL_EXPR:     break;
-  case RETURN_EXPR:    Result = EmitRETURN_EXPR(exp, DestLoc); break;
-  case SWITCH_EXPR:    Result = EmitSWITCH_EXPR(exp); break;
+  case LABEL_EXPR:  break;
+  case RETURN_EXPR: Result = EmitRETURN_EXPR(exp, DestLoc); break;
 
   // Exception handling.
   case EXC_PTR_EXPR:   Result = EmitEXC_PTR_EXPR(exp); break;
@@ -1930,86 +1932,6 @@
   return 0;
 }
 
-Value *TreeToLLVM::EmitSWITCH_EXPR(tree exp) {
-  tree Cases = SWITCH_LABELS(exp);
-
-  // Emit the condition.
-  Value *SwitchExp = Emit(SWITCH_COND(exp), 0);
-  bool ExpIsSigned = !TYPE_UNSIGNED(TREE_TYPE(SWITCH_COND(exp)));
-
-  // Emit the switch instruction.
-  SwitchInst *SI = Builder.CreateSwitch(SwitchExp, Builder.GetInsertBlock(),
-                                        TREE_VEC_LENGTH(Cases));
-  EmitBlock(BasicBlock::Create(Context));
-  // Default location starts out as fall-through
-  SI->setSuccessor(0, Builder.GetInsertBlock());
-
-  assert(!SWITCH_BODY(exp) && "not a gimple switch?");
-
-  BasicBlock *DefaultDest = NULL;
-  for (unsigned i = 0, e = TREE_VEC_LENGTH(Cases); i != e; ++i) {
-    BasicBlock *Dest = getLabelDeclBlock(CASE_LABEL(TREE_VEC_ELT(Cases, i)));
-
-    tree low = CASE_LOW(TREE_VEC_ELT(Cases, i));
-    if (!low) {
-      DefaultDest = Dest;
-      continue;
-    }
-
-    // Convert the integer to the right type.
-    Value *Val = Emit(low, 0);
-    Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(low)),
-                        SwitchExp->getType(), ExpIsSigned);
-    ConstantInt *LowC = cast<ConstantInt>(Val);
-
-    tree high = CASE_HIGH(TREE_VEC_ELT(Cases, i));
-    if (!high) {
-      SI->addCase(LowC, Dest); // Single destination.
-      continue;
-    }
-
-    // Otherwise, we have a range, like 'case 1 ... 17'.
-    Val = Emit(high, 0);
-    // Make sure the case value is the same type as the switch expression
-    Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(high)),
-                        SwitchExp->getType(), ExpIsSigned);
-    ConstantInt *HighC = cast<ConstantInt>(Val);
-
-    APInt Range = HighC->getValue() - LowC->getValue();
-    if (Range.ult(APInt(Range.getBitWidth(), 64))) {
-      // Add all of the necessary successors to the switch.
-      APInt CurrentValue = LowC->getValue();
-      while (1) {
-        SI->addCase(LowC, Dest);
-        if (LowC == HighC) break;  // Emitted the last one.
-        CurrentValue++;
-        LowC = ConstantInt::get(Context, CurrentValue);
-      }
-    } else {
-      // The range is too big to add to the switch - emit an "if".
-      Value *Diff = Builder.CreateSub(SwitchExp, LowC);
-      Value *Cond = Builder.CreateICmpULE(Diff,
-                                          ConstantInt::get(Context, Range));
-      BasicBlock *False_Block = BasicBlock::Create(Context);
-      Builder.CreateCondBr(Cond, Dest, False_Block);
-      EmitBlock(False_Block);
-    }
-  }
-
-  if (DefaultDest) {
-    if (SI->getSuccessor(0) == Builder.GetInsertBlock())
-      SI->setSuccessor(0, DefaultDest);
-    else {
-      Builder.CreateBr(DefaultDest);
-      // Emit a "fallthrough" block, which is almost certainly dead.
-      EmitBlock(BasicBlock::Create(Context));
-    }
-  }
-
-  return 0;
-}
-
-
 /// CreateExceptionValues - Create values used internally by exception handling.
 void TreeToLLVM::CreateExceptionValues() {
   // Check to see if the exception values have been constructed.
@@ -3382,7 +3304,7 @@
   const Type *RHSTy = ConvertType(TREE_TYPE(rhs));
 
   assert((LHSTy == RHSTy ||
-          (isa<PointerType>(LHSTy) && isa<PointerType>(RHSTy))) && 
+          (isa<PointerType>(LHSTy) && isa<PointerType>(RHSTy))) &&
          "Unexpected types for comparison");
 
   // Compute the LLVM opcodes corresponding to the GCC comparison.
@@ -8147,7 +8069,72 @@
   Value *V = Builder.CreatePtrToInt(Emit(dest, 0), TD.getIntPtrType(Context));
   Builder.CreateStore(V, IndirectGotoValue);
 
-  // NOTE: This is HORRIBLY INCORRECT in the presence of exception handlers.
+  // FIXME: This is HORRIBLY INCORRECT in the presence of exception handlers.
   // There should be one collector block per cleanup level!
   Builder.CreateBr(DestBB);
 }
+
+void TreeToLLVM::RenderGIMPLE_SWITCH(gimple stmt) {
+  // Emit the condition.
+  Value *Index = Emit(gimple_switch_index(stmt), 0);
+  bool IndexIsSigned = !TYPE_UNSIGNED(TREE_TYPE(gimple_switch_index(stmt)));
+
+  // Create the switch instruction.
+  tree default_label = CASE_LABEL(gimple_switch_label(stmt, 0));
+  SwitchInst *SI = Builder.CreateSwitch(Index, getLabelDeclBlock(default_label),
+                                        gimple_switch_num_labels(stmt));
+
+  // Add the switch cases.
+  BasicBlock *IfBlock = 0; // Set if a range was output as an "if".
+  for (size_t i = 1, e = gimple_switch_num_labels(stmt); i != e; ++i) {
+    tree label = gimple_switch_label(stmt, i);
+    BasicBlock *Dest = getLabelDeclBlock(CASE_LABEL(label));
+
+    // Convert the integer to the right type.
+    Value *Val = Emit(CASE_LOW(label), 0);
+    Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(CASE_LOW(label))),
+                        Index->getType(), IndexIsSigned);
+    ConstantInt *LowC = cast<ConstantInt>(Val);
+
+    if (!CASE_HIGH(label)) {
+      SI->addCase(LowC, Dest); // Single destination.
+      continue;
+    }
+
+    // Otherwise, we have a range, like 'case 1 ... 17'.
+    Val = Emit(CASE_HIGH(label), 0);
+    // Make sure the case value is the same type as the switch expression
+    Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(CASE_HIGH(label))),
+                        Index->getType(), IndexIsSigned);
+    ConstantInt *HighC = cast<ConstantInt>(Val);
+
+    APInt Range = HighC->getValue() - LowC->getValue();
+    if (Range.ult(APInt(Range.getBitWidth(), 64))) {
+      // Add all of the necessary successors to the switch.
+      APInt CurrentValue = LowC->getValue();
+      while (1) {
+        SI->addCase(LowC, Dest);
+        if (LowC == HighC) break;  // Emitted the last one.
+        CurrentValue++;
+        LowC = ConstantInt::get(Context, CurrentValue);
+      }
+    } else {
+      // The range is too big to add to the switch - emit an "if".
+      if (!IfBlock) {
+        IfBlock = BasicBlock::Create(Context);
+        EmitBlock(IfBlock);
+      }
+      Value *Diff = Builder.CreateSub(Index, LowC);
+      Value *Cond = Builder.CreateICmpULE(Diff,
+                                          ConstantInt::get(Context, Range));
+      BasicBlock *False_Block = BasicBlock::Create(Context);
+      Builder.CreateCondBr(Cond, Dest, False_Block);
+      EmitBlock(False_Block);
+    }
+  }
+
+  if (IfBlock) {
+    Builder.CreateBr(SI->getDefaultDest());
+    SI->setSuccessor(0, IfBlock);
+  }
+}

Modified: gcc-plugin/trunk/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/gcc-plugin/trunk/llvm-internal.h?rev=81675&r1=81674&r2=81675&view=diff

==============================================================================
--- gcc-plugin/trunk/llvm-internal.h (original)
+++ gcc-plugin/trunk/llvm-internal.h Sun Sep 13 11:49:37 2009
@@ -520,6 +520,7 @@
   // Render* - Convert GIMPLE to LLVM.
   void RenderGIMPLE_COND(gimple_statement_d *);
   void RenderGIMPLE_GOTO(gimple_statement_d *);
+  void RenderGIMPLE_SWITCH(gimple_statement_d *);
 
 private:
   void EmitAutomaticVariableDecl(tree_node *decl);
@@ -542,7 +543,6 @@
 
   // Control flow.
   Value *EmitRETURN_EXPR(tree_node *exp, const MemRef *DestLoc);
-  Value *EmitSWITCH_EXPR(tree_node *exp);
 
   // Expressions.
   Value *EmitSSA_NAME(tree_node *exp);





More information about the llvm-commits mailing list