Sqrt intrinsic

Perform math intrinsics on StrictMath when appropriate following Dalvik
change: https://android-review.googlesource.com/42932

Filter package name of intrinsic methods to reduce number of
comparisons.

Change-Id: Iff97c501d4386f76d3f2297406417fa3b76d0a8a
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index 1bfcf0e..ba580f8 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -978,6 +978,33 @@
 #endif
 }
 
+bool genInlinedSqrt(CompilationUnit* cUnit, CallInfo* info) {
+#if defined(TARGET_ARM)
+  LIR *branch;
+  RegLocation rlSrc = info->args[0];
+  RegLocation rlDest = inlineTargetWide(cUnit, info);  // double place for result
+  rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
+  RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true);
+  newLIR2(cUnit, kThumb2Vsqrtd, S2D(rlResult.lowReg, rlResult.highReg),
+          S2D(rlSrc.lowReg, rlSrc.highReg));
+  newLIR2(cUnit, kThumb2Vcmpd, S2D(rlResult.lowReg, rlResult.highReg),
+          S2D(rlResult.lowReg, rlResult.highReg));
+  newLIR0(cUnit, kThumb2Fmstat);
+  branch = newLIR2(cUnit, kThumbBCond, 0, kArmCondEq);
+  oatClobberCalleeSave(cUnit);
+  oatLockCallTemps(cUnit);  // Using fixed registers
+  int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pSqrt));
+  newLIR3(cUnit, kThumb2Fmrrd, r0, r1, S2D(rlSrc.lowReg, rlSrc.highReg));
+  newLIR1(cUnit, kThumbBlxR, rTgt);
+  newLIR3(cUnit, kThumb2Fmdrr, S2D(rlResult.lowReg, rlResult.highReg), r0, r1);
+  branch->target = newLIR0(cUnit, kPseudoTargetLabel);
+  storeValueWide(cUnit, rlDest, rlResult);
+  return true;
+#else
+  return false;
+#endif
+}
+
 bool genIntrinsic(CompilationUnit* cUnit, CallInfo* info)
 {
   if (info->optFlags & MIR_INLINED) {
@@ -994,53 +1021,64 @@
    * take advantage of/generate new useful dataflow info.
    */
   std::string tgtMethod(PrettyMethod(info->index, *cUnit->dex_file));
-  if (tgtMethod == "char java.lang.String.charAt(int)") {
-    return genInlinedCharAt(cUnit, info);
-  }
-  if (tgtMethod == "int java.lang.Math.min(int, int)") {
-    return genInlinedMinMaxInt(cUnit, info, true /* isMin */);
-  }
-  if (tgtMethod == "int java.lang.Math.max(int, int)") {
-    return genInlinedMinMaxInt(cUnit, info, false /* isMin */);
-  }
-  if (tgtMethod == "int java.lang.String.length()") {
-    return genInlinedStringIsEmptyOrLength(cUnit, info, false /* isEmpty */);
-  }
-  if (tgtMethod == "boolean java.lang.String.isEmpty()") {
-    return genInlinedStringIsEmptyOrLength(cUnit, info, true /* isEmpty */);
-  }
-  if (tgtMethod == "int java.lang.Math.abs(int)") {
-    return genInlinedAbsInt(cUnit, info);
-  }
-  if (tgtMethod == "long java.lang.Math.abs(long)") {
-    return genInlinedAbsLong(cUnit, info);
-  }
-  if (tgtMethod == "int java.lang.Float.floatToRawIntBits(float)") {
-    return genInlinedFloatCvt(cUnit, info);
-  }
-  if (tgtMethod == "float java.lang.Float.intBitsToFloat(int)") {
-    return genInlinedFloatCvt(cUnit, info);
-  }
-  if (tgtMethod == "long java.lang.Double.doubleToRawLongBits(double)") {
-    return genInlinedDoubleCvt(cUnit, info);
-  }
-  if (tgtMethod == "double java.lang.Double.longBitsToDouble(long)") {
-    return genInlinedDoubleCvt(cUnit, info);
-  }
-  if (tgtMethod == "int java.lang.String.indexOf(int, int)") {
-    return genInlinedIndexOf(cUnit, info, false /* base 0 */);
-  }
-  if (tgtMethod == "int java.lang.String.indexOf(int)") {
-    return genInlinedIndexOf(cUnit, info, true /* base 0 */);
-  }
-  if (tgtMethod == "int java.lang.String.compareTo(java.lang.String)") {
-    return genInlinedStringCompareTo(cUnit, info);
-  }
-  if (tgtMethod == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
-    return genInlinedCas32(cUnit, info, false);
-  }
-  if (tgtMethod == "boolean sun.misc.Unsafe.compareAndSwapObject(java.lang.Object, long, java.lang.Object, java.lang.Object)") {
-    return genInlinedCas32(cUnit, info, true);
+  if (tgtMethod.find(" java.lang") != std::string::npos) {
+    if (tgtMethod == "long java.lang.Double.doubleToRawLongBits(double)") {
+      return genInlinedDoubleCvt(cUnit, info);
+    }
+    if (tgtMethod == "double java.lang.Double.longBitsToDouble(long)") {
+      return genInlinedDoubleCvt(cUnit, info);
+    }
+    if (tgtMethod == "int java.lang.Float.floatToRawIntBits(float)") {
+      return genInlinedFloatCvt(cUnit, info);
+    }
+    if (tgtMethod == "float java.lang.Float.intBitsToFloat(int)") {
+      return genInlinedFloatCvt(cUnit, info);
+    }
+    if (tgtMethod == "int java.lang.Math.abs(int)" ||
+        tgtMethod == "int java.lang.StrictMath.abs(int)") {
+      return genInlinedAbsInt(cUnit, info);
+    }
+    if (tgtMethod == "long java.lang.Math.abs(long)" ||
+        tgtMethod == "long java.lang.StrictMath.abs(long)") {
+      return genInlinedAbsLong(cUnit, info);
+    }
+    if (tgtMethod == "int java.lang.Math.max(int, int)" ||
+        tgtMethod == "int java.lang.StrictMath.max(int, int)") {
+      return genInlinedMinMaxInt(cUnit, info, false /* isMin */);
+    }
+    if (tgtMethod == "int java.lang.Math.min(int, int)" ||
+        tgtMethod == "int java.lang.StrictMath.min(int, int)") {
+      return genInlinedMinMaxInt(cUnit, info, true /* isMin */);
+    }
+    if (tgtMethod == "double java.lang.Math.sqrt(double)" ||
+        tgtMethod == "double java.lang.StrictMath.sqrt(double)") {
+      return genInlinedSqrt(cUnit, info);
+    }
+    if (tgtMethod == "char java.lang.String.charAt(int)") {
+      return genInlinedCharAt(cUnit, info);
+    }
+    if (tgtMethod == "int java.lang.String.compareTo(java.lang.String)") {
+      return genInlinedStringCompareTo(cUnit, info);
+    }
+    if (tgtMethod == "boolean java.lang.String.isEmpty()") {
+      return genInlinedStringIsEmptyOrLength(cUnit, info, true /* isEmpty */);
+    }
+    if (tgtMethod == "int java.lang.String.indexOf(int, int)") {
+      return genInlinedIndexOf(cUnit, info, false /* base 0 */);
+    }
+    if (tgtMethod == "int java.lang.String.indexOf(int)") {
+      return genInlinedIndexOf(cUnit, info, true /* base 0 */);
+    }
+    if (tgtMethod == "int java.lang.String.length()") {
+      return genInlinedStringIsEmptyOrLength(cUnit, info, false /* isEmpty */);
+    }
+  } else if (tgtMethod.find("boolean sun.misc.Unsafe.compareAndSwap") != std::string::npos) {
+    if (tgtMethod == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
+      return genInlinedCas32(cUnit, info, false);
+    }
+    if (tgtMethod == "boolean sun.misc.Unsafe.compareAndSwapObject(java.lang.Object, long, java.lang.Object, java.lang.Object)") {
+      return genInlinedCas32(cUnit, info, true);
+    }
   }
   return false;
 }