[vm] Faster double.floorToDouble/ceilToDouble/truncateToDouble/roundToDouble in AOT mode
This change replaces graph intrinsics and call specializer code for
certain _Double methods with a body created in FlowGraphBuilder.
double.floorToDouble micro-benchmark on AOT/x64:
Before BenchFloorToDouble(RunTime): 642.3240205523442 us.
After: BenchFloorToDouble(RunTime): 268.0320289466631 us.
double.floor micro-benchmark on AOT/x64:
Before BenchFloor(RunTime): 760.7630277672118 us.
After: BenchFloor(RunTime): 537.2132688691916 us.
TEST=ci
Issue: https://github.com/dart-lang/sdk/issues/46650
Change-Id: I47f5d8a1bdc0f71965ad1763c7bc46540428c6cd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210652
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/vm/compiler/asm_intrinsifier.h b/runtime/vm/compiler/asm_intrinsifier.h
index 4745bad..9d3f04b 100644
--- a/runtime/vm/compiler/asm_intrinsifier.h
+++ b/runtime/vm/compiler/asm_intrinsifier.h
@@ -31,9 +31,6 @@
public:
static intptr_t ParameterSlotFromSp();
- static void IntrinsicCallPrologue(Assembler* assembler);
- static void IntrinsicCallEpilogue(Assembler* assembler);
-
private:
friend class Intrinsifier;
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index e7f2ee1..454fb02 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -28,24 +28,6 @@
return -1;
}
-void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
- COMPILE_ASSERT(IsAbiPreservedRegister(CODE_REG));
- COMPILE_ASSERT(IsAbiPreservedRegister(ARGS_DESC_REG));
- COMPILE_ASSERT(IsAbiPreservedRegister(CALLEE_SAVED_TEMP));
-
- // Save LR by moving it to a callee saved temporary register.
- __ Comment("IntrinsicCallPrologue");
- SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
- __ mov(CALLEE_SAVED_TEMP, Operand(LR)));
-}
-
-void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
- // Restore LR.
- __ Comment("IntrinsicCallEpilogue");
- RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(
- __ mov(LR, Operand(CALLEE_SAVED_TEMP)));
-}
-
// Allocate a GrowableObjectArray:: using the backing array specified.
// On stack: type argument (+1), data (+0).
void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 1e0134a..03d3818 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -28,27 +28,6 @@
return -1;
}
-void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
- COMPILE_ASSERT(IsAbiPreservedRegister(CODE_REG));
- COMPILE_ASSERT(!IsAbiPreservedRegister(ARGS_DESC_REG));
- COMPILE_ASSERT(IsAbiPreservedRegister(CALLEE_SAVED_TEMP));
- COMPILE_ASSERT(IsAbiPreservedRegister(CALLEE_SAVED_TEMP2));
- COMPILE_ASSERT(CALLEE_SAVED_TEMP != CODE_REG);
- COMPILE_ASSERT(CALLEE_SAVED_TEMP != ARGS_DESC_REG);
- COMPILE_ASSERT(CALLEE_SAVED_TEMP2 != CODE_REG);
- COMPILE_ASSERT(CALLEE_SAVED_TEMP2 != ARGS_DESC_REG);
-
- __ Comment("IntrinsicCallPrologue");
- SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(__ mov(CALLEE_SAVED_TEMP, LR));
- __ mov(CALLEE_SAVED_TEMP2, ARGS_DESC_REG);
-}
-
-void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
- __ Comment("IntrinsicCallEpilogue");
- RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(__ mov(LR, CALLEE_SAVED_TEMP));
- __ mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
-}
-
// Allocate a GrowableObjectArray:: using the backing array specified.
// On stack: type argument (+1), data (+0).
void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index a6f1c9d..9c52f2a 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -35,18 +35,6 @@
return 0;
}
-void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
- COMPILE_ASSERT(CALLEE_SAVED_TEMP != ARGS_DESC_REG);
-
- assembler->Comment("IntrinsicCallPrologue");
- assembler->movl(CALLEE_SAVED_TEMP, ARGS_DESC_REG);
-}
-
-void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
- assembler->Comment("IntrinsicCallEpilogue");
- assembler->movl(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
-}
-
// Allocate a GrowableObjectArray:: using the backing array specified.
// On stack: type argument (+2), data (+1), return-address (+0).
void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 3196c49..131a261 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -28,22 +28,6 @@
return 0;
}
-void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
- COMPILE_ASSERT(IsAbiPreservedRegister(CODE_REG));
- COMPILE_ASSERT(!IsAbiPreservedRegister(ARGS_DESC_REG));
- COMPILE_ASSERT(IsAbiPreservedRegister(CALLEE_SAVED_TEMP));
- COMPILE_ASSERT(CALLEE_SAVED_TEMP != CODE_REG);
- COMPILE_ASSERT(CALLEE_SAVED_TEMP != ARGS_DESC_REG);
-
- assembler->Comment("IntrinsicCallPrologue");
- assembler->movq(CALLEE_SAVED_TEMP, ARGS_DESC_REG);
-}
-
-void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
- assembler->Comment("IntrinsicCallEpilogue");
- assembler->movq(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
-}
-
// Allocate a GrowableObjectArray using the backing array specified.
// On stack: type argument (+2), data (+1), return-address (+0).
void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 28f499c..c7973a2 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -6178,10 +6178,7 @@
switch (kind) {
case MethodRecognizer::kDoubleTruncate:
case MethodRecognizer::kDoubleFloor:
- case MethodRecognizer::kDoubleCeil: {
- ASSERT(!TargetCPUFeatures::double_truncate_round_supported());
- return 1;
- }
+ case MethodRecognizer::kDoubleCeil:
case MethodRecognizer::kDoubleRound:
case MethodRecognizer::kMathAtan:
case MethodRecognizer::kMathTan:
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 911426b..d8b607c 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -8394,6 +8394,11 @@
return kUnboxedDouble;
}
+ virtual SpeculativeMode SpeculativeModeOfInput(intptr_t idx) const {
+ ASSERT(idx == 0);
+ return kNotSpeculative;
+ }
+
virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
virtual bool AttributesEqual(const Instruction& other) const {
@@ -8512,6 +8517,11 @@
return kUnboxedDouble;
}
+ virtual SpeculativeMode SpeculativeModeOfInput(intptr_t idx) const {
+ ASSERT((0 <= idx) && (idx < InputCount()));
+ return kNotSpeculative;
+ }
+
virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
virtual intptr_t InputCount() const { return inputs_->length(); }
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 944673b..c87f165 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -5344,30 +5344,36 @@
bool opt) const {
// Calling convention on x64 uses XMM0 and XMM1 to pass the first two
// double arguments and XMM0 to return the result.
- //
- // TODO(sjindel): allow XMM0 to be used. Requires refactoring InvokeDoublePow
- // to allow input 1/output register to be equal.
- ASSERT((InputCount() == 1) || (InputCount() == 2));
- const intptr_t kNumTemps =
- (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 4 : 1;
- LocationSummary* result = new (zone)
- LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
ASSERT(R13 != CALLEE_SAVED_TEMP);
ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0);
- result->set_temp(0, Location::RegisterLocation(R13));
- result->set_in(0, Location::FpuRegisterLocation(XMM2));
- if (InputCount() == 2) {
- result->set_in(1, Location::FpuRegisterLocation(XMM1));
- }
+
if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
+ ASSERT(InputCount() == 2);
+ const intptr_t kNumTemps = 4;
+ LocationSummary* result = new (zone)
+ LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
+ result->set_in(0, Location::FpuRegisterLocation(XMM2));
+ result->set_in(1, Location::FpuRegisterLocation(XMM1));
+ result->set_temp(0, Location::RegisterLocation(R13));
// Temp index 1.
result->set_temp(1, Location::RegisterLocation(RAX));
// Temp index 2.
result->set_temp(2, Location::FpuRegisterLocation(XMM4));
// Block XMM0 for the calling convention.
result->set_temp(3, Location::FpuRegisterLocation(XMM0));
+ result->set_out(0, Location::FpuRegisterLocation(XMM3));
+ return result;
}
- result->set_out(0, Location::FpuRegisterLocation(XMM3));
+ ASSERT((InputCount() == 1) || (InputCount() == 2));
+ const intptr_t kNumTemps = 1;
+ LocationSummary* result = new (zone)
+ LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall);
+ result->set_temp(0, Location::RegisterLocation(R13));
+ result->set_in(0, Location::FpuRegisterLocation(XMM0));
+ if (InputCount() == 2) {
+ result->set_in(1, Location::FpuRegisterLocation(XMM1));
+ }
+ result->set_out(0, Location::FpuRegisterLocation(XMM0));
return result;
}
@@ -5509,17 +5515,20 @@
InvokeDoublePow(compiler, this);
return;
}
- // Save RSP.
- __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP);
- __ ReserveAlignedFrameSpace(0);
- __ movaps(XMM0, locs()->in(0).fpu_reg());
+
+ ASSERT(locs()->in(0).fpu_reg() == XMM0);
if (InputCount() == 2) {
ASSERT(locs()->in(1).fpu_reg() == XMM1);
}
+ // Save RSP.
+ __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP);
+ __ ReserveAlignedFrameSpace(0);
+
ASSERT(TargetFunction().is_leaf()); // No deopt info needed.
__ CallRuntime(TargetFunction(), InputCount());
- __ movaps(locs()->out(0).fpu_reg(), XMM0);
+ ASSERT(locs()->out(0).fpu_reg() == XMM0);
+
// Restore RSP.
__ movq(RSP, locs()->temp(kSavedSpTempIndex).reg());
}
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index d386935..61e2f54 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -968,21 +968,6 @@
return TryInlineImplicitInstanceGetter(call);
}
-void CallSpecializer::ReplaceWithMathCFunction(
- InstanceCallInstr* call,
- MethodRecognizer::Kind recognized_kind) {
- ASSERT(call->type_args_len() == 0);
- AddReceiverCheck(call);
- ZoneGrowableArray<Value*>* args =
- new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
- for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
- args->Add(new (Z) Value(call->ArgumentAt(i)));
- }
- InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr(
- args, call->deopt_id(), recognized_kind, call->source());
- ReplaceCall(call, invoke);
-}
-
// Inline only simple, frequently called core library methods.
bool CallSpecializer::TryInlineInstanceMethod(InstanceCallInstr* call) {
const CallTargets& targets = call->Targets();
@@ -1034,23 +1019,6 @@
ReplaceCall(call, d2i_instr);
return true;
}
- case MethodRecognizer::kDoubleMod:
- case MethodRecognizer::kDoubleRound:
- ReplaceWithMathCFunction(call, recognized_kind);
- return true;
- case MethodRecognizer::kDoubleTruncate:
- case MethodRecognizer::kDoubleFloor:
- case MethodRecognizer::kDoubleCeil:
- if (!TargetCPUFeatures::double_truncate_round_supported()) {
- ReplaceWithMathCFunction(call, recognized_kind);
- } else {
- AddReceiverCheck(call);
- DoubleToDoubleInstr* d2d_instr =
- new (Z) DoubleToDoubleInstr(new (Z) Value(call->ArgumentAt(0)),
- recognized_kind, call->deopt_id());
- ReplaceCall(call, d2d_instr);
- }
- return true;
default:
break;
}
diff --git a/runtime/vm/compiler/call_specializer.h b/runtime/vm/compiler/call_specializer.h
index e82a69c..7e84402 100644
--- a/runtime/vm/compiler/call_specializer.h
+++ b/runtime/vm/compiler/call_specializer.h
@@ -172,9 +172,6 @@
bool TryOptimizeInstanceOfUsingStaticTypes(InstanceCallInstr* call,
const AbstractType& type);
- void ReplaceWithMathCFunction(InstanceCallInstr* call,
- MethodRecognizer::Kind recognized_kind);
-
bool TryStringLengthOneEquality(InstanceCallInstr* call, Token::Kind op_kind);
void SpecializePolymorphicInstanceCall(PolymorphicInstanceCallInstr* call);
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 4c3a5cf..4e16bfe 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1193,5 +1193,25 @@
return instructions;
}
+Fragment BaseFlowGraphBuilder::InvokeMathCFunction(
+ MethodRecognizer::Kind recognized_kind,
+ intptr_t num_inputs) {
+ InputsArray* args = GetArguments(num_inputs);
+ auto* instr = new (Z)
+ InvokeMathCFunctionInstr(args, GetNextDeoptId(), recognized_kind,
+ InstructionSource(TokenPosition::kNoSource));
+ Push(instr);
+ return Fragment(instr);
+}
+
+Fragment BaseFlowGraphBuilder::DoubleToDouble(
+ MethodRecognizer::Kind recognized_kind) {
+ Value* value = Pop();
+ auto* instr =
+ new (Z) DoubleToDoubleInstr(value, recognized_kind, GetNextDeoptId());
+ Push(instr);
+ return Fragment(instr);
+}
+
} // namespace kernel
} // namespace dart
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index edad1e4..f3ef8e0 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -436,6 +436,14 @@
// Sets raw parameter variables to inferred constant values.
Fragment InitConstantParameters();
+ Fragment InvokeMathCFunction(MethodRecognizer::Kind recognized_kind,
+ intptr_t num_inputs);
+
+ // Pops double value and converts it to double as specified
+ // by the recognized method (kDoubleTruncate,
+ // kDoubleFloor or kDoubleCeil).
+ Fragment DoubleToDouble(MethodRecognizer::Kind recognized_kind);
+
// Returns whether this function has a saved arguments descriptor array.
bool has_saved_args_desc_array() {
return function_.HasSavedArgumentsDescriptor();
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 2054bbb..870c86f 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -988,7 +988,7 @@
case UntaggedFunction::kSetterFunction:
case UntaggedFunction::kClosureFunction:
case UntaggedFunction::kConstructor: {
- if (B->IsRecognizedMethodForFlowGraph(function)) {
+ if (FlowGraphBuilder::IsRecognizedMethodForFlowGraph(function)) {
return B->BuildGraphOfRecognizedMethod(function);
}
return BuildGraphOfFunction(function.IsGenerativeConstructor());
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 0930d3d..2e2f061 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -8,6 +8,7 @@
#include "platform/globals.h"
#include "vm/class_id.h"
#include "vm/compiler/aot/precompiler.h"
+#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/il.h"
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/backend/locations.h"
@@ -891,6 +892,12 @@
case MethodRecognizer::kUtf8DecoderScan:
case MethodRecognizer::kHas63BitSmis:
return true;
+ case MethodRecognizer::kDoubleMod:
+ case MethodRecognizer::kDoubleRound:
+ case MethodRecognizer::kDoubleTruncate:
+ case MethodRecognizer::kDoubleFloor:
+ case MethodRecognizer::kDoubleCeil:
+ return FlowGraphCompiler::SupportsUnboxedDoubles();
default:
return false;
}
@@ -1506,6 +1513,24 @@
body += LoadIndexed(kIntPtrCid);
body += Box(kUnboxedIntPtr);
} break;
+ case MethodRecognizer::kDoubleMod:
+ case MethodRecognizer::kDoubleRound:
+ case MethodRecognizer::kDoubleTruncate:
+ case MethodRecognizer::kDoubleFloor:
+ case MethodRecognizer::kDoubleCeil: {
+ for (intptr_t i = 0, n = function.NumParameters(); i < n; ++i) {
+ body += LoadLocal(parsed_function_->RawParameterVariable(i));
+ }
+ if (!CompilerState::Current().is_aot() &&
+ TargetCPUFeatures::double_truncate_round_supported() &&
+ ((kind == MethodRecognizer::kDoubleTruncate) ||
+ (kind == MethodRecognizer::kDoubleFloor) ||
+ (kind == MethodRecognizer::kDoubleCeil))) {
+ body += DoubleToDouble(kind);
+ } else {
+ body += InvokeMathCFunction(kind, function.NumParameters());
+ }
+ } break;
default: {
UNREACHABLE();
break;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index f9d1a6e..20c5b77c 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -65,6 +65,10 @@
FlowGraph* BuildGraph();
+ // Returns true if given [function] is recognized for flow
+ // graph building and its body is expressed in a custom-built IL.
+ static bool IsRecognizedMethodForFlowGraph(const Function& function);
+
private:
BlockEntryInstr* BuildPrologue(BlockEntryInstr* normal_entry,
PrologueInfo* prologue_info);
@@ -145,8 +149,6 @@
Fragment NativeFunctionBody(const Function& function,
LocalVariable* first_parameter);
- // Every recognized method has a body expressed in IL.
- bool IsRecognizedMethodForFlowGraph(const Function& function);
FlowGraph* BuildGraphOfRecognizedMethod(const Function& function);
Fragment BuildTypedDataViewFactoryConstructor(const Function& function,
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 49287d4..a97c2fb 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -1121,40 +1121,6 @@
return BuildInvokeMathCFunction(flow_graph, MethodRecognizer::kMathLog);
}
-bool GraphIntrinsifier::Build_DoubleMod(FlowGraph* flow_graph) {
- return BuildInvokeMathCFunction(flow_graph, MethodRecognizer::kDoubleMod,
- /* num_parameters = */ 2);
-}
-
-bool GraphIntrinsifier::Build_DoubleCeil(FlowGraph* flow_graph) {
- // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
- // way.
- if (TargetCPUFeatures::double_truncate_round_supported()) return false;
-
- return BuildInvokeMathCFunction(flow_graph, MethodRecognizer::kDoubleCeil);
-}
-
-bool GraphIntrinsifier::Build_DoubleFloor(FlowGraph* flow_graph) {
- // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
- // way.
- if (TargetCPUFeatures::double_truncate_round_supported()) return false;
-
- return BuildInvokeMathCFunction(flow_graph, MethodRecognizer::kDoubleFloor);
-}
-
-bool GraphIntrinsifier::Build_DoubleTruncate(FlowGraph* flow_graph) {
- // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
- // way.
- if (TargetCPUFeatures::double_truncate_round_supported()) return false;
-
- return BuildInvokeMathCFunction(flow_graph,
- MethodRecognizer::kDoubleTruncate);
-}
-
-bool GraphIntrinsifier::Build_DoubleRound(FlowGraph* flow_graph) {
- return BuildInvokeMathCFunction(flow_graph, MethodRecognizer::kDoubleRound);
-}
-
bool GraphIntrinsifier::Build_ImplicitGetter(FlowGraph* flow_graph) {
// This code will only be invoked if our assumptions have been met (see
// [Intrinsifier::CanIntrinsifyFieldAccessor])
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 9680f0b..8bf5cf9 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -87,6 +87,11 @@
V(_Double, _sub, DoubleSub, 0x28474c2e) \
V(_Double, _mul, DoubleMul, 0x1f98c76c) \
V(_Double, _div, DoubleDiv, 0x287d3791) \
+ V(_Double, _modulo, DoubleMod, 0xfdb397ef) \
+ V(_Double, ceilToDouble, DoubleCeil, 0x5f1bced9) \
+ V(_Double, floorToDouble, DoubleFloor, 0x54b4cb48) \
+ V(_Double, roundToDouble, DoubleRound, 0x5649ca00) \
+ V(_Double, truncateToDouble, DoubleTruncate, 0x62d48659) \
V(::, min, MathMin, 0x504a28df) \
V(::, max, MathMax, 0xead7161a) \
V(::, _doublePow, MathDoublePow, 0x989f3334) \
@@ -366,11 +371,6 @@
V(_IntegerImplementation, >>, Integer_sar, 0x4a3615a7) \
V(_IntegerImplementation, >>>, Integer_shr, 0x2bac5209) \
V(_Double, unary-, DoubleFlipSignBit, 0x3d39082b) \
- V(_Double, truncateToDouble, DoubleTruncate, 0x62d48298) \
- V(_Double, roundToDouble, DoubleRound, 0x5649c63f) \
- V(_Double, floorToDouble, DoubleFloor, 0x54b4c787) \
- V(_Double, ceilToDouble, DoubleCeil, 0x5f1bcb18) \
- V(_Double, _modulo, DoubleMod, 0xfdb3942e)
#define GRAPH_INTRINSICS_LIST(V) \
GRAPH_CORE_INTRINSICS_LIST(V) \
diff --git a/sdk/lib/_internal/vm/lib/double.dart b/sdk/lib/_internal/vm/lib/double.dart
index ab3b88d..e1dca3d 100644
--- a/sdk/lib/_internal/vm/lib/double.dart
+++ b/sdk/lib/_internal/vm/lib/double.dart
@@ -67,7 +67,8 @@
return _modulo(other.toDouble());
}
- @pragma("vm:recognized", "graph-intrinsic")
+ @pragma("vm:recognized", "other")
+ @pragma("vm:prefer-inline")
@pragma("vm:exact-result-type", _Double)
double _modulo(double other) native "Double_modulo";
@@ -181,16 +182,20 @@
int ceil() => ceilToDouble().toInt();
int truncate() => truncateToDouble().toInt();
- @pragma("vm:recognized", "graph-intrinsic")
+ @pragma("vm:recognized", "other")
+ @pragma("vm:prefer-inline")
@pragma("vm:exact-result-type", _Double)
double roundToDouble() native "Double_round";
- @pragma("vm:recognized", "graph-intrinsic")
+ @pragma("vm:recognized", "other")
+ @pragma("vm:prefer-inline")
@pragma("vm:exact-result-type", _Double)
double floorToDouble() native "Double_floor";
- @pragma("vm:recognized", "graph-intrinsic")
+ @pragma("vm:recognized", "other")
+ @pragma("vm:prefer-inline")
@pragma("vm:exact-result-type", _Double)
double ceilToDouble() native "Double_ceil";
- @pragma("vm:recognized", "graph-intrinsic")
+ @pragma("vm:recognized", "other")
+ @pragma("vm:prefer-inline")
@pragma("vm:exact-result-type", _Double)
double truncateToDouble() native "Double_truncate";