Commit eb0e7437 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Introduce DeadValue and DeadEffect operators.

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/1186033006

Cr-Commit-Position: refs/heads/master@{#29104}
parent 7c36a7d9
......@@ -403,7 +403,7 @@ class AstGraphBuilder::FrameStateBeforeAndAfter {
if (count >= 1) {
// Add the frame state for after the operation.
DCHECK_EQ(IrOpcode::kDead,
DCHECK_EQ(IrOpcode::kDeadValue,
NodeProperties::GetFrameStateInput(node, 0)->opcode());
Node* frame_state_after =
......@@ -416,7 +416,7 @@ class AstGraphBuilder::FrameStateBeforeAndAfter {
if (count >= 2) {
// Add the frame state for before the operation.
DCHECK_EQ(IrOpcode::kDead,
DCHECK_EQ(IrOpcode::kDeadValue,
NodeProperties::GetFrameStateInput(node, 1)->opcode());
NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
}
......@@ -3759,8 +3759,7 @@ void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
OutputFrameStateCombine combine) {
if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
DCHECK_EQ(IrOpcode::kDead,
DCHECK_EQ(IrOpcode::kDeadValue,
NodeProperties::GetFrameStateInput(node, 0)->opcode());
NodeProperties::ReplaceFrameStateInput(
node, 0, environment()->Checkpoint(ast_id, combine));
......@@ -3815,9 +3814,9 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
}
for (int i = 0; i < frame_state_count; i++) {
// The frame state will be inserted later. Here we misuse
// the {DeadControl} node as a sentinel to be later overwritten
// the {DeadValue} node as a sentinel to be later overwritten
// with the real frame state.
*current_input++ = jsgraph()->DeadControl();
*current_input++ = jsgraph()->DeadValue();
}
if (has_effect) {
*current_input++ = environment_->GetEffectDependency();
......
......@@ -489,7 +489,7 @@ class AstGraphBuilder::Environment : public ZoneObject {
liveness_block_ = nullptr;
}
bool IsMarkedAsUnreachable() {
return GetControlDependency()->opcode() == IrOpcode::kDead;
return GetControlDependency()->opcode() == IrOpcode::kDeadControl;
}
// Merge another environment into this one.
......
......@@ -116,7 +116,9 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
#define CACHED_OP_LIST(V) \
V(Dead, Operator::kFoldable, 0, 0, 0, 0, 0, 1) \
V(DeadValue, Operator::kPure, 0, 0, 0, 1, 0, 0) \
V(DeadEffect, Operator::kPure, 0, 0, 0, 0, 1, 0) \
V(DeadControl, Operator::kFoldable, 0, 0, 0, 0, 0, 1) \
V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
V(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
......
......@@ -96,7 +96,6 @@ class CommonOperatorBuilder final : public ZoneObject {
public:
explicit CommonOperatorBuilder(Zone* zone);
const Operator* Dead();
const Operator* End(size_t control_input_count);
const Operator* Branch(BranchHint = BranchHint::kNone);
const Operator* IfTrue();
......@@ -111,6 +110,10 @@ class CommonOperatorBuilder final : public ZoneObject {
const Operator* Return();
const Operator* Terminate();
const Operator* DeadValue();
const Operator* DeadEffect();
const Operator* DeadControl();
const Operator* Start(int num_formal_parameters);
const Operator* Loop(int control_input_count);
const Operator* Merge(int control_input_count);
......
......@@ -47,7 +47,7 @@ class ControlReducerImpl final : public AdvancedReducer {
node->opcode() == IrOpcode::kLoop) {
// If a node has only one control input and it is dead, replace with dead.
Node* control = NodeProperties::GetControlInput(node);
if (control->opcode() == IrOpcode::kDead) {
if (control->opcode() == IrOpcode::kDeadControl) {
TRACE("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic());
return Replace(control);
}
......@@ -125,8 +125,10 @@ class ControlReducerImpl final : public AdvancedReducer {
auto const inputs = node->inputs();
for (auto it = inputs.begin(); n > 1; --n, ++it) {
Node* input = *it;
if (input->opcode() == IrOpcode::kDead) continue; // ignore dead inputs.
if (input != node && input != replacement) { // non-redundant input.
// Ignore dead inputs.
if (input->opcode() == IrOpcode::kDeadControl) continue;
// Non-redundant input.
if (input != node && input != replacement) {
if (replacement != NULL) return node;
replacement = input;
}
......@@ -148,7 +150,7 @@ class ControlReducerImpl final : public AdvancedReducer {
int live = 0;
for (int index = 0; index < node->InputCount(); ++index) {
// Skip dead inputs.
if (node->InputAt(index)->opcode() == IrOpcode::kDead) continue;
if (node->InputAt(index)->opcode() == IrOpcode::kDeadControl) continue;
// Compact live inputs.
if (index != live) node->ReplaceInput(live, node->InputAt(index));
++live;
......@@ -174,7 +176,7 @@ class ControlReducerImpl final : public AdvancedReducer {
int index = 0;
int live_index = 0;
for (Node* const input : node->inputs()) {
if (input->opcode() != IrOpcode::kDead) {
if (input->opcode() != IrOpcode::kDeadControl) {
live++;
live_index = index;
}
......@@ -288,7 +290,7 @@ class ControlReducerImpl final : public AdvancedReducer {
int live = 0;
for (int i = 0; i < merge->InputCount(); i++) {
// skip dead inputs.
if (merge->InputAt(i)->opcode() == IrOpcode::kDead) continue;
if (merge->InputAt(i)->opcode() == IrOpcode::kDeadControl) continue;
// compact live inputs.
if (live != i) node->ReplaceInput(live, node->InputAt(i));
live++;
......
......@@ -256,7 +256,7 @@ void GraphVisualizer::PrintNode(Node* node, bool gray) {
os_ << " shape=\"record\"\n";
switch (node->opcode()) {
case IrOpcode::kEnd:
case IrOpcode::kDead:
case IrOpcode::kDeadControl:
case IrOpcode::kStart:
os_ << " style=\"diagonals\"\n";
break;
......
......@@ -203,8 +203,13 @@ Node* JSGraph::EmptyFrameState() {
}
Node* JSGraph::DeadValue() {
return CACHED(kDeadValue, graph()->NewNode(common()->DeadValue()));
}
Node* JSGraph::DeadControl() {
return CACHED(kDeadControl, graph()->NewNode(common()->Dead()));
return CACHED(kDeadControl, graph()->NewNode(common()->DeadControl()));
}
......
......@@ -117,7 +117,10 @@ class JSGraph : public ZoneObject {
// cannot deopt.
Node* EmptyFrameState();
// Create a control node that serves as control dependency for dead nodes.
// Creates a value node that servers as value input for dead nodes.
Node* DeadValue();
// Creates a control node that serves as control dependency for dead nodes.
Node* DeadControl();
JSOperatorBuilder* javascript() const { return javascript_; }
......@@ -142,6 +145,7 @@ class JSGraph : public ZoneObject {
kOneConstant,
kNaNConstant,
kEmptyFrameState,
kDeadValue,
kDeadControl,
kNumCachedNodes // Must remain last.
};
......
......@@ -62,8 +62,8 @@ class JSCallFunctionAccessor {
class CopyVisitor {
public:
CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
: sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "Sentinel", 0, 0,
0, 0, 0, 0),
: sentinel_op_(IrOpcode::kDeadControl, Operator::kNoProperties,
"Sentinel", 0, 0, 0, 0, 0, 0),
sentinel_(target_graph->NewNode(&sentinel_op_)),
copies_(source_graph->NodeCount(), sentinel_, temp_zone),
source_graph_(source_graph),
......
......@@ -212,7 +212,7 @@ PeeledIteration* LoopPeeler::Peel(Graph* graph, CommonOperatorBuilder* common,
5 + (loop->TotalSize() + exits.size() + rets.size()) * 2;
Peeling peeling(graph, tmp_zone, estimated_peeled_size, &iter->node_pairs_);
Node* dead = graph->NewNode(common->Dead());
Node* dead = graph->NewNode(common->DeadControl());
// Map the loop header nodes to their entry values.
for (Node* node : loop_tree->HeaderNodes(loop)) {
......
......@@ -10,7 +10,6 @@
// Opcodes for control operators.
#define CONTROL_OP_LIST(V) \
V(Start) \
V(Dead) \
V(Loop) \
V(Branch) \
V(Switch) \
......@@ -27,6 +26,7 @@
V(Terminate) \
V(OsrNormalEntry) \
V(OsrLoopEntry) \
V(DeadControl) \
V(Throw) \
V(End)
......@@ -57,7 +57,10 @@
#define COMMON_OP_LIST(V) \
CONSTANT_OP_LIST(V) \
INNER_OP_LIST(V)
INNER_OP_LIST(V) \
V(DeadEffect) \
V(DeadValue)
// Opcodes for JavaScript operators.
#define JS_COMPARE_BINOP_LIST(V) \
......@@ -318,7 +321,7 @@ class IrOpcode {
// Returns true if opcode for common operator.
static bool IsCommonOpcode(Value value) {
return kStart <= value && value <= kProjection;
return kStart <= value && value <= kDeadValue;
}
// Returns true if opcode for control operator.
......
......@@ -117,7 +117,7 @@ int OperatorProperties::GetTotalInputCount(const Operator* op) {
bool OperatorProperties::IsBasicBlockBegin(const Operator* op) {
Operator::Opcode const opcode = op->opcode();
return opcode == IrOpcode::kStart || opcode == IrOpcode::kEnd ||
opcode == IrOpcode::kDead || opcode == IrOpcode::kLoop ||
opcode == IrOpcode::kDeadControl || opcode == IrOpcode::kLoop ||
opcode == IrOpcode::kMerge || opcode == IrOpcode::kIfTrue ||
opcode == IrOpcode::kIfFalse || opcode == IrOpcode::kIfSuccess ||
opcode == IrOpcode::kIfException || opcode == IrOpcode::kIfValue ||
......
......@@ -407,7 +407,7 @@ class SourcePositionWrapper final : public Reducer {
class JSGraphReducer final : public GraphReducer {
public:
JSGraphReducer(JSGraph* jsgraph, Zone* zone)
: GraphReducer(zone, jsgraph->graph(), jsgraph->TheHoleConstant(),
: GraphReducer(zone, jsgraph->graph(), jsgraph->DeadValue(),
jsgraph->DeadControl()) {}
~JSGraphReducer() final {}
};
......
......@@ -497,7 +497,7 @@ class RepresentationSelector {
// Common operators.
//------------------------------------------------------------------
case IrOpcode::kStart:
case IrOpcode::kDead:
case IrOpcode::kDeadControl:
return VisitLeaf(node, 0);
case IrOpcode::kParameter: {
// TODO(titzer): use representation from linkage.
......
......@@ -253,7 +253,6 @@ class Typer::Visitor : public Reducer {
#undef DECLARE_CASE
#define DECLARE_CASE(x) case IrOpcode::k##x:
DECLARE_CASE(Dead)
DECLARE_CASE(Loop)
DECLARE_CASE(Branch)
DECLARE_CASE(IfTrue)
......@@ -269,6 +268,7 @@ class Typer::Visitor : public Reducer {
DECLARE_CASE(Terminate)
DECLARE_CASE(OsrNormalEntry)
DECLARE_CASE(OsrLoopEntry)
DECLARE_CASE(DeadControl)
DECLARE_CASE(Throw)
DECLARE_CASE(End)
#undef DECLARE_CASE
......@@ -298,7 +298,6 @@ class Typer::Visitor : public Reducer {
#undef DECLARE_CASE
#define DECLARE_CASE(x) case IrOpcode::k##x:
DECLARE_CASE(Dead)
DECLARE_CASE(Loop)
DECLARE_CASE(Branch)
DECLARE_CASE(IfTrue)
......@@ -314,6 +313,7 @@ class Typer::Visitor : public Reducer {
DECLARE_CASE(Terminate)
DECLARE_CASE(OsrNormalEntry)
DECLARE_CASE(OsrLoopEntry)
DECLARE_CASE(DeadControl)
DECLARE_CASE(Throw)
DECLARE_CASE(End)
#undef DECLARE_CASE
......@@ -742,6 +742,17 @@ Bounds Typer::Visitor::TypeFinish(Node* node) {
}
Bounds Typer::Visitor::TypeDeadValue(Node* node) {
return Bounds(Type::None(zone()), Type::Any(zone()));
}
Bounds Typer::Visitor::TypeDeadEffect(Node* node) {
UNREACHABLE();
return Bounds();
}
Bounds Typer::Visitor::TypeFrameState(Node* node) {
// TODO(rossberg): Ideally FrameState wouldn't have a value output.
return Bounds(Type::None(zone()), Type::Internal(zone()));
......
......@@ -192,7 +192,9 @@ void Verifier::Visitor::Check(Node* node) {
// Type is empty.
CheckNotTyped(node);
break;
case IrOpcode::kDead:
case IrOpcode::kDeadValue:
case IrOpcode::kDeadEffect:
case IrOpcode::kDeadControl:
// Dead is never connected to the graph.
// TODO(mstarzinger): Make the GraphReducer immediately perform control
// reduction in case control is killed. This will prevent {Dead} from
......
......@@ -75,7 +75,7 @@ class ControlReducerTester : HandleAndZoneScope {
one(jsgraph.OneConstant()),
half(jsgraph.Constant(0.5)),
self(graph.NewNode(common.Int32Constant(0xaabbccdd))),
dead(graph.NewNode(common.Dead())) {
dead(graph.NewNode(common.DeadControl())) {
graph.SetEnd(end);
graph.SetStart(start);
leaf[0] = zero;
......@@ -185,12 +185,16 @@ class ControlReducerTester : HandleAndZoneScope {
if (use->opcode() == IrOpcode::kIfTrue) {
Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use);
if (expected == kTrue) CHECK_EQ(control, result);
if (expected == kFalse) CHECK_EQ(IrOpcode::kDead, result->opcode());
if (expected == kFalse) {
CHECK_EQ(IrOpcode::kDeadControl, result->opcode());
}
if (expected == kUnknown) CHECK_EQ(use, result);
} else if (use->opcode() == IrOpcode::kIfFalse) {
Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use);
if (expected == kFalse) CHECK_EQ(control, result);
if (expected == kTrue) CHECK_EQ(IrOpcode::kDead, result->opcode());
if (expected == kTrue) {
CHECK_EQ(IrOpcode::kDeadControl, result->opcode());
}
if (expected == kUnknown) CHECK_EQ(use, result);
} else {
UNREACHABLE();
......@@ -793,7 +797,7 @@ TEST(CMergeReduce_exhaustive_4) {
int count = selector.count;
if (count == 0) {
// result should be dead.
CHECK_EQ(IrOpcode::kDead, result->opcode());
CHECK_EQ(IrOpcode::kDeadControl, result->opcode());
} else if (count == 1) {
// merge should be replaced with one of the controls.
CHECK_EQ(controls[selector.single_index()], result);
......
......@@ -47,7 +47,7 @@ class LoopFinderTester : HandleAndZoneScope {
one(jsgraph.OneConstant()),
half(jsgraph.Constant(0.5)),
self(graph.NewNode(common.Int32Constant(0xaabbccdd))),
dead(graph.NewNode(common.Dead())),
dead(graph.NewNode(common.DeadControl())),
loop_tree(NULL) {
graph.SetEnd(end);
graph.SetStart(start);
......
......@@ -48,13 +48,15 @@ const SharedOperator kSharedOperators[] = {
value_input_count, effect_input_count, control_input_count, \
value_output_count, effect_output_count, control_output_count \
}
SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 0, 1),
SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
SHARED(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1),
SHARED(Return, Operator::kNoThrow, 1, 1, 1, 0, 0, 1),
SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)
SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1),
SHARED(DeadValue, Operator::kPure, 0, 0, 0, 1, 0, 0),
SHARED(DeadEffect, Operator::kPure, 0, 0, 0, 0, 1, 0),
SHARED(DeadControl, Operator::kFoldable, 0, 0, 0, 0, 0, 1)
#undef SHARED
};
......
......@@ -275,11 +275,11 @@ struct ReplaceWithValueReducer final : public AdvancedReducer {
using AdvancedReducer::ReplaceWithValue;
};
const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
const Operator kMockOperator(IrOpcode::kDeadControl, Operator::kNoProperties,
"MockOperator", 0, 0, 0, 1, 0, 0);
const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties,
const Operator kMockOpEffect(IrOpcode::kDeadControl, Operator::kNoProperties,
"MockOpEffect", 0, 1, 0, 1, 1, 0);
const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties,
const Operator kMockOpControl(IrOpcode::kDeadControl, Operator::kNoProperties,
"MockOpControl", 0, 0, 1, 1, 0, 1);
const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught;
......
......@@ -32,10 +32,10 @@ class GraphTrimmerTest : public GraphTest {
namespace {
const Operator kDead0(IrOpcode::kDead, Operator::kNoProperties, "Dead0", 0, 0,
1, 0, 0, 0);
const Operator kLive0(IrOpcode::kDead, Operator::kNoProperties, "Live0", 0, 0,
1, 0, 0, 1);
const Operator kDead0(IrOpcode::kDeadControl, Operator::kNoProperties, "Dead0",
0, 0, 1, 0, 0, 0);
const Operator kLive0(IrOpcode::kDeadControl, Operator::kNoProperties, "Live0",
0, 0, 1, 0, 0, 1);
} // namespace
......
......@@ -32,7 +32,7 @@ class NodePropertiesTest : public TestWithZone {
namespace {
const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
const Operator kMockOperator(IrOpcode::kDeadControl, Operator::kNoProperties,
"MockOperator", 0, 0, 0, 1, 1, 2);
const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties,
"MockCallOperator", 0, 0, 0, 0, 0, 2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment