Fix basic block construction

There was a bug in the CFG building mechanism that tiggered when
a backwards branch re-entered the current basic block at a point
other than the head.  In that case, we'd split the original basic block
in two.  However, the head of the old block then became the head
of the first of a new two block pair - and we really needed to continue
processing with the second of the pair.

Change-Id: Ieb9fdd5176d86cd0959bb9e91db9ca06075d4f21
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 89f63be..ecc281b 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -451,9 +451,10 @@
 }
 
 /* Process instructions with the kInstrCanBranch flag */
-STATIC void processCanBranch(CompilationUnit* cUnit, BasicBlock* curBlock,
-                             MIR* insn, int curOffset, int width, int flags,
-                             const u2* codePtr, const u2* codeEnd)
+STATIC BasicBlock* processCanBranch(CompilationUnit* cUnit,
+                                    BasicBlock* curBlock, MIR* insn,
+                                    int curOffset, int width, int flags,
+                                    const u2* codePtr, const u2* codeEnd)
 {
     int target = curOffset;
     switch (insn->dalvikInsn.opcode) {
@@ -482,11 +483,22 @@
             LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
                 << ") with kInstrCanBranch set";
     }
+    /*
+     * Some ugliness here.  It is possible that findBlock will
+     * split the current block.  In that case, we need to operate
+     * on the 2nd half on the split pair.  It isn't directly obvious
+     * when this happens, so we infer.
+     */
+    DCHECK(curBlock->lastMIRInsn == insn);
     BasicBlock *takenBlock = findBlock(cUnit, target,
                                        /* split */
                                        true,
                                        /* create */
                                        true);
+     if (curBlock->lastMIRInsn != insn) {
+         DCHECK(takenBlock->lastMIRInsn == insn);
+         curBlock = curBlock->fallThrough;
+    }
     curBlock->taken = takenBlock;
     oatSetBit(takenBlock->predecessors, curBlock->id);
 
@@ -521,6 +533,7 @@
                       true);
         }
     }
+    return curBlock;
 }
 
 /* Process instructions with the kInstrCanSwitch flag */
@@ -791,8 +804,8 @@
         int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
 
         if (flags & kInstrCanBranch) {
-            processCanBranch(cUnit.get(), curBlock, insn, curOffset, width, flags,
-                             codePtr, codeEnd);
+            curBlock = processCanBranch(cUnit.get(), curBlock, insn, curOffset,
+                                        width, flags, codePtr, codeEnd);
         } else if (flags & kInstrCanReturn) {
             curBlock->fallThrough = exitBlock;
             oatSetBit(exitBlock->predecessors, curBlock->id);