Revert "CFG rework for explicit exception edges"

This reverts commit 8b503db0432981c6b0b2271723f9bcf9448a554a.

Change-Id: I21d5255d827c63de6a229ef419f372fbcf4d16ed
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index af472b9..088768b 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -129,7 +129,6 @@
   kDebugCountOpcodes,
 #if defined(ART_USE_QUICK_COMPILER)
   kDebugDumpBitcodeFile,
-  kDebugVerifyBitcode,
 #endif
 };
 
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index 43cfa2f..1ecf61a 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -196,10 +196,9 @@
   kMirOpFusedCmpgDouble,
   kMirOpFusedCmpLong,
   kMirOpNop,
-  kMirOpNullCheck,
-  kMirOpRangeCheck,
-  kMirOpDivZeroCheck,
-  kMirOpCheck,
+  kMirOpNullNRangeUpCheck,
+  kMirOpNullNRangeDownCheck,
+  kMirOpLowerBound,
   kMirOpLast,
 };
 
@@ -246,10 +245,12 @@
   int optimizationFlags;
   int seqNum;
   union {
+    // Used by the inlined insn from the callee to find the mother method
+    const Method* calleeMethod;
+    // Used by the inlined invoke to find the class and method pointers
+    CallsiteInfo* callsiteInfo;
     // Used to quickly locate all Phi opcodes
     MIR* phiNext;
-    // Establish link between two halves of throwing instructions
-    MIR* throwInsn;
   } meta;
 };
 
@@ -277,6 +278,7 @@
   uint16_t nestingDepth;
   const Method* containingMethod;     // For blocks from the callee
   BBType blockType;
+  bool needFallThroughBranch;         // For blocks ended due to length limit
   bool isFallThroughFromInvoke;       // True means the block needs alignment
   MIR* firstMIRInsn;
   MIR* lastMIRInsn;
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index 99602f7..33ef0ad 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -822,16 +822,13 @@
   // 107 MIR_NOP
   DF_NOP,
 
-  // 108 MIR_NULL_CHECK
+  // 108 MIR_NULL_RANGE_UP_CHECK
   0,
 
-  // 109 MIR_RANGE_CHECK
+  // 109 MIR_NULL_RANGE_DOWN_CHECK
   0,
 
-  // 110 MIR_DIV_ZERO_CHECK
-  0,
-
-  // 111 MIR_CHECK
+  // 110 MIR_LOWER_BOUND
   0,
 };
 
@@ -858,29 +855,27 @@
 char* oatGetDalvikDisassembly(CompilationUnit* cUnit,
                               const DecodedInstruction& insn, const char* note)
 {
-  std::string str;
-  int opcode = insn.opcode;
+  char buffer[256];
+  Instruction::Code opcode = insn.opcode;
   int dfAttributes = oatDataFlowAttributes[opcode];
   int flags;
   char* ret;
 
-  if (opcode >= kMirOpFirst) {
-    if (opcode == kMirOpPhi) {
-      str.append("PHI");
-    } else if (opcode == kMirOpCheck) {
-      str.append("Check");
+  buffer[0] = 0;
+  if ((int)opcode >= (int)kMirOpFirst) {
+    if ((int)opcode == (int)kMirOpPhi) {
+      strcpy(buffer, "PHI");
     } else {
-      str.append(StringPrintf("Opcode %#x", opcode));
+      sprintf(buffer, "Opcode %#x", opcode);
     }
     flags = 0;
   } else {
-    str.append(Instruction::Name(insn.opcode));
-    flags = Instruction::Flags(insn.opcode);
+    strcpy(buffer, Instruction::Name(opcode));
+    flags = Instruction::Flags(opcode);
   }
 
-  if (note) {
-    str.append(note);
-  }
+  if (note)
+    strcat(buffer, note);
 
   /* For branches, decode the instructions to print out the branch targets */
   if (flags & Instruction::kBranch) {
@@ -888,11 +883,11 @@
     int offset = 0;
     switch (dalvikFormat) {
       case Instruction::k21t:
-        str.append(StringPrintf(" v%d,", insn.vA));
+        snprintf(buffer + strlen(buffer), 256, " v%d,", insn.vA);
         offset = (int) insn.vB;
         break;
       case Instruction::k22t:
-        str.append(StringPrintf(" v%d, v%d,", insn.vA, insn.vB));
+        snprintf(buffer + strlen(buffer), 256, " v%d, v%d,", insn.vA, insn.vB);
         offset = (int) insn.vC;
         break;
       case Instruction::k10t:
@@ -904,43 +899,45 @@
         LOG(FATAL) << "Unexpected branch format " << (int)dalvikFormat
                    << " / opcode " << (int)opcode;
     }
-    str.append(StringPrintf(" (%c%x)",
-                            offset > 0 ? '+' : '-',
-                            offset > 0 ? offset : -offset));
+    snprintf(buffer + strlen(buffer), 256, " (%c%x)",
+             offset > 0 ? '+' : '-',
+             offset > 0 ? offset : -offset);
   } else if (dfAttributes & DF_FORMAT_35C) {
     unsigned int i;
     for (i = 0; i < insn.vA; i++) {
-      if (i != 0) str.append(",");
-      str.append(StringPrintf(" v%d", insn.arg[i]));
+      if (i != 0) strcat(buffer, ",");
+        snprintf(buffer + strlen(buffer), 256, " v%d", insn.arg[i]);
     }
   }
   else if (dfAttributes & DF_FORMAT_3RC) {
-    str.append(StringPrintf(" v%d..v%d", insn.vC, insn.vC + insn.vA - 1));
+    snprintf(buffer + strlen(buffer), 256,
+             " v%d..v%d", insn.vC, insn.vC + insn.vA - 1);
   } else {
     if (dfAttributes & DF_A_IS_REG) {
-      str.append(StringPrintf(" v%d", insn.vA));
+      snprintf(buffer + strlen(buffer), 256, " v%d", insn.vA);
     }
     if (dfAttributes & DF_B_IS_REG) {
-      str.append(StringPrintf(", v%d", insn.vB));
+      snprintf(buffer + strlen(buffer), 256, ", v%d", insn.vB);
     } else if ((int)opcode < (int)kMirOpFirst) {
-      str.append(StringPrintf(", (#%d)", insn.vB));
+      snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn.vB);
     }
     if (dfAttributes & DF_C_IS_REG) {
-      str.append(StringPrintf(", v%d", insn.vC));
+      snprintf(buffer + strlen(buffer), 256, ", v%d", insn.vC);
     } else if ((int)opcode < (int)kMirOpFirst) {
-      str.append(StringPrintf(", (#%d)", insn.vC));
+      snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn.vC);
     }
   }
-  int length = str.length() + 1;
+  int length = strlen(buffer) + 1;
   ret = (char*)oatNew(cUnit, length, false, kAllocDFInfo);
-  strncpy(ret, str.c_str(), length);
+  memcpy(ret, buffer, length);
   return ret;
 }
 
