[wasm-gc] Clean up workarounds in optimizations

Earlier, we had to introduce some temporary workarounds in Turbofan to
enable optimizations for common wasm-gc patterns. These are now not
required, since these optimizations are applied in WasmTyper and WasmGCOperatorReducer.

Bug: v8:7748
Change-Id: I3a7bc4bd2a8023a438ee4620934ff3fcb8bcfc6a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3693999
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81011}
This commit is contained in:
Manos Koukoutos 2022-06-08 20:28:08 +00:00 committed by V8 LUCI CQ
parent cd21627b16
commit 31ece3e9e4
8 changed files with 12 additions and 151 deletions

View File

@ -15,15 +15,12 @@ namespace internal {
namespace compiler {
BranchElimination::BranchElimination(Editor* editor, JSGraph* js_graph,
Zone* zone,
SourcePositionTable* source_positions,
Phase phase)
Zone* zone, Phase phase)
: AdvancedReducer(editor),
jsgraph_(js_graph),
node_conditions_(js_graph->graph()->NodeCount(), zone),
reduced_(js_graph->graph()->NodeCount(), zone),
zone_(zone),
source_positions_(source_positions),
dead_(js_graph->Dead()),
phase_(phase) {}
@ -162,72 +159,6 @@ Reduction BranchElimination::ReduceBranch(Node* node) {
return TakeConditionsFromFirstControl(node);
}
// Simplify a trap following a merge.
// Assuming condition is in control1's path conditions, and !condition is in
// control2's path condtions, the following transformation takes place:
//
// control1 control2 condition effect1
// \ / \ / |
// Merge X | control1
// | / \ | /
// effect1 effect2 | | TrapIf control2
// \ | /| ==> | \ /
// EffectPhi | | effect2 Merge
// | / | | /
// condition | / \ | /
// \ | / EffectPhi
// TrapIf
// TODO(manoskouk): We require that the trap's effect input is the Merge's
// EffectPhi, so we can ensure that the new traps' effect inputs are not
// dominated by the Merge. Can we relax this?
bool BranchElimination::TryPullTrapIntoMerge(Node* node) {
DCHECK(node->opcode() == IrOpcode::kTrapIf ||
node->opcode() == IrOpcode::kTrapUnless);
Node* merge = NodeProperties::GetControlInput(node);
DCHECK_EQ(merge->opcode(), IrOpcode::kMerge);
Node* condition = NodeProperties::GetValueInput(node, 0);
Node* effect_input = NodeProperties::GetEffectInput(node);
if (!(effect_input->opcode() == IrOpcode::kEffectPhi &&
NodeProperties::GetControlInput(effect_input) == merge)) {
return false;
}
bool trapping_condition = node->opcode() == IrOpcode::kTrapIf;
base::SmallVector<Node*, 8> new_merge_inputs;
for (Edge edge : merge->input_edges()) {
Node* input = edge.to();
ControlPathConditions from_input = node_conditions_.Get(input);
Node* previous_branch;
bool condition_value;
if (!from_input.LookupCondition(condition, &previous_branch,
&condition_value)) {
return false;
}
if (condition_value == trapping_condition) {
Node* inputs[] = {
condition, NodeProperties::GetEffectInput(effect_input, edge.index()),
input};
Node* trap_clone = graph()->NewNode(node->op(), 3, inputs);
if (source_positions_) {
source_positions_->SetSourcePosition(
trap_clone, source_positions_->GetSourcePosition(node));
}
new_merge_inputs.emplace_back(trap_clone);
} else {
new_merge_inputs.emplace_back(input);
}
}
for (int i = 0; i < merge->InputCount(); i++) {
merge->ReplaceInput(i, new_merge_inputs[i]);
}
ReplaceWithValue(node, dead(), dead(), merge);
node->Kill();
Revisit(merge);
return true;
}
Reduction BranchElimination::ReduceTrapConditional(Node* node) {
DCHECK(node->opcode() == IrOpcode::kTrapIf ||
node->opcode() == IrOpcode::kTrapUnless);
@ -239,13 +170,6 @@ Reduction BranchElimination::ReduceTrapConditional(Node* node) {
// predecessor.
if (!reduced_.Get(control_input)) return NoChange();
// If the trap comes directly after a merge, pull it into the merge. This will
// unlock other optimizations later.
if (control_input->opcode() == IrOpcode::kMerge &&
TryPullTrapIntoMerge(node)) {
return Replace(dead());
}
ControlPathConditions from_input = node_conditions_.Get(control_input);
Node* previous_branch;
bool condition_value;

View File

@ -29,7 +29,7 @@ class V8_EXPORT_PRIVATE BranchElimination final
kLATE,
};
BranchElimination(Editor* editor, JSGraph* js_graph, Zone* zone,
SourcePositionTable* sourse_positions, Phase phase = kLATE);
Phase phase = kLATE);
~BranchElimination() final;
const char* reducer_name() const override { return "BranchElimination"; }
@ -109,7 +109,6 @@ class V8_EXPORT_PRIVATE BranchElimination final
Reduction ReduceStart(Node* node);
Reduction ReduceOtherControl(Node* node);
void SimplifyBranchCondition(Node* branch);
bool TryPullTrapIntoMerge(Node* node);
Reduction TakeConditionsFromFirstControl(Node* node);
Reduction UpdateConditions(Node* node, ControlPathConditions conditions);
@ -133,7 +132,6 @@ class V8_EXPORT_PRIVATE BranchElimination final
node_conditions_;
NodeAuxData<bool> reduced_;
Zone* zone_;
SourcePositionTable* source_positions_;
Node* dead_;
Phase phase_;
};

