Revert "[turbofan] add value input to DeadValue" and "[turbofan] add regression test for chromium:796041"
This reverts https://chromium-review.googlesource.com/c/v8/v8/+/848995 and https://chromium-review.googlesource.com/c/v8/v8/+/847011 Bug: chromium:798938 Change-Id: I4be8e5bca77037a278fd9882f0d76de1ae12c23f TBR: jarin@chromium.org Reviewed-on: https://chromium-review.googlesource.com/849995 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#50356}
This commit is contained in:
parent
4b107b9ec9
commit
9e2d001e86
@ -348,7 +348,8 @@ ZoneVector<MachineType> const* MachineTypesOf(Operator const* op) {
|
||||
|
||||
#define COMMON_CACHED_OP_LIST(V) \
|
||||
V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \
|
||||
V(Unreachable, Operator::kFoldable, 0, 1, 1, 1, 1, 0) \
|
||||
V(DeadValue, Operator::kFoldable, 0, 0, 0, 1, 0, 0) \
|
||||
V(Unreachable, Operator::kFoldable, 0, 1, 1, 0, 1, 0) \
|
||||
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) \
|
||||
@ -1285,11 +1286,6 @@ uint32_t ObjectIdOf(Operator const* op) {
|
||||
}
|
||||
}
|
||||
|
||||
MachineRepresentation DeadValueRepresentationOf(Operator const* op) {
|
||||
DCHECK_EQ(IrOpcode::kDeadValue, op->opcode());
|
||||
return OpParameter<MachineRepresentation>(op);
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::FrameState(
|
||||
BailoutId bailout_id, OutputFrameStateCombine state_combine,
|
||||
const FrameStateFunctionInfo* function_info) {
|
||||
@ -1405,14 +1401,6 @@ CommonOperatorBuilder::CreateFrameStateFunctionInfo(
|
||||
FrameStateFunctionInfo(type, parameter_count, local_count, shared_info);
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::DeadValue(MachineRepresentation rep) {
|
||||
return new (zone()) Operator1<MachineRepresentation>( // --
|
||||
IrOpcode::kDeadValue, Operator::kPure, // opcode
|
||||
"DeadValue", // name
|
||||
1, 0, 0, 1, 0, 0, // counts
|
||||
rep); // parameter
|
||||
}
|
||||
|
||||
#undef COMMON_CACHED_OP_LIST
|
||||
#undef CACHED_RETURN_LIST
|
||||
#undef CACHED_END_LIST
|
||||
|
@ -342,8 +342,6 @@ ArgumentsStateType ArgumentsStateTypeOf(Operator const*) WARN_UNUSED_RESULT;
|
||||
|
||||
uint32_t ObjectIdOf(Operator const*);
|
||||
|
||||
MachineRepresentation DeadValueRepresentationOf(Operator const*);
|
||||
|
||||
// Interface for building common operators that can be used at any level of IR,
|
||||
// including JavaScript, mid-level, and low-level.
|
||||
class V8_EXPORT_PRIVATE CommonOperatorBuilder final
|
||||
@ -352,7 +350,7 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final
|
||||
explicit CommonOperatorBuilder(Zone* zone);
|
||||
|
||||
const Operator* Dead();
|
||||
const Operator* DeadValue(MachineRepresentation rep);
|
||||
const Operator* DeadValue();
|
||||
const Operator* Unreachable();
|
||||
const Operator* End(size_t control_input_count);
|
||||
const Operator* Branch(BranchHint = BranchHint::kNone);
|
||||
|
@ -21,8 +21,10 @@ DeadCodeElimination::DeadCodeElimination(Editor* editor, Graph* graph,
|
||||
graph_(graph),
|
||||
common_(common),
|
||||
dead_(graph->NewNode(common->Dead())),
|
||||
dead_value_(graph->NewNode(common->DeadValue())),
|
||||
zone_(temp_zone) {
|
||||
NodeProperties::SetType(dead_, Type::None());
|
||||
NodeProperties::SetType(dead_value_, Type::None());
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -36,11 +38,11 @@ bool NoReturn(Node* node) {
|
||||
NodeProperties::GetTypeOrAny(node)->IsNone();
|
||||
}
|
||||
|
||||
Node* FindDeadInput(Node* node) {
|
||||
bool HasDeadInput(Node* node) {
|
||||
for (Node* input : node->inputs()) {
|
||||
if (NoReturn(input)) return input;
|
||||
if (NoReturn(input)) return true;
|
||||
}
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -207,27 +209,17 @@ Reduction DeadCodeElimination::ReducePhi(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kPhi, node->opcode());
|
||||
Reduction reduction = PropagateDeadControl(node);
|
||||
if (reduction.Changed()) return reduction;
|
||||
MachineRepresentation rep = PhiRepresentationOf(node->op());
|
||||
if (rep == MachineRepresentation::kNone ||
|
||||
if (PhiRepresentationOf(node->op()) == MachineRepresentation::kNone ||
|
||||
NodeProperties::GetTypeOrAny(node)->IsNone()) {
|
||||
return Replace(DeadValue(node, rep));
|
||||
}
|
||||
int input_count = node->op()->ValueInputCount();
|
||||
for (int i = 0; i < input_count; ++i) {
|
||||
Node* input = NodeProperties::GetValueInput(node, i);
|
||||
if (input->opcode() == IrOpcode::kDeadValue &&
|
||||
DeadValueRepresentationOf(input->op()) != rep) {
|
||||
NodeProperties::ReplaceValueInput(node, DeadValue(input, rep), i);
|
||||
}
|
||||
return Replace(dead_value());
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction DeadCodeElimination::ReducePureNode(Node* node) {
|
||||
DCHECK_EQ(0, node->op()->EffectInputCount());
|
||||
if (node->opcode() == IrOpcode::kDeadValue) return NoChange();
|
||||
if (Node* input = FindDeadInput(node)) {
|
||||
return Replace(DeadValue(input));
|
||||
if (HasDeadInput(node)) {
|
||||
return Replace(dead_value());
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
@ -242,7 +234,8 @@ Reduction DeadCodeElimination::ReduceUnreachableOrIfException(Node* node) {
|
||||
return Replace(effect);
|
||||
}
|
||||
if (effect->opcode() == IrOpcode::kUnreachable) {
|
||||
return Replace(effect);
|
||||
RelaxEffectsAndControls(node);
|
||||
return Replace(dead_value());
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
@ -253,10 +246,10 @@ Reduction DeadCodeElimination::ReduceEffectNode(Node* node) {
|
||||
if (effect->opcode() == IrOpcode::kDead) {
|
||||
return Replace(effect);
|
||||
}
|
||||
if (Node* input = FindDeadInput(node)) {
|
||||
if (HasDeadInput(node)) {
|
||||
if (effect->opcode() == IrOpcode::kUnreachable) {
|
||||
RelaxEffectsAndControls(node);
|
||||
return Replace(DeadValue(input));
|
||||
return Replace(dead_value());
|
||||
}
|
||||
|
||||
Node* control = node->op()->ControlInputCount() == 1
|
||||
@ -264,8 +257,7 @@ Reduction DeadCodeElimination::ReduceEffectNode(Node* node) {
|
||||
: graph()->start();
|
||||
Node* unreachable =
|
||||
graph()->NewNode(common()->Unreachable(), effect, control);
|
||||
NodeProperties::SetType(unreachable, Type::None());
|
||||
ReplaceWithValue(node, DeadValue(input), node, control);
|
||||
ReplaceWithValue(node, dead_value(), node, control);
|
||||
return Replace(unreachable);
|
||||
}
|
||||
|
||||
@ -278,12 +270,11 @@ Reduction DeadCodeElimination::ReduceDeoptimizeOrReturnOrTerminate(Node* node) {
|
||||
node->opcode() == IrOpcode::kTerminate);
|
||||
Reduction reduction = PropagateDeadControl(node);
|
||||
if (reduction.Changed()) return reduction;
|
||||
if (FindDeadInput(node) != nullptr) {
|
||||
if (HasDeadInput(node)) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node, 0);
|
||||
Node* control = NodeProperties::GetControlInput(node, 0);
|
||||
if (effect->opcode() != IrOpcode::kUnreachable) {
|
||||
effect = graph()->NewNode(common()->Unreachable(), effect, control);
|
||||
NodeProperties::SetType(effect, Type::None());
|
||||
}
|
||||
node->TrimInputCount(2);
|
||||
node->ReplaceInput(0, effect);
|
||||
@ -331,16 +322,6 @@ void DeadCodeElimination::TrimMergeOrPhi(Node* node, int size) {
|
||||
NodeProperties::ChangeOp(node, op);
|
||||
}
|
||||
|
||||
Node* DeadCodeElimination::DeadValue(Node* node, MachineRepresentation rep) {
|
||||
if (node->opcode() == IrOpcode::kDeadValue) {
|
||||
if (rep == DeadValueRepresentationOf(node->op())) return node;
|
||||
node = NodeProperties::GetValueInput(node, 0);
|
||||
}
|
||||
Node* dead_value = graph()->NewNode(common()->DeadValue(rep), node);
|
||||
NodeProperties::SetType(dead_value, Type::None());
|
||||
return dead_value;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/compiler/graph-reducer.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/machine-type.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -18,23 +17,13 @@ namespace compiler {
|
||||
class CommonOperatorBuilder;
|
||||
|
||||
// Propagates {Dead} control and {DeadValue} values through the graph and
|
||||
// thereby removes dead code.
|
||||
// We detect dead values based on types, replacing uses of nodes with
|
||||
// {Type::None()} with {DeadValue}. A pure node (other than a phi) using
|
||||
// {DeadValue} is replaced by {DeadValue}. When {DeadValue} hits the effect
|
||||
// chain, a crashing {Unreachable} node is inserted and the rest of the effect
|
||||
// chain is collapsed. We wait for the {EffectControlLinearizer} to connect
|
||||
// {Unreachable} nodes to the graph end, since this is much easier if there is
|
||||
// no floating control.
|
||||
// {DeadValue} has an input, which has to have {Type::None()}. This input is
|
||||
// important to maintain the dependency on the cause of the unreachable code.
|
||||
// {Unreachable} has a value output and {Type::None()} so it can be used by
|
||||
// {DeadValue}.
|
||||
// {DeadValue} nodes track a {MachineRepresentation} so they can be lowered to a
|
||||
// value-producing node. {DeadValue} has the runtime semantics of crashing and
|
||||
// behaves like a constant of its representation so it can be used in gap moves.
|
||||
// Since phi nodes are the only remaining use of {DeadValue}, this
|
||||
// representation is only adjusted for uses by phi nodes.
|
||||
// thereby removes dead code. When {DeadValue} hits the effect chain, a crashing
|
||||
// {Unreachable} node is inserted and the rest of the effect chain is collapsed.
|
||||
// We wait for the {EffectControlLinearizer} to connect {Unreachable} nodes to
|
||||
// the graph end, since this is much easier if there is no floating control.
|
||||
// We detect dead values based on types, pruning uses of DeadValue except for
|
||||
// uses by phi. These remaining uses are eliminated in the
|
||||
// {EffectControlLinearizer}, where they are replaced with dummy values.
|
||||
// In contrast to {DeadValue}, {Dead} can never remain in the graph.
|
||||
class V8_EXPORT_PRIVATE DeadCodeElimination final
|
||||
: public NON_EXPORTED_BASE(AdvancedReducer) {
|
||||
@ -64,16 +53,15 @@ class V8_EXPORT_PRIVATE DeadCodeElimination final
|
||||
|
||||
void TrimMergeOrPhi(Node* node, int size);
|
||||
|
||||
Node* DeadValue(Node* none_node,
|
||||
MachineRepresentation rep = MachineRepresentation::kNone);
|
||||
|
||||
Graph* graph() const { return graph_; }
|
||||
CommonOperatorBuilder* common() const { return common_; }
|
||||
Node* dead() const { return dead_; }
|
||||
Node* dead_value() const { return dead_value_; }
|
||||
|
||||
Graph* const graph_;
|
||||
CommonOperatorBuilder* const common_;
|
||||
Node* const dead_;
|
||||
Node* const dead_value_;
|
||||
Zone* zone_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DeadCodeElimination);
|
||||
|
@ -318,6 +318,28 @@ void TryCloneBranch(Node* node, BasicBlock* block, Zone* temp_zone,
|
||||
merge->Kill();
|
||||
}
|
||||
|
||||
Node* DummyValue(JSGraph* jsgraph, MachineRepresentation rep) {
|
||||
switch (rep) {
|
||||
case MachineRepresentation::kTagged:
|
||||
case MachineRepresentation::kTaggedSigned:
|
||||
return jsgraph->SmiConstant(0xDEAD);
|
||||
case MachineRepresentation::kTaggedPointer:
|
||||
return jsgraph->TheHoleConstant();
|
||||
case MachineRepresentation::kWord64:
|
||||
return jsgraph->Int64Constant(0xDEAD);
|
||||
case MachineRepresentation::kWord32:
|
||||
return jsgraph->Int32Constant(0xDEAD);
|
||||
case MachineRepresentation::kFloat64:
|
||||
return jsgraph->Float64Constant(0xDEAD);
|
||||
case MachineRepresentation::kFloat32:
|
||||
return jsgraph->Float32Constant(0xDEAD);
|
||||
case MachineRepresentation::kBit:
|
||||
return jsgraph->Int32Constant(0);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void EffectControlLinearizer::Run() {
|
||||
@ -347,6 +369,7 @@ void EffectControlLinearizer::Run() {
|
||||
// Iterate over the phis and update the effect phis.
|
||||
Node* effect_phi = nullptr;
|
||||
Node* terminate = nullptr;
|
||||
int predecessor_count = static_cast<int>(block->PredecessorCount());
|
||||
for (; instr < block->NodeCount(); instr++) {
|
||||
Node* node = block->NodeAt(instr);
|
||||
// Only go through the phis and effect phis.
|
||||
@ -357,7 +380,19 @@ void EffectControlLinearizer::Run() {
|
||||
DCHECK_NE(IrOpcode::kIfException, control->opcode());
|
||||
effect_phi = node;
|
||||
} else if (node->opcode() == IrOpcode::kPhi) {
|
||||
// Just skip phis.
|
||||
DCHECK_EQ(predecessor_count, node->op()->ValueInputCount());
|
||||
for (int i = 0; i < predecessor_count; ++i) {
|
||||
if (NodeProperties::GetValueInput(node, i)->opcode() ==
|
||||
IrOpcode::kDeadValue) {
|
||||
// Phi uses of {DeadValue} must originate from unreachable code. Due
|
||||
// to schedule freedom between the effect and the control chain,
|
||||
// they might still appear in reachable code. So we replace them
|
||||
// with a dummy value.
|
||||
NodeProperties::ReplaceValueInput(
|
||||
node, DummyValue(jsgraph(), PhiRepresentationOf(node->op())),
|
||||
i);
|
||||
}
|
||||
}
|
||||
} else if (node->opcode() == IrOpcode::kTerminate) {
|
||||
DCHECK_NULL(terminate);
|
||||
terminate = node;
|
||||
|
@ -251,23 +251,6 @@ class OperandGenerator {
|
||||
return Constant(OpParameter<ExternalReference>(node));
|
||||
case IrOpcode::kHeapConstant:
|
||||
return Constant(OpParameter<Handle<HeapObject>>(node));
|
||||
case IrOpcode::kDeadValue: {
|
||||
switch (DeadValueRepresentationOf(node->op())) {
|
||||
case MachineRepresentation::kBit:
|
||||
case MachineRepresentation::kWord32:
|
||||
case MachineRepresentation::kTagged:
|
||||
case MachineRepresentation::kTaggedSigned:
|
||||
case MachineRepresentation::kTaggedPointer:
|
||||
return Constant(static_cast<int32_t>(0));
|
||||
case MachineRepresentation::kFloat64:
|
||||
return Constant(static_cast<double>(0));
|
||||
case MachineRepresentation::kFloat32:
|
||||
return Constant(static_cast<float>(0));
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1147,9 +1147,6 @@ void InstructionSelector::VisitNode(Node* node) {
|
||||
case IrOpcode::kUnreachable:
|
||||
VisitUnreachable(node);
|
||||
return;
|
||||
case IrOpcode::kDeadValue:
|
||||
VisitDeadValue(node);
|
||||
return;
|
||||
case IrOpcode::kComment:
|
||||
VisitComment(node);
|
||||
return;
|
||||
@ -2623,12 +2620,6 @@ void InstructionSelector::VisitUnreachable(Node* node) {
|
||||
Emit(kArchDebugBreak, g.NoOutput());
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitDeadValue(Node* node) {
|
||||
OperandGenerator g(this);
|
||||
MarkAsRepresentation(DeadValueRepresentationOf(node->op()), node);
|
||||
Emit(kArchDebugBreak, g.DefineAsConstant(node));
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitComment(Node* node) {
|
||||
OperandGenerator g(this);
|
||||
InstructionOperand operand(g.UseImmediate(node));
|
||||
|
@ -352,7 +352,6 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
|
||||
void VisitThrow(Node* node);
|
||||
void VisitRetain(Node* node);
|
||||
void VisitUnreachable(Node* node);
|
||||
void VisitDeadValue(Node* node);
|
||||
|
||||
void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments,
|
||||
const CallDescriptor* descriptor, Node* node);
|
||||
|
@ -305,6 +305,10 @@ Node* JSGraph::Dead() {
|
||||
return CACHED(kDead, graph()->NewNode(common()->Dead()));
|
||||
}
|
||||
|
||||
Node* JSGraph::DeadValue() {
|
||||
return CACHED(kDeadValue, graph()->NewNode(common()->DeadValue()));
|
||||
}
|
||||
|
||||
void JSGraph::GetCachedNodes(NodeVector* nodes) {
|
||||
cache_.GetCachedNodes(nodes);
|
||||
for (size_t i = 0; i < arraysize(cached_nodes_); i++) {
|
||||
|
@ -155,6 +155,9 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
// Create a control node that serves as dependency for dead nodes.
|
||||
Node* Dead();
|
||||
|
||||
// Sentinel for a value resulting from unreachable computations.
|
||||
Node* DeadValue();
|
||||
|
||||
CommonOperatorBuilder* common() const { return common_; }
|
||||
JSOperatorBuilder* javascript() const { return javascript_; }
|
||||
SimplifiedOperatorBuilder* simplified() const { return simplified_; }
|
||||
@ -196,6 +199,7 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
kEmptyStateValues,
|
||||
kSingleDeadTypedStateValues,
|
||||
kDead,
|
||||
kDeadValue,
|
||||
kNumCachedNodes // Must remain last.
|
||||
};
|
||||
|
||||
|
@ -216,9 +216,7 @@ Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
|
||||
const Operator* op;
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedSigned),
|
||||
node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (IsWord(output_rep)) {
|
||||
if (output_type->Is(Type::Signed31())) {
|
||||
op = simplified()->ChangeInt31ToTaggedSigned();
|
||||
@ -338,9 +336,7 @@ Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
|
||||
Operator const* op;
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
|
||||
node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (output_rep == MachineRepresentation::kBit) {
|
||||
if (output_type->Is(Type::Boolean())) {
|
||||
op = simplified()->ChangeBitToTagged();
|
||||
@ -417,8 +413,7 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
|
||||
const Operator* op;
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (output_rep == MachineRepresentation::kBit) {
|
||||
if (output_type->Is(Type::Boolean())) {
|
||||
op = simplified()->ChangeBitToTagged();
|
||||
@ -496,8 +491,7 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
|
||||
const Operator* op = nullptr;
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (IsWord(output_rep)) {
|
||||
if (output_type->Is(Type::Signed32())) {
|
||||
// int32 -> float64 -> float32
|
||||
@ -557,8 +551,7 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
|
||||
const Operator* op = nullptr;
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (IsWord(output_rep)) {
|
||||
if (output_type->Is(Type::Signed32())) {
|
||||
op = machine()->ChangeInt32ToFloat64();
|
||||
@ -635,8 +628,7 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
const Operator* op = nullptr;
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (output_rep == MachineRepresentation::kBit) {
|
||||
return node; // Sloppy comparison -> word32
|
||||
} else if (output_rep == MachineRepresentation::kFloat64) {
|
||||
@ -775,8 +767,7 @@ Node* RepresentationChanger::GetBitRepresentationFor(
|
||||
const Operator* op;
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (output_rep == MachineRepresentation::kTagged ||
|
||||
output_rep == MachineRepresentation::kTaggedPointer) {
|
||||
if (output_type->Is(Type::BooleanOrNullOrUndefined())) {
|
||||
@ -821,8 +812,7 @@ Node* RepresentationChanger::GetWord64RepresentationFor(
|
||||
Node* node, MachineRepresentation output_rep, Type* output_type) {
|
||||
if (output_type->Is(Type::None())) {
|
||||
// This is an impossible value; it should not be used at runtime.
|
||||
return jsgraph()->graph()->NewNode(
|
||||
jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
|
||||
return jsgraph()->DeadValue();
|
||||
} else if (output_rep == MachineRepresentation::kBit) {
|
||||
return node; // Sloppy comparison -> word64
|
||||
}
|
||||
|
@ -965,7 +965,7 @@ Type* Typer::Visitor::TypeDead(Node* node) { return Type::None(); }
|
||||
|
||||
Type* Typer::Visitor::TypeDeadValue(Node* node) { return Type::None(); }
|
||||
|
||||
Type* Typer::Visitor::TypeUnreachable(Node* node) { return Type::None(); }
|
||||
Type* Typer::Visitor::TypeUnreachable(Node* node) { UNREACHABLE(); }
|
||||
|
||||
// JS comparison operators.
|
||||
|
||||
|
@ -236,19 +236,10 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
|
||||
// Dead is never connected to the graph.
|
||||
UNREACHABLE();
|
||||
case IrOpcode::kDeadValue:
|
||||
CheckValueInputIs(node, 0, Type::None());
|
||||
CheckTypeIs(node, Type::None());
|
||||
break;
|
||||
case IrOpcode::kUnreachable:
|
||||
CheckTypeIs(node, Type::None());
|
||||
for (Edge edge : node->use_edges()) {
|
||||
Node* use = edge.from();
|
||||
if (NodeProperties::IsValueEdge(edge) && all.IsLive(use)) {
|
||||
// {Unreachable} nodes can only be used by {DeadValue}, because they
|
||||
// don't actually produce a value.
|
||||
CHECK_EQ(IrOpcode::kDeadValue, use->opcode());
|
||||
}
|
||||
}
|
||||
CheckNotTyped(node);
|
||||
break;
|
||||
case IrOpcode::kBranch: {
|
||||
// Branch uses are IfTrue and IfFalse.
|
||||
|
@ -1,35 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
'use strict';
|
||||
|
||||
function f(abort, n, a, b) {
|
||||
if (abort) return;
|
||||
var x = a ? true : "" + a;
|
||||
if (!a) {
|
||||
var dead = n + 1 + 1;
|
||||
if(!b) {
|
||||
x = dead;
|
||||
}
|
||||
if (x) {
|
||||
x = false;
|
||||
}
|
||||
if (b) {
|
||||
x = false;
|
||||
}
|
||||
}
|
||||
return x + 1;
|
||||
}
|
||||
f(false, 5); f(false, 6); f(false, 7); f(false, 8);
|
||||
|
||||
function g(abort, a, b) {
|
||||
return f(abort, "abc", a, b);
|
||||
}
|
||||
|
||||
g(true); g(true); g(true); g(true);
|
||||
|
||||
%OptimizeFunctionOnNextCall(g);
|
||||
g(false);
|
Loading…
Reference in New Issue
Block a user