-std::string getSSAName(const CompilationUnit* cUnit, int ssaReg)
+char* getSSAName(const CompilationUnit* cUnit, int ssaReg, char* name)
 {
-  return StringPrintf("v%d_%d", SRegToVReg(cUnit, ssaReg),
-                     SRegToSubscript(cUnit, ssaReg));
+  sprintf(name, "v%d_%d", SRegToVReg(cUnit, ssaReg),
+          SRegToSubscript(cUnit, ssaReg));
+  return name;
 }
 
 /*
@@ -948,38 +945,32 @@
  */
 char* oatFullDisassembler(CompilationUnit* cUnit, const MIR* mir)
 {
-  std::string str;
+  char buffer[256];
+  char operand0[32], operand1[32];
   const DecodedInstruction* insn = &mir->dalvikInsn;
-  int opcode = insn->opcode;
+  Instruction::Code opcode = insn->opcode;
   int dfAttributes = oatDataFlowAttributes[opcode];
   char* ret;
   int length;
 
-  if (opcode >= kMirOpFirst) {
-    if (opcode == kMirOpPhi) {
-      int* incoming = (int*)mir->dalvikInsn.vB;
-      str.append(StringPrintf("PHI %s = (%s",
-                 getSSAName(cUnit, mir->ssaRep->defs[0]).c_str(),
-                 getSSAName(cUnit, mir->ssaRep->uses[0]).c_str()));
-      str.append(StringPrintf(":%d",incoming[0]));
+  buffer[0] = 0;
+  if (static_cast<int>(opcode) >= static_cast<int>(kMirOpFirst)) {
+    if (static_cast<int>(opcode) == static_cast<int>(kMirOpPhi)) {
+      snprintf(buffer, 256, "PHI %s = (%s",
+               getSSAName(cUnit, mir->ssaRep->defs[0], operand0),
+               getSSAName(cUnit, mir->ssaRep->uses[0], operand1));
       int i;
       for (i = 1; i < mir->ssaRep->numUses; i++) {
-        str.append(StringPrintf(", %s:%d",
-                                getSSAName(cUnit, mir->ssaRep->uses[i]).c_str(),
-                                incoming[i]));
+        snprintf(buffer + strlen(buffer), 256, ", %s",
+        getSSAName(cUnit, mir->ssaRep->uses[i], operand0));
       }
-      str.append(")");
-    } else if (opcode == kMirOpCheck) {
-      str.append("Check ");
-      str.append(Instruction::Name(mir->meta.throwInsn->dalvikInsn.opcode));
-    } else if (opcode == kMirOpNop) {
-      str.append("MirNop");
+      snprintf(buffer + strlen(buffer), 256, ")");
     } else {
-      str.append(StringPrintf("Opcode %#x", opcode));
+      sprintf(buffer, "Opcode %#x", opcode);
     }
     goto done;
   } else {
-    str.append(Instruction::Name(insn->opcode));
+    strcpy(buffer, Instruction::Name(opcode));
   }
 
   /* For branches, decode the instructions to print out the branch targets */
@@ -988,14 +979,14 @@
     int delta = 0;
     switch (dalvikFormat) {
       case Instruction::k21t:
-        str.append(StringPrintf(" %s, ",
-                   getSSAName(cUnit, mir->ssaRep->uses[0]).c_str()));
+        snprintf(buffer + strlen(buffer), 256, " %s, ",
+                 getSSAName(cUnit, mir->ssaRep->uses[0], operand0));
         delta = (int) insn->vB;
         break;
       case Instruction::k22t:
-        str.append(StringPrintf(" %s, %s, ",
-                 getSSAName(cUnit, mir->ssaRep->uses[0]).c_str(),
-                 getSSAName(cUnit, mir->ssaRep->uses[1]).c_str()));
+        snprintf(buffer + strlen(buffer), 256, " %s, %s, ",
+                 getSSAName(cUnit, mir->ssaRep->uses[0], operand0),
+                 getSSAName(cUnit, mir->ssaRep->uses[1], operand1));
         delta = (int) insn->vC;
         break;
       case Instruction::k10t:
@@ -1006,53 +997,54 @@
       default:
         LOG(FATAL) << "Unexpected branch format: " << (int)dalvikFormat;
       }
-      str.append(StringPrintf(" %04x", mir->offset + delta));
+      snprintf(buffer + strlen(buffer), 256, " %04x",
+               mir->offset + delta);
   } else if (dfAttributes & (DF_FORMAT_35C | DF_FORMAT_3RC)) {
     unsigned int i;
     for (i = 0; i < insn->vA; i++) {
-      if (i != 0) str.append(",");
-        str.append(" ");
-        str.append(getSSAName(cUnit, mir->ssaRep->uses[i]));
+      if (i != 0) strcat(buffer, ",");
+        snprintf(buffer + strlen(buffer), 256, " %s",
+                 getSSAName(cUnit, mir->ssaRep->uses[i], operand0));
     }
   } else {
     int udIdx;
     if (mir->ssaRep->numDefs) {
 
       for (udIdx = 0; udIdx < mir->ssaRep->numDefs; udIdx++) {
-        str.append(" ");
-        str.append(getSSAName(cUnit, mir->ssaRep->defs[udIdx]));
+        snprintf(buffer + strlen(buffer), 256, " %s",
+                 getSSAName(cUnit, mir->ssaRep->defs[udIdx], operand0));
       }
-      str.append(",");
+      strcat(buffer, ",");
     }
     if (mir->ssaRep->numUses) {
       /* No leading ',' for the first use */
-      str.append(" ");
-      str.append(getSSAName(cUnit, mir->ssaRep->uses[0]));
+      snprintf(buffer + strlen(buffer), 256, " %s",
+               getSSAName(cUnit, mir->ssaRep->uses[0], operand0));
       for (udIdx = 1; udIdx < mir->ssaRep->numUses; udIdx++) {
-        str.append(", ");
-        str.append(getSSAName(cUnit, mir->ssaRep->uses[udIdx]));
+        snprintf(buffer + strlen(buffer), 256, ", %s",
+                 getSSAName(cUnit, mir->ssaRep->uses[udIdx], operand0));
         }
       }
       if (static_cast<int>(opcode) < static_cast<int>(kMirOpFirst)) {
-        Instruction::Format dalvikFormat = Instruction::FormatOf(insn->opcode);
+        Instruction::Format dalvikFormat = Instruction::FormatOf(opcode);
         switch (dalvikFormat) {
           case Instruction::k11n:        // op vA, #+B
           case Instruction::k21s:        // op vAA, #+BBBB
           case Instruction::k21h:        // op vAA, #+BBBB00000[00000000]
           case Instruction::k31i:        // op vAA, #+BBBBBBBB
           case Instruction::k51l:        // op vAA, #+BBBBBBBBBBBBBBBB
-            str.append(StringPrintf(" #%#x", insn->vB));
+            snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vB);
             break;
           case Instruction::k21c:        // op vAA, thing@BBBB
           case Instruction::k31c:        // op vAA, thing@BBBBBBBB
-            str.append(StringPrintf(" @%#x", insn->vB));
+            snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vB);
             break;
           case Instruction::k22b:        // op vAA, vBB, #+CC
           case Instruction::k22s:        // op vA, vB, #+CCCC
-            str.append(StringPrintf(" #%#x", insn->vC));
+            snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vC);
             break;
           case Instruction::k22c:        // op vA, vB, thing@CCCC
-            str.append(StringPrintf(" @%#x", insn->vC));
+            snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vC);
             break;
           /* No need for special printing */
           default:
@@ -1062,38 +1054,44 @@
   }
 
 done:
