[turbofan] Add new JSIntrinsicsLowering reducer.
The lowering of intrinsics is therefore now decoupled from the general inlining logic. TEST=cctest,unittests R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/872363002 Cr-Commit-Position: refs/heads/master@{#26263}
This commit is contained in:
parent
8eb58b85a6
commit
4f1597a92d
4
BUILD.gn
4
BUILD.gn
@ -561,8 +561,8 @@ source_set("v8_base") {
|
||||
"src/compiler/js-graph.h",
|
||||
"src/compiler/js-inlining.cc",
|
||||
"src/compiler/js-inlining.h",
|
||||
"src/compiler/js-intrinsic-builder.cc",
|
||||
"src/compiler/js-intrinsic-builder.h",
|
||||
"src/compiler/js-intrinsic-lowering.cc",
|
||||
"src/compiler/js-intrinsic-lowering.h",
|
||||
"src/compiler/js-operator.cc",
|
||||
"src/compiler/js-operator.h",
|
||||
"src/compiler/js-typed-lowering.cc",
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "src/compiler/graph-inl.h"
|
||||
#include "src/compiler/graph-visualizer.h"
|
||||
#include "src/compiler/js-inlining.h"
|
||||
#include "src/compiler/js-intrinsic-builder.h"
|
||||
#include "src/compiler/js-operator.h"
|
||||
#include "src/compiler/node-aux-data-inl.h"
|
||||
#include "src/compiler/node-matchers.h"
|
||||
@ -36,11 +35,6 @@ class InlinerVisitor : public NullNodeVisitor {
|
||||
case IrOpcode::kJSCallFunction:
|
||||
inliner_->TryInlineJSCall(node);
|
||||
break;
|
||||
case IrOpcode::kJSCallRuntime:
|
||||
if (FLAG_turbo_inlining_intrinsics) {
|
||||
inliner_->TryInlineRuntimeCall(node);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -418,70 +412,6 @@ void JSInliner::TryInlineJSCall(Node* call_node) {
|
||||
inlinee.InlineAtCall(jsgraph_, call_node);
|
||||
}
|
||||
|
||||
|
||||
class JSCallRuntimeAccessor {
|
||||
public:
|
||||
explicit JSCallRuntimeAccessor(Node* call) : call_(call) {
|
||||
DCHECK_EQ(IrOpcode::kJSCallRuntime, call->opcode());
|
||||
}
|
||||
|
||||
Node* formal_argument(size_t index) {
|
||||
DCHECK(index < formal_arguments());
|
||||
return call_->InputAt(static_cast<int>(index));
|
||||
}
|
||||
|
||||
size_t formal_arguments() {
|
||||
size_t value_inputs = call_->op()->ValueInputCount();
|
||||
return value_inputs;
|
||||
}
|
||||
|
||||
Node* frame_state() const {
|
||||
return NodeProperties::GetFrameStateInput(call_);
|
||||
}
|
||||
Node* context() const { return NodeProperties::GetContextInput(call_); }
|
||||
Node* control() const { return NodeProperties::GetControlInput(call_); }
|
||||
Node* effect() const { return NodeProperties::GetEffectInput(call_); }
|
||||
|
||||
const Runtime::Function* function() const {
|
||||
return Runtime::FunctionForId(CallRuntimeParametersOf(call_->op()).id());
|
||||
}
|
||||
|
||||
NodeVector inputs(Zone* zone) const {
|
||||
NodeVector inputs(zone);
|
||||
for (Node* const node : call_->inputs()) {
|
||||
inputs.push_back(node);
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
private:
|
||||
Node* call_;
|
||||
};
|
||||
|
||||
|
||||
void JSInliner::TryInlineRuntimeCall(Node* call_node) {
|
||||
JSCallRuntimeAccessor call(call_node);
|
||||
const Runtime::Function* f = call.function();
|
||||
|
||||
if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSIntrinsicBuilder intrinsic_builder(jsgraph_);
|
||||
|
||||
ResultAndEffect r = intrinsic_builder.BuildGraphFor(
|
||||
f->function_id, call.inputs(jsgraph_->zone()));
|
||||
|
||||
if (r.first != NULL) {
|
||||
if (FLAG_trace_turbo_inlining) {
|
||||
PrintF("Inlining %s into %s\n", f->name,
|
||||
info_->shared_info()->DebugName()->ToCString().get());
|
||||
}
|
||||
NodeProperties::ReplaceWithValue(call_node, r.first, r.second);
|
||||
call_node->RemoveAllInputs();
|
||||
DCHECK_EQ(0, call_node->UseCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace v8::internal::compiler
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -21,7 +21,6 @@ class JSInliner {
|
||||
|
||||
void Inline();
|
||||
void TryInlineJSCall(Node* node);
|
||||
void TryInlineRuntimeCall(Node* node);
|
||||
|
||||
private:
|
||||
friend class InlinerVisitor;
|
||||
|
@ -1,140 +0,0 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/common-operator.h"
|
||||
#include "src/compiler/diamond.h"
|
||||
#include "src/compiler/js-intrinsic-builder.h"
|
||||
#include "src/compiler/js-operator.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
ResultAndEffect JSIntrinsicBuilder::BuildGraphFor(Runtime::FunctionId id,
|
||||
const NodeVector& arguments) {
|
||||
switch (id) {
|
||||
case Runtime::kInlineIsSmi:
|
||||
return BuildGraphFor_IsSmi(arguments);
|
||||
case Runtime::kInlineIsNonNegativeSmi:
|
||||
return BuildGraphFor_IsNonNegativeSmi(arguments);
|
||||
case Runtime::kInlineIsArray:
|
||||
return BuildMapCheck(arguments[0], arguments[2], JS_ARRAY_TYPE);
|
||||
case Runtime::kInlineIsRegExp:
|
||||
return BuildMapCheck(arguments[0], arguments[2], JS_REGEXP_TYPE);
|
||||
case Runtime::kInlineIsFunction:
|
||||
return BuildMapCheck(arguments[0], arguments[2], JS_FUNCTION_TYPE);
|
||||
case Runtime::kInlineValueOf:
|
||||
return BuildGraphFor_ValueOf(arguments);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ResultAndEffect();
|
||||
}
|
||||
|
||||
ResultAndEffect JSIntrinsicBuilder::BuildGraphFor_IsSmi(
|
||||
const NodeVector& arguments) {
|
||||
Node* object = arguments[0];
|
||||
SimplifiedOperatorBuilder simplified(jsgraph_->zone());
|
||||
Node* condition = graph()->NewNode(simplified.ObjectIsSmi(), object);
|
||||
|
||||
return ResultAndEffect(condition, arguments[2]);
|
||||
}
|
||||
|
||||
|
||||
ResultAndEffect JSIntrinsicBuilder::BuildGraphFor_IsNonNegativeSmi(
|
||||
const NodeVector& arguments) {
|
||||
Node* object = arguments[0];
|
||||
SimplifiedOperatorBuilder simplified(jsgraph_->zone());
|
||||
Node* condition =
|
||||
graph()->NewNode(simplified.ObjectIsNonNegativeSmi(), object);
|
||||
|
||||
return ResultAndEffect(condition, arguments[2]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* if (_isSmi(object)) {
|
||||
* return false
|
||||
* } else {
|
||||
* return %_GetMapInstanceType(object) == map_type
|
||||
* }
|
||||
*/
|
||||
ResultAndEffect JSIntrinsicBuilder::BuildMapCheck(Node* object, Node* effect,
|
||||
InstanceType map_type) {
|
||||
SimplifiedOperatorBuilder simplified(jsgraph_->zone());
|
||||
|
||||
Node* is_smi = graph()->NewNode(simplified.ObjectIsSmi(), object);
|
||||
Diamond d(graph(), common(), is_smi);
|
||||
|
||||
Node* map = graph()->NewNode(simplified.LoadField(AccessBuilder::ForMap()),
|
||||
object, effect, d.if_false);
|
||||
|
||||
Node* instance_type = graph()->NewNode(
|
||||
simplified.LoadField(AccessBuilder::ForMapInstanceType()), map, map,
|
||||
d.if_false);
|
||||
|
||||
Node* has_map_type =
|
||||
graph()->NewNode(jsgraph_->machine()->Word32Equal(), instance_type,
|
||||
jsgraph_->Int32Constant(map_type));
|
||||
|
||||
Node* phi = d.Phi(static_cast<MachineType>(kTypeBool | kRepTagged),
|
||||
jsgraph_->FalseConstant(), has_map_type);
|
||||
|
||||
Node* ephi = d.EffectPhi(effect, instance_type);
|
||||
|
||||
return ResultAndEffect(phi, ephi);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* if (%_isSmi(object)) {
|
||||
* return object;
|
||||
* } else if (%_GetMapInstanceType(object) == JS_VALUE_TYPE) {
|
||||
* return %_LoadValueField(object);
|
||||
* } else {
|
||||
* return object;
|
||||
* }
|
||||
*/
|
||||
ResultAndEffect JSIntrinsicBuilder::BuildGraphFor_ValueOf(
|
||||
const NodeVector& arguments) {
|
||||
Node* object = arguments[0];
|
||||
Node* effect = arguments[2];
|
||||
SimplifiedOperatorBuilder simplified(jsgraph_->zone());
|
||||
|
||||
Node* is_smi = graph()->NewNode(simplified.ObjectIsSmi(), object);
|
||||
|
||||
Diamond if_is_smi(graph(), common(), is_smi);
|
||||
|
||||
Node* map = graph()->NewNode(simplified.LoadField(AccessBuilder::ForMap()),
|
||||
object, effect, if_is_smi.if_false);
|
||||
|
||||
Node* instance_type = graph()->NewNode(
|
||||
simplified.LoadField(AccessBuilder::ForMapInstanceType()), map, map,
|
||||
if_is_smi.if_false);
|
||||
|
||||
Node* is_value =
|
||||
graph()->NewNode(jsgraph_->machine()->Word32Equal(), instance_type,
|
||||
jsgraph_->Constant(JS_VALUE_TYPE));
|
||||
|
||||
Diamond if_is_value(graph(), common(), is_value);
|
||||
if_is_value.Nest(if_is_smi, false);
|
||||
|
||||
Node* value =
|
||||
graph()->NewNode(simplified.LoadField(AccessBuilder::ForValue()), object,
|
||||
instance_type, if_is_value.if_true);
|
||||
|
||||
Node* phi_is_value = if_is_value.Phi(kTypeAny, value, object);
|
||||
|
||||
Node* phi = if_is_smi.Phi(kTypeAny, object, phi_is_value);
|
||||
|
||||
Node* ephi = if_is_smi.EffectPhi(effect, instance_type);
|
||||
|
||||
return ResultAndEffect(phi, ephi);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace v8::internal::compiler
|
@ -1,40 +0,0 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_JS_INTRINSIC_BUILDER_H_
|
||||
#define V8_COMPILER_JS_INTRINSIC_BUILDER_H_
|
||||
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/v8.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
typedef std::pair<Node*, Node*> ResultAndEffect;
|
||||
|
||||
class JSIntrinsicBuilder {
|
||||
public:
|
||||
explicit JSIntrinsicBuilder(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
|
||||
|
||||
ResultAndEffect BuildGraphFor(Runtime::FunctionId id,
|
||||
const NodeVector& arguments);
|
||||
|
||||
private:
|
||||
ResultAndEffect BuildMapCheck(Node* object, Node* effect,
|
||||
InstanceType map_type);
|
||||
ResultAndEffect BuildGraphFor_IsSmi(const NodeVector& arguments);
|
||||
ResultAndEffect BuildGraphFor_IsNonNegativeSmi(const NodeVector& arguments);
|
||||
ResultAndEffect BuildGraphFor_ValueOf(const NodeVector& arguments);
|
||||
|
||||
|
||||
Graph* graph() const { return jsgraph_->graph(); }
|
||||
CommonOperatorBuilder* common() const { return jsgraph_->common(); }
|
||||
JSGraph* jsgraph_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace v8::internal::compiler
|
||||
|
||||
#endif // V8_COMPILER_JS_INTRINSIC_BUILDER_H_
|
194
src/compiler/js-intrinsic-lowering.cc
Normal file
194
src/compiler/js-intrinsic-lowering.cc
Normal file
@ -0,0 +1,194 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/js-intrinsic-lowering.h"
|
||||
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/node-properties-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
JSIntrinsicLowering::JSIntrinsicLowering(JSGraph* jsgraph)
|
||||
: jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::Reduce(Node* node) {
|
||||
if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange();
|
||||
const Runtime::Function* const f =
|
||||
Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).id());
|
||||
if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange();
|
||||
switch (f->function_id) {
|
||||
case Runtime::kInlineIsSmi:
|
||||
return ReduceInlineIsSmi(node);
|
||||
case Runtime::kInlineIsNonNegativeSmi:
|
||||
return ReduceInlineIsNonNegativeSmi(node);
|
||||
case Runtime::kInlineIsArray:
|
||||
return ReduceInlineIsInstanceType(node, JS_ARRAY_TYPE);
|
||||
case Runtime::kInlineIsFunction:
|
||||
return ReduceInlineIsInstanceType(node, JS_FUNCTION_TYPE);
|
||||
case Runtime::kInlineIsRegExp:
|
||||
return ReduceInlineIsInstanceType(node, JS_REGEXP_TYPE);
|
||||
case Runtime::kInlineValueOf:
|
||||
return ReduceInlineValueOf(node);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::ReduceInlineIsSmi(Node* node) {
|
||||
return Change(node, simplified()->ObjectIsSmi());
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::ReduceInlineIsNonNegativeSmi(Node* node) {
|
||||
return Change(node, simplified()->ObjectIsNonNegativeSmi());
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::ReduceInlineIsInstanceType(
|
||||
Node* node, InstanceType instance_type) {
|
||||
// if (%_IsSmi(value)) {
|
||||
// return false;
|
||||
// } else {
|
||||
// return %_GetInstanceType(%_GetMap(value)) == instance_type;
|
||||
// }
|
||||
MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged);
|
||||
|
||||
Node* value = NodeProperties::GetValueInput(node, 0);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
|
||||
Node* branch = graph()->NewNode(common()->Branch(), check, control);
|
||||
|
||||
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
||||
Node* etrue = effect;
|
||||
Node* vtrue = jsgraph()->FalseConstant();
|
||||
|
||||
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
||||
Node* efalse = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
|
||||
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value,
|
||||
effect, if_false),
|
||||
effect, if_false);
|
||||
Node* vfalse = graph()->NewNode(machine()->Word32Equal(), efalse,
|
||||
jsgraph()->Int32Constant(instance_type));
|
||||
|
||||
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
|
||||
|
||||
// Replace all effect uses of {node} with the {ephi}.
|
||||
Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
|
||||
NodeProperties::ReplaceWithValue(node, node, ephi);
|
||||
|
||||
// Turn the {node} into a Phi.
|
||||
return Change(node, common()->Phi(type, 2), vtrue, vfalse, merge);
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::ReduceInlineValueOf(Node* node) {
|
||||
// if (%_IsSmi(value)) {
|
||||
// return value;
|
||||
// } else if (%_GetInstanceType(%_GetMap(value)) == JS_VALUE_TYPE) {
|
||||
// return %_GetValue(value);
|
||||
// } else {
|
||||
// return value;
|
||||
// }
|
||||
const Operator* const merge_op = common()->Merge(2);
|
||||
const Operator* const ephi_op = common()->EffectPhi(2);
|
||||
const Operator* const phi_op = common()->Phi(kMachAnyTagged, 2);
|
||||
|
||||
Node* value = NodeProperties::GetValueInput(node, 0);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
|
||||
Node* branch0 = graph()->NewNode(common()->Branch(), check0, control);
|
||||
|
||||
Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
|
||||
Node* etrue0 = effect;
|
||||
Node* vtrue0 = value;
|
||||
|
||||
Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
|
||||
Node* efalse0;
|
||||
Node* vfalse0;
|
||||
{
|
||||
Node* check1 = graph()->NewNode(
|
||||
machine()->Word32Equal(),
|
||||
graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
|
||||
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
|
||||
value, effect, if_false0),
|
||||
effect, if_false0),
|
||||
jsgraph()->Int32Constant(JS_VALUE_TYPE));
|
||||
Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
|
||||
|
||||
Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
||||
Node* etrue1 =
|
||||
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForValue()),
|
||||
value, effect, if_true1);
|
||||
Node* vtrue1 = etrue1;
|
||||
|
||||
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
||||
Node* efalse1 = effect;
|
||||
Node* vfalse1 = value;
|
||||
|
||||
Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1);
|
||||
efalse0 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1);
|
||||
vfalse0 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1);
|
||||
}
|
||||
|
||||
Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
|
||||
|
||||
|
||||
// Replace all effect uses of {node} with the {ephi0}.
|
||||
Node* ephi0 = graph()->NewNode(ephi_op, etrue0, efalse0, merge0);
|
||||
NodeProperties::ReplaceWithValue(node, node, ephi0);
|
||||
|
||||
// Turn the {node} into a Phi.
|
||||
return Change(node, phi_op, vtrue0, vfalse0, merge0);
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op) {
|
||||
// Remove the effects from the node and update its effect usages.
|
||||
NodeProperties::ReplaceWithValue(node, node);
|
||||
// Remove the inputs corresponding to context, effect and control.
|
||||
NodeProperties::RemoveNonValueInputs(node);
|
||||
// Finally update the operator to the new one.
|
||||
node->set_op(op);
|
||||
return Changed(node);
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
|
||||
Node* b, Node* c) {
|
||||
node->set_op(op);
|
||||
node->ReplaceInput(0, a);
|
||||
node->ReplaceInput(1, b);
|
||||
node->ReplaceInput(2, c);
|
||||
node->TrimInputCount(3);
|
||||
return Changed(node);
|
||||
}
|
||||
|
||||
|
||||
Graph* JSIntrinsicLowering::graph() const { return jsgraph()->graph(); }
|
||||
|
||||
|
||||
CommonOperatorBuilder* JSIntrinsicLowering::common() const {
|
||||
return jsgraph()->common();
|
||||
}
|
||||
|
||||
|
||||
MachineOperatorBuilder* JSIntrinsicLowering::machine() const {
|
||||
return jsgraph()->machine();
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
52
src/compiler/js-intrinsic-lowering.h
Normal file
52
src/compiler/js-intrinsic-lowering.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_JS_INTRINSIC_LOWERING_H_
|
||||
#define V8_COMPILER_JS_INTRINSIC_LOWERING_H_
|
||||
|
||||
#include "src/compiler/graph-reducer.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
// Forward declarations.
|
||||
class CommonOperatorBuilder;
|
||||
class JSGraph;
|
||||
class MachineOperatorBuilder;
|
||||
|
||||
|
||||
// Lowers certain JS-level runtime calls.
|
||||
class JSIntrinsicLowering FINAL : public Reducer {
|
||||
public:
|
||||
explicit JSIntrinsicLowering(JSGraph* jsgraph);
|
||||
~JSIntrinsicLowering() FINAL {}
|
||||
|
||||
Reduction Reduce(Node* node) FINAL;
|
||||
|
||||
private:
|
||||
Reduction ReduceInlineIsSmi(Node* node);
|
||||
Reduction ReduceInlineIsNonNegativeSmi(Node* node);
|
||||
Reduction ReduceInlineIsInstanceType(Node* node, InstanceType instance_type);
|
||||
Reduction ReduceInlineValueOf(Node* node);
|
||||
|
||||
Reduction Change(Node* node, const Operator* op);
|
||||
Reduction Change(Node* node, const Operator* op, Node* a, Node* b, Node* c);
|
||||
|
||||
Graph* graph() const;
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
CommonOperatorBuilder* common() const;
|
||||
MachineOperatorBuilder* machine() const;
|
||||
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
|
||||
|
||||
JSGraph* jsgraph_;
|
||||
SimplifiedOperatorBuilder simplified_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_JS_INTRINSIC_LOWERING_H_
|
@ -24,6 +24,7 @@
|
||||
#include "src/compiler/js-context-specialization.h"
|
||||
#include "src/compiler/js-generic-lowering.h"
|
||||
#include "src/compiler/js-inlining.h"
|
||||
#include "src/compiler/js-intrinsic-lowering.h"
|
||||
#include "src/compiler/js-typed-lowering.h"
|
||||
#include "src/compiler/jump-threading.h"
|
||||
#include "src/compiler/load-elimination.h"
|
||||
@ -428,12 +429,14 @@ struct TypedLoweringPhase {
|
||||
LoadElimination load_elimination;
|
||||
JSBuiltinReducer builtin_reducer(data->jsgraph());
|
||||
JSTypedLowering typed_lowering(data->jsgraph(), temp_zone);
|
||||
JSIntrinsicLowering intrinsic_lowering(data->jsgraph());
|
||||
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
|
||||
CommonOperatorReducer common_reducer;
|
||||
GraphReducer graph_reducer(data->graph(), temp_zone);
|
||||
graph_reducer.AddReducer(&vn_reducer);
|
||||
graph_reducer.AddReducer(&builtin_reducer);
|
||||
graph_reducer.AddReducer(&typed_lowering);
|
||||
graph_reducer.AddReducer(&intrinsic_lowering);
|
||||
graph_reducer.AddReducer(&load_elimination);
|
||||
graph_reducer.AddReducer(&simple_reducer);
|
||||
graph_reducer.AddReducer(&common_reducer);
|
||||
|
@ -854,10 +854,10 @@ class RepresentationSelector {
|
||||
if (lower()) {
|
||||
Node* is_tagged = jsgraph_->graph()->NewNode(
|
||||
jsgraph_->machine()->WordAnd(), node->InputAt(0),
|
||||
jsgraph_->Int32Constant(static_cast<int>(kSmiTagMask)));
|
||||
jsgraph_->IntPtrConstant(kSmiTagMask));
|
||||
Node* is_smi = jsgraph_->graph()->NewNode(
|
||||
jsgraph_->machine()->WordEqual(), is_tagged,
|
||||
jsgraph_->Int32Constant(kSmiTag));
|
||||
jsgraph_->IntPtrConstant(kSmiTag));
|
||||
DeferReplacement(node, is_smi);
|
||||
}
|
||||
break;
|
||||
@ -868,13 +868,13 @@ class RepresentationSelector {
|
||||
if (lower()) {
|
||||
Node* is_tagged = jsgraph_->graph()->NewNode(
|
||||
jsgraph_->machine()->WordAnd(), node->InputAt(0),
|
||||
jsgraph_->Int32Constant(static_cast<int>(kSmiTagMask)));
|
||||
jsgraph_->IntPtrConstant(kSmiTagMask));
|
||||
Node* is_smi = jsgraph_->graph()->NewNode(
|
||||
jsgraph_->machine()->WordEqual(), is_tagged,
|
||||
jsgraph_->Int32Constant(kSmiTag));
|
||||
jsgraph_->IntPtrConstant(kSmiTag));
|
||||
Node* is_non_neg = jsgraph_->graph()->NewNode(
|
||||
jsgraph_->machine()->IntLessThanOrEqual(),
|
||||
jsgraph_->Int32Constant(0), node->InputAt(0));
|
||||
jsgraph_->IntPtrConstant(0), node->InputAt(0));
|
||||
Node* is_non_neg_smi = jsgraph_->graph()->NewNode(
|
||||
jsgraph_->machine()->Word32And(), is_smi, is_non_neg);
|
||||
DeferReplacement(node, is_non_neg_smi);
|
||||
|
@ -1442,6 +1442,16 @@ Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
|
||||
|
||||
|
||||
Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
|
||||
switch (CallRuntimeParametersOf(node->op()).id()) {
|
||||
case Runtime::kInlineIsSmi:
|
||||
case Runtime::kInlineIsNonNegativeSmi:
|
||||
case Runtime::kInlineIsArray:
|
||||
case Runtime::kInlineIsFunction:
|
||||
case Runtime::kInlineIsRegExp:
|
||||
return Bounds(Type::None(zone()), Type::Boolean(zone()));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Bounds::Unbounded(zone());
|
||||
}
|
||||
|
||||
|
@ -403,11 +403,8 @@ DEFINE_BOOL(context_specialization, false,
|
||||
"enable context specialization in TurboFan")
|
||||
DEFINE_BOOL(turbo_deoptimization, false, "enable deoptimization in TurboFan")
|
||||
DEFINE_BOOL(turbo_inlining, false, "enable inlining in TurboFan")
|
||||
DEFINE_BOOL(turbo_inlining_intrinsics, false,
|
||||
"enable inlining of intrinsics in TurboFan")
|
||||
DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining")
|
||||
DEFINE_BOOL(loop_assignment_analysis, true, "perform loop assignment analysis")
|
||||
DEFINE_IMPLICATION(turbo_inlining_intrinsics, turbo_inlining)
|
||||
DEFINE_IMPLICATION(turbo_inlining, turbo_types)
|
||||
DEFINE_BOOL(turbo_profiling, false, "enable profiling in TurboFan")
|
||||
// TODO(dcarney): this is just for experimentation, remove when default.
|
||||
|
@ -11,7 +11,6 @@ using namespace v8::internal::compiler;
|
||||
uint32_t flags = CompilationInfo::kInliningEnabled;
|
||||
|
||||
TEST(IsSmi) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_IsSmi(a); })", flags);
|
||||
|
||||
@ -25,7 +24,6 @@ TEST(IsSmi) {
|
||||
|
||||
|
||||
TEST(IsNonNegativeSmi) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_IsNonNegativeSmi(a); })", flags);
|
||||
|
||||
@ -39,7 +37,6 @@ TEST(IsNonNegativeSmi) {
|
||||
|
||||
|
||||
TEST(IsMinusZero) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags);
|
||||
|
||||
@ -53,7 +50,6 @@ TEST(IsMinusZero) {
|
||||
|
||||
|
||||
TEST(IsArray) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_IsArray(a); })", flags);
|
||||
|
||||
@ -69,7 +65,6 @@ TEST(IsArray) {
|
||||
|
||||
|
||||
TEST(IsObject) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_IsObject(a); })", flags);
|
||||
|
||||
@ -85,7 +80,6 @@ TEST(IsObject) {
|
||||
|
||||
|
||||
TEST(IsFunction) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_IsFunction(a); })", flags);
|
||||
|
||||
@ -101,7 +95,6 @@ TEST(IsFunction) {
|
||||
|
||||
|
||||
TEST(IsRegExp) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
|
||||
|
||||
@ -117,7 +110,6 @@ TEST(IsRegExp) {
|
||||
|
||||
|
||||
TEST(ClassOf) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_ClassOf(a); })", flags);
|
||||
|
||||
@ -133,7 +125,6 @@ TEST(ClassOf) {
|
||||
|
||||
|
||||
TEST(ObjectEquals) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_ObjectEquals(a,b); })", flags);
|
||||
CompileRun("var o = {}");
|
||||
@ -148,7 +139,6 @@ TEST(ObjectEquals) {
|
||||
|
||||
|
||||
TEST(ValueOf) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_ValueOf(a); })", flags);
|
||||
|
||||
@ -160,7 +150,6 @@ TEST(ValueOf) {
|
||||
|
||||
|
||||
TEST(SetValueOf) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_SetValueOf(a,b); })", flags);
|
||||
|
||||
@ -171,7 +160,6 @@ TEST(SetValueOf) {
|
||||
|
||||
|
||||
TEST(StringCharFromCode) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a) { return %_StringCharFromCode(a); })", flags);
|
||||
|
||||
@ -182,7 +170,6 @@ TEST(StringCharFromCode) {
|
||||
|
||||
|
||||
TEST(StringCharAt) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_StringCharAt(a,b); })", flags);
|
||||
|
||||
@ -193,7 +180,6 @@ TEST(StringCharAt) {
|
||||
|
||||
|
||||
TEST(StringCharCodeAt) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_StringCharCodeAt(a,b); })",
|
||||
flags);
|
||||
@ -205,7 +191,6 @@ TEST(StringCharCodeAt) {
|
||||
|
||||
|
||||
TEST(StringAdd) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
|
||||
|
||||
@ -216,7 +201,6 @@ TEST(StringAdd) {
|
||||
|
||||
|
||||
TEST(StringSubString) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_SubString(a,b,b+3); })", flags);
|
||||
|
||||
@ -227,7 +211,6 @@ TEST(StringSubString) {
|
||||
|
||||
|
||||
TEST(StringCompare) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_StringCompare(a,b); })", flags);
|
||||
|
||||
@ -238,7 +221,6 @@ TEST(StringCompare) {
|
||||
|
||||
|
||||
TEST(CallFunction) {
|
||||
FLAG_turbo_inlining_intrinsics = true;
|
||||
FLAG_turbo_deoptimization = true;
|
||||
FunctionTester T("(function(a,b) { return %_CallFunction(a, 1, 2, 3, b); })",
|
||||
flags);
|
||||
|
215
test/unittests/compiler/js-intrinsic-lowering-unittest.cc
Normal file
215
test/unittests/compiler/js-intrinsic-lowering-unittest.cc
Normal file
@ -0,0 +1,215 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/js-intrinsic-lowering.h"
|
||||
#include "src/compiler/js-operator.h"
|
||||
#include "test/unittests/compiler/graph-unittest.h"
|
||||
#include "test/unittests/compiler/node-test-utils.h"
|
||||
#include "testing/gmock-support.h"
|
||||
|
||||
using testing::_;
|
||||
using testing::AllOf;
|
||||
using testing::BitEq;
|
||||
using testing::Capture;
|
||||
using testing::CaptureEq;
|
||||
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class JSIntrinsicLoweringTest : public GraphTest {
|
||||
public:
|
||||
JSIntrinsicLoweringTest() : GraphTest(3), javascript_(zone()) {}
|
||||
~JSIntrinsicLoweringTest() OVERRIDE {}
|
||||
|
||||
protected:
|
||||
Reduction Reduce(Node* node) {
|
||||
MachineOperatorBuilder machine(zone());
|
||||
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine);
|
||||
JSIntrinsicLowering reducer(&jsgraph);
|
||||
return reducer.Reduce(node);
|
||||
}
|
||||
|
||||
JSOperatorBuilder* javascript() { return &javascript_; }
|
||||
|
||||
private:
|
||||
JSOperatorBuilder javascript_;
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// %_IsSmi
|
||||
|
||||
|
||||
TEST_F(JSIntrinsicLoweringTest, InlineIsSmi) {
|
||||
Node* const input = Parameter(0);
|
||||
Node* const context = Parameter(1);
|
||||
Node* const effect = graph()->start();
|
||||
Node* const control = graph()->start();
|
||||
Reduction const r = Reduce(
|
||||
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1),
|
||||
input, context, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsObjectIsSmi(input));
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// %_IsNonNegativeSmi
|
||||
|
||||
|
||||
TEST_F(JSIntrinsicLoweringTest, InlineIsNonNegativeSmi) {
|
||||
Node* const input = Parameter(0);
|
||||
Node* const context = Parameter(1);
|
||||
Node* const effect = graph()->start();
|
||||
Node* const control = graph()->start();
|
||||
Reduction const r = Reduce(graph()->NewNode(
|
||||
javascript()->CallRuntime(Runtime::kInlineIsNonNegativeSmi, 1), input,
|
||||
context, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(r.replacement(), IsObjectIsNonNegativeSmi(input));
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// %_IsArray
|
||||
|
||||
|
||||
TEST_F(JSIntrinsicLoweringTest, InlineIsArray) {
|
||||
Node* const input = Parameter(0);
|
||||
Node* const context = Parameter(1);
|
||||
Node* const effect = graph()->start();
|
||||
Node* const control = graph()->start();
|
||||
Reduction const r = Reduce(
|
||||
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsArray, 1),
|
||||
input, context, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
|
||||
Node* phi = r.replacement();
|
||||
Capture<Node*> branch, if_false;
|
||||
EXPECT_THAT(
|
||||
phi,
|
||||
IsPhi(
|
||||
static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
|
||||
IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
|
||||
IsLoadField(AccessBuilder::ForMap(), input,
|
||||
effect, CaptureEq(&if_false)),
|
||||
effect, _),
|
||||
IsInt32Constant(JS_ARRAY_TYPE)),
|
||||
IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
|
||||
IsBranch(IsObjectIsSmi(input), control))),
|
||||
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// %_IsFunction
|
||||
|
||||
|
||||
TEST_F(JSIntrinsicLoweringTest, InlineIsFunction) {
|
||||
Node* const input = Parameter(0);
|
||||
Node* const context = Parameter(1);
|
||||
Node* const effect = graph()->start();
|
||||
Node* const control = graph()->start();
|
||||
Reduction const r = Reduce(
|
||||
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsFunction, 1),
|
||||
input, context, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
|
||||
Node* phi = r.replacement();
|
||||
Capture<Node*> branch, if_false;
|
||||
EXPECT_THAT(
|
||||
phi,
|
||||
IsPhi(
|
||||
static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
|
||||
IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
|
||||
IsLoadField(AccessBuilder::ForMap(), input,
|
||||
effect, CaptureEq(&if_false)),
|
||||
effect, _),
|
||||
IsInt32Constant(JS_FUNCTION_TYPE)),
|
||||
IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
|
||||
IsBranch(IsObjectIsSmi(input), control))),
|
||||
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// %_IsRegExp
|
||||
|
||||
|
||||
TEST_F(JSIntrinsicLoweringTest, InlineIsRegExp) {
|
||||
Node* const input = Parameter(0);
|
||||
Node* const context = Parameter(1);
|
||||
Node* const effect = graph()->start();
|
||||
Node* const control = graph()->start();
|
||||
Reduction const r = Reduce(
|
||||
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsRegExp, 1),
|
||||
input, context, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
|
||||
Node* phi = r.replacement();
|
||||
Capture<Node*> branch, if_false;
|
||||
EXPECT_THAT(
|
||||
phi,
|
||||
IsPhi(
|
||||
static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(),
|
||||
IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(),
|
||||
IsLoadField(AccessBuilder::ForMap(), input,
|
||||
effect, CaptureEq(&if_false)),
|
||||
effect, _),
|
||||
IsInt32Constant(JS_REGEXP_TYPE)),
|
||||
IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
|
||||
IsBranch(IsObjectIsSmi(input), control))),
|
||||
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// %_ValueOf
|
||||
|
||||
|
||||
TEST_F(JSIntrinsicLoweringTest, InlineValueOf) {
|
||||
Node* const input = Parameter(0);
|
||||
Node* const context = Parameter(1);
|
||||
Node* const effect = graph()->start();
|
||||
Node* const control = graph()->start();
|
||||
Reduction const r = Reduce(
|
||||
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineValueOf, 1),
|
||||
input, context, effect, control));
|
||||
ASSERT_TRUE(r.Changed());
|
||||
|
||||
Node* phi = r.replacement();
|
||||
Capture<Node*> branch0, if_false0, branch1, if_true1;
|
||||
EXPECT_THAT(
|
||||
phi,
|
||||
IsPhi(
|
||||
kMachAnyTagged, input,
|
||||
IsPhi(kMachAnyTagged, IsLoadField(AccessBuilder::ForValue(), input,
|
||||
effect, CaptureEq(&if_true1)),
|
||||
input,
|
||||
IsMerge(
|
||||
AllOf(CaptureEq(&if_true1), IsIfTrue(CaptureEq(&branch1))),
|
||||
IsIfFalse(AllOf(
|
||||
CaptureEq(&branch1),
|
||||
IsBranch(
|
||||
IsWord32Equal(
|
||||
IsLoadField(
|
||||
AccessBuilder::ForMapInstanceType(),
|
||||
IsLoadField(AccessBuilder::ForMap(), input,
|
||||
effect, CaptureEq(&if_false0)),
|
||||
effect, _),
|
||||
IsInt32Constant(JS_VALUE_TYPE)),
|
||||
CaptureEq(&if_false0)))))),
|
||||
IsMerge(
|
||||
IsIfTrue(AllOf(CaptureEq(&branch0),
|
||||
IsBranch(IsObjectIsSmi(input), control))),
|
||||
AllOf(CaptureEq(&if_false0), IsIfFalse(CaptureEq(&branch0))))));
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -1473,6 +1473,8 @@ IS_UNOP_MATCHER(Float64RoundTruncate)
|
||||
IS_UNOP_MATCHER(Float64RoundTiesAway)
|
||||
IS_UNOP_MATCHER(NumberToInt32)
|
||||
IS_UNOP_MATCHER(NumberToUint32)
|
||||
IS_UNOP_MATCHER(ObjectIsSmi)
|
||||
IS_UNOP_MATCHER(ObjectIsNonNegativeSmi)
|
||||
#undef IS_UNOP_MATCHER
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -131,6 +131,8 @@ Matcher<Node*> IsStoreElement(const Matcher<ElementAccess>& access_matcher,
|
||||
const Matcher<Node*>& value_matcher,
|
||||
const Matcher<Node*>& effect_matcher,
|
||||
const Matcher<Node*>& control_matcher);
|
||||
Matcher<Node*> IsObjectIsSmi(const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsObjectIsNonNegativeSmi(const Matcher<Node*>& value_matcher);
|
||||
|
||||
Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
|
||||
const Matcher<Node*>& base_matcher,
|
||||
|
@ -51,6 +51,7 @@
|
||||
'compiler/instruction-sequence-unittest.cc',
|
||||
'compiler/instruction-sequence-unittest.h',
|
||||
'compiler/js-builtin-reducer-unittest.cc',
|
||||
'compiler/js-intrinsic-lowering-unittest.cc',
|
||||
'compiler/js-operator-unittest.cc',
|
||||
'compiler/js-typed-lowering-unittest.cc',
|
||||
'compiler/load-elimination-unittest.cc',
|
||||
|
@ -466,8 +466,8 @@
|
||||
'../../src/compiler/js-graph.h',
|
||||
'../../src/compiler/js-inlining.cc',
|
||||
'../../src/compiler/js-inlining.h',
|
||||
'../../src/compiler/js-intrinsic-builder.cc',
|
||||
'../../src/compiler/js-intrinsic-builder.h',
|
||||
'../../src/compiler/js-intrinsic-lowering.cc',
|
||||
'../../src/compiler/js-intrinsic-lowering.h',
|
||||
'../../src/compiler/js-operator.cc',
|
||||
'../../src/compiler/js-operator.h',
|
||||
'../../src/compiler/js-typed-lowering.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user