From 60b4e00770a364c8ce70e1780b061d6d112de59f Mon Sep 17 00:00:00 2001 From: Florian Schneider Date: Tue, 22 Sep 2015 18:28:01 +0200 Subject: [PATCH] VM: Intrinsify some common SIMD methods to speed up precompiled SIMD code. This speeds up precompiled code using SIMD (around 2x on Tracer). Also fix printing of recognized methods which was off-by-one. BUG= R=johnmccutchan@google.com Review URL: https://codereview.chromium.org//1347203005 . --- runtime/vm/intrinsifier.cc | 138 ++++++++++++++++++++++++++++++-- runtime/vm/method_recognizer.cc | 3 +- runtime/vm/method_recognizer.h | 11 ++- 3 files changed, 139 insertions(+), 13 deletions(-) diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc index 5e24dd35739..76e9b63e383 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(); diff --git a/runtime/vm/method_recognizer.cc b/runtime/vm/method_recognizer.cc index d0b941e4af2..45a6f59743f 100644 --- a/runtime/vm/method_recognizer.cc +++ b/runtime/vm/method_recognizer.cc @@ -28,7 +28,8 @@ bool MethodRecognizer::PolymorphicTarget(const Function& function) { #define KIND_TO_STRING(class_name, function_name, enum_name, fp) \ #enum_name, static const char* recognized_list_method_name[] = { -RECOGNIZED_LIST(KIND_TO_STRING) + "Unknown", + RECOGNIZED_LIST(KIND_TO_STRING) }; #undef KIND_TO_STRING diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h index eb752f95936..a931290e30d 100644 --- a/runtime/vm/method_recognizer.h +++ b/runtime/vm/method_recognizer.h @@ -64,10 +64,6 @@ namespace dart { V(Float32x4, Float32x4.fromFloat64x2, Float32x4FromFloat64x2, 1327692716) \ V(_Float32x4, shuffle, Float32x4Shuffle, 1636488139) \ V(_Float32x4, shuffleMix, Float32x4ShuffleMix, 654814229) \ - V(_Float32x4, get:x, Float32x4ShuffleX, 384969722) \ - V(_Float32x4, get:y, Float32x4ShuffleY, 1398121942) \ - V(_Float32x4, get:z, Float32x4ShuffleZ, 1178175605) \ - V(_Float32x4, get:w, Float32x4ShuffleW, 480951003) \ V(_Float32x4, get:signMask, Float32x4GetSignMask, 630880675) \ V(_Float32x4, _cmpequal, Float32x4Equal, 571062952) \ V(_Float32x4, _cmpgt, Float32x4GreaterThan, 1613543295) \ @@ -285,6 +281,13 @@ namespace dart { V(_Float64Array, []=, Float64ArraySetIndexed, 887301703) \ V(_Float64Array, [], Float64ArrayGetIndexed, 1959896670) \ V(_TypedList, get:length, TypedDataLength, 522684521) \ + V(_Float32x4, get:x, Float32x4ShuffleX, 384969722) \ + V(_Float32x4, get:y, Float32x4ShuffleY, 1398121942) \ + V(_Float32x4, get:z, Float32x4ShuffleZ, 1178175605) \ + V(_Float32x4, get:w, Float32x4ShuffleW, 480951003) \ + V(_Float32x4, _mul, Float32x4Mul, 1703784673) \ + V(_Float32x4, _sub, Float32x4Sub, 1302598822) \ + V(_Float32x4, _add, Float32x4Add, 182344215) \ #define GRAPH_CORE_INTRINSICS_LIST(V) \ V(_List, get:length, ObjectArrayLength, 1181471893) \