-  length = str.length() + 1;
+  length = strlen(buffer) + 1;
   ret = (char*) oatNew(cUnit, length, false, kAllocDFInfo);
-  strncpy(ret, str.c_str(), length);
+  memcpy(ret, buffer, length);
   return ret;
 }
 
 char* oatGetSSAString(CompilationUnit* cUnit, SSARepresentation* ssaRep)
 {
-  std::string str;
+  char buffer[256];
   char* ret;
   int i;
 
+  buffer[0] = 0;
   for (i = 0; i < ssaRep->numDefs; i++) {
     int ssaReg = ssaRep->defs[i];
-    str.append(StringPrintf("s%d(v%d_%d) ", ssaReg,
-                            SRegToVReg(cUnit, ssaReg),
-                            SRegToSubscript(cUnit, ssaReg)));
+    sprintf(buffer + strlen(buffer), "s%d(v%d_%d) ", ssaReg,
+            SRegToVReg(cUnit, ssaReg), SRegToSubscript(cUnit, ssaReg));
   }
 
   if (ssaRep->numDefs) {
-    str.append("<- ");
+    strcat(buffer, "<- ");
   }
 
   for (i = 0; i < ssaRep->numUses; i++) {
+    int len = strlen(buffer);
     int ssaReg = ssaRep->uses[i];
-    str.append(StringPrintf("s%d(v%d_%d) ", ssaReg, SRegToVReg(cUnit, ssaReg),
-               SRegToSubscript(cUnit, ssaReg)));
+
+    if (snprintf(buffer + len, 250 - len, "s%d(v%d_%d) ", ssaReg,
+                 SRegToVReg(cUnit, ssaReg),
+                 SRegToSubscript(cUnit, ssaReg))) {
+      strcat(buffer, "...");
+      break;
+    }
   }
 
-  int length = str.length() + 1;
+  int length = strlen(buffer) + 1;
   ret = (char*)oatNew(cUnit, length, false, kAllocDFInfo);
-  strncpy(ret, str.c_str(), length);
+  memcpy(ret, buffer, length);
   return ret;
 }
 
