mirror of
https://github.com/intel/llvm.git
synced 2026-02-05 13:21:04 +08:00
*) Factors slice union computation out of LoopFusion into Analysis/Utils (where other iteration slice utilities exist).
*) Generalizes slice union computation to take the union of slices computed on all loads/stores pairs between source and destination loop nests.
*) Fixes a bug in FlatAffineConstraints::addSliceBounds where redundant constraints were added.
*) Takes care of a TODO to expose FlatAffineConstraints::mergeAndAlignIds as a public method.
--
PiperOrigin-RevId: 250561529
115 lines
4.0 KiB
C++
115 lines
4.0 KiB
C++
//===- TestLoopFusion.cpp - Test loop fusion ------------------------------===//
|
|
//
|
|
// Copyright 2019 The MLIR Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// =============================================================================
|
|
//
|
|
// This file implements a pass to test various loop fusion utility functions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/AffineOps/AffineOps.h"
|
|
#include "mlir/Analysis/AffineAnalysis.h"
|
|
#include "mlir/Analysis/AffineStructures.h"
|
|
#include "mlir/Analysis/Passes.h"
|
|
#include "mlir/Analysis/Utils.h"
|
|
#include "mlir/IR/Builders.h"
|
|
#include "mlir/Pass/Pass.h"
|
|
#include "mlir/StandardOps/Ops.h"
|
|
#include "mlir/Transforms/LoopFusionUtils.h"
|
|
#include "mlir/Transforms/Passes.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#define DEBUG_TYPE "test-loop-fusion"
|
|
|
|
using namespace mlir;
|
|
|
|
static llvm::cl::OptionCategory clOptionsCategory(DEBUG_TYPE " options");
|
|
|
|
static llvm::cl::opt<bool> clTestDependenceCheck(
|
|
"test-loop-fusion-dependence-check",
|
|
llvm::cl::desc("Enable testing of loop fusion dependence check"),
|
|
llvm::cl::cat(clOptionsCategory));
|
|
|
|
namespace {
|
|
|
|
struct TestLoopFusion : public FunctionPass<TestLoopFusion> {
|
|
void runOnFunction() override;
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
FunctionPassBase *mlir::createTestLoopFusionPass() {
|
|
return new TestLoopFusion;
|
|
}
|
|
|
|
// Gathers all AffineForOps in 'block' at 'currLoopDepth' in 'depthToLoops'.
|
|
static void
|
|
gatherLoops(Block *block, unsigned currLoopDepth,
|
|
DenseMap<unsigned, SmallVector<AffineForOp, 2>> &depthToLoops) {
|
|
auto &loopsAtDepth = depthToLoops[currLoopDepth];
|
|
for (auto &op : *block) {
|
|
if (auto forOp = dyn_cast<AffineForOp>(op)) {
|
|
loopsAtDepth.push_back(forOp);
|
|
gatherLoops(forOp.getBody(), currLoopDepth + 1, depthToLoops);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run fusion dependence check on 'loops[i]' and 'loops[j]' at 'loopDepth'.
|
|
// Emits a remark on 'loops[i]' if a fusion-preventing dependence exists.
|
|
static void testDependenceCheck(SmallVector<AffineForOp, 2> &loops, unsigned i,
|
|
unsigned j, unsigned loopDepth) {
|
|
AffineForOp srcForOp = loops[i];
|
|
AffineForOp dstForOp = loops[j];
|
|
mlir::ComputationSliceState sliceUnion;
|
|
// TODO(andydavis) Test at deeper loop depths current loop depth + 1.
|
|
FusionResult result =
|
|
mlir::canFuseLoops(srcForOp, dstForOp, loopDepth + 1, &sliceUnion);
|
|
if (result.value == FusionResult::FailBlockDependence) {
|
|
srcForOp.getOperation()->emitRemark("block-level dependence preventing"
|
|
" fusion of loop nest ")
|
|
<< i << " into loop nest " << j << " at depth " << loopDepth;
|
|
}
|
|
}
|
|
|
|
void TestLoopFusion::runOnFunction() {
|
|
// Gather all AffineForOps by loop depth.
|
|
DenseMap<unsigned, SmallVector<AffineForOp, 2>> depthToLoops;
|
|
for (auto &block : getFunction()) {
|
|
gatherLoops(&block, /*currLoopDepth=*/0, depthToLoops);
|
|
}
|
|
|
|
// Run tests on all combinations of src/dst loop nests in 'depthToLoops'.
|
|
for (auto &depthAndLoops : depthToLoops) {
|
|
unsigned loopDepth = depthAndLoops.first;
|
|
auto &loops = depthAndLoops.second;
|
|
unsigned numLoops = loops.size();
|
|
for (unsigned j = 0; j < numLoops; ++j) {
|
|
for (unsigned k = 0; k < numLoops; ++k) {
|
|
if (j == k)
|
|
continue;
|
|
if (clTestDependenceCheck)
|
|
testDependenceCheck(loops, j, k, loopDepth);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static PassRegistration<TestLoopFusion>
|
|
pass("test-loop-fusion", "Tests loop fusion utility functions.");
|