summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nikita Iashchenko <nikitai@google.com> 2021-01-20 21:52:54 +0000
committer Nikita Iashchenko <nikitai@google.com> 2021-02-10 12:33:48 +0000
commit745da80dbf169d83e2acb847b0c9c07985d51bdf (patch)
treea01990e419ee49fe255a6df108027a89b568975a
parent16f7f8e384f0ae13c53525ff12affbc00605b0ec (diff)
Add Math.multiplyHigh intrinsic
Test: ./art/test/testrunner/testrunner.py --target --optimizing --64 -t 082-inline-execute Test: ./art/test/testrunner/testrunner.py --host --optimizing --64 -t 082-inline-execute Change-Id: I4b6cafa8b9e513eca7c5c139440024d87a7ef758
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc17
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc1
-rw-r--r--compiler/optimizing/intrinsics_x86.cc1
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc21
-rw-r--r--runtime/image.cc4
-rw-r--r--runtime/interpreter/interpreter_intrinsics.cc1
-rw-r--r--runtime/intrinsics_list.h1
-rw-r--r--test/082-inline-execute/src/Main.java7
8 files changed, 51 insertions, 2 deletions
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index d58d8f4b0a..d0c64c2230 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -3856,6 +3856,23 @@ void IntrinsicCodeGeneratorARM64::VisitLongDivideUnsigned(HInvoke* invoke) {
GenerateDivideUnsigned(invoke, codegen_);
}
+void IntrinsicLocationsBuilderARM64::VisitMathMultiplyHigh(HInvoke* invoke) {
+ CreateIntIntToIntLocations(allocator_, invoke);
+}
+
+void IntrinsicCodeGeneratorARM64::VisitMathMultiplyHigh(HInvoke* invoke) {
+ LocationSummary* locations = invoke->GetLocations();
+ MacroAssembler* masm = codegen_->GetVIXLAssembler();
+ DataType::Type type = invoke->GetType();
+ DCHECK(type == DataType::Type::kInt64);
+
+ Register x = RegisterFrom(locations->InAt(0), type);
+ Register y = RegisterFrom(locations->InAt(1), type);
+ Register out = RegisterFrom(locations->Out(), type);
+
+ __ Smulh(out, x, y);
+}
+
class VarHandleSlowPathARM64 : public IntrinsicSlowPathARM64 {
public:
VarHandleSlowPathARM64(HInvoke* invoke, std::memory_order order)
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 42156d43c5..2a2f245025 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -5371,6 +5371,7 @@ UNIMPLEMENTED_INTRINSIC(ARMVIXL, FP16Greater)
UNIMPLEMENTED_INTRINSIC(ARMVIXL, FP16GreaterEquals)
UNIMPLEMENTED_INTRINSIC(ARMVIXL, FP16Less)
UNIMPLEMENTED_INTRINSIC(ARMVIXL, FP16LessEquals)
+UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMultiplyHigh)
UNIMPLEMENTED_INTRINSIC(ARMVIXL, StringStringIndexOf);
UNIMPLEMENTED_INTRINSIC(ARMVIXL, StringStringIndexOfAfter);
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index a4f1bd1df2..b0c4b5736f 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -4613,6 +4613,7 @@ UNIMPLEMENTED_INTRINSIC(X86, FP16Greater)
UNIMPLEMENTED_INTRINSIC(X86, FP16GreaterEquals)
UNIMPLEMENTED_INTRINSIC(X86, FP16Less)
UNIMPLEMENTED_INTRINSIC(X86, FP16LessEquals)
+UNIMPLEMENTED_INTRINSIC(X86, MathMultiplyHigh)
UNIMPLEMENTED_INTRINSIC(X86, StringStringIndexOf);
UNIMPLEMENTED_INTRINSIC(X86, StringStringIndexOfAfter);
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 7d056f9c59..63511817c0 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2830,6 +2830,27 @@ void IntrinsicCodeGeneratorX86_64::VisitIntegerDivideUnsigned(HInvoke* invoke) {
__ Bind(slow_path->GetExitLabel());
}
+void IntrinsicLocationsBuilderX86_64::VisitMathMultiplyHigh(HInvoke* invoke) {
+ LocationSummary* locations =
+ new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
+ locations->SetInAt(0, Location::RegisterLocation(RAX));
+ locations->SetInAt(1, Location::RequiresRegister());
+ locations->SetOut(Location::RegisterLocation(RDX));
+ locations->AddTemp(Location::RegisterLocation(RAX));
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitMathMultiplyHigh(HInvoke* invoke) {
+ X86_64Assembler* assembler = GetAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+
+ CpuRegister y = locations->InAt(1).AsRegister<CpuRegister>();
+
+ DCHECK_EQ(locations->InAt(0).AsRegister<Register>(), RAX);
+ DCHECK_EQ(locations->Out().AsRegister<Register>(), RDX);
+
+ __ imulq(y);
+}
+
UNIMPLEMENTED_INTRINSIC(X86_64, FloatIsInfinite)
UNIMPLEMENTED_INTRINSIC(X86_64, DoubleIsInfinite)
diff --git a/runtime/image.cc b/runtime/image.cc
index 6c7be3c24d..60870773a0 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -29,8 +29,8 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-// Last change: Reference.refersTo() intrinsic.
-const uint8_t ImageHeader::kImageVersion[] = { '0', '9', '4', '\0' };
+// Last change: Math.multiplyHigh intrinsic.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '9', '5', '\0' };
ImageHeader::ImageHeader(uint32_t image_reservation_size,
uint32_t component_count,
diff --git a/runtime/interpreter/interpreter_intrinsics.cc b/runtime/interpreter/interpreter_intrinsics.cc
index 369615c9ee..7236bad5de 100644
--- a/runtime/interpreter/interpreter_intrinsics.cc
+++ b/runtime/interpreter/interpreter_intrinsics.cc
@@ -500,6 +500,7 @@ bool MterpHandleIntrinsic(ShadowFrame* shadow_frame,
UNIMPLEMENTED_CASE(MathRint /* (D)D */)
UNIMPLEMENTED_CASE(MathRoundDouble /* (D)J */)
UNIMPLEMENTED_CASE(MathRoundFloat /* (F)I */)
+ UNIMPLEMENTED_CASE(MathMultiplyHigh /* (JJ)J */)
UNIMPLEMENTED_CASE(SystemArrayCopyChar /* ([CI[CII)V */)
UNIMPLEMENTED_CASE(SystemArrayCopy /* (Ljava/lang/Object;ILjava/lang/Object;II)V */)
UNIMPLEMENTED_CASE(ThreadCurrentThread /* ()Ljava/lang/Thread; */)
diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h
index 86d35cbc0a..c0ef1c9a68 100644
--- a/runtime/intrinsics_list.h
+++ b/runtime/intrinsics_list.h
@@ -156,6 +156,7 @@
V(MathRint, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "rint", "(D)D") \
V(MathRoundDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(D)J") \
V(MathRoundFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "round", "(F)I") \
+ V(MathMultiplyHigh, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "multiplyHigh", "(JJ)J") \
V(SystemArrayCopyChar, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "([CI[CII)V") \
V(SystemArrayCopy, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/System;", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V") \
V(ThreadCurrentThread, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Thread;", "currentThread", "()Ljava/lang/Thread;") \
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index 5597947cfc..f4a234b437 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -44,6 +44,7 @@ public class Main {
test_Math_isNaN_F();
test_Math_isInfinite_D();
test_Math_isInfinite_F();
+ test_Math_multiplyHigh();
test_Short_reverseBytes();
test_Integer_reverseBytes();
test_Long_reverseBytes();
@@ -978,6 +979,12 @@ public class Main {
Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80000001)));
}
+ public static void test_Math_multiplyHigh() {
+ Math.multiplyHigh(2L, 3L);
+ Assert.assertEquals(Math.multiplyHigh(2L, 3L), 0L);
+ Assert.assertEquals(Math.multiplyHigh(Long.MAX_VALUE, Long.MAX_VALUE), 4611686018427387903L);
+ }
+
public static void test_StrictMath_abs_I() {
StrictMath.abs(-1);
Assert.assertEquals(StrictMath.abs(0), 0);