@@ -1185,10 +1183,8 @@
   int ssaReg = cUnit->numSSARegs++;
   oatInsertGrowableList(cUnit, cUnit->ssaBaseVRegs, vReg);
   oatInsertGrowableList(cUnit, cUnit->ssaSubscripts, subscript);
-  std::string ssaName = getSSAName(cUnit, ssaReg);
-  char* name = (char*)oatNew(cUnit, ssaName.length() + 1, false, kAllocDFInfo);
-  strncpy(name, ssaName.c_str(), ssaName.length() + 1);
-  oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)name);
+  char* name = (char*)oatNew(cUnit, SSA_NAME_MAX, true, kAllocDFInfo);
+  oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)getSSAName(cUnit, ssaReg, name));
   DCHECK_EQ(cUnit->ssaBaseVRegs->numUsed, cUnit->ssaSubscripts->numUsed);
   return ssaReg;
 }
@@ -1496,10 +1492,8 @@
   for (i = 0; i < numDalvikReg; i++) {
     oatInsertGrowableList(cUnit, cUnit->ssaBaseVRegs, i);
     oatInsertGrowableList(cUnit, cUnit->ssaSubscripts, 0);
-    std::string ssaName = getSSAName(cUnit, i);
-    char* name = (char*)oatNew(cUnit, ssaName.length() + 1, true, kAllocDFInfo);
-    strncpy(name, ssaName.c_str(), ssaName.length() + 1);
-    oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)name);
+    char* name = (char*)oatNew(cUnit, SSA_NAME_MAX, true, kAllocDFInfo);
+    oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)getSSAName(cUnit, i, name));
   }
 
   /*
@@ -1693,14 +1687,14 @@
   BasicBlock* tbb = bb;
   mir = advanceMIR(cUnit, &tbb, mir, NULL, false);
   while (mir != NULL) {
-    int opcode = mir->dalvikInsn.opcode;
     if ((mir->dalvikInsn.opcode == Instruction::MOVE_RESULT) ||
         (mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) ||
         (mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE)) {
       break;
     }
     // Keep going if pseudo op, otherwise terminate
-    if (opcode < kNumPackedOpcodes) {
+    if (mir->dalvikInsn.opcode <
+        static_cast<Instruction::Code>(kNumPackedOpcodes)) {
       mir = NULL;
     } else {
       mir = advanceMIR(cUnit, &tbb, mir, NULL, false);
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 932a39f..7585b77 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -54,7 +54,6 @@
   //(1 << kDebugCountOpcodes) |
 #if defined(ART_USE_QUICK_COMPILER)
   //(1 << kDebugDumpBitcodeFile) |
-  //(1 << kDebugVerifyBitcode) |
 #endif
   0;
 
@@ -155,8 +154,10 @@
   }
 
   /* Handle the fallthrough path */
+  bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch;
   bottomBlock->fallThrough = origBlock->fallThrough;
   origBlock->fallThrough = bottomBlock;
+  origBlock->needFallThroughBranch = true;
   oatInsertGrowableList(cUnit, bottomBlock->predecessors,
                         (intptr_t)origBlock);
   if (bottomBlock->fallThrough) {
@@ -288,12 +289,12 @@
                                                               blockIdx);
     if (bb == NULL) break;
     if (bb->blockType == kEntryBlock) {
-      fprintf(file, "  entry_%d [shape=Mdiamond];\n", bb->id);
+      fprintf(file, "  entry [shape=Mdiamond];\n");
     } else if (bb->blockType == kExitBlock) {
-      fprintf(file, "  exit_%d [shape=Mdiamond];\n", bb->id);
+      fprintf(file, "  exit [shape=Mdiamond];\n");
     } else if (bb->blockType == kDalvikByteCode) {
-      fprintf(file, "  block%04x_%d [shape=record,label = \"{ \\\n",
-              bb->startOffset, bb->id);
+      fprintf(file, "  block%04x [shape=record,label = \"{ \\\n",
+              bb->startOffset);
       const MIR *mir;
         fprintf(file, "    {block id %d\\l}%s\\\n", bb->id,
                 bb->firstMIRInsn ? " | " : " ");
@@ -326,8 +327,8 @@
     }
 
     if (bb->successorBlockList.blockListType != kNotUsed) {
-      fprintf(file, "  succ%04x_%d [shape=%s,label = \"{ \\\n",
-              bb->startOffset, bb->id,
+      fprintf(file, "  succ%04x [shape=%s,label = \"{ \\\n",
+              bb->startOffset,
               (bb->successorBlockList.blockListType == kCatch) ?
                "Mrecord" : "record");
       GrowableListIterator iterator;
@@ -355,8 +356,8 @@
       fprintf(file, "  }\"];\n\n");
 
       oatGetBlockName(bb, blockName1);
-      fprintf(file, "  %s:s -> succ%04x_%d:n [style=dashed]\n",
-              blockName1, bb->startOffset, bb->id);
+      fprintf(file, "  %s:s -> succ%04x:n [style=dashed]\n",
+              blockName1, bb->startOffset);
 
       if (bb->successorBlockList.blockListType == kPackedSwitch ||
           bb->successorBlockList.blockListType == kSparseSwitch) {
@@ -373,8 +374,8 @@
           BasicBlock *destBlock = successorBlockInfo->block;
 
           oatGetBlockName(destBlock, blockName2);
-          fprintf(file, "  succ%04x_%d:f%d:e -> %s:n\n", bb->startOffset,
-                  bb->id, succId++, blockName2);
+          fprintf(file, "  succ%04x:f%d:e -> %s:n\n", bb->startOffset,
+                  succId++, blockName2);
         }
       }
     }
