#include "src/compiler/ast-loop-assignment-analyzer.h"
#include "src/compiler/control-builders.h"
#include "src/compiler/machine-operator.h"
+#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties-inl.h"
#include "src/compiler/node-properties.h"
#include "src/full-codegen.h"
}
-Node* AstGraphBuilder::BuildToBoolean(Node* value) {
- // TODO(mstarzinger): Possible optimization is to NOP for boolean values.
- return NewNode(javascript()->ToBoolean(), value);
+Node* AstGraphBuilder::BuildToBoolean(Node* input) {
+ // TODO(titzer): this should be in a JSOperatorReducer.
+ switch (input->opcode()) {
+ case IrOpcode::kInt32Constant:
+ return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0));
+ case IrOpcode::kFloat64Constant:
+ return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0));
+ case IrOpcode::kNumberConstant:
+ return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0));
+ case IrOpcode::kHeapConstant: {
+ Handle<Object> object = HeapObjectMatcher<Object>(input).Value().handle();
+ if (object->IsTrue()) return jsgraph_->TrueConstant();
+ if (object->IsFalse()) return jsgraph_->FalseConstant();
+ // TODO(turbofan): other constants.
+ break;
+ }
+ default:
+ break;
+ }
+ if (NodeProperties::IsTyped(input)) {
+ Type* upper = NodeProperties::GetBounds(input).upper;
+ if (upper->Is(Type::Boolean())) return input;
+ }
+
+ return NewNode(javascript()->ToBoolean(), input);
}
return Int32Constant(bit_cast<int32_t>(value));
}
+ // Creates a HeapConstant node for either true or false.
+ Node* BooleanConstant(bool is_true) {
+ return is_true ? TrueConstant() : FalseConstant();
+ }
+
// Creates a Int64Constant node, usually canonicalized.
Node* Int64Constant(int64_t value);
Node* Uint64Constant(uint64_t value) {
#include "src/compiler/js-inlining.h"
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/machine-operator-reducer.h"
-#include "src/compiler/phi-reducer.h"
#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h"
#include "src/compiler/schedule.h"
graph_builder.CreateGraph();
context_node = graph_builder.GetFunctionContext();
}
- {
- PhaseScope phase_scope(pipeline_statistics.get(), "phi reduction");
- PhiReducer phi_reducer;
- GraphReducer graph_reducer(data.graph());
- graph_reducer.AddReducer(&phi_reducer);
- graph_reducer.ReduceGraph();
- // TODO(mstarzinger): Running reducer once ought to be enough for everyone.
- graph_reducer.ReduceGraph();
- graph_reducer.ReduceGraph();
- }
VerifyAndPrintGraph(data.graph(), "Initial untyped", true);
+ {
+ PhaseScope phase_scope(pipeline_statistics.get(),
+ "early control reduction");
+ SourcePositionTable::Scope pos(data.source_positions(),
+ SourcePosition::Unknown());
+ ZonePool::Scope zone_scope(data.zone_pool());
+ ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(),
+ data.common());
+
+ VerifyAndPrintGraph(data.graph(), "Early Control reduced", true);
+ }
+
if (info()->is_context_specializing()) {
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
}
{
- PhaseScope phase_scope(pipeline_statistics.get(), "control reduction");
+ PhaseScope phase_scope(pipeline_statistics.get(),
+ "late control reduction");
SourcePositionTable::Scope pos(data.source_positions(),
SourcePosition::Unknown());
ZonePool::Scope zone_scope(data.zone_pool());
ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(),
data.common());
- VerifyAndPrintGraph(data.graph(), "Control reduced");
+ VerifyAndPrintGraph(data.graph(), "Late Control reduced");
}
}
// backwards from end through control edges, building and connecting the
// basic blocks for control nodes.
void Run() {
- Graph* graph = scheduler_->graph_;
- FixNode(schedule_->start(), graph->start());
- Queue(graph->end());
+ Queue(scheduler_->graph_->end());
while (!queue_.empty()) { // Breadth-first backwards traversal.
Node* node = queue_.front();
for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) {
ConnectBlocks(*i); // Connect block to its predecessor/successors.
}
-
- FixNode(schedule_->end(), graph->end());
}
// Run the control flow graph construction for a minimal control-connected
private:
void FixNode(BasicBlock* block, Node* node) {
schedule_->AddNode(block, node);
- scheduler_->GetData(node)->is_connected_control_ = true;
scheduler_->UpdatePlacement(node, Scheduler::kFixed);
}
void Queue(Node* node) {
- // Mark the connected control nodes as they queued.
+ // Mark the connected control nodes as they are queued.
Scheduler::SchedulerData* data = scheduler_->GetData(node);
if (!data->is_connected_control_) {
+ data->is_connected_control_ = true;
BuildBlocks(node);
queue_.push(node);
control_.push_back(node);
- data->is_connected_control_ = true;
}
}
void BuildBlocks(Node* node) {
switch (node->opcode()) {
+ case IrOpcode::kEnd:
+ FixNode(schedule_->end(), node);
+ break;
+ case IrOpcode::kStart:
+ FixNode(schedule_->start(), node);
+ break;
case IrOpcode::kLoop:
case IrOpcode::kMerge:
- case IrOpcode::kTerminate:
BuildBlockForNode(node);
break;
+ case IrOpcode::kTerminate: {
+ // Put Terminate in the loop to which it refers.
+ Node* loop = NodeProperties::GetControlInput(node);
+ BasicBlock* block = BuildBlockForNode(loop);
+ FixNode(block, node);
+ break;
+ }
case IrOpcode::kBranch:
BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse);
break;
}
}
- void BuildBlockForNode(Node* node) {
- if (schedule_->block(node) == NULL) {
- BasicBlock* block = schedule_->NewBasicBlock();
+ BasicBlock* BuildBlockForNode(Node* node) {
+ BasicBlock* block = schedule_->block(node);
+ if (block == NULL) {
+ block = schedule_->NewBasicBlock();
Trace("Create block B%d for #%d:%s\n", block->id().ToInt(), node->id(),
node->op()->mnemonic());
FixNode(block, node);
}
+ return block;
}
void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a,
graph.SetEnd(end);
- Schedule* schedule = ComputeAndVerifySchedule(5, &graph);
+ Schedule* schedule = ComputeAndVerifySchedule(6, &graph);
BasicBlock* block = schedule->block(loop);
CHECK_NE(NULL, loop);
CHECK_EQ(block, schedule->block(effect));