[turbofan] Introduce CheckUnless.

Similarly to CheckIf, CheckUnless is a deoptimization without a specific
frame state. A frame state is assigned during effect-control linearization
(and CheckUnless is turned into DeoptimizeUnless).

At the moment, the new operator is only used at one place in native context
specialization, but we should use it everywhere. The advantage of
CHeckUnless is that it avoids non-truncating uses of values by frame
states. This particular change is aimed at Octane's crypto, where this
enables to turn one NumberMultiply into Int32Mul, and thus improve
the score by more than 10% (it also needs minus zero truncation and
typing to be improved, but those CLs are already in flight).

BUG=v8:4470
R=bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/2080113002
Cr-Commit-Position: refs/heads/master@{#37085}
This commit is contained in:
jarin 2016-06-19 20:46:32 -07:00 committed by Commit bot
parent e03c090d1b
commit 85fde59d53
9 changed files with 43 additions and 4 deletions

View File

@ -458,6 +458,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckIf:
state = LowerCheckIf(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckUnless:
state = LowerCheckUnless(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckFloat64Hole:
state = LowerCheckFloat64Hole(node, frame_state, *effect, *control);
break;
@ -1331,6 +1334,17 @@ EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state,
return ValueEffectControl(node, node, node);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckUnless(Node* node, Node* frame_state,
Node* effect, Node* control) {
NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control);
DCHECK_NOT_NULL(frame_state);
node->InsertInput(graph()->zone(), 1, frame_state);
NodeProperties::ChangeOp(node, common()->DeoptimizeUnless());
return ValueEffectControl(node, node, node);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state,
Node* effect, Node* control) {

View File

@ -97,6 +97,8 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect,
Node* control);
ValueEffectControl LowerCheckUnless(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerPlainPrimitiveToNumber(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerPlainPrimitiveToWord32(Node* node, Node* effect,

View File

@ -573,10 +573,9 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// TODO(turbofan): This is ugly as hell! We should probably introduce
// macro-ish operators for property access that encapsulate this whole
// mess.
Node* deoptimize =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
effect, fallthrough_control);
this_controls.push_back(deoptimize);
Node* deoptimize = graph()->NewNode(
simplified()->CheckUnless(), check, effect, fallthrough_control);
this_controls.push_back(fallthrough_control);
this_effects.push_back(deoptimize);
fallthrough_control = nullptr;
} else {

View File

@ -242,6 +242,7 @@
V(CheckFloat64Hole) \
V(CheckTaggedHole) \
V(CheckIf) \
V(CheckUnless) \
V(TruncateTaggedToWord32) \
V(TruncateTaggedToFloat64) \
V(Allocate) \

View File

@ -1192,6 +1192,11 @@ class RepresentationSelector {
case IrOpcode::kHeapConstant:
return VisitLeaf(node, MachineRepresentation::kTagged);
case IrOpcode::kCheckIf:
case IrOpcode::kCheckUnless:
ProcessInput(node, 0, UseInfo::Bool());
ProcessRemainingInputs(node, 1);
return;
case IrOpcode::kDeoptimizeIf:
case IrOpcode::kDeoptimizeUnless:
ProcessInput(node, 0, UseInfo::Bool());

View File

@ -366,6 +366,13 @@ struct SimplifiedOperatorGlobalCache final {
};
CheckIfOperator kCheckIf;
struct CheckUnlessOperator final : public Operator {
CheckUnlessOperator()
: Operator(IrOpcode::kCheckUnless, Operator::kPure, "CheckUnless", 1, 1,
1, 0, 1, 0) {}
};
CheckUnlessOperator kCheckUnless;
template <PretenureFlag kPretenure>
struct AllocateOperator final : public Operator1<PretenureFlag> {
AllocateOperator()
@ -442,6 +449,10 @@ const Operator* SimplifiedOperatorBuilder::CheckIf() {
return &cache_.kCheckIf;
}
const Operator* SimplifiedOperatorBuilder::CheckUnless() {
return &cache_.kCheckUnless;
}
const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
return new (zone()) Operator(IrOpcode::kReferenceEqual,
Operator::kCommutative | Operator::kPure,

View File

@ -245,6 +245,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
const Operator* CheckTaggedHole(CheckTaggedHoleMode);
const Operator* CheckIf();
const Operator* CheckUnless();
const Operator* ObjectIsCallable();
const Operator* ObjectIsNumber();

View File

@ -2052,6 +2052,11 @@ Type* Typer::Visitor::TypeCheckIf(Node* node) {
return nullptr;
}
Type* Typer::Visitor::TypeCheckUnless(Node* node) {
UNREACHABLE();
return nullptr;
}
Type* Typer::Visitor::TypeTruncateTaggedToWord32(Node* node) {
Type* arg = Operand(node, 0);
// TODO(jarin): DCHECK(arg->Is(Type::NumberOrUndefined()));

View File

@ -279,6 +279,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kDeoptimizeIf:
case IrOpcode::kDeoptimizeUnless:
case IrOpcode::kCheckIf:
case IrOpcode::kCheckUnless:
// Type is empty.
CheckNotTyped(node);
break;