@@ -643,20 +644,18 @@
 }
 
 /* Process instructions with the kThrow flag */
-BasicBlock* processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock,
-                            MIR* insn, int curOffset, int width, int flags,
-                            ArenaBitVector* tryBlockAddr, const u2* codePtr,
-                            const u2* codeEnd)
+void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, MIR* insn,
+                     int curOffset, int width, int flags,
+                     ArenaBitVector* tryBlockAddr, const u2* codePtr,
+                     const u2* codeEnd)
 {
   const DexFile::CodeItem* code_item = cUnit->code_item;
-  bool inTryBlock = oatIsBitSet(tryBlockAddr, curOffset);
 
   /* In try block */
-  if (inTryBlock) {
+  if (oatIsBitSet(tryBlockAddr, curOffset)) {
     CatchHandlerIterator iterator(*code_item, curOffset);
 
     if (curBlock->successorBlockList.blockListType != kNotUsed) {
-      LOG(INFO) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
       LOG(FATAL) << "Successor block list already in use: "
                  << (int)curBlock->successorBlockList.blockListType;
     }
@@ -689,46 +688,37 @@
     oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
   }
 
-  if (insn->dalvikInsn.opcode == Instruction::THROW){
-    if ((codePtr < codeEnd) && contentIsInsn(codePtr)) {
-      // Force creation of new block following THROW via side-effect
-      findBlock(cUnit, curOffset + width, /* split */ false,
-                /* create */ true, /* immedPredBlockP */ NULL);
-    }
-    if (!inTryBlock) {
-       // Don't split a THROW that can't rethrow - we're done.
-      return curBlock;
+  /*
+   * Force the current block to terminate.
+   *
+   * Data may be present before codeEnd, so we need to parse it to know
+   * whether it is code or data.
+   */
+  if (codePtr < codeEnd) {
+    /* Create a fallthrough block for real instructions (incl. NOP) */
+    if (contentIsInsn(codePtr)) {
+      BasicBlock *fallthroughBlock = findBlock(cUnit,
+                                               curOffset + width,
+                                               /* split */
+                                               false,
+                                               /* create */
+                                               true,
+                                               /* immedPredBlockP */
+                                               NULL);
+      /*
+       * THROW is an unconditional branch.  NOTE:
+       * THROW_VERIFICATION_ERROR is also an unconditional
+       * branch, but we shouldn't treat it as such until we have
+       * a dead code elimination pass (which won't be important
+       * until inlining w/ constant propagation is implemented.
+       */
+      if (insn->dalvikInsn.opcode != Instruction::THROW) {
+        curBlock->fallThrough = fallthroughBlock;
+        oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
+                              (intptr_t)curBlock);
+      }
     }
   }
-
-  /*
-   * Split the potentially-throwing instruction into two parts.
-   * The first half will be a pseudo-op that captures the exception
-   * edges and terminates the basic block.  It always falls through.
-   * Then, create a new basic block that begins with the throwing instruction
-   * (minus exceptions).  Note: this new basic block must NOT be entered into
-   * the blockMap.  If the potentially-throwing instruction is the target of a
-   * future branch, we need to find the check psuedo half.  The new
-   * basic block containing the work portion of the instruction should
-   * only be entered via fallthrough from the block containing the
-   * pseudo exception edge MIR.  Note also that this new block is
-   * not automatically terminated after the work portion, and may
-   * contain following instructions.
-   */
-  BasicBlock *newBlock = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
-  oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t)newBlock);
-  newBlock->startOffset = insn->offset;
-  curBlock->fallThrough = newBlock;
-  oatInsertGrowableList(cUnit, newBlock->predecessors, (intptr_t)curBlock);
-  MIR* newInsn = (MIR*)oatNew(cUnit, sizeof(MIR), true, kAllocMIR);
-  *newInsn = *insn;
-  insn->dalvikInsn.opcode =
-      static_cast<Instruction::Code>(kMirOpCheck);
-  // Associate the two halves
-  insn->meta.throwInsn = newInsn;
-  newInsn->meta.throwInsn = insn;
-  oatAppendMIR(newBlock, newInsn);
-  return newBlock;
 }
 
 void oatInit(CompilationUnit* cUnit, const Compiler& compiler) {
@@ -773,11 +763,15 @@
   cUnit->numRegs = code_item->registers_size_ - cUnit->numIns;
   cUnit->numOuts = code_item->outs_size_;
 #if defined(ART_USE_QUICK_COMPILER)
-  DCHECK((cUnit->instructionSet == kThumb2) ||
-         (cUnit->instructionSet == kX86) ||
-         (cUnit->instructionSet == kMips));
-  if (cUnit->instructionSet == kThumb2) {
-    // TODO: remove this once x86 is tested
+  // TODO: fix bug and remove this workaround
+  std::string methodName = PrettyMethod(method_idx, dex_file);
+  if ((methodName.find("gdata2.AndroidGDataClient.createAndExecuteMethod")
+      != std::string::npos) || (methodName.find("hG.a") != std::string::npos)
+      || (methodName.find("hT.a(hV, java.lang.String, java.lang.String, java")
+      != std::string::npos) || (methodName.find("AndroidHttpTransport.exchange")
+      != std::string::npos)) {
+    LOG(INFO) << "Skipping bitcode generation for " << methodName;
+  } else {
     cUnit->genBitcode = true;
   }
 #endif
@@ -797,7 +791,6 @@
   }
 #if defined(ART_USE_QUICK_COMPILER)
   if (cUnit->genBitcode) {
-    //cUnit->enableDebug |= (1 << kDebugVerifyBitcode);
     //cUnit->printMe = true;
     //cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
     // Disable non-safe optimizations for now
@@ -965,8 +958,8 @@
         }
       }
     } else if (flags & Instruction::kThrow) {
-      curBlock = processCanThrow(cUnit.get(), curBlock, insn, curOffset,
-                                 width, flags, tryBlockAddr, codePtr, codeEnd);
+      processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
+                      tryBlockAddr, codePtr, codeEnd);
     } else if (flags & Instruction::kSwitch) {
       processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
     }
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index f4e735a..500b1b2 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -89,6 +89,20 @@
   return false;
 }
 
