[turbofan] Constant propagation for JumpIfFalse/JumpIfTrue.

The JumpIfFalse and JumpIfTrue bytecodes test the accumulator, and
branch based on whether the accumulator is true or false (no other
value allowed, and in fact TurboFan would blow up if you would pass
anything else, since Branch operator can only deal with Boolean).
So for either branch we know exactly the value of the accumulator,
and we can update the environment to this constant value instead.

This helps to avoid the useless bit materialization that currently
happens when || or && is being used in a value context.

R=jarin@chromium.org
BUG=v8:5267

Review-Url: https://codereview.chromium.org/2666283002
Cr-Commit-Position: refs/heads/master@{#42843}
This commit is contained in:
bmeurer 2017-02-01 01:51:40 -08:00 committed by Commit bot
parent c67dc7e243
commit 158ac92871
6 changed files with 43 additions and 7 deletions

View File

@ -2969,6 +2969,10 @@ Node* CodeStubAssembler::IsWeakCell(Node* object) {
return HasInstanceType(object, WEAK_CELL_TYPE);
}
Node* CodeStubAssembler::IsBoolean(Node* object) {
return IsBooleanMap(LoadMap(object));
}
Node* CodeStubAssembler::IsName(Node* object) {
return Int32LessThanOrEqual(LoadInstanceType(object),
Int32Constant(LAST_NAME_TYPE));

View File

@ -685,6 +685,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsJSReceiver(Node* object);
Node* IsMap(Node* object);
Node* IsCallableMap(Node* map);
Node* IsBoolean(Node* object);
Node* IsName(Node* object);
Node* IsSymbol(Node* object);
Node* IsPrivateSymbol(Node* object);

View File

@ -2072,11 +2072,25 @@ void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
}
void BytecodeGraphBuilder::BuildJumpIfFalse() {
BuildJumpIfNot(environment()->LookupAccumulator());
NewBranch(environment()->LookupAccumulator());
Environment* if_true_environment = environment()->Copy();
environment()->BindAccumulator(jsgraph()->FalseConstant());
NewIfFalse();
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
if_true_environment->BindAccumulator(jsgraph()->TrueConstant());
set_environment(if_true_environment);
NewIfTrue();
}
void BytecodeGraphBuilder::BuildJumpIfTrue() {
BuildJumpIf(environment()->LookupAccumulator());
NewBranch(environment()->LookupAccumulator());
Environment* if_false_environment = environment()->Copy();
environment()->BindAccumulator(jsgraph()->TrueConstant());
NewIfTrue();
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
if_false_environment->BindAccumulator(jsgraph()->FalseConstant());
set_environment(if_false_environment);
NewIfFalse();
}
void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() {

View File

@ -894,6 +894,7 @@ class RepresentationSelector {
// Helper for handling selects.
void VisitSelect(Node* node, Truncation truncation,
SimplifiedLowering* lowering) {
DCHECK(TypeOf(node->InputAt(0))->Is(Type::Boolean()));
ProcessInput(node, 0, UseInfo::Bool());
MachineRepresentation output =
@ -1424,10 +1425,12 @@ class RepresentationSelector {
return;
}
case IrOpcode::kBranch:
case IrOpcode::kBranch: {
DCHECK(TypeOf(node->InputAt(0))->Is(Type::Boolean()));
ProcessInput(node, 0, UseInfo::Bool());
EnqueueInput(node, NodeProperties::FirstControlIndex(node));
return;
}
case IrOpcode::kSwitch:
ProcessInput(node, 0, UseInfo::TruncatingWord32());
EnqueueInput(node, NodeProperties::FirstControlIndex(node));

View File

@ -207,6 +207,8 @@ void Verifier::Visitor::Check(Node* node) {
}
CHECK_EQ(1, count_true);
CHECK_EQ(1, count_false);
// Condition must be a Boolean.
CheckValueInputIs(node, 0, Type::Boolean());
// Type is empty.
CheckNotTyped(node);
break;

View File

@ -2407,46 +2407,58 @@ void Interpreter::DoJumpConstant(InterpreterAssembler* assembler) {
// JumpIfTrue <imm>
//
// Jump by number of bytes represented by an immediate operand if the
// accumulator contains true.
// accumulator contains true. This only works for boolean inputs, and
// will misbehave if passed arbitrary input values.
void Interpreter::DoJumpIfTrue(InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* relative_jump = __ BytecodeOperandUImmWord(0);
Node* true_value = __ BooleanConstant(true);
CSA_ASSERT(assembler, assembler->TaggedIsNotSmi(accumulator));
CSA_ASSERT(assembler, assembler->IsBoolean(accumulator));
__ JumpIfWordEqual(accumulator, true_value, relative_jump);
}
// JumpIfTrueConstant <idx>
//
// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
// if the accumulator contains true.
// if the accumulator contains true. This only works for boolean inputs, and
// will misbehave if passed arbitrary input values.
void Interpreter::DoJumpIfTrueConstant(InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* index = __ BytecodeOperandIdx(0);
Node* relative_jump = __ LoadAndUntagConstantPoolEntry(index);
Node* true_value = __ BooleanConstant(true);
CSA_ASSERT(assembler, assembler->TaggedIsNotSmi(accumulator));
CSA_ASSERT(assembler, assembler->IsBoolean(accumulator));
__ JumpIfWordEqual(accumulator, true_value, relative_jump);
}
// JumpIfFalse <imm>
//
// Jump by number of bytes represented by an immediate operand if the
// accumulator contains false.
// accumulator contains false. This only works for boolean inputs, and
// will misbehave if passed arbitrary input values.
void Interpreter::DoJumpIfFalse(InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* relative_jump = __ BytecodeOperandUImmWord(0);
Node* false_value = __ BooleanConstant(false);
CSA_ASSERT(assembler, assembler->TaggedIsNotSmi(accumulator));
CSA_ASSERT(assembler, assembler->IsBoolean(accumulator));
__ JumpIfWordEqual(accumulator, false_value, relative_jump);
}
// JumpIfFalseConstant <idx>
//
// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
// if the accumulator contains false.
// if the accumulator contains false. This only works for boolean inputs, and
// will misbehave if passed arbitrary input values.
void Interpreter::DoJumpIfFalseConstant(InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* index = __ BytecodeOperandIdx(0);
Node* relative_jump = __ LoadAndUntagConstantPoolEntry(index);
Node* false_value = __ BooleanConstant(false);
CSA_ASSERT(assembler, assembler->TaggedIsNotSmi(accumulator));
CSA_ASSERT(assembler, assembler->IsBoolean(accumulator));
__ JumpIfWordEqual(accumulator, false_value, relative_jump);
}