30 compiler_->is_optimizing_ =
true;
33 compiler_->is_optimizing_ = old_is_optimizing_;
38 bool old_is_optimizing_;
49 compiler->assembler()->Comment(
"Graph intrinsic begin");
52 if (block->IsGraphEntry())
continue;
60 if (FLAG_code_comments)
compiler->EmitComment(instr);
62 ASSERT(instr->IsParallelMove() ||
67 compiler->assembler()->Comment(
"Graph intrinsic end");
78 intptr_t block_id = 1;
79 graph_entry->set_normal_entry(
84 new FlowGraph(parsed_function, graph_entry, block_id, prologue_info,
86 compiler->set_intrinsic_flow_graph(*graph);
90 switch (
function.recognized_kind()) {
91#define EMIT_CASE(class_name, function_name, enum_name, fp) \
92 case MethodRecognizer::k##enum_name: \
93 if (!Build_##enum_name(graph)) return false; \
134 return kUnboxedDouble;
136 return kUnboxedFloat32x4;
138 return kUnboxedInt32x4;
140 return kUnboxedFloat64x2;
143 return kNoRepresentation;
156 const Slot& length_field) {
163 builder->AddDefinition(safe_index);
169 if (
function.is_unboxed_parameter_at(arg_index)) {
170 FATAL(
"Unsupported unboxed parameter %" Pd " in %s", arg_index,
171 function.ToFullyQualifiedCString());
178 intptr_t arg_index) {
180 if (
function.is_unboxed_parameter_at(arg_index)) {
194 if (representation == kUnboxedFloat) {
197 representation = kUnboxedDouble;
199 if (!
function.has_unboxed_return()) {
210 if (
function.has_unboxed_return() &&
value->representation() == kTagged) {
219 intptr_t array_cid) {
238#if defined(TARGET_ARCH_IS_32_BIT)
249 auto const unbox_rep = rep == kUnboxedInt32 ? kUnboxedUint32 : rep;
256 *value_check,
builder.Source()));
263 new Value(array), Slot::PointerBase_data(),
280#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \
281 bool GraphIntrinsifier::Build_##enum_name##SetIndexed( \
282 FlowGraph* flow_graph) { \
283 return IntrinsifyArraySetIndexed( \
284 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \
285 MethodRecognizer::k##enum_name##SetIndexed)); \
300#undef DEFINE_ARRAY_SETTER_INTRINSIC
302#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \
303 bool GraphIntrinsifier::Build_##enum_name##SetIndexed( \
304 FlowGraph* flow_graph) { \
305 return IntrinsifyArraySetIndexed( \
306 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \
307 MethodRecognizer::k##enum_name##SetIndexed)); \
313#undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
315#define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) \
316 bool GraphIntrinsifier::Build_##enum_name##SetIndexed( \
317 FlowGraph* flow_graph) { \
318 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \
321 return IntrinsifyArraySetIndexed( \
322 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \
323 MethodRecognizer::k##enum_name##SetIndexed)); \
330#undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC
351 *value_check,
builder.Source()));
367bool GraphIntrinsifier::Build_Float32x4Mul(
FlowGraph* flow_graph) {
368 return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kMUL);
371bool GraphIntrinsifier::Build_Float32x4Div(FlowGraph* flow_graph) {
372 return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kDIV);
375bool GraphIntrinsifier::Build_Float32x4Sub(FlowGraph* flow_graph) {
376 return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kSUB);
379bool GraphIntrinsifier::Build_Float32x4Add(FlowGraph* flow_graph) {
380 return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kADD);
383bool GraphIntrinsifier::Build_Float64x2Mul(FlowGraph* flow_graph) {
384 return BuildSimdOp(flow_graph, kFloat64x2Cid, Token::kMUL);
387bool GraphIntrinsifier::Build_Float64x2Div(FlowGraph* flow_graph) {
388 return BuildSimdOp(flow_graph, kFloat64x2Cid, Token::kDIV);
391bool GraphIntrinsifier::Build_Float64x2Sub(FlowGraph* flow_graph) {
392 return BuildSimdOp(flow_graph, kFloat64x2Cid, Token::kSUB);
395bool GraphIntrinsifier::Build_Float64x2Add(FlowGraph* flow_graph) {
396 return BuildSimdOp(flow_graph, kFloat64x2Cid, Token::kADD);
412 !
function.is_unboxed_parameter_at(0)
413 ?
builder.AddUnboxInstr(kUnboxedFloat32x4,
new Value(receiver),
427bool GraphIntrinsifier::Build_Float32x4GetX(
FlowGraph* flow_graph) {
431bool GraphIntrinsifier::Build_Float32x4GetY(FlowGraph* flow_graph) {
435bool GraphIntrinsifier::Build_Float32x4GetZ(FlowGraph* flow_graph) {
439bool GraphIntrinsifier::Build_Float32x4GetW(FlowGraph* flow_graph) {
459bool GraphIntrinsifier::Build_ObjectArrayLength(
FlowGraph* flow_graph) {
463bool GraphIntrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) {
464 return BuildLoadField(flow_graph, Slot::GrowableObjectArray_length());
467bool GraphIntrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) {
471bool GraphIntrinsifier::Build_TypedListBaseLength(FlowGraph* flow_graph) {
475bool GraphIntrinsifier::Build_ByteDataViewLength(FlowGraph* flow_graph) {
479bool GraphIntrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
480 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
481 auto normal_entry = graph_entry->normal_entry();
482 BlockBuilder
builder(flow_graph, normal_entry,
false);
484 Definition* array =
builder.AddParameter(0);
487 Definition* backing_store =
builder.AddDefinition(
new LoadFieldInstr(
488 new Value(array), Slot::GrowableObjectArray_data(),
builder.Source()));
489 Definition* capacity =
builder.AddDefinition(
new LoadFieldInstr(
490 new Value(backing_store), Slot::Array_length(),
builder.Source()));
496bool GraphIntrinsifier::Build_ObjectArraySetIndexedUnchecked(
497 FlowGraph* flow_graph) {
498 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
499 auto normal_entry = graph_entry->normal_entry();
500 BlockBuilder
builder(flow_graph, normal_entry,
false);
502 Definition* array =
builder.AddParameter(0);
503 Definition* index =
builder.AddParameter(1);
511 Slot::Array_length());
513 builder.AddInstruction(
new StoreIndexedInstr(
519 Definition* null_def =
builder.AddNullDefinition();
524bool GraphIntrinsifier::Build_GrowableArraySetIndexedUnchecked(
525 FlowGraph* flow_graph) {
526 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
527 auto normal_entry = graph_entry->normal_entry();
528 BlockBuilder
builder(flow_graph, normal_entry,
false);
530 Definition* array =
builder.AddParameter(0);
531 Definition* index =
builder.AddParameter(1);
539 Slot::GrowableObjectArray_length());
541 Definition* backing_store =
builder.AddDefinition(
new LoadFieldInstr(
542 new Value(array), Slot::GrowableObjectArray_data(),
builder.Source()));
544 builder.AddInstruction(
new StoreIndexedInstr(
550 Definition* null_def =
builder.AddNullDefinition();
555bool GraphIntrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) {
556 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
557 auto normal_entry = graph_entry->normal_entry();
558 BlockBuilder
builder(flow_graph, normal_entry,
false);
560 Definition* growable_array =
builder.AddParameter(0);
562 Zone* zone = flow_graph->zone();
569 *value_check,
builder.Source()));
571 builder.AddInstruction(
new StoreFieldInstr(
572 Slot::GrowableObjectArray_data(),
new Value(growable_array),
575 Definition* null_def =
builder.AddNullDefinition();
580bool GraphIntrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) {
581 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
582 auto normal_entry = graph_entry->normal_entry();
583 BlockBuilder
builder(flow_graph, normal_entry,
false);
585 Definition* growable_array =
builder.AddParameter(0);
593 builder.AddInstruction(
new StoreFieldInstr(
594 Slot::GrowableObjectArray_length(),
new Value(growable_array),
596 Definition* null_def =
builder.AddNullDefinition();
616bool GraphIntrinsifier::Build_Smi_bitNegate(
FlowGraph* flow_graph) {
620bool GraphIntrinsifier::Build_Integer_negate(FlowGraph* flow_graph) {
643bool GraphIntrinsifier::Build_Integer_add(
FlowGraph* flow_graph) {
647bool GraphIntrinsifier::Build_Integer_sub(FlowGraph* flow_graph) {
651bool GraphIntrinsifier::Build_Integer_mul(FlowGraph* flow_graph) {
655bool GraphIntrinsifier::Build_Integer_mod(FlowGraph* flow_graph) {
659bool GraphIntrinsifier::Build_Integer_truncDivide(FlowGraph* flow_graph) {
663bool GraphIntrinsifier::Build_Integer_bitAnd(FlowGraph* flow_graph) {
667bool GraphIntrinsifier::Build_Integer_bitOr(FlowGraph* flow_graph) {
671bool GraphIntrinsifier::Build_Integer_bitXor(FlowGraph* flow_graph) {
675bool GraphIntrinsifier::Build_Integer_sar(FlowGraph* flow_graph) {
679bool GraphIntrinsifier::Build_Integer_shr(FlowGraph* flow_graph) {
688 if (
function.is_unboxed_double_parameter_at(index)) {
690 }
else if (
function.is_unboxed_integer_parameter_at(index)) {
696 return builder->AddDefinition(to_double);
699 return builder->AddUnboxInstr(kUnboxedDouble,
value, is_checked);
703bool GraphIntrinsifier::Build_DoubleFlipSignBit(
FlowGraph* flow_graph) {
711 if (unboxed_value ==
nullptr) {
714 Definition* unboxed_result =
builder.AddDefinition(
new UnaryDoubleOpInstr(
emscripten::val Uint32Array
emscripten::val Uint16Array
emscripten::val Float32Array
emscripten::val Uint8Array
ParallelMoveInstr * parallel_move() const
bool HasParallelMove() const
static BoxInstr * Create(Representation from, Value *value)
static Cids * CreateMonomorphic(Zone *zone, intptr_t cid)
static void RunGraphIntrinsicPipeline(CompilerPassState *state)
static CompilerState & Current()
static constexpr intptr_t kNoOSRDeoptId
static constexpr intptr_t kNone
static bool SupportsUnboxedSimd128()
static bool ShouldPrint(const Function &function, uint8_t **compiler_pass_filter=nullptr)
const GrowableArray< BlockEntryInstr * > & reverse_postorder() const
GraphEntryInstr * graph_entry() const
static Representation ReturnRepresentationOf(const Function &function)
void RemoveRedefinitions(bool keep_checks=false)
void ComputeDominators(GrowableArray< BitVector * > *dominance_frontier)
const Function & function() const
bool has_unboxed_return() const
bool HasOptionalParameters() const
bool is_unboxed_parameter_at(intptr_t index) const
FunctionEntryInstr * normal_entry() const
~GraphIntrinsicCodeGenScope()
GraphIntrinsicCodeGenScope(FlowGraphCompiler *compiler)
virtual void EmitNativeCode(FlowGraphCompiler *compiler)
bool always_calls() const
const Function & function() const
static SimdOpInstr * Create(Kind kind, Value *left, Value *right, intptr_t deopt_id)
static Kind KindForOperator(MethodRecognizer::Kind kind)
static const Slot & GetLengthFieldForArrayCid(intptr_t array_cid)
static bool GraphIntrinsify(const ParsedFunction &parsed_function, FlowGraphCompiler *compiler)
static word ElementSizeFor(intptr_t cid)
#define THR_Print(format,...)
constexpr bool FLAG_support_il_printer
Dart_NativeFunction function
#define EMIT_CASE(class_name, function_name, enum_name, fp)
#define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name)
#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
static constexpr intptr_t kWordSize
static void VerifyParameterIsBoxed(BlockBuilder *builder, intptr_t arg_index)
static bool BuildBinarySmiOp(FlowGraph *flow_graph, Token::Kind op_kind)
static bool IntrinsifyArraySetIndexed(FlowGraph *flow_graph, intptr_t array_cid)
static Definition * CreateBoxedParameterIfNeeded(BlockBuilder *builder, Definition *value, Representation representation, intptr_t arg_index)
static void EmitCodeFor(FlowGraphCompiler *compiler, FlowGraph *graph)
static Definition * PrepareIndexedOp(FlowGraph *flow_graph, BlockBuilder *builder, Definition *array, Definition *index, const Slot &length_field)
static bool BuildSimdOp(FlowGraph *flow_graph, intptr_t cid, Token::Kind kind)
static Representation RepresentationForCid(intptr_t cid)
static Definition * CreateUnboxedResultIfNeeded(BlockBuilder *builder, Definition *value)
static bool BuildFloat32x4Get(FlowGraph *flow_graph, MethodRecognizer::Kind kind)
static Definition * ConvertOrUnboxDoubleParameter(BlockBuilder *builder, Definition *value, intptr_t index, bool is_checked)
static bool BuildUnarySmiOp(FlowGraph *flow_graph, Token::Kind op_kind)
static bool BuildLoadField(FlowGraph *flow_graph, const Slot &field)
static Definition * CreateBoxedResultIfNeeded(BlockBuilder *builder, Definition *value, Representation representation)
bool IsTypedDataClassId(intptr_t index)
bool IsClampedTypedDataBaseClassId(intptr_t index)
static int8_t data[kExtLength]
static constexpr intptr_t kInvalidTryIndex
bool IsExternalTypedDataClassId(intptr_t index)
DECLARE_FLAG(bool, show_invisible_frames)
#define GRAPH_INTRINSICS_LIST(V)
static constexpr Representation NativeRepresentation(Representation rep)
static intptr_t BoxCid(Representation rep)
static constexpr bool IsUnboxedInteger(Representation rep)
static constexpr bool IsUnboxed(Representation rep)
static Representation RepresentationOfArrayElement(classid_t cid)