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 .
This commit is contained in:
Florian Schneider 2015-09-22 18:28:01 +02:00
parent 847847dd95
commit 60b4e00770
3 changed files with 139 additions and 13 deletions

View file

@ -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();

View file

@ -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

View file

@ -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) \