Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Unified Diff: src/compiler/js-typed-lowering.cc

Issue 800833003: [turbofan] Correctify JSToBoolean lowering. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Improve simplified lowering. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/js-typed-lowering.cc
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
index 2338866d6d2274830dff5b132128ca3f9216659b..d9a627a1cf6a299b70636199f42c5a0ce4402fad 100644
--- a/src/compiler/js-typed-lowering.cc
+++ b/src/compiler/js-typed-lowering.cc
@@ -490,124 +490,34 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
}
-Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
- if (input->opcode() == IrOpcode::kJSToBoolean) {
- // Recursively try to reduce the input first.
- Reduction result = ReduceJSToBoolean(input);
- if (result.Changed()) return result;
- return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x)
- }
- // Check if we have a cached conversion.
- Node* conversion = FindConversion<IrOpcode::kJSToBoolean>(input);
- if (conversion) return Replace(conversion);
+Reduction JSTypedLowering::ReduceJSUnaryNot(Node* node) {
+ Node* input = node->InputAt(0);
Type* input_type = NodeProperties::GetBounds(input).upper;
if (input_type->Is(Type::Boolean())) {
- return Changed(input); // JSToBoolean(x:boolean) => x
- }
- if (input_type->Is(Type::Undefined())) {
- // JSToBoolean(undefined) => #false
- return Replace(jsgraph()->FalseConstant());
- }
- if (input_type->Is(Type::Null())) {
- // JSToBoolean(null) => #false
- return Replace(jsgraph()->FalseConstant());
- }
- if (input_type->Is(Type::DetectableReceiver())) {
- // JSToBoolean(x:detectable) => #true
- return Replace(jsgraph()->TrueConstant());
- }
- if (input_type->Is(Type::Undetectable())) {
- // JSToBoolean(x:undetectable) => #false
- return Replace(jsgraph()->FalseConstant());
- }
- if (input_type->Is(Type::OrderedNumber())) {
- // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x, #0))
- Node* cmp = graph()->NewNode(simplified()->NumberEqual(), input,
- jsgraph()->ZeroConstant());
- Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
- return Replace(inv);
- }
- if (input_type->Is(Type::String())) {
- // JSToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0))
- FieldAccess access = AccessBuilder::ForStringLength();
- Node* length = graph()->NewNode(simplified()->LoadField(access), input,
- graph()->start(), graph()->start());
- Node* cmp = graph()->NewNode(simplified()->NumberEqual(), length,
- jsgraph()->ZeroConstant());
- Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
- return Replace(inv);
+ // JSUnaryNot(x:boolean,context) => BooleanNot(x)
+ node->set_op(simplified()->BooleanNot());
+ node->TrimInputCount(1);
+ return Changed(node);
}
- return NoChange();
+ // JSUnaryNot(x,context) => BooleanNot(AnyToBoolean(x))
+ node->set_op(simplified()->BooleanNot());
+ node->ReplaceInput(0, graph()->NewNode(simplified()->AnyToBoolean(), input));
+ node->TrimInputCount(1);
+ return Changed(node);
}
Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
- // Try to reduce the input first.
- Node* const input = node->InputAt(0);
- Reduction reduction = ReduceJSToBooleanInput(input);
- if (reduction.Changed()) return reduction;
- if (input->opcode() == IrOpcode::kPhi) {
- // JSToBoolean(phi(x1,...,xn,control),context)
- // => phi(JSToBoolean(x1,no-context),...,JSToBoolean(xn,no-context))
- int const input_count = input->InputCount() - 1;
- Node* const control = input->InputAt(input_count);
- DCHECK_LE(0, input_count);
- DCHECK(NodeProperties::IsControl(control));
- DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean()));
- DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean()));
- node->set_op(common()->Phi(kMachAnyTagged, input_count));
- for (int i = 0; i < input_count; ++i) {
- // We must be very careful not to introduce cycles when pushing
- // operations into phis. It is safe for {value}, since it appears
- // as input to the phi that we are replacing, but it's not safe
- // to simply reuse the context of the {node}. However, ToBoolean()
- // does not require a context anyways, so it's safe to discard it
- // here and pass the dummy context.
- Node* const value = ConvertToBoolean(input->InputAt(i));
- if (i < node->InputCount()) {
- node->ReplaceInput(i, value);
- } else {
- node->AppendInput(graph()->zone(), value);
- }
- }
- if (input_count < node->InputCount()) {
- node->ReplaceInput(input_count, control);
- } else {
- node->AppendInput(graph()->zone(), control);
- }
- node->TrimInputCount(input_count + 1);
- return Changed(node);
- }
- if (input->opcode() == IrOpcode::kSelect) {
- // JSToBoolean(select(c,x1,x2),context)
- // => select(c,JSToBoolean(x1,no-context),...,JSToBoolean(x2,no-context))
- int const input_count = input->InputCount();
- BranchHint const input_hint = SelectParametersOf(input->op()).hint();
- DCHECK_EQ(3, input_count);
- DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean()));
- DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean()));
- node->set_op(common()->Select(kMachAnyTagged, input_hint));
- node->InsertInput(graph()->zone(), 0, input->InputAt(0));
- for (int i = 1; i < input_count; ++i) {
- // We must be very careful not to introduce cycles when pushing
- // operations into selects. It is safe for {value}, since it appears
- // as input to the select that we are replacing, but it's not safe
- // to simply reuse the context of the {node}. However, ToBoolean()
- // does not require a context anyways, so it's safe to discard it
- // here and pass the dummy context.
- Node* const value = ConvertToBoolean(input->InputAt(i));
- node->ReplaceInput(i, value);
- }
- DCHECK_EQ(3, node->InputCount());
- return Changed(node);
- }
- InsertConversion(node);
- if (node->InputAt(1) != jsgraph()->NoContextConstant()) {
- // JSToBoolean(x,context) => JSToBoolean(x,no-context)
- node->ReplaceInput(1, jsgraph()->NoContextConstant());
- return Changed(node);
+ Node* input = node->InputAt(0);
+ Type* input_type = NodeProperties::GetBounds(input).upper;
+ if (input_type->Is(Type::Boolean())) {
+ // JSToBoolean(x:boolean,context) => x
+ return Replace(input);
}
- return NoChange();
+ // JSToBoolean(x,context) => AnyToBoolean(x)
+ node->set_op(simplified()->AnyToBoolean());
+ node->TrimInputCount(1);
+ return Changed(node);
}
@@ -972,18 +882,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceNumberBinop(node, simplified()->NumberDivide());
case IrOpcode::kJSModulus:
return ReduceNumberBinop(node, simplified()->NumberModulus());
- case IrOpcode::kJSUnaryNot: {
- Reduction result = ReduceJSToBooleanInput(node->InputAt(0));
- if (result.Changed()) {
- // JSUnaryNot(x:boolean) => BooleanNot(x)
- node = result.replacement();
- } else {
- // JSUnaryNot(x) => BooleanNot(JSToBoolean(x))
- node->set_op(javascript()->ToBoolean());
- }
- Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
- return Replace(value);
- }
+ case IrOpcode::kJSUnaryNot:
+ return ReduceJSUnaryNot(node);
case IrOpcode::kJSToBoolean:
return ReduceJSToBoolean(node);
case IrOpcode::kJSToNumber:
@@ -1005,17 +905,6 @@ Reduction JSTypedLowering::Reduce(Node* node) {
}
-Node* JSTypedLowering::ConvertToBoolean(Node* input) {
- // Avoid inserting too many eager ToBoolean() operations.
- Reduction const reduction = ReduceJSToBooleanInput(input);
- if (reduction.Changed()) return reduction.replacement();
- Node* const conversion = graph()->NewNode(javascript()->ToBoolean(), input,
- jsgraph()->NoContextConstant());
- InsertConversion(conversion);
- return conversion;
-}
-
-
Node* JSTypedLowering::ConvertToNumber(Node* input) {
DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive()));
// Avoid inserting too many eager ToNumber() operations.
@@ -1043,8 +932,7 @@ Node* JSTypedLowering::FindConversion(Node* input) {
void JSTypedLowering::InsertConversion(Node* conversion) {
- DCHECK(conversion->opcode() == IrOpcode::kJSToBoolean ||
- conversion->opcode() == IrOpcode::kJSToNumber);
+ DCHECK(conversion->opcode() == IrOpcode::kJSToNumber);
size_t const input_id = conversion->InputAt(0)->id();
if (input_id >= conversions_.size()) {
conversions_.resize(2 * input_id + 1);
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698