Commit 0c0042cc authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[TurboProp] Add the ability for GraphAssembler to update basic blocks.

Adds the ability for the GraphAssembler to operate on, and maintain, a
scheduled graph. This will be used by TurboProp to maintain the initial
schedule created before effect-control-linearization, by updating this schedule
during effect-control, select and memory lowering stages rather than doing a
later reschedule.

In order to do this, an internal BlockUpdater is added to GraphAssembler,
which is enabled by passing the schedule to the GraphAssembler. The
GraphAssembler is modified to call into the block updater when nodes are added
and updates the schedule with new basic blocks when new control flow is updated.

BUG=v8:9684

Change-Id: I6d428ad21d869c472bb20f43cc8caf44722f090a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1841355
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64519}
parent 9c8f8fad
......@@ -41,7 +41,7 @@ class EffectControlLinearizer {
mask_array_index_(mask_array_index),
source_positions_(source_positions),
node_origins_(node_origins),
graph_assembler_(js_graph, nullptr, nullptr, temp_zone),
graph_assembler_(js_graph, temp_zone),
frame_state_zapper_(nullptr) {}
void Run();
......@@ -253,7 +253,6 @@ class EffectControlLinearizer {
Node* SmiShiftBitsConstant();
void TransitionElementsTo(Node* node, Node* array, ElementsKind from,
ElementsKind to);
void ConnectUnreachableToEnd(Node* effect, Node* control);
Factory* factory() const { return isolate()->factory(); }
Isolate* isolate() const { return jsgraph()->isolate(); }
......@@ -558,6 +557,8 @@ void EffectControlLinearizer::Run() {
for (BasicBlock* block : *(schedule()->rpo_order())) {
size_t instr = 0;
gasm()->Reset(block);
// The control node should be the first.
Node* control = block->NodeAt(instr);
DCHECK(NodeProperties::IsControl(control));
......@@ -740,6 +741,8 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
source_positions_->GetSourcePosition(node));
NodeOriginTable::Scope origin_scope(node_origins_, "process node", node);
gasm()->InitializeEffectControl(*effect, *control);
// If the node needs to be wired into the effect/control chain, do this
// here. Pass current frame state for lowering to eager deoptimization.
if (TryWireInStateEffect(node, *frame_state, effect, control)) {
......@@ -821,10 +824,12 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
*control = node;
}
gasm()->AddNode(node);
// Break the effect chain on {Unreachable} and reconnect to the graph end.
// Mark the following code for deletion by connecting to the {Dead} node.
if (node->opcode() == IrOpcode::kUnreachable) {
ConnectUnreachableToEnd(*effect, *control);
gasm()->ConnectUnreachableToEnd();
*effect = *control = jsgraph()->Dead();
}
}
......@@ -833,7 +838,6 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
Node* frame_state,
Node** effect,
Node** control) {
gasm()->Reset(*effect, *control);
Node* result = nullptr;
switch (node->opcode()) {
case IrOpcode::kChangeBitToTagged:
......@@ -1327,19 +1331,12 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
node->op()->mnemonic());
}
*effect = gasm()->ExtractCurrentEffect();
*control = gasm()->ExtractCurrentControl();
*effect = gasm()->current_effect();
*control = gasm()->current_control();
NodeProperties::ReplaceUses(node, result, *effect, *control);
return true;
}
void EffectControlLinearizer::ConnectUnreachableToEnd(Node* effect,
Node* control) {
DCHECK_EQ(effect->opcode(), IrOpcode::kUnreachable);
Node* throw_node = graph()->NewNode(common()->Throw(), effect, control);
NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
}
#define __ gasm()->
Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) {
......
This diff is collapsed.
......@@ -18,6 +18,9 @@ class Graph;
namespace compiler {
class Schedule;
class BasicBlock;
#define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \
V(ChangeInt32ToInt64) \
V(ChangeInt32ToFloat64) \
......@@ -125,8 +128,9 @@ class GraphAssemblerLabel {
Node* PhiAt(size_t index);
template <typename... Reps>
explicit GraphAssemblerLabel(GraphAssemblerLabelType type, Reps... reps)
: type_(type) {
explicit GraphAssemblerLabel(GraphAssemblerLabelType type,
BasicBlock* basic_block, Reps... reps)
: type_(type), basic_block_(basic_block) {
STATIC_ASSERT(VarCount == sizeof...(reps));
MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
reps...};
......@@ -149,9 +153,11 @@ class GraphAssemblerLabel {
return type_ == GraphAssemblerLabelType::kDeferred;
}
bool IsLoop() const { return type_ == GraphAssemblerLabelType::kLoop; }
BasicBlock* basic_block() { return basic_block_; }
bool is_bound_ = false;
GraphAssemblerLabelType const type_;
BasicBlock* basic_block_;
size_t merged_count_ = 0;
Node* effect_;
Node* control_;
......@@ -161,38 +167,46 @@ class GraphAssemblerLabel {
class GraphAssembler {
public:
GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, Zone* zone);
// Constructs a GraphAssembler that operates on an unscheduled graph.
GraphAssembler(JSGraph* jsgraph, Zone* zone);
// Constructs a GraphAssembler that operates on a scheduled graph, updating
// the schedule in the process.
GraphAssembler(JSGraph* jsgraph, Schedule* schedule, Zone* zone);
~GraphAssembler();
void Reset(Node* effect, Node* control);
void Reset(BasicBlock* block);
void InitializeEffectControl(Node* effect, Node* control);
// Create label.
template <typename... Reps>
static GraphAssemblerLabel<sizeof...(Reps)> MakeLabelFor(
GraphAssemblerLabel<sizeof...(Reps)> MakeLabelFor(
GraphAssemblerLabelType type, Reps... reps) {
return GraphAssemblerLabel<sizeof...(Reps)>(type, reps...);
return GraphAssemblerLabel<sizeof...(Reps)>(
type, NewBasicBlock(type == GraphAssemblerLabelType::kDeferred),
reps...);
}
// Convenience wrapper for creating non-deferred labels.
template <typename... Reps>
static GraphAssemblerLabel<sizeof...(Reps)> MakeLabel(Reps... reps) {
GraphAssemblerLabel<sizeof...(Reps)> MakeLabel(Reps... reps) {
return MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, reps...);
}
// Convenience wrapper for creating loop labels.
template <typename... Reps>
static GraphAssemblerLabel<sizeof...(Reps)> MakeLoopLabel(Reps... reps) {
GraphAssemblerLabel<sizeof...(Reps)> MakeLoopLabel(Reps... reps) {
return MakeLabelFor(GraphAssemblerLabelType::kLoop, reps...);
}
// Convenience wrapper for creating deferred labels.
template <typename... Reps>
static GraphAssemblerLabel<sizeof...(Reps)> MakeDeferredLabel(Reps... reps) {
GraphAssemblerLabel<sizeof...(Reps)> MakeDeferredLabel(Reps... reps) {
return MakeLabelFor(GraphAssemblerLabelType::kDeferred, reps...);
}
// Value creation.
Node* IntPtrConstant(intptr_t value);
Node* Uint32Constant(int32_t value);
Node* Uint32Constant(uint32_t value);
Node* Int32Constant(int32_t value);
Node* Int64Constant(int64_t value);
Node* UniqueIntPtrConstant(intptr_t value);
......@@ -288,19 +302,42 @@ class GraphAssembler {
void GotoIfNot(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label,
Vars...);
// Extractors (should be only used when destructing/resetting the assembler).
Node* ExtractCurrentControl();
Node* ExtractCurrentEffect();
// Updates current effect and control based on outputs of {node}.
void UpdateEffectControlWith(Node* node);
// Adds {node} to the current position and updates assembler's current effect
// and control.
Node* AddNode(Node* node);
// Finalizes the {block} being processed by the assembler, returning the
// finalized block (which may be different from the original block).
BasicBlock* FinalizeCurrentBlock(BasicBlock* block);
void ConnectUnreachableToEnd();
Node* current_control() { return current_control_; }
Node* current_effect() { return current_effect_; }
private:
class BasicBlockUpdater;
// Adds a decompression node if pointer compression is enabled and the
// representation loaded is a compressed one. To be used after loads.
Node* InsertDecompressionIfNeeded(MachineRepresentation rep, Node* value);
// Adds a compression node if pointer compression is enabled and the
// representation to be stored is a compressed one. To be used before stores.
Node* InsertCompressionIfNeeded(MachineRepresentation rep, Node* value);
// Control flow helpers.
template <typename... Vars>
void MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars... vars);
BasicBlock* NewBasicBlock(bool deferred);
void BindBasicBlock(BasicBlock* block);
void GotoBasicBlock(BasicBlock* block);
void GotoIfBasicBlock(BasicBlock* block, Node* branch,
IrOpcode::Value goto_if);
Node* AddClonedNode(Node* node);
Operator const* ToNumberOperator();
......@@ -319,6 +356,7 @@ class GraphAssembler {
JSGraph* jsgraph_;
Node* current_effect_;
Node* current_control_;
std::unique_ptr<BasicBlockUpdater> block_updater_;
};
template <size_t VarCount>
......@@ -412,8 +450,22 @@ void GraphAssembler::Bind(GraphAssemblerLabel<VarCount>* label) {
current_control_ = label->control_;
current_effect_ = label->effect_;
BindBasicBlock(label->basic_block());
label->SetBound();
if (label->merged_count_ > 1 || label->IsLoop()) {
AddNode(label->control_);
AddNode(label->effect_);
for (size_t i = 0; i < VarCount; i++) {
AddNode(label->bindings_[i]);
}
} else {
// If the basic block does not have a control node, insert a dummy
// Merge node, so that other passes have a control node to start from.
current_control_ =
AddNode(graph()->NewNode(common()->Merge(1), current_control_));
}
}
template <typename... Vars>
......@@ -422,6 +474,8 @@ void GraphAssembler::Goto(GraphAssemblerLabel<sizeof...(Vars)>* label,
DCHECK_NOT_NULL(current_control_);
DCHECK_NOT_NULL(current_effect_);
MergeState(label, vars...);
GotoBasicBlock(label->basic_block());
current_control_ = nullptr;
current_effect_ = nullptr;
}
......@@ -438,7 +492,8 @@ void GraphAssembler::GotoIf(Node* condition,
current_control_ = graph()->NewNode(common()->IfTrue(), branch);
MergeState(label, vars...);
current_control_ = graph()->NewNode(common()->IfFalse(), branch);
GotoIfBasicBlock(label->basic_block(), branch, IrOpcode::kIfTrue);
current_control_ = AddNode(graph()->NewNode(common()->IfFalse(), branch));
}
template <typename... Vars>
......@@ -452,7 +507,8 @@ void GraphAssembler::GotoIfNot(Node* condition,
current_control_ = graph()->NewNode(common()->IfFalse(), branch);
MergeState(label, vars...);
current_control_ = graph()->NewNode(common()->IfTrue(), branch);
GotoIfBasicBlock(label->basic_block(), branch, IrOpcode::kIfFalse);
current_control_ = AddNode(graph()->NewNode(common()->IfTrue(), branch));
}
template <typename... Args>
......@@ -471,7 +527,7 @@ Node* GraphAssembler::Call(const Operator* op, Args... args) {
Node* call = graph()->NewNode(op, size, args_array);
DCHECK_EQ(0, op->ControlOutputCount());
current_effect_ = call;
return call;
return AddNode(call);
}
} // namespace compiler
......
......@@ -50,7 +50,7 @@ MemoryLowering::MemoryLowering(JSGraph* jsgraph, Zone* zone,
const char* function_debug_name)
: jsgraph_(jsgraph),
zone_(zone),
graph_assembler_(jsgraph, nullptr, nullptr, zone),
graph_assembler_(jsgraph, zone),
allocation_folding_(allocation_folding),
poisoning_level_(poisoning_level),
write_barrier_assert_failed_(callback),
......@@ -96,7 +96,7 @@ Reduction MemoryLowering::ReduceAllocateRaw(
Node* effect = node->InputAt(1);
Node* control = node->InputAt(2);
gasm()->Reset(effect, control);
gasm()->InitializeEffectControl(effect, control);
Node* allocate_builtin;
if (allocation_type == AllocationType::kYoung) {
......@@ -162,8 +162,8 @@ Reduction MemoryLowering::ReduceAllocateRaw(
// Compute the effective inner allocated address.
value = __ BitcastWordToTagged(
__ IntAdd(state->top(), __ IntPtrConstant(kHeapObjectTag)));
effect = __ ExtractCurrentEffect();
control = __ ExtractCurrentControl();
effect = gasm()->current_effect();
control = gasm()->current_control();
// Extend the allocation {group}.
group->Add(value);
......@@ -216,8 +216,8 @@ Reduction MemoryLowering::ReduceAllocateRaw(
// Compute the initial object address.
value = __ BitcastWordToTagged(
__ IntAdd(done.PhiAt(0), __ IntPtrConstant(kHeapObjectTag)));
effect = __ ExtractCurrentEffect();
control = __ ExtractCurrentControl();
effect = gasm()->current_effect();
control = gasm()->current_control();
// Start a new allocation group.
AllocationGroup* group =
......@@ -264,8 +264,8 @@ Reduction MemoryLowering::ReduceAllocateRaw(
__ Bind(&done);
value = done.PhiAt(0);
effect = __ ExtractCurrentEffect();
control = __ ExtractCurrentControl();
effect = gasm()->current_effect();
control = gasm()->current_control();
if (state_ptr) {
// Create an unfoldable allocation group.
......
......@@ -75,6 +75,19 @@ void BasicBlock::set_loop_header(BasicBlock* loop_header) {
loop_header_ = loop_header;
}
void BasicBlock::TrimNodes(iterator new_end) { nodes_.erase(new_end, end()); }
void BasicBlock::ResetRPOInfo() {
loop_number_ = -1;
rpo_number_ = -1;
dominator_depth_ = -1;
dominator_ = nullptr;
rpo_next_ = nullptr;
loop_header_ = nullptr;
loop_end_ = nullptr;
loop_depth_ = 0;
}
// static
BasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
while (b1 != b2) {
......
......@@ -114,6 +114,11 @@ class V8_EXPORT_PRIVATE BasicBlock final
nodes_.insert(insertion_point, insertion_start, insertion_end);
}
// Trim basic block to end at {new_end}.
void TrimNodes(iterator new_end);
void ResetRPOInfo();
// Accessors.
Control control() const { return control_; }
void set_control(Control control);
......@@ -148,6 +153,8 @@ class V8_EXPORT_PRIVATE BasicBlock final
int32_t rpo_number() const { return rpo_number_; }
void set_rpo_number(int32_t rpo_number);
NodeVector* nodes() { return &nodes_; }
// Loop membership helpers.
inline bool IsLoopHeader() const { return loop_end_ != nullptr; }
bool LoopContains(BasicBlock* block) const;
......@@ -268,6 +275,7 @@ class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) {
Zone* zone() const { return zone_; }
private:
friend class GraphAssembler;
friend class Scheduler;
friend class BasicBlockInstrumentor;
friend class RawMachineAssembler;
......
......@@ -15,8 +15,7 @@ namespace internal {
namespace compiler {
SelectLowering::SelectLowering(JSGraph* jsgraph, Zone* zone)
: graph_assembler_(jsgraph, nullptr, nullptr, zone),
start_(jsgraph->graph()->start()) {}
: graph_assembler_(jsgraph, zone), start_(jsgraph->graph()->start()) {}
SelectLowering::~SelectLowering() = default;
......@@ -34,7 +33,7 @@ Node* SelectLowering::LowerSelect(Node* node) {
Node* vtrue = node->InputAt(1);
Node* vfalse = node->InputAt(2);
gasm()->Reset(start(), start());
gasm()->InitializeEffectControl(start(), start());
auto done = __ MakeLabel(p.representation());
......
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