Index: runtime/vm/intrinsifier.cc |
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc |
index 5e24dd35739cf3ef92ae6be446fe713656cb9c05..48498e10012f614d5f7712193614787b78fd9b43 100644 |
--- a/runtime/vm/intrinsifier.cc |
+++ b/runtime/vm/intrinsifier.cc |
@@ -501,6 +501,128 @@ 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.AddDefinition( |
+ UnboxInstr::Create(kUnboxedFloat32x4, |
+ new Value(left), |
Cutch
2015/09/22 15:48:05
What about creating a helper:
Definition* Unbox(R
Florian Schneider
2015/09/22 16:13:38
Done.
|
+ Isolate::kNoDeoptId)); |
+ // Manually adjust reaching type because there is no type propagation |
+ // when building intrinsics. |
+ left_simd->AsUnbox()->value()->SetReachingType( |
+ ZoneCompileType::Wrap(CompileType::FromCid(kFloat32x4Cid))); |
+ |
+ Definition* right_simd = builder.AddDefinition( |
+ UnboxInstr::Create(kUnboxedFloat32x4, |
+ new Value(right), |
+ Isolate::kNoDeoptId)); |
+ // Manually adjust reaching type because there is no type propagation |
+ // when building intrinsics. |
+ right_simd->AsUnbox()->value()->SetReachingType( |
+ ZoneCompileType::Wrap(CompileType::FromCid(kFloat32x4Cid))); |
+ 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.AddDefinition( |
+ UnboxInstr::Create(kUnboxedFloat32x4, |
+ new Value(receiver), |
+ Isolate::kNoDeoptId)); |
+ // Manually adjust reaching type because there is no type propagation |
+ // when building intrinsics. |
+ unboxed_receiver->AsUnbox()->value()->SetReachingType( |
+ ZoneCompileType::Wrap(CompileType::FromCid(kFloat32x4Cid))); |
Cutch
2015/09/22 15:48:05
Use helper here too
Florian Schneider
2015/09/22 16:13:38
Done.
|
+ |
+ 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(); |