[wasm] Fix loop unrolling being skipped

As part of https://crrev.com/c/4200642 loop peeling was enabled for
loops containing a getCodeUnit instruction.
As a side effect this also affected loop unrolling now only happening
if getCodeUnit was used in the loop body which is fixed by this
change.

Bug: chromium:1412781
Change-Id: I60e3a524340cfbdb907ae2ee5b46cbb6f514775c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4219103
Auto-Submit: Matthias Liedtke <mliedtke@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Manos Koukoutos <manoskouk@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85671}
This commit is contained in:
Matthias Liedtke 2023-02-03 16:37:00 +01:00 committed by V8 LUCI CQ
parent 81857203e9
commit 65a0aaab04
3 changed files with 12 additions and 8 deletions

View File

@ -554,7 +554,7 @@ LoopTree* LoopFinder::BuildLoopTree(Graph* graph, TickCounter* tick_counter,
// static
ZoneUnorderedSet<Node*>* LoopFinder::FindSmallInnermostLoopFromHeader(
Node* loop_header, AllNodes& all_nodes, Zone* zone, size_t max_size,
bool calls_are_large) {
Purpose purpose) {
auto* visited = zone->New<ZoneUnorderedSet<Node*>>(zone);
std::vector<Node*> queue;
@ -598,16 +598,16 @@ ZoneUnorderedSet<Node*>* LoopFinder::FindSmallInnermostLoopFromHeader(
}
// All uses are outside the loop, do nothing.
break;
// If {calls_are_large}, call nodes are considered to have unbounded size,
// If unrolling, call nodes are considered to have unbounded size,
// i.e. >max_size, with the exception of certain wasm builtins.
case IrOpcode::kTailCall:
case IrOpcode::kJSWasmCall:
case IrOpcode::kJSCall:
if (calls_are_large) return nullptr;
if (purpose == Purpose::kLoopUnrolling) return nullptr;
ENQUEUE_USES(use, true)
break;
case IrOpcode::kCall: {
if (!calls_are_large) {
if (purpose == Purpose::kLoopPeeling) {
ENQUEUE_USES(use, true);
break;
}
@ -679,7 +679,7 @@ ZoneUnorderedSet<Node*>* LoopFinder::FindSmallInnermostLoopFromHeader(
// Only peel functions containing instructions for which loop peeling is known
// to be useful. TODO(7748): Add more instructions to get more benefits out of
// loop peeling.
if (!has_instruction_worth_peeling) {
if (purpose == Purpose::kLoopPeeling && !has_instruction_worth_peeling) {
return nullptr;
}
return visited;

View File

@ -181,6 +181,8 @@ class V8_EXPORT_PRIVATE LoopFinder {
static bool HasMarkedExits(LoopTree* loop_tree, const LoopTree::Loop* loop);
#if V8_ENABLE_WEBASSEMBLY
enum class Purpose { kLoopPeeling, kLoopUnrolling };
// Find all nodes in the loop headed by {loop_header} if it contains no nested
// loops.
// Assumption: *if* this loop has no nested loops, all exits from the loop are
@ -192,7 +194,7 @@ class V8_EXPORT_PRIVATE LoopFinder {
// 3) a nested loop is found in the loop.
static ZoneUnorderedSet<Node*>* FindSmallInnermostLoopFromHeader(
Node* loop_header, AllNodes& all_nodes, Zone* zone, size_t max_size,
bool calls_are_large);
Purpose purpose);
#endif
};

View File

@ -1733,7 +1733,8 @@ struct WasmLoopUnrollingPhase {
loop_info.header, all_nodes, temp_zone,
// Only discover the loop until its size is the maximum unrolled
// size for its depth.
maximum_unrollable_size(loop_info.nesting_depth), true);
maximum_unrollable_size(loop_info.nesting_depth),
LoopFinder::Purpose::kLoopUnrolling);
if (loop == nullptr) continue;
UnrollLoop(loop_info.header, loop, loop_info.nesting_depth, data->graph(),
data->common(), temp_zone, data->source_positions(),
@ -1755,7 +1756,8 @@ struct WasmLoopPeelingPhase {
ZoneUnorderedSet<Node*>* loop =
LoopFinder::FindSmallInnermostLoopFromHeader(
loop_info.header, all_nodes, temp_zone,
v8_flags.wasm_loop_peeling_max_size, false);
v8_flags.wasm_loop_peeling_max_size,
LoopFinder::Purpose::kLoopPeeling);
if (loop == nullptr) continue;
PeelWasmLoop(loop_info.header, loop, data->graph(), data->common(),
temp_zone, data->source_positions(), data->node_origins());