+// Try to find the next move result which might have an FP target
+SSARepresentation* findFPMoveResult(MIR* mir)
+{
+  SSARepresentation* res = NULL;
+  for (; mir; mir = mir->next) {
+    if ((mir->dalvikInsn.opcode == Instruction::MOVE_RESULT) ||
+        (mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE)) {
+      res = mir->ssaRep;
+      break;
+    }
+  }
+  return res;
+}
+
 /*
  * Infer types and sizes.  We don't need to track change on sizes,
  * as it doesn't propagate.  We're guaranteed at least one pass through
@@ -222,12 +236,14 @@
         const char* shorty = oatGetShortyFromTargetIdx(cUnit, target_idx);
         // Handle result type if floating point
         if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
-          MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
+          // Find move-result that consumes this result
+          SSARepresentation* tgtRep = findFPMoveResult(mir->next);
+          // Might be in next basic block
+          if (!tgtRep) {
+            tgtRep = findFPMoveResult(bb->fallThrough->firstMIRInsn);
+          }
           // Result might not be used at all, so no move-result
-          if (moveResultMIR && (moveResultMIR->dalvikInsn.opcode !=
-              Instruction::MOVE_RESULT_OBJECT)) {
-            SSARepresentation* tgtRep = moveResultMIR->ssaRep;
-            DCHECK(tgtRep != NULL);
+          if (tgtRep) {
             tgtRep->fpDef[0] = true;
             changed |= setFp(cUnit, tgtRep->defs[0], true);
             if (shorty[0] == 'D') {
diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc
index c865718..571208f 100644
--- a/src/compiler/Utility.cc
+++ b/src/compiler/Utility.cc
@@ -687,20 +687,19 @@
 {
   switch (bb->blockType) {
     case kEntryBlock:
-      snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id);
+      snprintf(name, BLOCK_NAME_LEN, "entry");
       break;
     case kExitBlock:
-      snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id);
+      snprintf(name, BLOCK_NAME_LEN, "exit");
       break;
     case kDalvikByteCode:
-      snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->startOffset, bb->id);
+      snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
       break;
     case kExceptionHandling:
-      snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->startOffset,
-               bb->id);
+      snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
       break;
     default:
-      snprintf(name, BLOCK_NAME_LEN, "??_%d", bb->id);
+      snprintf(name, BLOCK_NAME_LEN, "??");
       break;
   }
 }
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index b2cbc69..864372a 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -51,7 +51,7 @@
   llvm::Value* placeholder = getLLVMValue(cUnit, sReg);
   if (placeholder == NULL) {
     // This can happen on instruction rewrite on verification failure
-    LOG(WARNING) << "Null placeholder";
+    LOG(WARNING) << "Null placeholder - invalid CFG";
     return;
   }
   placeholder->replaceAllUsesWith(val);
@@ -307,6 +307,7 @@
   llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction(
       greenland::IntrinsicHelper::Throw);
   cUnit->irb->CreateCall(func, src);
+  cUnit->irb->CreateUnreachable();
 }
 
 void convertMonitorEnterExit(CompilationUnit* cUnit, int optFlags,
@@ -811,15 +812,6 @@
 
   bool objectDefinition = false;
 
-  if (cUnit->printMe) {
-    if ((int)opcode < kMirOpFirst) {
-      LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x"
-                << std::hex << (int)opcode;
-    } else {
-      LOG(INFO) << ".. opcode 0x" << std::hex << (int)opcode;
-    }
-  }
-
   /* Prep Src and Dest locations */
   int nextSreg = 0;
   int nextLoc = 0;
@@ -1300,24 +1292,10 @@
 
    case Instruction::THROW:
       convertThrow(cUnit, rlSrc[0]);
-      /*
-       * If this throw is standalone, terminate.
-       * If it might rethrow, force termination
-       * of the following block.
-       */
-      if (bb->fallThrough == NULL) {
-        cUnit->irb->CreateUnreachable();
-      } else {
-        bb->fallThrough->fallThrough = NULL;
-        bb->fallThrough->taken = NULL;
-      }
       break;
 
    case Instruction::THROW_VERIFICATION_ERROR:
       convertThrowVerificationError(cUnit, vA, vB);
