| Index: runtime/vm/intrinsifier.cc
|
| diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
|
| index 5e24dd35739cf3ef92ae6be446fe713656cb9c05..76e9b63e3837d2e84946d741a7591e7ede01bdb0 100644
|
| --- a/runtime/vm/intrinsifier.cc
|
| +++ b/runtime/vm/intrinsifier.cc
|
| @@ -211,6 +211,19 @@ void Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
|
| }
|
|
|
|
|
| +static intptr_t CidForRepresentation(Representation rep) {
|
| + switch (rep) {
|
| + case kUnboxedDouble:
|
| + return kDoubleCid;
|
| + case kUnboxedFloat32x4:
|
| + return kFloat32x4Cid;
|
| + default:
|
| + UNREACHABLE();
|
| + return kIllegalCid;
|
| + }
|
| +}
|
| +
|
| +
|
| class BlockBuilder : public ValueObject {
|
| public:
|
| BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry)
|
| @@ -256,6 +269,16 @@ class BlockBuilder : public ValueObject {
|
| new ConstantInstr(Object::ZoneHandle(Object::null())));
|
| }
|
|
|
| + Definition* AddUnboxInstr(Representation rep, Value* value) {
|
| + Definition* unboxed_value = AddDefinition(
|
| + UnboxInstr::Create(rep, value, Isolate::kNoDeoptId));
|
| + // Manually adjust reaching type because there is no type propagation
|
| + // when building intrinsics.
|
| + unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap(
|
| + CompileType::FromCid(CidForRepresentation(rep))));
|
| + return unboxed_value;
|
| + }
|
| +
|
| private:
|
| FlowGraph* flow_graph_;
|
| BlockEntryInstr* entry_;
|
| @@ -450,14 +473,8 @@ bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) {
|
| Isolate::kNoDeoptId,
|
| value_check,
|
| builder.TokenPos()));
|
| - Definition* double_value = builder.AddDefinition(
|
| - UnboxInstr::Create(kUnboxedDouble,
|
| - new Value(value),
|
| - Isolate::kNoDeoptId));
|
| - // Manually adjust reaching type because there is no type propagation
|
| - // when building intrinsics.
|
| - double_value->AsUnbox()->value()->SetReachingType(
|
| - ZoneCompileType::Wrap(CompileType::FromCid(kDoubleCid)));
|
| + Definition* double_value =
|
| + builder.AddUnboxInstr(kUnboxedDouble, new Value(value));
|
|
|
| builder.AddInstruction(
|
| new StoreIndexedInstr(new Value(array),
|
| @@ -501,6 +518,111 @@ bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) {
|
| }
|
|
|
|
|
| +static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) {
|
| + if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false;
|
| +
|
| + GraphEntryInstr* graph_entry = flow_graph->graph_entry();
|
| + TargetEntryInstr* normal_entry = graph_entry->normal_entry();
|
| + BlockBuilder builder(flow_graph, normal_entry);
|
| +
|
| + Definition* right = builder.AddParameter(1);
|
| + Definition* left = builder.AddParameter(2);
|
| +
|
| + const ICData& value_check = ICData::ZoneHandle(ICData::New(
|
| + flow_graph->function(),
|
| + String::Handle(flow_graph->function().name()),
|
| + Object::empty_array(), // Dummy args. descr.
|
| + Isolate::kNoDeoptId,
|
| + 1));
|
| + value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function());
|
| + // Check argument. Receiver (left) is known to be a Float32x4.
|
| + builder.AddInstruction(
|
| + new CheckClassInstr(new Value(right),
|
| + Isolate::kNoDeoptId,
|
| + value_check,
|
| + builder.TokenPos()));
|
| + Definition* left_simd =
|
| + builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(left));
|
| +
|
| + Definition* right_simd =
|
| + builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(right));
|
| +
|
| + Definition* unboxed_result = builder.AddDefinition(
|
| + new BinaryFloat32x4OpInstr(kind,
|
| + new Value(left_simd),
|
| + new Value(right_simd),
|
| + Isolate::kNoDeoptId));
|
| + Definition* result = builder.AddDefinition(
|
| + BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result)));
|
| + builder.AddIntrinsicReturn(new Value(result));
|
| + return true;
|
| +}
|
| +
|
| +
|
| +bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) {
|
| + return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL);
|
| +}
|
| +
|
| +
|
| +bool Intrinsifier::Build_Float32x4Sub(FlowGraph* flow_graph) {
|
| + return BuildBinaryFloat32x4Op(flow_graph, Token::kSUB);
|
| +}
|
| +
|
| +
|
| +bool Intrinsifier::Build_Float32x4Add(FlowGraph* flow_graph) {
|
| + return BuildBinaryFloat32x4Op(flow_graph, Token::kADD);
|
| +}
|
| +
|
| +
|
| +static bool BuildFloat32x4Shuffle(FlowGraph* flow_graph,
|
| + MethodRecognizer::Kind kind) {
|
| + if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false;
|
| + GraphEntryInstr* graph_entry = flow_graph->graph_entry();
|
| + TargetEntryInstr* normal_entry = graph_entry->normal_entry();
|
| + BlockBuilder builder(flow_graph, normal_entry);
|
| +
|
| + Definition* receiver = builder.AddParameter(1);
|
| +
|
| + Definition* unboxed_receiver =
|
| + builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver));
|
| +
|
| + Definition* unboxed_result = builder.AddDefinition(
|
| + new Simd32x4ShuffleInstr(kind,
|
| + new Value(unboxed_receiver),
|
| + 0,
|
| + Isolate::kNoDeoptId));
|
| +
|
| + Definition* result = builder.AddDefinition(
|
| + BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result)));
|
| + builder.AddIntrinsicReturn(new Value(result));
|
| + return true;
|
| +}
|
| +
|
| +
|
| +bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) {
|
| + return BuildFloat32x4Shuffle(flow_graph,
|
| + MethodRecognizer::kFloat32x4ShuffleX);
|
| +}
|
| +
|
| +
|
| +bool Intrinsifier::Build_Float32x4ShuffleY(FlowGraph* flow_graph) {
|
| + return BuildFloat32x4Shuffle(flow_graph,
|
| + MethodRecognizer::kFloat32x4ShuffleY);
|
| +}
|
| +
|
| +
|
| +bool Intrinsifier::Build_Float32x4ShuffleZ(FlowGraph* flow_graph) {
|
| + return BuildFloat32x4Shuffle(flow_graph,
|
| + MethodRecognizer::kFloat32x4ShuffleZ);
|
| +}
|
| +
|
| +
|
| +bool Intrinsifier::Build_Float32x4ShuffleW(FlowGraph* flow_graph) {
|
| + return BuildFloat32x4Shuffle(flow_graph,
|
| + MethodRecognizer::kFloat32x4ShuffleW);
|
| +}
|
| +
|
| +
|
| static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) {
|
| GraphEntryInstr* graph_entry = flow_graph->graph_entry();
|
| TargetEntryInstr* normal_entry = graph_entry->normal_entry();
|
|
|