Extend a trace with a backward branch into a loop.

When seeing a trace that ends with a backward branch, exhaust all code
blocks reachable from that trace and try to identify if there exists a
non-nested loop. If the derived loop is found to be too complex or only
acyclic code is seen, revert to the original compilation mechanism to
translate a simple trace.

This CL uses the whole-method parser/dataflow analysis framework to
identify such loops. No optimization/codegen are performed yet.

Bug: 4086718

Change-Id: I19ed3ee53ea1cbda33940c533de8e9220e647156
diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.c
index 76744bd..26068a1 100644
--- a/vm/compiler/Dataflow.c
+++ b/vm/compiler/Dataflow.c
@@ -1694,7 +1694,6 @@
     const DecodedInstruction *insn = &mir->dalvikInsn;
     int opcode = insn->opcode;
     int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
-    int flags = dexGetFlagsFromOpcode(insn->opcode);
     char *ret;
     int length;
 
@@ -1719,6 +1718,7 @@
         strcpy(buffer, dexGetOpcodeName(opcode));
     }
 
+    int flags = dexGetFlagsFromOpcode(opcode);
     /* For branches, decode the instructions to print out the branch targets */
     if (flags & kInstrCanBranch) {
         InstructionFormat dalvikFormat = dexGetFormatFromOpcode(insn->opcode);
@@ -2393,6 +2393,7 @@
     while (true) {
         BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
         if (bb == NULL) break;
+        if (bb->hidden == true) continue;
         if (bb->blockType == kDalvikByteCode ||
             bb->blockType == kTraceEntryBlock ||
             bb->blockType == kMethodEntryBlock ||
@@ -2430,6 +2431,7 @@
                 BasicBlock *bb =
                     (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
                 if (bb == NULL) break;
+                if (bb->hidden == true) continue;
                 change |= (*func)(cUnit, bb);
             }
         }