Commit c5a71f02 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Turn common Guard operator into simplified TypeGuard.

The type guard should never be used after the effect/control
linearization pass, so making it a simplified operator better
expresses the intended use. Also this way none of the common
operators actually has any dependency on the type system.

Drive-by-fix: Properly print the type parameter to a TypeGuard operator.

BUG=chromium:612142
R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/1994503002
Cr-Commit-Position: refs/heads/master@{#36304}
parent 529e3332
......@@ -70,8 +70,6 @@ Reduction CommonOperatorReducer::Reduce(Node* node) {
return ReduceReturn(node);
case IrOpcode::kSelect:
return ReduceSelect(node);
case IrOpcode::kGuard:
return ReduceGuard(node);
default:
break;
}
......@@ -396,16 +394,6 @@ Reduction CommonOperatorReducer::ReduceSelect(Node* node) {
}
Reduction CommonOperatorReducer::ReduceGuard(Node* node) {
DCHECK_EQ(IrOpcode::kGuard, node->opcode());
Node* const input = NodeProperties::GetValueInput(node, 0);
Type* const input_type = NodeProperties::GetTypeOrAny(input);
Type* const guard_type = OpParameter<Type*>(node);
if (input_type->Is(guard_type)) return Replace(input);
return NoChange();
}
Reduction CommonOperatorReducer::Change(Node* node, Operator const* op,
Node* a) {
node->ReplaceInput(0, a);
......
......@@ -36,7 +36,6 @@ class CommonOperatorReducer final : public AdvancedReducer {
Reduction ReducePhi(Node* node);
Reduction ReduceReturn(Node* node);
Reduction ReduceSelect(Node* node);
Reduction ReduceGuard(Node* node);
Reduction Change(Node* node, Operator const* op, Node* a);
Reduction Change(Node* node, Operator const* op, Node* a, Node* b);
......
......@@ -760,15 +760,6 @@ const Operator* CommonOperatorBuilder::EffectPhi(int effect_input_count) {
}
const Operator* CommonOperatorBuilder::Guard(Type* type) {
return new (zone()) Operator1<Type*>( // --
IrOpcode::kGuard, Operator::kKontrol, // opcode
"Guard", // name
1, 0, 1, 1, 0, 0, // counts
type); // parameter
}
const Operator* CommonOperatorBuilder::StateValues(int arguments) {
switch (arguments) {
#define CACHED_STATE_VALUES(arguments) \
......
......@@ -12,10 +12,6 @@
namespace v8 {
namespace internal {
// Forward declarations.
class Type;
namespace compiler {
// Forward declarations.
......@@ -191,7 +187,6 @@ class CommonOperatorBuilder final : public ZoneObject {
int value_input_count);
const Operator* EffectPhi(int effect_input_count);
const Operator* CheckPoint();
const Operator* Guard(Type* type);
const Operator* BeginRegion();
const Operator* FinishRegion();
const Operator* StateValues(int arguments);
......
......@@ -351,8 +351,8 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect,
Node** control) {
ValueEffectControl state(nullptr, nullptr, nullptr);
switch (node->opcode()) {
case IrOpcode::kGuard:
state = LowerGuard(node, *effect, *control);
case IrOpcode::kTypeGuard:
state = LowerTypeGuard(node, *effect, *control);
break;
case IrOpcode::kChangeBitToTagged:
state = LowerChangeBitToTagged(node, *effect, *control);
......@@ -414,8 +414,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect,
return true;
}
EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::LowerGuard(
Node* node, Node* effect, Node* control) {
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerTypeGuard(Node* node, Node* effect,
Node* control) {
Node* value = node->InputAt(0);
return ValueEffectControl(value, effect, control);
}
......
......@@ -41,7 +41,7 @@ class EffectControlLinearizer {
};
bool TryWireInStateEffect(Node* node, Node** effect, Node** control);
ValueEffectControl LowerGuard(Node* node, Node* effect, Node* control);
ValueEffectControl LowerTypeGuard(Node* node, Node* effect, Node* control);
ValueEffectControl LowerChangeBitToTagged(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerChangeInt31ToTaggedSigned(Node* node, Node* effect,
......
......@@ -712,7 +712,7 @@ bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep,
}
break;
case IrOpcode::kSelect:
case IrOpcode::kGuard:
case IrOpcode::kTypeGuard:
if (SetEscaped(rep)) {
TRACE("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
rep->id(), rep->op()->mnemonic(), use->id(),
......
......@@ -137,7 +137,7 @@ Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
Reduction JSIntrinsicLowering::ReduceDoubleHi(Node* node) {
// Tell the compiler to assume number input.
Node* renamed = graph()->NewNode(common()->Guard(Type::Number()),
Node* renamed = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
node->InputAt(0), graph()->start());
node->ReplaceInput(0, renamed);
return Change(node, machine()->Float64ExtractHighWord32());
......@@ -146,7 +146,7 @@ Reduction JSIntrinsicLowering::ReduceDoubleHi(Node* node) {
Reduction JSIntrinsicLowering::ReduceDoubleLo(Node* node) {
// Tell the compiler to assume number input.
Node* renamed = graph()->NewNode(common()->Guard(Type::Number()),
Node* renamed = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
node->InputAt(0), graph()->start());
node->ReplaceInput(0, renamed);
return Change(node, machine()->Float64ExtractLowWord32());
......
......@@ -305,7 +305,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
this_control =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
this_effect, this_control);
this_value = graph()->NewNode(common()->Guard(Type::Number()),
this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
this_value, this_control);
if (!field_index.is_inobject() || field_index.is_hidden_field() ||
......@@ -348,8 +348,9 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
this_control =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
this_effect, this_control);
this_value = graph()->NewNode(common()->Guard(type_cache_.kSmi),
this_value, this_control);
this_value =
graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi),
this_value, this_control);
} else if (field_type->Is(Type::TaggedPointer())) {
Node* check =
graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
......@@ -690,8 +691,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
graph()->NewNode(simplified()->ObjectIsNumber(), this_index);
this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
frame_state, this_effect, this_control);
this_index = graph()->NewNode(common()->Guard(Type::Number()), this_index,
this_control);
this_index = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
this_index, this_control);
}
// Convert the {index} to an unsigned32 value and check if the result is
......@@ -813,8 +814,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
}
// Rename the result to represent the actual type (not polluted by the
// hole).
this_value = graph()->NewNode(common()->Guard(element_type), this_value,
this_control);
this_value = graph()->NewNode(simplified()->TypeGuard(element_type),
this_value, this_control);
} else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
// Perform the hole check on the result.
Node* check =
......@@ -847,14 +848,14 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
frame_state, this_effect, this_control);
this_value = graph()->NewNode(common()->Guard(type_cache_.kSmi),
this_value = graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi),
this_value, this_control);
} else if (IsFastDoubleElementsKind(elements_kind)) {
Node* check =
graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
frame_state, this_effect, this_control);
this_value = graph()->NewNode(common()->Guard(Type::Number()),
this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
this_value, this_control);
}
this_effect = graph()->NewNode(simplified()->StoreElement(element_access),
......
......@@ -4,7 +4,6 @@
#include "src/compiler/load-elimination.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
......@@ -57,8 +56,8 @@ Reduction LoadElimination::ReduceLoadField(Node* node) {
return Replace(value);
} else {
Node* renamed = graph()->NewNode(
common()->Guard(Type::Intersect(stored_value_type, load_type,
graph()->zone())),
simplified()->TypeGuard(Type::Intersect(
stored_value_type, load_type, graph()->zone())),
value, NodeProperties::GetControlInput(node));
ReplaceWithValue(node, renamed);
return Replace(renamed);
......
......@@ -11,25 +11,26 @@ namespace v8 {
namespace internal {
namespace compiler {
class CommonOperatorBuilder;
class Graph;
class SimplifiedOperatorBuilder;
class LoadElimination final : public AdvancedReducer {
public:
explicit LoadElimination(Editor* editor, Graph* graph,
CommonOperatorBuilder* common)
: AdvancedReducer(editor), graph_(graph), common_(common) {}
SimplifiedOperatorBuilder* simplified)
: AdvancedReducer(editor), graph_(graph), simplified_(simplified) {}
~LoadElimination() final;
Reduction Reduce(Node* node) final;
private:
CommonOperatorBuilder* common() const { return common_; }
Graph* graph() { return graph_; }
SimplifiedOperatorBuilder* simplified() const { return simplified_; }
Graph* graph() const { return graph_; }
Reduction ReduceLoadField(Node* node);
Graph* graph_;
CommonOperatorBuilder* common_;
Graph* const graph_;
SimplifiedOperatorBuilder* const simplified_;
};
} // namespace compiler
......
......@@ -48,7 +48,6 @@
V(Phi) \
V(EffectPhi) \
V(CheckPoint) \
V(Guard) \
V(BeginRegion) \
V(FinishRegion) \
V(FrameState) \
......@@ -220,7 +219,8 @@
V(ObjectIsReceiver) \
V(ObjectIsSmi) \
V(ObjectIsString) \
V(ObjectIsUndetectable)
V(ObjectIsUndetectable) \
V(TypeGuard)
// Opcodes for Machine-level operators.
#define MACHINE_COMPARE_BINOP_LIST(V) \
......
......@@ -864,7 +864,7 @@ struct TypedLoweringPhase {
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common());
LoadElimination load_elimination(&graph_reducer, data->graph(),
data->common());
data->jsgraph()->simplified());
JSBuiltinReducer builtin_reducer(&graph_reducer, data->jsgraph());
MaybeHandle<LiteralsArray> literals_array =
data->info()->is_native_context_specializing()
......
......@@ -8,6 +8,7 @@
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/operator-properties.h"
#include "src/compiler/simplified-operator.h"
#include "src/conversions-inl.h"
#include "src/type-cache.h"
......@@ -121,6 +122,8 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
}
case IrOpcode::kReferenceEqual:
return ReduceReferenceEqual(node);
case IrOpcode::kTypeGuard:
return ReduceTypeGuard(node);
default:
break;
}
......@@ -143,6 +146,14 @@ Reduction SimplifiedOperatorReducer::ReduceReferenceEqual(Node* node) {
return NoChange();
}
Reduction SimplifiedOperatorReducer::ReduceTypeGuard(Node* node) {
DCHECK_EQ(IrOpcode::kTypeGuard, node->opcode());
Node* const input = NodeProperties::GetValueInput(node, 0);
Type* const input_type = NodeProperties::GetTypeOrAny(input);
Type* const guard_type = TypeOf(node->op());
if (input_type->Is(guard_type)) return Replace(input);
return NoChange();
}
Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
Node* a) {
......
......@@ -30,6 +30,7 @@ class SimplifiedOperatorReducer final : public Reducer {
private:
Reduction ReduceReferenceEqual(Node* node);
Reduction ReduceTypeGuard(Node* node);
Reduction Change(Node* node, const Operator* op, Node* a);
Reduction ReplaceFloat64(double value);
......
......@@ -172,6 +172,11 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
return OpParameter<ElementAccess>(op);
}
Type* TypeOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode());
return OpParameter<Type*>(op);
}
#define PURE_OP_LIST(V) \
V(BooleanNot, Operator::kNoProperties, 1) \
V(BooleanToNumber, Operator::kNoProperties, 1) \
......@@ -282,6 +287,22 @@ const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
"ReferenceEqual", 2, 0, 0, 1, 0, 0);
}
const Operator* SimplifiedOperatorBuilder::TypeGuard(Type* type) {
class TypeGuardOperator final : public Operator1<Type*> {
public:
explicit TypeGuardOperator(Type* type)
: Operator1<Type*>( // --
IrOpcode::kTypeGuard, Operator::kPure, // opcode
"TypeGuard", // name
1, 0, 1, 1, 0, 0, // counts
type) {} // parameter
void PrintParameter(std::ostream& os) const final {
parameter()->PrintTo(os);
}
};
return new (zone()) TypeGuardOperator(type);
}
const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) {
switch (pretenure) {
......
......@@ -102,6 +102,7 @@ std::ostream& operator<<(std::ostream&, ElementAccess const&);
ElementAccess const& ElementAccessOf(const Operator* op) WARN_UNUSED_RESULT;
Type* TypeOf(const Operator* op) WARN_UNUSED_RESULT;
// Interface for building simplified operators, which represent the
// medium-level operations of V8, including adding numbers, allocating objects,
......@@ -182,6 +183,8 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* ObjectIsString();
const Operator* ObjectIsUndetectable();
const Operator* TypeGuard(Type* type);
const Operator* Allocate(PretenureFlag pretenure = NOT_TENURED);
const Operator* LoadField(FieldAccess const&);
......
......@@ -699,10 +699,9 @@ Type* Typer::Visitor::TypeEffectPhi(Node* node) {
return nullptr;
}
Type* Typer::Visitor::TypeGuard(Node* node) {
Type* Typer::Visitor::TypeTypeGuard(Node* node) {
Type* input_type = Operand(node, 0);
Type* guard_type = OpParameter<Type*>(node);
Type* guard_type = TypeOf(node->op());
return Type::Intersect(input_type, guard_type, zone());
}
......
......@@ -417,7 +417,7 @@ void Verifier::Visitor::Check(Node* node) {
CHECK_EQ(input_count, 1 + effect_count);
break;
}
case IrOpcode::kGuard:
case IrOpcode::kTypeGuard:
// TODO(bmeurer): what are the constraints on these?
break;
case IrOpcode::kCheckPoint:
......
......@@ -92,7 +92,7 @@ TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleLo) {
input, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64ExtractLowWord32(IsGuard(Type::Number(), input, _)));
IsFloat64ExtractLowWord32(IsTypeGuard(Type::Number(), input, _)));
}
......@@ -109,8 +109,8 @@ TEST_F(JSIntrinsicLoweringTest, InlineOptimizedDoubleHi) {
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleHi, 1),
input, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat64ExtractHighWord32(IsGuard(Type::Number(), input, _)));
EXPECT_THAT(r.replacement(), IsFloat64ExtractHighWord32(
IsTypeGuard(Type::Number(), input, _)));
}
......
......@@ -14,23 +14,20 @@ namespace compiler {
class LoadEliminationTest : public TypedGraphTest {
public:
LoadEliminationTest()
: TypedGraphTest(3), common_(zone()), simplified_(zone()) {}
LoadEliminationTest() : TypedGraphTest(3), simplified_(zone()) {}
~LoadEliminationTest() override {}
protected:
Reduction Reduce(Node* node) {
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
LoadElimination reducer(&graph_reducer, graph(), common());
LoadElimination reducer(&graph_reducer, graph(), simplified());
return reducer.Reduce(node);
}
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
CommonOperatorBuilder* common() { return &common_; }
private:
CommonOperatorBuilder common_;
SimplifiedOperatorBuilder simplified_;
};
......
......@@ -1309,12 +1309,12 @@ class IsStackSlotMatcher final : public NodeMatcher {
const Matcher<MachineRepresentation> rep_matcher_;
};
class IsGuardMatcher final : public NodeMatcher {
class IsTypeGuardMatcher final : public NodeMatcher {
public:
IsGuardMatcher(const Matcher<Type*>& type_matcher,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kGuard),
IsTypeGuardMatcher(const Matcher<Type*>& type_matcher,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kTypeGuard),
type_matcher_(type_matcher),
value_matcher_(value_matcher),
control_matcher_(control_matcher) {}
......@@ -2015,11 +2015,11 @@ Matcher<Node*> IsTailCall(
effect_matcher, control_matcher));
}
Matcher<Node*> IsGuard(const Matcher<Type*>& type_matcher,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher) {
Matcher<Node*> IsTypeGuard(const Matcher<Type*>& type_matcher,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher) {
return MakeMatcher(
new IsGuardMatcher(type_matcher, value_matcher, control_matcher));
new IsTypeGuardMatcher(type_matcher, value_matcher, control_matcher));
}
Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher,
......
......@@ -387,9 +387,9 @@ Matcher<Node*> IsWord32PairSar(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsStackSlot();
Matcher<Node*> IsGuard(const Matcher<Type*>& type_matcher,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsTypeGuard(const Matcher<Type*>& type_matcher,
const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher);
} // namespace compiler
} // namespace internal
......
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