Index: runtime/vm/flow_graph_optimizer.cc |
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc |
index 71fa92ad78a6938c626bdd0f6d2a904629c17184..dc7187067a069a3699de203d37b08c11370aba4c 100644 |
--- a/runtime/vm/flow_graph_optimizer.cc |
+++ b/runtime/vm/flow_graph_optimizer.cc |
@@ -556,6 +556,10 @@ static bool HasOnlyTwoFloat32x4s(const ICData& ic_data) { |
ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid); |
} |
+static bool HasOnlyTwoUint32x4s(const ICData& ic_data) { |
+ return (ic_data.NumberOfChecks() == 1) && |
+ ICDataHasReceiverArgumentClassIds(ic_data, kUint32x4Cid, kUint32x4Cid); |
+} |
// Returns false if the ICData contains anything other than the 4 combinations |
// of Mint and Smi for the receiver and argument classes. |
@@ -1034,6 +1038,8 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, |
operands_type = kSmiCid; |
} else if (HasTwoMintOrSmi(ic_data)) { |
operands_type = kMintCid; |
+ } else if (HasOnlyTwoUint32x4s(ic_data)) { |
+ operands_type = kUint32x4Cid; |
} else { |
return false; |
} |
@@ -1120,8 +1126,28 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, |
// Replace call. |
BinaryFloat32x4OpInstr* float32x4_bin_op = |
new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), |
- call); |
+ call->deopt_id()); |
ReplaceCall(call, float32x4_bin_op); |
+ } else if (operands_type == kUint32x4Cid) { |
+ // Type check left. |
+ AddCheckClass(left, |
+ ICData::ZoneHandle( |
+ call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
+ call->deopt_id(), |
+ call->env(), |
+ call); |
+ // Type check right. |
+ AddCheckClass(right, |
+ ICData::ZoneHandle( |
+ call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
+ call->deopt_id(), |
+ call->env(), |
+ call); |
+ // Replace call. |
+ BinaryUint32x4OpInstr* uint32x4_bin_op = |
+ new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right), |
+ call->deopt_id()); |
+ ReplaceCall(call, uint32x4_bin_op); |
} else if (op_kind == Token::kMOD) { |
// TODO(vegorov): implement fast path code for modulo. |
ASSERT(operands_type == kSmiCid); |
@@ -1416,7 +1442,24 @@ bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
Float32x4ShuffleInstr* instr = new Float32x4ShuffleInstr( |
getter, |
new Value(call->ArgumentAt(0)), |
- call); |
+ call->deopt_id()); |
+ ReplaceCall(call, instr); |
+ return true; |
+} |
+ |
+ |
+bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call, |
+ MethodRecognizer::Kind getter) { |
+ AddCheckClass(call->ArgumentAt(0), |
+ ICData::ZoneHandle( |
+ call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
+ call->deopt_id(), |
+ call->env(), |
+ call); |
+ Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr( |
+ getter, |
+ new Value(call->ArgumentAt(0)), |
+ call->deopt_id()); |
ReplaceCall(call, instr); |
return true; |
} |
@@ -1496,6 +1539,16 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
return false; |
} |
return InlineFloat32x4Getter(call, recognized_kind); |
+ case MethodRecognizer::kUint32x4GetFlagX: |
+ case MethodRecognizer::kUint32x4GetFlagY: |
+ case MethodRecognizer::kUint32x4GetFlagZ: |
+ case MethodRecognizer::kUint32x4GetFlagW: { |
+ if (!ic_data.HasReceiverClassId(kUint32x4Cid) || |
+ !ic_data.HasOneTarget()) { |
+ return false; |
+ } |
+ return InlineUint32x4Getter(call, recognized_kind); |
+ } |
default: |
ASSERT(recognized_kind == MethodRecognizer::kUnknown); |
} |
@@ -1763,6 +1816,10 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
return TryInlineFloat32x4Method(call, recognized_kind); |
} |
+ |
+ if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
+ return TryInlineUint32x4Method(call, recognized_kind); |
+ } |
return false; |
} |
@@ -1790,7 +1847,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
// Replace call. |
Float32x4ComparisonInstr* cmp = |
new Float32x4ComparisonInstr(recognized_kind, new Value(left), |
- new Value(right), call); |
+ new Value(right), call->deopt_id()); |
ReplaceCall(call, cmp); |
return true; |
} |
@@ -1807,7 +1864,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
call); |
Float32x4MinMaxInstr* minmax = |
new Float32x4MinMaxInstr(recognized_kind, new Value(left), |
- new Value(right), call); |
+ new Value(right), call->deopt_id()); |
ReplaceCall(call, minmax); |
return true; |
} |
@@ -1826,7 +1883,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
// register and can be destroyed. |
Float32x4ScaleInstr* scale = |
new Float32x4ScaleInstr(recognized_kind, new Value(right), |
- new Value(left), call); |
+ new Value(left), call->deopt_id()); |
ReplaceCall(call, scale); |
return true; |
} |
@@ -1841,7 +1898,8 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
call->env(), |
call); |
Float32x4SqrtInstr* sqrt = |
- new Float32x4SqrtInstr(recognized_kind, new Value(left), call); |
+ new Float32x4SqrtInstr(recognized_kind, new Value(left), |
+ call->deopt_id()); |
ReplaceCall(call, sqrt); |
return true; |
} |
@@ -1861,7 +1919,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
Float32x4WithInstr* with = new Float32x4WithInstr(recognized_kind, |
new Value(left), |
new Value(right), |
- call); |
+ call->deopt_id()); |
ReplaceCall(call, with); |
return true; |
} |
@@ -1876,7 +1934,8 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
call->env(), |
call); |
Float32x4ZeroArgInstr* zeroArg = |
- new Float32x4ZeroArgInstr(recognized_kind, new Value(left), call); |
+ new Float32x4ZeroArgInstr(recognized_kind, new Value(left), |
+ call->deopt_id()); |
ReplaceCall(call, zeroArg); |
return true; |
} |
@@ -1894,7 +1953,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
Float32x4ClampInstr* clamp = new Float32x4ClampInstr(new Value(left), |
new Value(lower), |
new Value(upper), |
- call); |
+ call->deopt_id()); |
ReplaceCall(call, clamp); |
return true; |
} |
@@ -1908,10 +1967,75 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
call->env(), |
call); |
Float32x4ToUint32x4Instr* cast = |
- new Float32x4ToUint32x4Instr(new Value(left), call); |
+ new Float32x4ToUint32x4Instr(new Value(left), call->deopt_id()); |
+ ReplaceCall(call, cast); |
+ return true; |
+ } |
+ default: |
+ return false; |
+ } |
+} |
+ |
+ |
+bool FlowGraphOptimizer::TryInlineUint32x4Method( |
+ InstanceCallInstr* call, |
+ MethodRecognizer::Kind recognized_kind) { |
+ ASSERT(call->HasICData()); |
+ switch (recognized_kind) { |
+ case MethodRecognizer::kUint32x4Select: { |
+ Definition* mask = call->ArgumentAt(0); |
+ Definition* trueValue = call->ArgumentAt(1); |
+ Definition* falseValue = call->ArgumentAt(2); |
+ // Type check left. |
+ AddCheckClass(mask, |
+ ICData::ZoneHandle( |
+ call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
+ call->deopt_id(), |
+ call->env(), |
+ call); |
+ Uint32x4SelectInstr* select = new Uint32x4SelectInstr( |
+ new Value(mask), |
+ new Value(trueValue), |
+ new Value(falseValue), |
+ call->deopt_id()); |
+ ReplaceCall(call, select); |
+ return true; |
+ } |
+ case MethodRecognizer::kUint32x4ToUint32x4: { |
+ Definition* left = call->ArgumentAt(0); |
+ // Type check left. |
+ AddCheckClass(left, |
+ ICData::ZoneHandle( |
+ call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
+ call->deopt_id(), |
+ call->env(), |
+ call); |
+ Uint32x4ToFloat32x4Instr* cast = |
+ new Uint32x4ToFloat32x4Instr(new Value(left), call->deopt_id()); |
ReplaceCall(call, cast); |
return true; |
} |
+ case MethodRecognizer::kUint32x4WithFlagX: |
+ case MethodRecognizer::kUint32x4WithFlagY: |
+ case MethodRecognizer::kUint32x4WithFlagZ: |
+ case MethodRecognizer::kUint32x4WithFlagW: { |
+ Definition* left = call->ArgumentAt(0); |
+ Definition* flag = call->ArgumentAt(1); |
+ // Type check left. |
+ AddCheckClass(left, |
+ ICData::ZoneHandle( |
+ call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
+ call->deopt_id(), |
+ call->env(), |
+ call); |
+ Uint32x4SetFlagInstr* setFlag = new Uint32x4SetFlagInstr( |
+ recognized_kind, |
+ new Value(left), |
+ new Value(flag), |
+ call->deopt_id()); |
+ ReplaceCall(call, setFlag); |
+ return true; |
+ } |
default: |
return false; |
} |
@@ -2297,11 +2421,12 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { |
new MathSqrtInstr(new Value(call->ArgumentAt(0)), call); |
ReplaceCall(call, sqrt); |
} else if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { |
- Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call); |
+ Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call->deopt_id()); |
ReplaceCall(call, zero); |
} else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { |
Float32x4SplatInstr* splat = |
- new Float32x4SplatInstr(new Value(call->ArgumentAt(1)), call); |
+ new Float32x4SplatInstr(new Value(call->ArgumentAt(1)), |
+ call->deopt_id()); |
ReplaceCall(call, splat); |
} else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { |
Float32x4ConstructorInstr* con = |
@@ -2309,7 +2434,15 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { |
new Value(call->ArgumentAt(2)), |
new Value(call->ArgumentAt(3)), |
new Value(call->ArgumentAt(4)), |
- call); |
+ call->deopt_id()); |
+ ReplaceCall(call, con); |
+ } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) { |
+ Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr( |
+ new Value(call->ArgumentAt(1)), |
+ new Value(call->ArgumentAt(2)), |
+ new Value(call->ArgumentAt(3)), |
+ new Value(call->ArgumentAt(4)), |
+ call->deopt_id()); |
ReplaceCall(call, con); |
} |
} |
@@ -5366,6 +5499,38 @@ void ConstantPropagator::VisitFloat32x4ToUint32x4( |
} |
+void ConstantPropagator::VisitUint32x4BoolConstructor( |
+ Uint32x4BoolConstructorInstr* instr) { |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
+void ConstantPropagator::VisitUint32x4GetFlag(Uint32x4GetFlagInstr* instr) { |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
+void ConstantPropagator::VisitUint32x4SetFlag(Uint32x4SetFlagInstr* instr) { |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
+void ConstantPropagator::VisitUint32x4Select(Uint32x4SelectInstr* instr) { |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
+void ConstantPropagator::VisitUint32x4ToFloat32x4( |
+ Uint32x4ToFloat32x4Instr* instr) { |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
+void ConstantPropagator::VisitBinaryUint32x4Op(BinaryUint32x4OpInstr* instr) { |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) { |
const Object& value = instr->value()->definition()->constant_value(); |
if (IsNonConstant(value)) { |