View File

@ -84,9 +84,8 @@ bool IsConstantObject(Node* object) {
}
bool IsFreshObject(Node* object) {
DCHECK_IMPLIES(NodeProperties::IsFreshObject(object),
!IsConstantObject(object));
return NodeProperties::IsFreshObject(object);
return object->opcode() == IrOpcode::kAllocate ||
object->opcode() == IrOpcode::kAllocateRaw;
}
} // namespace CsaLoadEliminationHelpers

View File

@ -289,22 +289,6 @@ Node* MachineOperatorReducer::TruncateInt64ToInt32(Node* value) {
return reduction.Changed() ? reduction.replacement() : node;
}
namespace {
bool ObjectsMayAlias(Node* a, Node* b) {
if (a != b) {
if (NodeProperties::IsFreshObject(b)) std::swap(a, b);
if (NodeProperties::IsFreshObject(a) &&
(NodeProperties::IsFreshObject(b) ||
b->opcode() == IrOpcode::kParameter ||
b->opcode() == IrOpcode::kLoadImmutable ||
IrOpcode::IsConstantOpcode(b->opcode()))) {
return false;
}
}
return true;
}
} // namespace
// Perform constant folding and strength reduction on machine operators.
Reduction MachineOperatorReducer::Reduce(Node* node) {
switch (node->opcode()) {
@ -360,11 +344,6 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
}
// TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
// This is a workaround for not having escape analysis for wasm
// (machine-level) turbofan graphs.
if (!ObjectsMayAlias(m.left().node(), m.right().node())) {
return ReplaceBool(false);
}
break;
}
case IrOpcode::kInt32Add:
@ -2080,11 +2059,6 @@ Reduction MachineOperatorReducer::ReduceWord32Equal(Node* node) {
return Changed(node);
}
}
// This is a workaround for not having escape analysis for wasm
// (machine-level) turbofan graphs.
if (!ObjectsMayAlias(m.left().node(), m.right().node())) {
return ReplaceBool(false);
}
return NoChange();
}

View File