-      UNIMPLEMENTED(WARNING) << "Need dead code elimination pass"
-                             << " - disabling bitcode verification";
-      cUnit->enableDebug &= ~(1 << kDebugVerifyBitcode);
       break;
 
     case Instruction::MOVE_RESULT_WIDE:
@@ -1328,8 +1306,7 @@
        * Instruction rewriting on verification failure can eliminate
        * the invoke that feeds this move0result.  It won't ever be reached,
        * so we can ignore it.
-       * TODO: verify that previous instruction is THROW_VERIFICATION_ERROR,
-       * or better, add dead-code elimination.
+       * TODO: verify that previous instruction if THROW_VERIFICATION_ERROR
        */
       UNIMPLEMENTED(WARNING) << "Need to verify previous inst was rewritten";
 #else
@@ -1672,13 +1649,6 @@
       UNIMPLEMENTED(WARNING) << "unimp kMirOpPhi";
       break;
     }
-    case kMirOpNop:
-      if ((mir == bb->lastMIRInsn) && (bb->taken == NULL) &&
-          (bb->fallThrough == NULL)) {
-        cUnit->irb->CreateUnreachable();
-      }
-      break;
-
 #if defined(TARGET_ARM)
     case kMirOpFusedCmplFloat:
       UNIMPLEMENTED(WARNING) << "unimp kMirOpFusedCmpFloat";
@@ -1750,16 +1720,6 @@
   cUnit->irb->SetInsertPoint(llvmBB);
   setDexOffset(cUnit, bb->startOffset);
 
-  if (cUnit->printMe) {
-    LOG(INFO) << "................................";
-    LOG(INFO) << "Block id " << bb->id;
-    if (llvmBB != NULL) {
-      LOG(INFO) << "label " << llvmBB->getName().str().c_str();
-    } else {
-      LOG(INFO) << "llvmBB is NULL";
-    }
-  }
-
   if (bb->blockType == kEntryBlock) {
     setMethodInfo(cUnit);
     bool *canBeRef = (bool*)  oatNew(cUnit, sizeof(bool) *
@@ -1799,6 +1759,8 @@
     /*
      * Because we're deferring null checking, delete the associated empty
      * exception block.
+     * TODO: add new block type for exception blocks that we generate
+     * greenland code for.
      */
     llvmBB->eraseFromParent();
     return false;
@@ -1808,9 +1770,8 @@
 
     setDexOffset(cUnit, mir->offset);
 
-    int opcode = mir->dalvikInsn.opcode;
-    Instruction::Format dalvikFormat =
-        Instruction::FormatOf(mir->dalvikInsn.opcode);
+    Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
+    Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
 
     /* If we're compiling for the debugger, generate an update callout */
     if (cUnit->genDebugger) {
@@ -1818,43 +1779,7 @@
       //genDebuggerUpdate(cUnit, mir->offset);
     }
 
-    if (opcode == kMirOpCheck) {
-      // Combine check and work halves of throwing instruction.
-      MIR* workHalf = mir->meta.throwInsn;
-      mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
-      opcode = mir->dalvikInsn.opcode;
-      SSARepresentation* ssaRep = workHalf->ssaRep;
-      workHalf->ssaRep = mir->ssaRep;
-      mir->ssaRep = ssaRep;
-      workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
-      if (bb->successorBlockList.blockListType == kCatch) {
-        llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction(
-            greenland::IntrinsicHelper::CatchTargets);
-        llvm::Value* switchKey =
-            cUnit->irb->CreateCall(intr, cUnit->irb->getInt32(mir->offset));
-        GrowableListIterator iter;
-        oatGrowableListIteratorInit(&bb->successorBlockList.blocks, &iter);
-        // New basic block to use for work half
-        llvm::BasicBlock* workBB =
-            llvm::BasicBlock::Create(*cUnit->context, "", cUnit->func);
-        llvm::SwitchInst* sw =
-            cUnit->irb->CreateSwitch(switchKey, workBB,
-                                     bb->successorBlockList.blocks.numUsed);
-        while (true) {
-          SuccessorBlockInfo *successorBlockInfo =
-              (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iter);
-          if (successorBlockInfo == NULL) break;
-          llvm::BasicBlock *target =
-              getLLVMBlock(cUnit, successorBlockInfo->block->id);
-          int typeIndex = successorBlockInfo->key;
-          sw->addCase(cUnit->irb->getInt32(typeIndex), target);
-        }
-        llvmBB = workBB;
-        cUnit->irb->SetInsertPoint(llvmBB);
-      }
-    }
-
-    if (opcode >= kMirOpFirst) {
+    if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
       convertExtendedMIR(cUnit, bb, mir, llvmBB);
       continue;
     }
@@ -1862,9 +1787,8 @@
     bool notHandled = convertMIRNode(cUnit, mir, bb, llvmBB,
                                      NULL /* labelList */);
     if (notHandled) {
-      Instruction::Code dalvikOpcode = static_cast<Instruction::Code>(opcode);
       LOG(WARNING) << StringPrintf("%#06x: Op %#x (%s) / Fmt %d not handled",
-                                   mir->offset, opcode,
+                                   mir->offset, dalvikOpcode,
                                    Instruction::Name(dalvikOpcode),
                                    dalvikFormat);
     }
@@ -2062,14 +1986,7 @@
   cUnit->irb->SetInsertPoint(cUnit->entryBB);
   cUnit->irb->CreateBr(cUnit->entryTargetBB);
 
-  if (cUnit->enableDebug & (1 << kDebugVerifyBitcode)) {
-     if (llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction)) {
-       LOG(INFO) << "Bitcode verification FAILED for "
-                 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file)
-                 << " of size " << cUnit->insnsSize;
-       cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
-     }
-  }
+  //llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction);
 
   if (cUnit->enableDebug & (1 << kDebugDumpBitcodeFile)) {
     // Write bitcode to file
@@ -3214,24 +3131,6 @@
               cvtShiftOp(cUnit, Instruction::USHR_INT, callInst);
               break;
 
-            case greenland::IntrinsicHelper::CatchTargets: {
-                llvm::SwitchInst* swInst =
-                    llvm::dyn_cast<llvm::SwitchInst>(nextIt);
-                DCHECK(swInst != NULL);
-                /*
-                 * Discard the edges and the following conditional branch.
-                 * Do a direct branch to the default target (which is the
-                 * "work" portion of the pair.
-                 * TODO: awful code layout - rework
-                 */
-                 llvm::BasicBlock* targetBB = swInst->getDefaultDest();
-                 DCHECK(targetBB != NULL);
-                 opUnconditionalBranch(cUnit,
-                                       cUnit->blockToLabelMap.Get(targetBB));
-                 ++it;
-              }
-              break;
-
             default:
               LOG(FATAL) << "Unexpected intrinsic " << (int)id << ", "
                          << cUnit->intrinsic_helper->GetName(id);
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index d32c9fb..e56e627 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -819,10 +819,9 @@
   "kMirFusedCmpgDouble",
   "kMirFusedCmpLong",
   "kMirNop",
-  "kMirOpNullCheck",
-  "kMirOpRangeCheck",
-  "kMirOpDivZeroCheck",
-  "kMirOpCheck",
+  "kMirOpNullNRangeUpCheck",
+  "kMirOpNullNRangeDownCheck",
+  "kMirOpLowerBound",
 };
 
 /* Extended MIR instructions like PHI */
