Files
clang-p2996/mlir/lib/Dialect/SCF/Transforms/RotateWhileLoop.cpp
Victor Perez e8f07cdb57 [MLIR][SCF] Define -scf-rotate-while pass (#99850)
Define SCF dialect patterns rotating `scf.while` loops leveraging
existing `mlir::scf::wrapWhileLoopInZeroTripCheck`. `forceCreateCheck`
is always `false` as the pattern would lead to an infinite recursion
otherwise.

This pattern rotates `scf.while` ops, mutating them from "while" loops to
"do-while" loops. A guard checking the condition for the first iteration
is inserted. Note this guard can be optimized away if the compiler can
prove the loop will be executed at least once.

Using this pattern, the following while loop:

```mlir
scf.while (%arg0 = %init) : (i32) -> i64 {
  %val = .., %arg0 : i64
  %cond = arith.cmpi .., %arg0 : i32
  scf.condition(%cond) %val : i64
} do {
^bb0(%arg1: i64):
  %next = .., %arg1 : i32
  scf.yield %next : i32
}
```

Can be transformed into:

``` mlir
%pre_val = .., %init : i64
%pre_cond = arith.cmpi .., %init : i32
scf.if %pre_cond -> i64 {
  %res = scf.while (%arg1 = %va0) : (i64) -> i64 {
    // Original after block
    %next = .., %arg1 : i32
    // Original before block
    %val = .., %next : i64
    %cond = arith.cmpi .., %next : i32
    scf.condition(%cond) %val : i64
  } do {
  ^bb0(%arg2: i64):
    %scf.yield %arg2 : i32
  }
  scf.yield %res : i64
} else {
  scf.yield %pre_val : i64
}
```

The test pass for `wrapWhileLoopInZeroTripCheck` has been modified to
use the new pattern when `forceCreateCheck=false`.

---------

Signed-off-by: Victor Perez <victor.perez@codeplay.com>
2024-07-30 10:06:01 +02:00

45 lines
1.6 KiB
C++

//===- RotateWhileLoop.cpp - scf.while loop rotation ----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Rotates `scf.while` loops.
//
//===----------------------------------------------------------------------===//
#include "mlir/Dialect/SCF/Transforms/Patterns.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
using namespace mlir;
namespace {
struct RotateWhileLoopPattern : OpRewritePattern<scf::WhileOp> {
using OpRewritePattern<scf::WhileOp>::OpRewritePattern;
LogicalResult matchAndRewrite(scf::WhileOp whileOp,
PatternRewriter &rewriter) const final {
// Setting this option would lead to infinite recursion on a greedy driver
// as 'do-while' loops wouldn't be skipped.
constexpr bool forceCreateCheck = false;
FailureOr<scf::WhileOp> result =
scf::wrapWhileLoopInZeroTripCheck(whileOp, rewriter, forceCreateCheck);
// scf::wrapWhileLoopInZeroTripCheck hasn't yet implemented a failure
// mechanism. 'do-while' loops are simply returned unmodified. In order to
// stop recursion, we check input and output operations differ.
return success(succeeded(result) && *result != whileOp);
}
};
} // namespace
namespace mlir {
namespace scf {
void populateSCFRotateWhileLoopPatterns(RewritePatternSet &patterns) {
patterns.add<RotateWhileLoopPattern>(patterns.getContext());
}
} // namespace scf
} // namespace mlir