@ -601,35 +601,6 @@ bool NodeProperties::AllValueInputsAreTyped(Node* node) {
return true;
}
// static
bool NodeProperties::IsFreshObject(Node* node) {
if (node->opcode() == IrOpcode::kAllocate ||
node->opcode() == IrOpcode::kAllocateRaw)
return true;
#if V8_ENABLE_WEBASSEMBLY
if (node->opcode() == IrOpcode::kCall) {
// TODO(manoskouk): Currently, some wasm builtins are called with in
// CallDescriptor::kCallWasmFunction mode. Make sure this is synced if the
// calling mechanism is refactored.
if (CallDescriptorOf(node->op())->kind() !=
CallDescriptor::kCallBuiltinPointer) {
return false;
}
NumberMatcher matcher(node->InputAt(0));
if (matcher.HasResolvedValue()) {
Builtin callee = static_cast<Builtin>(matcher.ResolvedValue());
// Note: Make sure to only add builtins which are guaranteed to return a
// fresh object. E.g. kWasmAllocateFixedArray may return the canonical
// empty array.
return callee == Builtin::kWasmAllocateArray_Uninitialized ||
callee == Builtin::kWasmAllocateStructWithRtt ||
callee == Builtin::kWasmAllocateObjectWrapper;
}
}
#endif // V8_ENABLE_WEBASSEMBLY
return false;
}
// static
bool NodeProperties::IsInputRange(Edge edge, int first, int num) {
if (num == 0) return false;

View File

@ -143,10 +143,6 @@ class V8_EXPORT_PRIVATE NodeProperties {
}
}
// Determines if {node} has an allocating opcode, or is a builtin known to
// return a fresh object.
static bool IsFreshObject(Node* node);
// ---------------------------------------------------------------------------
// Miscellaneous mutators.

View File

@ -1885,8 +1885,7 @@ struct LoadEliminationPhase {
temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
data->jsgraph()->Dead(), data->observe_node_manager());
BranchElimination branch_condition_elimination(
&graph_reducer, data->jsgraph(), temp_zone, data->source_positions(),
BranchElimination::kEARLY);
&graph_reducer, data->jsgraph(), temp_zone, BranchElimination::kEARLY);
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common(), temp_zone);
RedundancyElimination redundancy_elimination(&graph_reducer, temp_zone);
@ -1955,8 +1954,8 @@ struct LateOptimizationPhase {
data->jsgraph()->Dead(), data->observe_node_manager());
LateEscapeAnalysis escape_analysis(&graph_reducer, data->graph(),
data->common(), temp_zone);
BranchElimination branch_condition_elimination(
&graph_reducer, data->jsgraph(), temp_zone, data->source_positions());
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common(), temp_zone);
ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone());
@ -2152,7 +2151,7 @@ struct WasmOptimizationPhase {
data->machine(), temp_zone, BranchSemantics::kMachine);
ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone());
BranchElimination branch_condition_elimination(
&graph_reducer, data->jsgraph(), temp_zone, data->source_positions());
&graph_reducer, data->jsgraph(), temp_zone);
AddReducer(data, &graph_reducer, &machine_reducer);
AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &common_reducer);
@ -2207,7 +2206,7 @@ struct CsaEarlyOptimizationPhase {
data->machine(), temp_zone, BranchSemantics::kMachine);
ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone());
BranchElimination branch_condition_elimination(
&graph_reducer, data->jsgraph(), temp_zone, data->source_positions());
&graph_reducer, data->jsgraph(), temp_zone);
AddReducer(data, &graph_reducer, &machine_reducer);
AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &common_reducer);
@ -2225,8 +2224,8 @@ struct CsaOptimizationPhase {
GraphReducer graph_reducer(
temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
data->jsgraph()->Dead(), data->observe_node_manager());
BranchElimination branch_condition_elimination(
&graph_reducer, data->jsgraph(), temp_zone, data->source_positions());
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common(), temp_zone);
MachineOperatorReducer machine_reducer(&graph_reducer, data->jsgraph(),

View File

@ -31,7 +31,7 @@ class BranchEliminationTest : public GraphTest {
GraphReducer graph_reducer(zone(), graph(), tick_counter(), broker(),
jsgraph.Dead());
BranchElimination branch_condition_elimination(&graph_reducer, &jsgraph,
zone(), nullptr);
zone());
graph_reducer.AddReducer(&branch_condition_elimination);
graph_reducer.ReduceGraph();
}