[TurboProp] Remove the second schedule for TurboProp.
This rearranges the TurboProp pipeline to avoid the need for a second schedule of the graph. To do this, it moves the final schedule creation before effect-control-linearization (which used a temporary schedule previously, and with TurboFan). It then enables the block updater in the graph assembler for effect control linearization and does select and memory lowering in a new ScheduledMachineLowering phase to maintain this existing schedule during these lowering passes. BUG=v8:9684 Change-Id: I6a7790b010f8b152dd01d85aa95ee5d4f99087a5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1847351 Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#64537}
This commit is contained in:
parent
e0c1ca5a30
commit
22fd955507
2
BUILD.gn
2
BUILD.gn
@ -1828,6 +1828,8 @@ v8_compiler_sources = [
|
||||
"src/compiler/representation-change.h",
|
||||
"src/compiler/schedule.cc",
|
||||
"src/compiler/schedule.h",
|
||||
"src/compiler/scheduled-machine-lowering.cc",
|
||||
"src/compiler/scheduled-machine-lowering.h",
|
||||
"src/compiler/scheduler.cc",
|
||||
"src/compiler/scheduler.h",
|
||||
"src/compiler/select-lowering.cc",
|
||||
|
@ -34,14 +34,17 @@ class EffectControlLinearizer {
|
||||
Zone* temp_zone,
|
||||
SourcePositionTable* source_positions,
|
||||
NodeOriginTable* node_origins,
|
||||
MaskArrayIndexEnable mask_array_index)
|
||||
MaskArrayIndexEnable mask_array_index,
|
||||
MaintainSchedule maintain_schedule)
|
||||
: js_graph_(js_graph),
|
||||
schedule_(schedule),
|
||||
temp_zone_(temp_zone),
|
||||
mask_array_index_(mask_array_index),
|
||||
maintain_schedule_(maintain_schedule),
|
||||
source_positions_(source_positions),
|
||||
node_origins_(node_origins),
|
||||
graph_assembler_(js_graph, temp_zone),
|
||||
graph_assembler_(js_graph, temp_zone,
|
||||
should_maintain_schedule() ? schedule : nullptr),
|
||||
frame_state_zapper_(nullptr) {}
|
||||
|
||||
void Run();
|
||||
@ -253,6 +256,10 @@ class EffectControlLinearizer {
|
||||
void TransitionElementsTo(Node* node, Node* array, ElementsKind from,
|
||||
ElementsKind to);
|
||||
|
||||
bool should_maintain_schedule() const {
|
||||
return maintain_schedule_ == MaintainSchedule::kMaintain;
|
||||
}
|
||||
|
||||
Factory* factory() const { return isolate()->factory(); }
|
||||
Isolate* isolate() const { return jsgraph()->isolate(); }
|
||||
JSGraph* jsgraph() const { return js_graph_; }
|
||||
@ -270,6 +277,7 @@ class EffectControlLinearizer {
|
||||
Schedule* schedule_;
|
||||
Zone* temp_zone_;
|
||||
MaskArrayIndexEnable mask_array_index_;
|
||||
MaintainSchedule maintain_schedule_;
|
||||
RegionObservability region_observability_ = RegionObservability::kObservable;
|
||||
SourcePositionTable* source_positions_;
|
||||
NodeOriginTable* node_origins_;
|
||||
@ -544,6 +552,8 @@ void EffectControlLinearizer::Run() {
|
||||
ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
|
||||
NodeVector inputs_buffer(temp_zone());
|
||||
|
||||
// TODO(rmcilroy) We should not depend on having rpo_order on schedule, and
|
||||
// instead just do our own RPO walk here.
|
||||
for (BasicBlock* block : *(schedule()->rpo_order())) {
|
||||
gasm()->Reset(block);
|
||||
|
||||
@ -704,7 +714,8 @@ void EffectControlLinearizer::Run() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (block->control() == BasicBlock::kBranch) {
|
||||
if (!should_maintain_schedule() &&
|
||||
block->control() == BasicBlock::kBranch) {
|
||||
TryCloneBranch(block->control_input(), block, temp_zone(), graph(),
|
||||
common(), &block_effects, source_positions_,
|
||||
node_origins_);
|
||||
@ -732,6 +743,7 @@ void EffectControlLinearizer::Run() {
|
||||
UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
|
||||
&block_effects);
|
||||
}
|
||||
|
||||
schedule_->rpo_order()->clear();
|
||||
}
|
||||
|
||||
@ -757,6 +769,13 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state) {
|
||||
source_positions_->GetSourcePosition(node));
|
||||
NodeOriginTable::Scope origin_scope(node_origins_, "process node", node);
|
||||
|
||||
// If basic block is unreachable after this point, update the node's effect
|
||||
// and control inputs to mark it as dead, but don't process further.
|
||||
if (gasm()->current_effect() == jsgraph()->Dead()) {
|
||||
UpdateEffectControlForNode(node);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
@ -6053,10 +6072,11 @@ Node* EffectControlLinearizer::LowerDateNow(Node* node) {
|
||||
void LinearizeEffectControl(JSGraph* graph, Schedule* schedule, Zone* temp_zone,
|
||||
SourcePositionTable* source_positions,
|
||||
NodeOriginTable* node_origins,
|
||||
MaskArrayIndexEnable mask_array_index) {
|
||||
MaskArrayIndexEnable mask_array_index,
|
||||
MaintainSchedule maintain_schedule) {
|
||||
EffectControlLinearizer linearizer(graph, schedule, temp_zone,
|
||||
source_positions, node_origins,
|
||||
mask_array_index);
|
||||
mask_array_index, maintain_schedule);
|
||||
linearizer.Run();
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,12 @@ class SourcePositionTable;
|
||||
|
||||
enum class MaskArrayIndexEnable { kDoNotMaskArrayIndex, kMaskArrayIndex };
|
||||
|
||||
enum class MaintainSchedule { kMaintain, kDiscard };
|
||||
|
||||
V8_EXPORT_PRIVATE void LinearizeEffectControl(
|
||||
JSGraph* graph, Schedule* schedule, Zone* temp_zone,
|
||||
SourcePositionTable* source_positions, NodeOriginTable* node_origins,
|
||||
MaskArrayIndexEnable mask_array_index);
|
||||
MaskArrayIndexEnable mask_array_index, MaintainSchedule maintain_schedule);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
|
@ -261,11 +261,16 @@ void GraphAssembler::BasicBlockUpdater::AddThrow(Node* node) {
|
||||
}
|
||||
schedule_->AddThrow(current_block_, node);
|
||||
|
||||
// Clear original successors and update the original control and control input
|
||||
// to the throw, since this block is now connected directly to end().
|
||||
saved_successors_.clear();
|
||||
// Clear original successors and replace the block's original control and
|
||||
// control input to the throw, since this block is now connected directly to
|
||||
// the end.
|
||||
if (original_control_input_ != nullptr) {
|
||||
NodeProperties::ReplaceUses(original_control_input_, node, nullptr, node);
|
||||
original_control_input_->Kill();
|
||||
}
|
||||
original_control_input_ = node;
|
||||
original_control_ = BasicBlock::kThrow;
|
||||
saved_successors_.clear();
|
||||
}
|
||||
|
||||
void GraphAssembler::BasicBlockUpdater::UpdateSuccessors(BasicBlock* block) {
|
||||
@ -317,19 +322,14 @@ BasicBlock* GraphAssembler::BasicBlockUpdater::Finalize(BasicBlock* original) {
|
||||
return block;
|
||||
}
|
||||
|
||||
GraphAssembler::GraphAssembler(JSGraph* jsgraph, Zone* zone)
|
||||
GraphAssembler::GraphAssembler(JSGraph* jsgraph, Zone* zone, Schedule* schedule)
|
||||
: temp_zone_(zone),
|
||||
jsgraph_(jsgraph),
|
||||
current_effect_(nullptr),
|
||||
current_control_(nullptr),
|
||||
block_updater_(nullptr) {}
|
||||
|
||||
GraphAssembler::GraphAssembler(JSGraph* jsgraph, Schedule* schedule, Zone* zone)
|
||||
: temp_zone_(zone),
|
||||
jsgraph_(jsgraph),
|
||||
current_effect_(nullptr),
|
||||
current_control_(nullptr),
|
||||
block_updater_(new BasicBlockUpdater(schedule, jsgraph->graph(), zone)) {}
|
||||
block_updater_(schedule != nullptr ? new BasicBlockUpdater(
|
||||
schedule, jsgraph->graph(), zone)
|
||||
: nullptr) {}
|
||||
|
||||
GraphAssembler::~GraphAssembler() = default;
|
||||
|
||||
@ -660,7 +660,15 @@ void GraphAssembler::GotoIfBasicBlock(BasicBlock* block, Node* branch,
|
||||
|
||||
BasicBlock* GraphAssembler::FinalizeCurrentBlock(BasicBlock* block) {
|
||||
if (block_updater_) {
|
||||
return block_updater_->Finalize(block);
|
||||
block = block_updater_->Finalize(block);
|
||||
if (current_control_ == jsgraph()->Dead()) {
|
||||
// If the block's end is unreachable, then reset current effect and
|
||||
// control to that of the block's throw control node.
|
||||
DCHECK(block->control() == BasicBlock::kThrow);
|
||||
Node* throw_node = block->control_input();
|
||||
current_control_ = NodeProperties::GetControlInput(throw_node);
|
||||
current_effect_ = NodeProperties::GetEffectInput(throw_node);
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
@ -167,11 +167,9 @@ class GraphAssemblerLabel {
|
||||
|
||||
class GraphAssembler {
|
||||
public:
|
||||
// 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);
|
||||
// Constructs a GraphAssembler. If {schedule} is not null, the graph assembler
|
||||
// will maintain the schedule as it updates blocks.
|
||||
GraphAssembler(JSGraph* jsgraph, Zone* zone, Schedule* schedule = nullptr);
|
||||
~GraphAssembler();
|
||||
|
||||
void Reset(BasicBlock* block);
|
||||
|
@ -44,13 +44,17 @@ class MemoryLowering::AllocationGroup final : public ZoneObject {
|
||||
};
|
||||
|
||||
MemoryLowering::MemoryLowering(JSGraph* jsgraph, Zone* zone,
|
||||
GraphAssembler* graph_assembler,
|
||||
PoisoningMitigationLevel poisoning_level,
|
||||
AllocationFolding allocation_folding,
|
||||
WriteBarrierAssertFailedCallback callback,
|
||||
const char* function_debug_name)
|
||||
: jsgraph_(jsgraph),
|
||||
: isolate_(jsgraph->isolate()),
|
||||
zone_(zone),
|
||||
graph_assembler_(jsgraph, zone),
|
||||
graph_zone_(jsgraph->graph()->zone()),
|
||||
common_(jsgraph->common()),
|
||||
machine_(jsgraph->machine()),
|
||||
graph_assembler_(graph_assembler),
|
||||
allocation_folding_(allocation_folding),
|
||||
poisoning_level_(poisoning_level),
|
||||
write_barrier_assert_failed_(callback),
|
||||
@ -195,7 +199,7 @@ Reduction MemoryLowering::ReduceAllocateRaw(
|
||||
if (!allocate_operator_.is_set()) {
|
||||
auto descriptor = AllocateDescriptor{};
|
||||
auto call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
graph()->zone(), descriptor, descriptor.GetStackParameterCount(),
|
||||
graph_zone(), descriptor, descriptor.GetStackParameterCount(),
|
||||
CallDescriptor::kCanUseRoots, Operator::kNoThrow);
|
||||
allocate_operator_.set(common()->Call(call_descriptor));
|
||||
}
|
||||
@ -256,7 +260,7 @@ Reduction MemoryLowering::ReduceAllocateRaw(
|
||||
if (!allocate_operator_.is_set()) {
|
||||
auto descriptor = AllocateDescriptor{};
|
||||
auto call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
graph()->zone(), descriptor, descriptor.GetStackParameterCount(),
|
||||
graph_zone(), descriptor, descriptor.GetStackParameterCount(),
|
||||
CallDescriptor::kCanUseRoots, Operator::kNoThrow);
|
||||
allocate_operator_.set(common()->Call(call_descriptor));
|
||||
}
|
||||
@ -275,22 +279,6 @@ Reduction MemoryLowering::ReduceAllocateRaw(
|
||||
}
|
||||
}
|
||||
|
||||
// Replace all effect uses of {node} with the {effect} and replace
|
||||
// all value uses of {node} with the {value}.
|
||||
for (Edge edge : node->use_edges()) {
|
||||
if (NodeProperties::IsEffectEdge(edge)) {
|
||||
edge.UpdateTo(effect);
|
||||
} else if (NodeProperties::IsValueEdge(edge)) {
|
||||
edge.UpdateTo(value);
|
||||
} else {
|
||||
DCHECK(NodeProperties::IsControlEdge(edge));
|
||||
edge.UpdateTo(control);
|
||||
}
|
||||
}
|
||||
|
||||
// Kill the {node} to make sure we don't leave dangling dead uses.
|
||||
node->Kill();
|
||||
|
||||
return Replace(value);
|
||||
}
|
||||
|
||||
@ -318,8 +306,8 @@ Reduction MemoryLowering::ReduceLoadElement(Node* node) {
|
||||
Reduction MemoryLowering::ReduceLoadField(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kLoadField, node->opcode());
|
||||
FieldAccess const& access = FieldAccessOf(node->op());
|
||||
Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
|
||||
node->InsertInput(graph()->zone(), 1, offset);
|
||||
Node* offset = __ IntPtrConstant(access.offset - access.tag());
|
||||
node->InsertInput(graph_zone(), 1, offset);
|
||||
MachineType type = access.machine_type;
|
||||
if (NeedsPoisoning(access.load_sensitivity)) {
|
||||
NodeProperties::ChangeOp(node, machine()->PoisonedLoad(type));
|
||||
@ -367,8 +355,8 @@ Reduction MemoryLowering::ReduceStoreField(Node* node,
|
||||
Node* value = node->InputAt(1);
|
||||
WriteBarrierKind write_barrier_kind = ComputeWriteBarrierKind(
|
||||
node, object, value, state, access.write_barrier_kind);
|
||||
Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
|
||||
node->InsertInput(graph()->zone(), 1, offset);
|
||||
Node* offset = __ IntPtrConstant(access.offset - access.tag());
|
||||
node->InsertInput(graph_zone(), 1, offset);
|
||||
NodeProperties::ChangeOp(
|
||||
node, machine()->Store(StoreRepresentation(
|
||||
access.machine_type.representation(), write_barrier_kind)));
|
||||
@ -534,18 +522,6 @@ bool MemoryLowering::AllocationState::IsYoungGenerationAllocation() const {
|
||||
return group() && group()->IsYoungGenerationAllocation();
|
||||
}
|
||||
|
||||
Graph* MemoryLowering::graph() const { return jsgraph()->graph(); }
|
||||
|
||||
Isolate* MemoryLowering::isolate() const { return jsgraph()->isolate(); }
|
||||
|
||||
CommonOperatorBuilder* MemoryLowering::common() const {
|
||||
return jsgraph()->common();
|
||||
}
|
||||
|
||||
MachineOperatorBuilder* MemoryLowering::machine() const {
|
||||
return jsgraph()->machine();
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -71,7 +71,8 @@ class MemoryLowering final : public Reducer {
|
||||
Node* node, Node* object, const char* name, Zone* temp_zone)>;
|
||||
|
||||
MemoryLowering(
|
||||
JSGraph* jsgraph, Zone* zone, PoisoningMitigationLevel poisoning_level,
|
||||
JSGraph* jsgraph, Zone* zone, GraphAssembler* graph_assembler,
|
||||
PoisoningMitigationLevel poisoning_level,
|
||||
AllocationFolding allocation_folding =
|
||||
AllocationFolding::kDontAllocationFolding,
|
||||
WriteBarrierAssertFailedCallback callback = [](Node*, Node*, const char*,
|
||||
@ -110,17 +111,20 @@ class MemoryLowering final : public Reducer {
|
||||
bool NeedsPoisoning(LoadSensitivity load_sensitivity) const;
|
||||
|
||||
Graph* graph() const;
|
||||
Isolate* isolate() const;
|
||||
Isolate* isolate() const { return isolate_; }
|
||||
Zone* zone() const { return zone_; }
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
CommonOperatorBuilder* common() const;
|
||||
MachineOperatorBuilder* machine() const;
|
||||
GraphAssembler* gasm() { return &graph_assembler_; }
|
||||
Zone* graph_zone() const { return graph_zone_; }
|
||||
CommonOperatorBuilder* common() const { return common_; }
|
||||
MachineOperatorBuilder* machine() const { return machine_; }
|
||||
GraphAssembler* gasm() const { return graph_assembler_; }
|
||||
|
||||
SetOncePointer<const Operator> allocate_operator_;
|
||||
JSGraph* const jsgraph_;
|
||||
Isolate* isolate_;
|
||||
Zone* zone_;
|
||||
GraphAssembler graph_assembler_;
|
||||
Zone* graph_zone_;
|
||||
CommonOperatorBuilder* common_;
|
||||
MachineOperatorBuilder* machine_;
|
||||
GraphAssembler* graph_assembler_;
|
||||
AllocationFolding allocation_folding_;
|
||||
PoisoningMitigationLevel poisoning_level_;
|
||||
WriteBarrierAssertFailedCallback write_barrier_assert_failed_;
|
||||
|
@ -185,8 +185,10 @@ MemoryOptimizer::MemoryOptimizer(
|
||||
JSGraph* jsgraph, Zone* zone, PoisoningMitigationLevel poisoning_level,
|
||||
MemoryLowering::AllocationFolding allocation_folding,
|
||||
const char* function_debug_name, TickCounter* tick_counter)
|
||||
: memory_lowering_(jsgraph, zone, poisoning_level, allocation_folding,
|
||||
WriteBarrierAssertFailed, function_debug_name),
|
||||
: graph_assembler_(jsgraph, zone),
|
||||
memory_lowering_(jsgraph, zone, &graph_assembler_, poisoning_level,
|
||||
allocation_folding, WriteBarrierAssertFailed,
|
||||
function_debug_name),
|
||||
jsgraph_(jsgraph),
|
||||
empty_state_(AllocationState::Empty(zone)),
|
||||
pending_(zone),
|
||||
@ -311,8 +313,17 @@ void MemoryOptimizer::VisitAllocateRaw(Node* node,
|
||||
}
|
||||
}
|
||||
|
||||
memory_lowering()->ReduceAllocateRaw(
|
||||
Reduction reduction = memory_lowering()->ReduceAllocateRaw(
|
||||
node, allocation_type, allocation.allow_large_objects(), &state);
|
||||
CHECK(reduction.Changed() && reduction.replacement() != node);
|
||||
|
||||
// Replace all uses of node and kill the node to make sure we don't leave
|
||||
// dangling dead uses.
|
||||
NodeProperties::ReplaceUses(node, reduction.replacement(),
|
||||
graph_assembler_.current_effect(),
|
||||
graph_assembler_.current_control());
|
||||
node->Kill();
|
||||
|
||||
EnqueueUses(state->effect(), state);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef V8_COMPILER_MEMORY_OPTIMIZER_H_
|
||||
#define V8_COMPILER_MEMORY_OPTIMIZER_H_
|
||||
|
||||
#include "src/compiler/graph-assembler.h"
|
||||
#include "src/compiler/memory-lowering.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
@ -78,6 +79,7 @@ class MemoryOptimizer final {
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
Zone* zone() const { return zone_; }
|
||||
|
||||
GraphAssembler graph_assembler_;
|
||||
MemoryLowering memory_lowering_;
|
||||
JSGraph* jsgraph_;
|
||||
AllocationState const* const empty_state_;
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "src/compiler/pipeline-statistics.h"
|
||||
#include "src/compiler/redundancy-elimination.h"
|
||||
#include "src/compiler/schedule.h"
|
||||
#include "src/compiler/scheduled-machine-lowering.h"
|
||||
#include "src/compiler/scheduler.h"
|
||||
#include "src/compiler/select-lowering.h"
|
||||
#include "src/compiler/serializer-for-background-compilation.h"
|
||||
@ -1645,7 +1646,7 @@ struct EffectControlLinearizationPhase {
|
||||
// - introduce effect phis and rewire effects to get SSA again.
|
||||
LinearizeEffectControl(data->jsgraph(), schedule, temp_zone,
|
||||
data->source_positions(), data->node_origins(),
|
||||
mask_array_index);
|
||||
mask_array_index, MaintainSchedule::kDiscard);
|
||||
}
|
||||
{
|
||||
// The {EffectControlLinearizer} might leave {Dead} nodes behind, so we
|
||||
@ -1759,7 +1760,8 @@ struct LateOptimizationPhase {
|
||||
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
|
||||
data->broker(), data->common(),
|
||||
data->machine(), temp_zone);
|
||||
SelectLowering select_lowering(data->jsgraph(), temp_zone);
|
||||
GraphAssembler graph_assembler(data->jsgraph(), temp_zone);
|
||||
SelectLowering select_lowering(&graph_assembler, data->graph());
|
||||
// TODO(v8:7703, solanes): go back to using #if guards once
|
||||
// FLAG_turbo_decompression_elimination gets removed.
|
||||
DecompressionElimination decompression_elimination(
|
||||
@ -1806,20 +1808,48 @@ struct DecompressionOptimizationPhase {
|
||||
}
|
||||
};
|
||||
|
||||
struct MidTierMachineLoweringPhase {
|
||||
static const char* phase_name() { return "V8.TFMidTierMachineLoweringPhase"; }
|
||||
struct ScheduledEffectControlLinearizationPhase {
|
||||
static const char* phase_name() {
|
||||
return "V8.TFScheduledEffectControlLinearizationPhase";
|
||||
}
|
||||
|
||||
void Run(PipelineData* data, Zone* temp_zone) {
|
||||
GraphReducer graph_reducer(temp_zone, data->graph(),
|
||||
&data->info()->tick_counter(),
|
||||
data->jsgraph()->Dead());
|
||||
SelectLowering select_lowering(data->jsgraph(), temp_zone);
|
||||
MemoryLowering memory_lowering(data->jsgraph(), temp_zone,
|
||||
data->info()->GetPoisoningMitigationLevel());
|
||||
MaskArrayIndexEnable mask_array_index =
|
||||
(data->info()->GetPoisoningMitigationLevel() !=
|
||||
PoisoningMitigationLevel::kDontPoison)
|
||||
? MaskArrayIndexEnable::kMaskArrayIndex
|
||||
: MaskArrayIndexEnable::kDoNotMaskArrayIndex;
|
||||
// Post-pass for wiring the control/effects
|
||||
// - connect allocating representation changes into the control&effect
|
||||
// chains and lower them,
|
||||
// - get rid of the region markers,
|
||||
// - introduce effect phis and rewire effects to get SSA again.
|
||||
LinearizeEffectControl(data->jsgraph(), data->schedule(), temp_zone,
|
||||
data->source_positions(), data->node_origins(),
|
||||
mask_array_index, MaintainSchedule::kMaintain);
|
||||
|
||||
AddReducer(data, &graph_reducer, &memory_lowering);
|
||||
AddReducer(data, &graph_reducer, &select_lowering);
|
||||
graph_reducer.ReduceGraph();
|
||||
// TODO(rmcilroy) Avoid having to rebuild rpo_order on schedule each time.
|
||||
Scheduler::ComputeSpecialRPO(temp_zone, data->schedule());
|
||||
TraceSchedule(data->info(), data, data->schedule(),
|
||||
"effect linearization schedule");
|
||||
}
|
||||
};
|
||||
|
||||
struct ScheduledMachineLoweringPhase {
|
||||
static const char* phase_name() {
|
||||
return "V8.TFScheduledMachineLoweringPhase";
|
||||
}
|
||||
|
||||
void Run(PipelineData* data, Zone* temp_zone) {
|
||||
ScheduledMachineLowering machine_lowering(
|
||||
data->jsgraph(), data->schedule(), temp_zone, data->source_positions(),
|
||||
data->node_origins(), data->info()->GetPoisoningMitigationLevel());
|
||||
machine_lowering.Run();
|
||||
|
||||
// TODO(rmcilroy) Avoid having to rebuild rpo_order on schedule each time.
|
||||
Scheduler::ComputeSpecialRPO(temp_zone, data->schedule());
|
||||
TraceSchedule(data->info(), data, data->schedule(),
|
||||
"machine lowered schedule");
|
||||
}
|
||||
};
|
||||
|
||||
@ -2498,19 +2528,20 @@ bool PipelineImpl::OptimizeGraphForMidTier(Linkage* linkage) {
|
||||
|
||||
data->BeginPhaseKind("V8.TFBlockBuilding");
|
||||
|
||||
Run<EffectControlLinearizationPhase>();
|
||||
RunPrintAndVerify(EffectControlLinearizationPhase::phase_name(), true);
|
||||
ComputeScheduledGraph();
|
||||
|
||||
Run<MidTierMachineLoweringPhase>();
|
||||
RunPrintAndVerify(MidTierMachineLoweringPhase::phase_name(), true);
|
||||
Run<ScheduledEffectControlLinearizationPhase>();
|
||||
RunPrintAndVerify(ScheduledEffectControlLinearizationPhase::phase_name(),
|
||||
true);
|
||||
|
||||
Run<ScheduledMachineLoweringPhase>();
|
||||
RunPrintAndVerify(ScheduledMachineLoweringPhase::phase_name(), true);
|
||||
|
||||
data->source_positions()->RemoveDecorator();
|
||||
if (data->info()->trace_turbo_json_enabled()) {
|
||||
data->node_origins()->RemoveDecorator();
|
||||
}
|
||||
|
||||
ComputeScheduledGraph();
|
||||
|
||||
return SelectInstructions(linkage);
|
||||
}
|
||||
|
||||
|
69
src/compiler/scheduled-machine-lowering.cc
Normal file
69
src/compiler/scheduled-machine-lowering.cc
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/scheduled-machine-lowering.h"
|
||||
|
||||
#include "src/compiler/compiler-source-position-table.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/node-origin-table.h"
|
||||
#include "src/compiler/node-properties.h"
|
||||
#include "src/compiler/schedule.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
ScheduledMachineLowering::ScheduledMachineLowering(
|
||||
JSGraph* js_graph, Schedule* schedule, Zone* temp_zone,
|
||||
SourcePositionTable* source_positions, NodeOriginTable* node_origins,
|
||||
PoisoningMitigationLevel poison_level)
|
||||
: schedule_(schedule),
|
||||
graph_assembler_(js_graph, temp_zone, schedule),
|
||||
select_lowering_(&graph_assembler_, js_graph->graph()),
|
||||
memory_lowering_(js_graph, temp_zone, &graph_assembler_, poison_level),
|
||||
reducers_({&select_lowering_, &memory_lowering_}, temp_zone),
|
||||
source_positions_(source_positions),
|
||||
node_origins_(node_origins) {}
|
||||
|
||||
void ScheduledMachineLowering::Run() {
|
||||
// TODO(rmcilroy) We should not depend on having rpo_order on schedule, and
|
||||
// instead just do our own RPO walk here.
|
||||
for (BasicBlock* block : *(schedule()->rpo_order())) {
|
||||
BasicBlock::iterator instr = block->begin();
|
||||
BasicBlock::iterator end_instr = block->end();
|
||||
gasm()->Reset(block);
|
||||
|
||||
for (; instr != end_instr; instr++) {
|
||||
Node* node = *instr;
|
||||
Reduction reduction;
|
||||
for (auto reducer : reducers_) {
|
||||
reduction = reducer->Reduce(node);
|
||||
if (reduction.Changed()) break;
|
||||
}
|
||||
if (reduction.Changed()) {
|
||||
Node* replacement = reduction.replacement();
|
||||
if (replacement != node) {
|
||||
// Replace all uses of node and kill the node to make sure we don't
|
||||
// leave dangling dead uses.
|
||||
NodeProperties::ReplaceUses(node, replacement,
|
||||
gasm()->current_effect(),
|
||||
gasm()->current_control());
|
||||
node->Kill();
|
||||
} else {
|
||||
gasm()->AddNode(replacement);
|
||||
}
|
||||
} else {
|
||||
gasm()->AddNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
gasm()->FinalizeCurrentBlock(block);
|
||||
}
|
||||
|
||||
schedule_->rpo_order()->clear();
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
51
src/compiler/scheduled-machine-lowering.h
Normal file
51
src/compiler/scheduled-machine-lowering.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_SCHEDULED_MACHINE_LOWERING_H_
|
||||
#define V8_COMPILER_SCHEDULED_MACHINE_LOWERING_H_
|
||||
|
||||
#include "src/compiler/graph-assembler.h"
|
||||
#include "src/compiler/memory-lowering.h"
|
||||
#include "src/compiler/select-lowering.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class NodeOriginTable;
|
||||
class Schedule;
|
||||
class SourcePositionTable;
|
||||
|
||||
// Performs machine lowering on an already scheduled graph.
|
||||
class ScheduledMachineLowering final {
|
||||
public:
|
||||
ScheduledMachineLowering(JSGraph* js_graph, Schedule* schedule,
|
||||
Zone* temp_zone,
|
||||
SourcePositionTable* source_positions,
|
||||
NodeOriginTable* node_origins,
|
||||
PoisoningMitigationLevel poison_level);
|
||||
~ScheduledMachineLowering() = default;
|
||||
|
||||
void Run();
|
||||
|
||||
private:
|
||||
bool LowerNode(Node* node);
|
||||
|
||||
GraphAssembler* gasm() { return &graph_assembler_; }
|
||||
Schedule* schedule() { return schedule_; }
|
||||
|
||||
Schedule* schedule_;
|
||||
GraphAssembler graph_assembler_;
|
||||
SelectLowering select_lowering_;
|
||||
MemoryLowering memory_lowering_;
|
||||
ZoneVector<Reducer*> reducers_;
|
||||
SourcePositionTable* source_positions_;
|
||||
NodeOriginTable* node_origins_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_SCHEDULED_MACHINE_LOWERING_H_
|
@ -6,27 +6,28 @@
|
||||
|
||||
#include "src/compiler/common-operator.h"
|
||||
#include "src/compiler/diamond.h"
|
||||
#include "src/compiler/graph-assembler.h"
|
||||
#include "src/compiler/graph.h"
|
||||
#include "src/compiler/node.h"
|
||||
#include "src/compiler/node-properties.h"
|
||||
#include "src/compiler/node.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
SelectLowering::SelectLowering(JSGraph* jsgraph, Zone* zone)
|
||||
: graph_assembler_(jsgraph, zone), start_(jsgraph->graph()->start()) {}
|
||||
SelectLowering::SelectLowering(GraphAssembler* graph_assembler, Graph* graph)
|
||||
: graph_assembler_(graph_assembler), start_(graph->start()) {}
|
||||
|
||||
SelectLowering::~SelectLowering() = default;
|
||||
|
||||
Reduction SelectLowering::Reduce(Node* node) {
|
||||
if (node->opcode() != IrOpcode::kSelect) return NoChange();
|
||||
return Changed(LowerSelect(node));
|
||||
return LowerSelect(node);
|
||||
}
|
||||
|
||||
#define __ gasm()->
|
||||
|
||||
Node* SelectLowering::LowerSelect(Node* node) {
|
||||
Reduction SelectLowering::LowerSelect(Node* node) {
|
||||
SelectParameters const p = SelectParametersOf(node->op());
|
||||
|
||||
Node* condition = node->InputAt(0);
|
||||
@ -41,7 +42,7 @@ Node* SelectLowering::LowerSelect(Node* node) {
|
||||
__ Goto(&done, vfalse);
|
||||
__ Bind(&done);
|
||||
|
||||
return done.PhiAt(0);
|
||||
return Changed(done.PhiAt(0));
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
@ -5,30 +5,32 @@
|
||||
#ifndef V8_COMPILER_SELECT_LOWERING_H_
|
||||
#define V8_COMPILER_SELECT_LOWERING_H_
|
||||
|
||||
#include "src/compiler/graph-assembler.h"
|
||||
#include "src/compiler/graph-reducer.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
// Forward declarations.
|
||||
class GraphAssembler;
|
||||
|
||||
// Lowers Select nodes to diamonds.
|
||||
class SelectLowering final : public Reducer {
|
||||
public:
|
||||
SelectLowering(JSGraph* jsgraph, Zone* zone);
|
||||
SelectLowering(GraphAssembler* graph_assembler, Graph* graph);
|
||||
~SelectLowering() override;
|
||||
|
||||
const char* reducer_name() const override { return "SelectLowering"; }
|
||||
|
||||
Reduction Reduce(Node* node) override;
|
||||
|
||||
Node* LowerSelect(Node* node);
|
||||
|
||||
private:
|
||||
GraphAssembler* gasm() { return &graph_assembler_; }
|
||||
Node* start() { return start_; }
|
||||
Reduction LowerSelect(Node* node);
|
||||
|
||||
GraphAssembler graph_assembler_;
|
||||
GraphAssembler* gasm() const { return graph_assembler_; }
|
||||
Node* start() const { return start_; }
|
||||
|
||||
GraphAssembler* graph_assembler_;
|
||||
Node* start_;
|
||||
};
|
||||
|
||||
|
@ -85,9 +85,9 @@ TEST_F(EffectControlLinearizerTest, SimpleLoad) {
|
||||
schedule.AddReturn(start, ret);
|
||||
|
||||
// Run the state effect introducer.
|
||||
LinearizeEffectControl(jsgraph(), &schedule, zone(), source_positions(),
|
||||
node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex);
|
||||
LinearizeEffectControl(
|
||||
jsgraph(), &schedule, zone(), source_positions(), node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex, MaintainSchedule::kDiscard);
|
||||
|
||||
EXPECT_THAT(load,
|
||||
IsLoadField(AccessBuilder::ForHeapNumberValue(), heap_number,
|
||||
@ -147,9 +147,9 @@ TEST_F(EffectControlLinearizerTest, DiamondLoad) {
|
||||
schedule.AddReturn(mblock, ret);
|
||||
|
||||
// Run the state effect introducer.
|
||||
LinearizeEffectControl(jsgraph(), &schedule, zone(), source_positions(),
|
||||
node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex);
|
||||
LinearizeEffectControl(
|
||||
jsgraph(), &schedule, zone(), source_positions(), node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex, MaintainSchedule::kDiscard);
|
||||
|
||||
// The effect input to the return should be an effect phi with the
|
||||
// newly introduced effectful change operators.
|
||||
@ -214,9 +214,9 @@ TEST_F(EffectControlLinearizerTest, LoopLoad) {
|
||||
schedule.AddReturn(rblock, ret);
|
||||
|
||||
// Run the state effect introducer.
|
||||
LinearizeEffectControl(jsgraph(), &schedule, zone(), source_positions(),
|
||||
node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex);
|
||||
LinearizeEffectControl(
|
||||
jsgraph(), &schedule, zone(), source_positions(), node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex, MaintainSchedule::kDiscard);
|
||||
|
||||
ASSERT_THAT(ret, IsReturn(load, load, if_true));
|
||||
EXPECT_THAT(load, IsLoadField(AccessBuilder::ForHeapNumberValue(),
|
||||
@ -277,9 +277,9 @@ TEST_F(EffectControlLinearizerTest, CloneBranch) {
|
||||
schedule.AddNode(mblock, merge);
|
||||
schedule.AddNode(mblock, graph()->end());
|
||||
|
||||
LinearizeEffectControl(jsgraph(), &schedule, zone(), source_positions(),
|
||||
node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex);
|
||||
LinearizeEffectControl(
|
||||
jsgraph(), &schedule, zone(), source_positions(), node_origins(),
|
||||
MaskArrayIndexEnable::kDoNotMaskArrayIndex, MaintainSchedule::kDiscard);
|
||||
|
||||
Capture<Node *> branch1_capture, branch2_capture;
|
||||
EXPECT_THAT(
|
||||
|
Loading…
Reference in New Issue
Block a user