Compiler intrinsics

Add intrinsic support.  Some of these appear to be of
limited value, so we may end up removing a few.  In general,
the instrinsics provide small, but measurable, gains.

Only Arm is currently supported, but most of these should
work for our other targets as well.

This is an interim solution.  My plan is to the intrinsic
recognition action up into the basic block building phase once
we start doing inlining.

Change-Id: Ia2913f2cdecaa4e80469caf69dbf8e2f61d4506a
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index a87c401..19282d1 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -1655,6 +1655,35 @@
     return mir;
 }
 
+/*
+ * To be used at an invoke mir.  If the logically next mir node represents
+ * a move-result, return it.  Else, return NULL.  If a move-result exists,
+ * it is required to immediately follow the invoke with no intervening
+ * opcodes or incoming arcs.  However, if the result of the invoke is not
+ * used, a move-result may not be present.
+ */
+MIR* oatFindMoveResult(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
+                       bool wide)
+{
+    BasicBlock* tbb = bb;
+    mir = advanceMIR(cUnit, &tbb, mir, NULL, false);
+    while (mir != NULL) {
+        if (!wide && mir->dalvikInsn.opcode == Instruction::MOVE_RESULT) {
+            break;
+        }
+        if (wide && mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE) {
+            break;
+        }
+        // Keep going if pseudo op, otherwise terminate
+        if (mir->dalvikInsn.opcode < static_cast<Instruction::Code>(kNumPackedOpcodes)) {
+            mir = NULL;
+        } else {
+            mir = advanceMIR(cUnit, &tbb, mir, NULL, false);
+        }
+    }
+    return mir;
+}
+
 void squashDupRangeChecks(CompilationUnit* cUnit, BasicBlock** pBp, MIR* mir,
                           int arraySreg, int indexSreg)
 {