|
FLANG
|
#include "flang/Optimizer/Builder/CUFCommon.h"#include "flang/Optimizer/Dialect/FIRDialect.h"#include "flang/Optimizer/Dialect/FIROps.h"#include "flang/Optimizer/Dialect/FIROpsSupport.h"#include "flang/Optimizer/Dialect/FIRType.h"#include "flang/Optimizer/Transforms/Passes.h"#include "mlir/Dialect/Arith/IR/Arith.h"#include "mlir/Dialect/OpenACC/OpenACC.h"#include "mlir/Dialect/OpenMP/OpenMPDialect.h"#include "mlir/IR/Builders.h"#include "mlir/Interfaces/LoopLikeInterface.h"#include "mlir/Pass/Pass.h"#include "llvm/ADT/Statistic.h"#include "llvm/Support/Debug.h"#include "flang/Optimizer/Transforms/Passes.h.inc"Namespaces | |
| namespace | fir |
Macros | |
| #define | GEN_PASS_DEF_LOOPTRIPCOUNTVERSIONING |
| #define | DEBUG_TYPE "flang-loop-tripcount-versioning" |
Versions an innermost loop whose runtime trip count is likely to equal a compile-time constant N:
if (ub == N) { copy of the loop with ub := N } else { original loop }
Both arms are the original loop with only the bound changed, so the transformation is legal wherever the guard is uniform, which holds on a CPU and not on a GPU: a thread-varying guard could split threads across two copies of a barrier, so device code is excluded. The constant trip count lets LLVM fully unroll the fast arm, or vectorize it without a remainder loop.
Heuristic: the loop variable is the leading subscript of an explicit-shape array whose declared leading extent N is at most max-section-extent. For a(1:m, :) = 0 with real :: a(4, n), the inner loop is versioned on m == 4. Loops are skipped when N times the number of FIR operations in the body exceeds max-unrolled-ops, a proxy for whether LLVM will fully unroll the fast arm. This runs on FIR, the only level where both the loop and the array's declared type exist.