@@ -957,17 +956,7 @@
       newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
     }
 
-    if ((int)dalvikOpcode == (int)kMirOpCheck) {
-      // Combine check and work halves of throwing instruction.
-      MIR* workHalf = mir->meta.throwInsn;
-      mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
-      SSARepresentation* ssaRep = workHalf->ssaRep;
-      workHalf->ssaRep = mir->ssaRep;
-      mir->ssaRep = ssaRep;
-      workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
-    }
-
-    if ((int)dalvikOpcode >= (int)kMirOpFirst) {
+    if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
       handleExtendedMethodMIR(cUnit, bb, mir);
       continue;
     }
diff --git a/src/greenland/intrinsic_func_list.def b/src/greenland/intrinsic_func_list.def
index a0f64d6..0ebebb2 100644
--- a/src/greenland/intrinsic_func_list.def
+++ b/src/greenland/intrinsic_func_list.def
@@ -66,23 +66,11 @@
 // Exception
 //----------------------------------------------------------------------------
 
-// Should not expand - introduces the catch targets for a potentially
-// throwing instruction.  The result is a switch key and this
-// instruction will be followed by a switch statement.  The catch
-// targets will be enumerated as cases of the switch, with the fallthrough
-// designating the block containing the potentially throwing instruction.
-// bool dex_lang_catch_targets(int dex_pc)
-_EVAL_DEF_INTRINSICS_FUNC(CatchTargets,
-                          dex_lang_catch_targets,
-                          kAttrReadOnly | kAttrNoThrow,
-                          kInt32Ty,
-                          _EXPAND_ARG1(kInt32ConstantTy))
-
 // JavaObject* dex_lang_get_current_exception()
 _EVAL_DEF_INTRINSICS_FUNC(GetException,
                           dex_lang_get_current_exception,
                           kAttrReadOnly | kAttrNoThrow,
-                          kJavaObjectTy,
+                           kJavaObjectTy,
                           _EXPAND_ARG0())
 
 // bool dex_lang_is_exception_pending()
@@ -1186,28 +1174,28 @@
                           kInt32Ty,
                           _EXPAND_ARG1(kInt32Ty))
 
-// JavaObject* const_obj(int)
+// int const_obj(int)
 _EVAL_DEF_INTRINSICS_FUNC(ConstObj,
                           dex_lang_const_obj,
                           kAttrReadOnly | kAttrNoThrow,
                           kJavaObjectTy,
                           _EXPAND_ARG1(kInt32Ty))
 
-// long const_long(long)
+// int const_long(long)
 _EVAL_DEF_INTRINSICS_FUNC(ConstLong,
                           dex_lang_const_long,
                           kAttrReadOnly | kAttrNoThrow,
                           kInt64Ty,
                           _EXPAND_ARG1(kInt64Ty))
 
-// float const_float(int)
+// int const_float(int)
 _EVAL_DEF_INTRINSICS_FUNC(ConstFloat,
                           dex_lang_const_Float,
                           kAttrReadOnly | kAttrNoThrow,
                           kFloatTy,
                           _EXPAND_ARG1(kInt32Ty))
 
-// double const_double(long)
+// int const_double(long)
 _EVAL_DEF_INTRINSICS_FUNC(ConstDouble,
                           dex_lang_const_Double,
                           kAttrReadOnly | kAttrNoThrow,