class AffineForOp;
struct LogicalResult;
-namespace linalg {
+namespace loop {
class ForOp;
-}
+} // end namespace loop
/// Convert a perfect affine loop nest with the outermost loop identified by
/// `forOp` into a gpu::Launch operation. Map `numBlockDims` outer loops to
/// parallelization is performed, it is under the responsibility of the caller
/// to strip-mine the loops and to perform the dependence analysis before
/// calling the conversion.
-LogicalResult convertLinalgLoopNestToGPULaunch(linalg::ForOp forOp,
- unsigned numBlockDims,
- unsigned numThreadDims);
+LogicalResult convertLoopNestToGPULaunch(loop::ForOp forOp,
+ unsigned numBlockDims,
+ unsigned numThreadDims);
} // namespace mlir
#endif // MLIR_CONVERSION_LOOPSTOGPU_LOOPSTOGPU_H_
Usage:
linalg.copy(%arg0, %arg1) : !linalg.view<?xf32>, !linalg.view<?xf32>
- One possible lowering to affine form is:
+ One possible lowering to loop form is:
%0 = linalg.dim %arg0, 0 : index
- linalg.for %i0 = %c0 to %0 step %c1 {
+ loop.for %i0 = %c0 to %0 step %c1 {
%1 = linalg.load %arg0[%i0] : !linalg.view<?xf32>
linalg.store %1, %arg1[%i0] : !linalg.view<?xf32>
}
outputPermutation : (i, j, k) -> (k, j, i)} :
!linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- One possible lowering to affine form is:
+ One possible lowering to loop form is:
%0 = linalg.dim %arg0, 0
%1 = linalg.dim %arg0, 1
%2 = linalg.dim %arg0, 2
- linalg.for %i0 = %c0 to %{{.*}} step %c1 {
- linalg.for %i1 = %c0 to %{{.*}} step %c1 {
- linalg.for %i2 = %c0 to %{{.*}} step %c1 {
+ loop.for %i0 = %c0 to %{{.*}} step %c1 {
+ loop.for %i1 = %c0 to %{{.*}} step %c1 {
+ loop.for %i2 = %c0 to %{{.*}} step %c1 {
%3 = linalg.load %arg0[%i0, %i2, %i1] : !linalg.view<?x?x?xf32>
linalg.store %3, %arg1[%i2, %i1, %i0] : !linalg.view<?x?x?xf32>
namespace linalg {
-/// The "linalg.for" operation represents a loop nest taking 3 SSA value as
-/// operands that represent the lower bound, upper bound and step respectively.
-/// The operation defines an SSA value for its induction variable. It has one
-/// region capturing the loop body. The induction variable is represented as an
-/// argument of this region. This SSA value always has type index, which is the
-/// size of the machine word. The step is a value of type index, required to be
-/// positive.
-/// The lower and upper bounds specify a half-open range: the range includes the
-/// lower bound but does not include the upper bound.
-///
-/// The body region must contain exactly one block that terminates with
-/// "linalg.terminator". Calling linalg::ForOp::build will create such region
-/// and insert the terminator, so will the parsing even in cases if it is absent
-/// from the custom format. For example:
-///
-/// ```mlir
-/// linalg.for %iv = %lb to %ub step %step {
-/// ... // body
-/// }
-/// ```
-class ForOp
- : public Op<ForOp, OpTrait::NOperands<3>::Impl, OpTrait::ZeroResult> {
-public:
- using Op::Op;
-
- // Hooks to customize behavior of this op.
- static void build(Builder *builder, OperationState *result, Value *lb,
- Value *ub, Value *step);
- LogicalResult verify();
- static ParseResult parse(OpAsmParser *parser, OperationState *result);
- void print(OpAsmPrinter *p);
-
- static StringRef getOperationName() { return "linalg.for"; }
-
- /// Return a Builder set up to insert operations immediately before the
- /// terminator.
- OpBuilder getBodyBuilder() {
- Block *body = getBody();
- return OpBuilder(body, std::prev(body->end()));
- }
-
- /// Get the body of the ForOp.
- Block *getBody() { return &getRegion().front(); }
-
- /// Get the body region of the ForOp.
- Region &getRegion() { return getOperation()->getRegion(0); }
-
- /// Returns the induction variable for this loop.
- Value *getInductionVar() { return getBody()->getArgument(0); }
-
- //===--------------------------------------------------------------------===//
- // Bounds and step
- //===--------------------------------------------------------------------===//
- /// Returns the lower bound operand.
- Value *getLowerBound() { return getOperand(0); }
-
- /// Returns the upper bound operand.
- Value *getUpperBound() { return getOperand(1); }
-
- /// Returns loop step.
- Value *getStep() { return getOperand(2); }
-
- /// Set lower bound.
- void setLowerBound(Value *lb) { setOperand(0, lb); }
-
- /// Set upper bound.
- void setUpperBound(Value *ub) { setOperand(1, ub); }
-
- /// Set loop step.
- void setStep(Value *step) { setOperand(2, step); }
-};
-
-/// Returns the loop parent of an induction variable. If the provided value is
-/// not an induction variable, then return nullptr.
-ForOp getForInductionVarOwner(Value *val);
-
/// A linalg.LoadOp is the counterpart of load but operating on ViewType
/// instead of MemRefType.
///
}]>];
}
-def TerminatorOp :
- Linalg_Op<"terminator", [NativeOpTrait<"IsTerminator">]> {
- let summary = "linalg terminator operation";
- let description = [{
- "linalg.terminator" is a special terminator operation for blocks inside
- linalg loops and branches. It unconditionally transmits the control flow to
- the successor of the operation enclosing the region.
-
- This operation does _not_ have a custom syntax. However, linalg control
- operations omit the terminator in their custom syntax for brevity.
-
- linalg.terminator
- }];
-
- // No custom parsing/printing form.
- let parser = ?;
- let printer = ?;
-
- // Fully specified by traits.
- let verifier = ?;
-}
-
def SubViewOp : Linalg_Op<"subview", [NoSideEffect]>,
Arguments<(ins View:$view, Variadic<Index>:$ranges)>,
Results<(outs View)> {
#ifndef MLIR_LINALG_UTILS_H_
#define MLIR_LINALG_UTILS_H_
+#include "mlir/Dialect/LoopOps/LoopOps.h"
#include "mlir/EDSC/Helpers.h"
#include "mlir/Linalg/IR/LinalgOps.h"
#include "mlir/Support/LLVM.h"
class AffineExpr;
class AffineMap;
class OperationFolder;
+
namespace edsc {
-/// A LoopRangeBuilder is a generic NestedBuilder for linalg.for operations.
+/// A LoopRangeBuilder is a generic NestedBuilder for loop.for operations.
/// More specifically it is meant to be used as a temporary object for
/// representing any nested MLIR construct that is "related to" an mlir::Value*
/// (for now an induction variable).
class LoopRangeBuilder : public NestedBuilder {
public:
- /// Constructs a new linalg::ForOp and captures the associated induction
+ /// Constructs a new loop.for and captures the associated induction
/// variable. A ValueHandle pointer is passed as the first argument and is the
/// *only* way to capture the loop induction variable.
LoopRangeBuilder(ValueHandle *iv, ValueHandle range);
ValueHandle operator()(std::function<void(void)> fun = nullptr);
};
-/// Helper class to sugar building linalg.for loop nests from ranges.
+/// Helper class to sugar building loop.for loop nests from ranges.
/// This is similar to edsc::LoopNestBuilder except it works on ranges directly.
-/// In the current implementation it produces linalg.for operations.
+/// In the current implementation it produces loop.for operations.
class LoopNestRangeBuilder {
public:
LoopNestRangeBuilder(llvm::ArrayRef<edsc::ValueHandle *> ivs,
struct TiledLinalgOp {
LinalgOp op;
- SmallVector<ForOp, 8> loops;
+ SmallVector<loop::ForOp, 8> loops;
};
/// Performs standalone tiling of a single LinalgOp by `tileSizes`.
// limitations under the License.
// =============================================================================
//
-// This file implements a pass to convert std.for, std.if and std.terminator ops
-// into standard CFG ops.
+// This file implements a pass to convert loop.for, loop.if and loop.terminator
+// ops into standard CFG ops.
//
//===----------------------------------------------------------------------===//
// first/last blocks in the parent region. The original loop operation is
// replaced by the initialization operations that set up the initial value of
// the loop induction variable (%iv) and computes the loop bounds that are loop-
-// invariant for affine loops. The operations following the original std.for
+// invariant for affine loops. The operations following the original loop.for
// are split out into a separate continuation (exit) block. A condition block is
// created before the continuation block. It checks the exit condition of the
// loop and branches either to the continuation block, or to the first block of
PatternRewriter &rewriter) const override;
};
-// Create a CFG subgraph for the std.if operation (including its "then" and
+// Create a CFG subgraph for the loop.if operation (including its "then" and
// optional "else" operation blocks). We maintain the invariants that the
// subgraph has a single entry and a single exit point, and that the entry/exit
// blocks are respectively the first/last block of the enclosing region. The
-// operations following the std.if are split into a continuation (subgraph
+// operations following the loop.if are split into a continuation (subgraph
// exit) block. The condition is lowered to a chain of blocks that implement the
// short-circuit scheme. Condition blocks are created by splitting out an empty
-// block from the block that contains the std.if operation. They
+// block from the block that contains the loop.if operation. They
// conditionally branch to either the first block of the "then" region, or to
// the first block of the "else" region. If the latter is absent, they branch
// to the continuation block instead. The last blocks of "then" and "else"
auto ifOp = cast<IfOp>(op);
auto loc = op->getLoc();
- // Start by splitting the block containing the 'std.if' into two parts.
+ // Start by splitting the block containing the 'loop.if' into two parts.
// The part before will contain the condition, the part after will be the
// continuation point.
auto *condBlock = rewriter.getInsertionBlock();
auto opPosition = rewriter.getInsertionPoint();
auto *continueBlock = rewriter.splitBlock(condBlock, opPosition);
- // Move blocks from the "then" region to the region containing 'std.if',
+ // Move blocks from the "then" region to the region containing 'loop.if',
// place it before the continuation block, and branch to it.
auto &thenRegion = ifOp.thenRegion();
auto *thenBlock = &thenRegion.front();
rewriter.inlineRegionBefore(thenRegion, continueBlock);
// Move blocks from the "else" region (if present) to the region containing
- // 'std.if', place it before the continuation block and branch to it. It
+ // 'loop.if', place it before the continuation block and branch to it. It
// will be placed after the "then" regions.
auto *elseBlock = continueBlock;
auto &elseRegion = ifOp.elseRegion();
#include "mlir/Conversion/LoopsToGPU/LoopsToGPU.h"
#include "mlir/AffineOps/AffineOps.h"
+#include "mlir/Dialect/LoopOps/LoopOps.h"
#include "mlir/GPU/GPUDialect.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/Builders.h"
-#include "mlir/Linalg/IR/LinalgOps.h"
#include "mlir/StandardOps/Ops.h"
#include "mlir/Transforms/LowerAffine.h"
#include "mlir/Transforms/RegionUtils.h"
#define DEBUG_TYPE "loops-to-gpu"
using namespace mlir;
+using namespace mlir::loop;
// Extract an indexed value from KernelDim3.
static Value *getDim3Value(const gpu::KernelDim3 &dim3, unsigned pos) {
static Operation::operand_range getLowerBoundOperands(AffineForOp forOp) {
return forOp.getLowerBoundOperands();
}
-static SmallVector<Value *, 1> getLowerBoundOperands(linalg::ForOp forOp) {
- SmallVector<Value *, 1> bounds(1, forOp.getLowerBound());
+static SmallVector<Value *, 1> getLowerBoundOperands(ForOp forOp) {
+ SmallVector<Value *, 1> bounds(1, forOp.lowerBound());
return bounds;
}
static Operation::operand_range getUpperBoundOperands(AffineForOp forOp) {
return forOp.getUpperBoundOperands();
}
-static SmallVector<Value *, 1> getUpperBoundOperands(linalg::ForOp forOp) {
- SmallVector<Value *, 1> bounds(1, forOp.getUpperBound());
+static SmallVector<Value *, 1> getUpperBoundOperands(ForOp forOp) {
+ SmallVector<Value *, 1> bounds(1, forOp.upperBound());
return bounds;
}
static Value *getOrCreateStep(AffineForOp forOp, OpBuilder &builder) {
return builder.create<ConstantIndexOp>(forOp.getLoc(), forOp.getStep());
}
-static Value *getOrCreateStep(linalg::ForOp forOp, OpBuilder &) {
- return forOp.getStep();
-}
+static Value *getOrCreateStep(ForOp forOp, OpBuilder &) { return forOp.step(); }
// Get a Value for the loop lower bound. If the value requires computation,
// materialize the instructions using builder.
static Value *getOrEmitLowerBound(AffineForOp forOp, OpBuilder &builder) {
return lowerAffineLowerBound(forOp, builder);
}
-static Value *getOrEmitLowerBound(linalg::ForOp forOp, OpBuilder &) {
- return forOp.getLowerBound();
+static Value *getOrEmitLowerBound(ForOp forOp, OpBuilder &) {
+ return forOp.lowerBound();
}
// Get a Value for the loop upper bound. If the value requires computation,
static Value *getOrEmitUpperBound(AffineForOp forOp, OpBuilder &builder) {
return lowerAffineUpperBound(forOp, builder);
}
-static Value *getOrEmitUpperBound(linalg::ForOp forOp, OpBuilder &) {
- return forOp.getUpperBound();
+static Value *getOrEmitUpperBound(ForOp forOp, OpBuilder &) {
+ return forOp.upperBound();
}
+// TODO(ntv): uniformize back once AffineForOp is in ODS.
+static Region &getRegion(ForOp op) { return op.region(); }
+static Region &getRegion(AffineForOp op) { return op.getRegion(); }
+static Block *getBody(ForOp op) { return op.body(); }
+static Block *getBody(AffineForOp op) { return op.getBody(); }
+
// Check the structure of the loop nest:
// - there are enough loops to map to numBlockDims + numThreadDims;
// - the loops are perfectly nested;
}
OpTy currentLoop = forOp;
- Region &limit = forOp.getRegion();
+ Region &limit = getRegion(forOp);
for (unsigned i = 0, e = numBlockDims + numThreadDims; i < e; ++i) {
- Operation *nested = ¤tLoop.getBody()->front();
+ Operation *nested = &getBody(currentLoop)->front();
if (!areValuesDefinedAbove(getLowerBoundOperands(currentLoop), limit) ||
!areValuesDefinedAbove(getUpperBoundOperands(currentLoop), limit))
return currentLoop.emitError(
if (i == e - 1)
break;
- auto begin = currentLoop.getBody()->begin(),
- end = currentLoop.getBody()->end();
- if (currentLoop.getBody()->empty() || std::next(begin, 2) != end)
+ auto begin = getBody(currentLoop)->begin(),
+ end = getBody(currentLoop)->end();
+ if (getBody(currentLoop)->empty() || std::next(begin, 2) != end)
return currentLoop.emitError(
"expected perfectly nested loops in the body");
steps.push_back(step);
if (i != numLoops - 1)
- currentLoop = cast<OpTy>(¤tLoop.getBody()->front());
+ currentLoop = cast<OpTy>(&getBody(currentLoop)->front());
}
return currentLoop;
}
// Still assuming perfect nesting so there are no values other than induction
// variables that are defined in one loop and used in deeper loops.
llvm::SetVector<Value *> valuesToForwardSet;
- getUsedValuesDefinedAbove(innermostForOp.getRegion(), rootForOp.getRegion(),
+ getUsedValuesDefinedAbove(getRegion(innermostForOp), getRegion(rootForOp),
valuesToForwardSet);
auto valuesToForward = valuesToForwardSet.takeVector();
auto originallyForwardedValues = valuesToForward.size();
// gpu return and move the operations from the loop body block to the gpu
// launch body block. Do not move the entire block because of the difference
// in block arguments.
- Operation &terminator = innermostForOp.getBody()->back();
+ Operation &terminator = getBody(innermostForOp)->back();
Location terminatorLoc = terminator.getLoc();
terminator.erase();
- builder.setInsertionPointToEnd(innermostForOp.getBody());
+ builder.setInsertionPointToEnd(getBody(innermostForOp));
builder.create<gpu::Return>(terminatorLoc);
launchOp.getBody().front().getOperations().splice(
launchOp.getBody().front().begin(),
- innermostForOp.getBody()->getOperations());
+ getBody(innermostForOp)->getOperations());
// Remap the loop iterators to use block/thread identifiers instead. Loops
// may iterate from LB with step S whereas GPU thread/block ids always iterate
LogicalResult mlir::convertAffineLoopNestToGPULaunch(AffineForOp forOp,
unsigned numBlockDims,
unsigned numThreadDims) {
- return convertLoopNestToGPULaunch(forOp, numBlockDims, numThreadDims);
+ return ::convertLoopNestToGPULaunch(forOp, numBlockDims, numThreadDims);
}
-LogicalResult mlir::convertLinalgLoopNestToGPULaunch(linalg::ForOp forOp,
- unsigned numBlockDims,
- unsigned numThreadDims) {
- return convertLoopNestToGPULaunch(forOp, numBlockDims, numThreadDims);
+LogicalResult mlir::convertLoopNestToGPULaunch(ForOp forOp,
+ unsigned numBlockDims,
+ unsigned numThreadDims) {
+ return ::convertLoopNestToGPULaunch(forOp, numBlockDims, numThreadDims);
}
#include "mlir/Conversion/LoopsToGPU/LoopsToGPUPass.h"
#include "mlir/AffineOps/AffineOps.h"
#include "mlir/Conversion/LoopsToGPU/LoopsToGPU.h"
-#include "mlir/Linalg/IR/LinalgOps.h"
+#include "mlir/Dialect/LoopOps/LoopOps.h"
#include "mlir/Pass/Pass.h"
#include "llvm/Support/CommandLine.h"
#define PASS_NAME "convert-loops-to-gpu"
using namespace mlir;
+using namespace mlir::loop;
static llvm::cl::OptionCategory clOptionsCategory(PASS_NAME " options");
static llvm::cl::opt<unsigned>
if (failed(convertAffineLoopNestToGPULaunch(forOp, numBlockDims,
numThreadDims)))
signalPassFailure();
- } else if (auto forOp = dyn_cast<linalg::ForOp>(&op)) {
- if (failed(convertLinalgLoopNestToGPULaunch(forOp, numBlockDims,
- numThreadDims)))
+ } else if (auto forOp = dyn_cast<ForOp>(&op)) {
+ if (failed(convertLoopNestToGPULaunch(forOp, numBlockDims,
+ numThreadDims)))
signalPassFailure();
}
}
//===----------------------------------------------------------------------===//
#include "mlir/Linalg/IR/LinalgOps.h"
+#include "mlir/Dialect/LoopOps/LoopOps.h"
#include "mlir/EDSC/Helpers.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
using namespace mlir::edsc::intrinsics;
using namespace mlir::linalg;
-////////////////////////////////////////////////////////////////////////////////
-// ForOp.
-////////////////////////////////////////////////////////////////////////////////
-// Check that if a "block" has a terminator, it is an `TerminatorOp`.
-static LogicalResult checkHasTerminator(OpState &op, Block &block) {
- if (block.empty() || isa<linalg::TerminatorOp>(block.back()))
- return success();
-
- return op.emitOpError("expects regions to end with '" +
- linalg::TerminatorOp::getOperationName() + "'")
- .attachNote()
- << "in custom textual format, the absence of terminator implies '"
- << linalg::TerminatorOp::getOperationName() << "'";
-}
-
-// Insert `linalg.terminator` at the end of the ForOp only region's only block
-// if it does not have a terminator already. If a new `linalg.terminator` is
-// inserted, the location is specified by `loc`. If the region is empty, insert
-// a new block first.
-static void ensureTerminator(Region ®ion, Builder &builder, Location loc) {
- impl::ensureRegionTerminator<linalg::TerminatorOp>(region, builder, loc);
-}
-
-void mlir::linalg::ForOp::build(Builder *builder, OperationState *result,
- Value *lb, Value *ub, Value *step) {
- result->addOperands({lb, ub, step});
- Region *bodyRegion = result->addRegion();
- Block *body = new Block();
- body->addArgument(IndexType::get(builder->getContext()));
- bodyRegion->push_back(body);
- ensureTerminator(*bodyRegion, *builder, result->location);
-}
-
-LogicalResult mlir::linalg::ForOp::verify() {
- if (!getLowerBound()->getType().isa<IndexType>())
- return emitOpError("lower bound operand must be an index");
- if (!getUpperBound()->getType().isa<IndexType>())
- return emitOpError("upper bound operand must be an index");
- if (!getStep()->getType().dyn_cast<IndexType>())
- return emitOpError("step operand must be an index");
- if (auto cst = dyn_cast_or_null<ConstantIndexOp>(getStep()->getDefiningOp()))
- if (cst.getValue() <= 0)
- return emitOpError("constant step operand must be positive");
-
- if (std::next(getOperation()->getRegions().begin()) !=
- getOperation()->getRegions().end())
- return emitOpError("operation expected to have exactly one region");
-
- auto &bodyRegion = getOperation()->getRegion(0);
- // The body region must contain a single basic block.
- if (bodyRegion.empty() || std::next(bodyRegion.begin()) != bodyRegion.end())
- return emitOpError("expected body region to have a single block");
- // Check that the body defines as single block argument for the induction
- // variable.
- auto *body = getBody();
- if (body->getNumArguments() != 1 ||
- !body->getArgument(0)->getType().isIndex())
- return emitOpError("expected body to have a single index argument for "
- "the induction variable");
- if (failed(checkHasTerminator(*this, *body)))
- return failure();
- return success();
-}
-
-void mlir::linalg::ForOp::print(OpAsmPrinter *p) {
- *p << getOperationName() << " " << *getInductionVar() << " = "
- << *getLowerBound() << " to " << *getUpperBound() << " step "
- << *getStep();
- p->printRegion(getRegion(),
- /*printEntryBlockArgs=*/false,
- /*printBlockTerminators=*/false);
- p->printOptionalAttrDict(getAttrs());
-}
-
-ParseResult mlir::linalg::ForOp::parse(OpAsmParser *parser,
- OperationState *result) {
- auto &builder = parser->getBuilder();
- OpAsmParser::OperandType inductionVariable, lb, ub, step;
- // Parse the induction variable followed by '='.
- if (parser->parseRegionArgument(inductionVariable) || parser->parseEqual())
- return failure();
-
- // Parse loop bounds.
- Type indexType = builder.getIndexType();
- if (parser->parseOperand(lb) ||
- parser->resolveOperand(lb, indexType, result->operands) ||
- parser->parseKeyword("to") || parser->parseOperand(ub) ||
- parser->resolveOperand(ub, indexType, result->operands) ||
- parser->parseKeyword("step") || parser->parseOperand(step) ||
- parser->resolveOperand(step, indexType, result->operands))
- return failure();
-
- // Parse the body region.
- Region *body = result->addRegion();
- if (parser->parseRegion(*body, inductionVariable, indexType))
- return failure();
-
- ensureTerminator(*body, builder, result->location);
-
- // Parse the optional attribute list.
- if (parser->parseOptionalAttributeDict(result->attributes))
- return failure();
-
- return success();
-}
-
-mlir::linalg::ForOp mlir::linalg::getForInductionVarOwner(Value *val) {
- auto *ivArg = dyn_cast<BlockArgument>(val);
- if (!ivArg)
- return ForOp();
- assert(ivArg->getOwner() && "unlinked block argument");
- return dyn_cast<ForOp>(ivArg->getOwner()->getContainingOp());
-}
-
////////////////////////////////////////////////////////////////////////////////
// LoadOp.
////////////////////////////////////////////////////////////////////////////////
OpBuilder b(linalgOp.getOperation());
auto nLoops = nPar + nRed + nWin;
if (nLoops > 0) {
- auto innermostLoop = linalg::getForInductionVarOwner(allIvs.back());
+ auto innermostLoop = loop::getForInductionVarOwner(allIvs.back());
// accounts for linalg.terminator in loop.
b = innermostLoop.getBodyBuilder();
}
mlir::linalg::LinalgDialect::LinalgDialect(MLIRContext *context)
: Dialect(getDialectNamespace(), context) {
addTypes<BufferType, RangeType, ViewType>();
- addOperations<ForOp, LoadOp, RangeOp, StoreOp, SliceOp, ViewOp>();
+ addOperations<LoadOp, RangeOp, StoreOp, SliceOp, ViewOp>();
addOperations<
#define GET_OP_LIST
#include "mlir/Linalg/IR/LinalgOps.cpp.inc"
// limitations under the License.
// =============================================================================
+#include "mlir/Conversion/ControlFlowToCFG/ConvertControlFlowToCFG.h"
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
#include "mlir/EDSC/Builders.h"
});
}
-// Converts a `linalg.for` op to CFG form before actual conversion to the LLVM
-// dialect starts.
-static void lowerLinalgForToCFG(FuncOp &f) {
- // Collect all the For operations. We do this as a prepass to avoid
- // invalidating the walker with our rewrite.
- SmallVector<linalg::ForOp, 8> instsToRewrite;
- f.walk<linalg::ForOp>(
- [&](linalg::ForOp op) { instsToRewrite.push_back(op); });
-
- for (auto forOp : llvm::reverse(instsToRewrite)) {
- auto *op = forOp.getOperation();
- auto loc = op->getLoc();
- using namespace edsc::op;
- OpBuilder builder(op);
- ScopedContext scope(builder, loc);
- ValueHandle lb(forOp.getLowerBound()), ub(forOp.getUpperBound()),
- step(forOp.getStep());
-
- // 1. Split Block into init and end blocks, create body and condition blocks
- // with the `iv` block argument.
- auto *initBlock = op->getBlock();
- auto *endBlock = initBlock->splitBlock(op);
- BlockHandle conditionBlock, bodyBlock;
- ValueHandle iv(IndexType::get(op->getContext()));
- BlockBuilder(&conditionBlock, {&iv})();
- BlockBuilder(&bodyBlock, {})();
-
- // 2. Create and fill the condition block whose sole purpose is to evaluate
- // iv and branch to either `bodyBlock` or `endBlock`. Add all branches to
- // the `conditionBlock`.
- // clang-format off
- BlockBuilder(conditionBlock, Append())([&] {
- auto cmp = cmpi(CmpIPredicate::SGT, ub, iv);
- cond_br(cmp, bodyBlock, {}, endBlock, {});
- });
- BlockBuilder(bodyBlock, Append())([&] {
- br(conditionBlock, addi(iv, step));
- });
- BlockBuilder(initBlock, Append())([&] {
- br(conditionBlock, lb);
- });
- // clang-format on
-
- // 3. Move the instructions from the for loop to the body, update all uses
- // of the induction variable and clean up.
- auto *oldBody = forOp.getBody();
- bodyBlock.getBlock()->getOperations().splice(
- bodyBlock.getBlock()->begin(), oldBody->getOperations(),
- oldBody->begin(), std::prev(oldBody->end()));
- forOp.getInductionVar()->replaceAllUsesWith(iv);
- forOp.erase();
- }
-}
-
void LowerLinalgToLLVMPass::runOnModule() {
auto module = getModule();
- for (auto f : module.getOps<FuncOp>()) {
+ for (auto f : module.getOps<FuncOp>())
lowerLinalgSubViewOps(f);
- lowerLinalgForToCFG(f);
- }
// Convert to the LLVM IR dialect using the converter defined above.
OwningRewritePatternList patterns;
LinalgTypeConverter converter(&getContext());
populateAffineToStdConversionPatterns(patterns, &getContext());
+ populateLoopToStdConversionPatterns(patterns, &getContext());
populateStdToLLVMConversionPatterns(converter, patterns);
populateLinalgToLLVMConversionPatterns(converter, patterns, &getContext());
//
//===----------------------------------------------------------------------===//
+#include "mlir/Dialect/LoopOps/LoopOps.h"
#include "mlir/EDSC/Helpers.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineExprVisitor.h"
using namespace mlir::edsc::intrinsics;
using namespace mlir::linalg;
using namespace mlir::linalg::intrinsics;
+using namespace mlir::loop;
#define DEBUG_TYPE "linalg-tiling"
SmallVector<ForOp, 8> loops;
loops.reserve(ivs.size());
for (auto iv : ivs)
- loops.push_back(linalg::getForInductionVarOwner(iv));
+ loops.push_back(loop::getForInductionVarOwner(iv));
return TiledLinalgOp{res, loops};
}
//===----------------------------------------------------------------------===//
#include "mlir/Linalg/Utils/Utils.h"
+#include "mlir/Dialect/LoopOps/LoopOps.h"
#include "mlir/EDSC/Helpers.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/Linalg/Passes.h"
#include "mlir/Linalg/Utils/Intrinsics.h"
#include "mlir/Pass/Pass.h"
+#include "mlir/StandardOps/Ops.h"
#include "mlir/Support/STLExtras.h"
#include "mlir/Transforms/FoldUtils.h"
using namespace mlir::edsc::intrinsics;
using namespace mlir::linalg;
using namespace mlir::linalg::intrinsics;
+using namespace mlir::loop;
mlir::edsc::LoopRangeBuilder::LoopRangeBuilder(ValueHandle *iv,
ValueHandle range) {
auto lb = rangeOp.min();
auto ub = rangeOp.max();
auto step = rangeOp.step();
- auto forOp = OperationHandle::createOp<linalg::ForOp>(lb, ub, step);
+ auto forOp = OperationHandle::createOp<ForOp>(lb, ub, step);
*iv = ValueHandle(forOp.getInductionVar());
- auto *body = forOp.getBody();
+ auto *body = forOp.body();
enter(body, /*prev=*/1);
}
mlir::edsc::LoopRangeBuilder::LoopRangeBuilder(ValueHandle *iv,
SubViewOp::Range range) {
- auto forOp = OperationHandle::createOp<linalg::ForOp>(range.min, range.max,
- range.step);
+ auto forOp =
+ OperationHandle::createOp<ForOp>(range.min, range.max, range.step);
*iv = ValueHandle(forOp.getInductionVar());
- auto *body = forOp.getBody();
+ auto *body = forOp.body();
enter(body, /*prev=*/1);
}
%c3 = constant 3 : index
// CHECK: subi %{{.*}}, %{{.*}} : index
// CHECK-NEXT: %[[range_i:.*]] = divis {{.*}}, %{{.*}} : index
- linalg.for %i0 = %c0 to %c42 step %c3 {
+ loop.for %i0 = %c0 to %c42 step %c3 {
// CHECK: subi %{{.*}}, %{{.*}} : index
// CHECK-NEXT: %[[range_j:.*]] = divis {{.*}}, %{{.*}} : index
- linalg.for %i1 = %c3 to %c42 step %arg1 {
+ loop.for %i1 = %c3 to %c42 step %arg1 {
// CHECK: gpu.launch
// CHECK-SAME: blocks
// CHECK-SAME: threads
}
// No RAW dependences, the pass does not fuse RAR atm.
// FUSE-0-LABEL: func @f1
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
// FUSE-2-LABEL: func @f1
-// FUSE-2-NOT: linalg.for
+// FUSE-2-NOT: loop.for
// FUSE-23-LABEL: func @f1
-// FUSE-23-NOT: linalg.for
+// FUSE-23-NOT: loop.for
// FUSE-234-LABEL: func @f1
-// FUSE-234-NOT: linalg.for
+// FUSE-234-NOT: loop.for
func @f2(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
}
// No tiling => no fusion
// FUSE-0-LABEL: func @f2
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
//
// FUSE-2-LABEL: func @f2
// FUSE-2: %[[C_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// FUSE-2: linalg.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
// FUSE-2: linalg.matmul
// FUSE-2: linalg.matmul
//
// FUSE-23-LABEL: func @f2
// FUSE-23: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
// FUSE-23: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
// FUSE-23: linalg.matmul
// FUSE-23: linalg.matmul
//
// FUSE-234: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
// FUSE-234: linalg.matmul
// FUSE-234: linalg.matmul
}
// No tiling => no fusion
// FUSE-0-LABEL: func @f3
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
//
// Read to %C does not get tiled along 1st dimension => no fusion
// FUSE-2-LABEL: func @f3
-// FUSE-2-NOT: linalg.for
+// FUSE-2-NOT: loop.for
//
// FUSE-23-LABEL: func @f3
// FUSE-23: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
// FUSE-23: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
// FUSE-23: linalg.matmul
// FUSE-23: linalg.matmul
//
// FUSE-234: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
// FUSE-234: linalg.matmul
// FUSE-234: linalg.matmul
}
// No tiling => no fusion
// FUSE-0-LABEL: func @f4
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
//
// Read to %D does not get tiled along 1st dimension => no fusion
// FUSE-2-LABEL: func @f4
// FUSE-2: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
// FUSE-2: %[[C_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// FUSE-2: linalg.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
// FUSE-2: linalg.matmul
// FUSE-2: linalg.matmul
//
// FUSE-23-LABEL: func @f4
// FUSE-23: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
// FUSE-23: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
// FUSE-23: linalg.matmul
// FUSE-23: linalg.matmul
// FUSE-23: linalg.matmul
// FUSE-234: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
// FUSE-234: linalg.matmul
// FUSE-234: linalg.matmul
// FUSE-234: linalg.matmul
}
// No tiling => no fusion
// FUSE-0-LABEL: func @f5
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
//
// FUSE-2-LABEL: func @f5
// FUSE-2: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
// FUSE-2: %[[D_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// FUSE-2: linalg.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
// FUSE-2: linalg.matmul
// FUSE-2: linalg.matmul
//
// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
// FUSE-23: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
// FUSE-23: %[[B_1:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
// FUSE-23: linalg.matmul
// FUSE-23: linalg.matmul
//
// FUSE-234: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
// FUSE-234: %[[B_1:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
// FUSE-234: linalg.matmul
// FUSE-234: linalg.matmul
// interleaved dependence.
// No tiling => no fusion
// FUSE-0-LABEL: func @f6
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
//
// Read to D is not tiled along 1st dimension => no fusion
// FUSE-2-LABEL: func @f6
-// FUSE-2-NOT: linalg.for
+// FUSE-2-NOT: loop.for
//
// FUSE-23-LABEL: func @f6
//
// immediately following read.
// No tiling => no fusion
// FUSE-0-LABEL: func @f7
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
//
// Read to %C (in 3rd matmul) is not tiled along 1st dimension => no fusion
// FUSE-2-LABEL: func @f7
-// FUSE-2-NOT: linalg.for
+// FUSE-2-NOT: loop.for
//
// FUSE-23-LABEL: func @f7
// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
// FUSE-23: %[[A_0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?xf32>
// FUSE-23: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
-// FUSE-23: linalg.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
// FUSE-23: linalg.matmul
// FUSE-23: linalg.matmul
// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
// FUSE-234: %[[A_0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?xf32>
// FUSE-234: %[[A_1:.*]] = linalg.dim %arg0, 1 : !linalg.view<?x?xf32>
// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-234: linalg.for %{{.*}} = %{{.*}} to %[[A_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[A_1]] step %{{.*}} {
// FUSE-234: linalg.matmul
// FUSE-234: linalg.matmul
// FUSE-234: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
// In this example, %D can never be fused because the WAR on %C would be violated
// No tiling => no fusion
// FUSE-0-LABEL: func @f8
-// FUSE-0-NOT: linalg.for
+// FUSE-0-NOT: loop.for
//
// FUSE-2-LABEL: func @f8
-// FUSE-2-NOT: linalg.for
+// FUSE-2-NOT: loop.for
//
// FUSE-23-LABEL: func @f8
-// FUSE-23-NOT: linalg.for
+// FUSE-23-NOT: loop.for
//
// FUSE-234-LABEL: func @f8
-// FUSE-234-NOT: linalg.for
+// FUSE-234-NOT: loop.for
// CHECK: %{{.*}} = llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
// CHECK: llvm.return %{{.*}} : !llvm<"{ i64, i64, i64 }">
-func @linalg_for(%arg0 : index, %arg1 : index, %arg2 : index) {
- linalg.for %i0 = %arg0 to %arg1 step %arg2 {
- %a = muli %i0, %arg0 : index
- }
- return
-}
-// CHECK-LABEL: func @linalg_for(%{{.*}}: !llvm.i64, %{{.*}}: !llvm.i64, %{{.*}}: !llvm.i64) {
-// CHECK: llvm.br ^bb2(%{{.*}} : !llvm.i64)
-// CHECK: ^bb1: // pred: ^bb2
-// CHECK: llvm.return
-// CHECK: ^bb2(%{{.*}}: !llvm.i64): // 2 preds: ^bb0, ^bb3
-// CHECK: %{{.*}} = llvm.icmp "sgt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.cond_br %{{.*}}, ^bb3, ^bb1
-// CHECK: ^bb3: // pred: ^bb2
-// CHECK: %{{.*}} = llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: %{{.*}} = llvm.add %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.br ^bb2(%{{.*}} : !llvm.i64)
-
-func @linalg_for_2(%arg0 : index, %arg1 : index, %arg2 : index) {
- linalg.for %i0 = %arg0 to %arg1 step %arg2 {
- linalg.for %i1 = %arg0 to %arg1 step %arg2 {
- %a = muli %i0, %i1 : index
- }
- linalg.for %i2 = %arg0 to %arg1 step %arg2 {
- %b = muli %i0, %i2 : index
- }
- }
- return
-}
-// CHECK-LABEL: func @linalg_for_2(%{{.*}}: !llvm.i64, %{{.*}}: !llvm.i64, %{{.*}}: !llvm.i64) {
-// CHECK: llvm.br ^bb2(%{{.*}} : !llvm.i64)
-// CHECK: ^bb1: // pred: ^bb2
-// CHECK: llvm.return
-// CHECK: ^bb2(%{{.*}}: !llvm.i64): // 2 preds: ^bb0, ^bb5
-// CHECK: %{{.*}} = llvm.icmp "sgt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.cond_br %{{.*}}, ^bb3, ^bb1
-// CHECK: ^bb3: // pred: ^bb2
-// CHECK: llvm.br ^bb8(%{{.*}} : !llvm.i64)
-// CHECK: ^bb4: // pred: ^bb8
-// CHECK: llvm.br ^bb6(%{{.*}} : !llvm.i64)
-// CHECK: ^bb5: // pred: ^bb6
-// CHECK: %{{.*}} = llvm.add %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.br ^bb2(%{{.*}} : !llvm.i64)
-// CHECK: ^bb6(%{{.*}}: !llvm.i64): // 2 preds: ^bb4, ^bb7
-// CHECK: %{{.*}} = llvm.icmp "sgt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.cond_br %{{.*}}, ^bb7, ^bb5
-// CHECK: ^bb7: // pred: ^bb6
-// CHECK: %{{.*}} = llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: %{{.*}} = llvm.add %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.br ^bb6(%{{.*}} : !llvm.i64)
-// CHECK: ^bb8(%{{.*}}: !llvm.i64): // 2 preds: ^bb3, ^bb9
-// CHECK: %{{.*}} = llvm.icmp "sgt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.cond_br %{{.*}}, ^bb9, ^bb4
-// CHECK: ^bb9: // pred: ^bb8
-// CHECK: %{{.*}} = llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: %{{.*}} = llvm.add %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK: llvm.br ^bb8(%{{.*}} : !llvm.i64)
-
func @subview(%arg0: !linalg.view<?x?xf32>) {
%c0 = constant 0 : index
%0 = linalg.subview %arg0[%c0, %c0, %c0, %c0, %c0, %c0] : !linalg.view<?x?xf32>
// CHECK: %[[M:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?x?xf32>
// CHECK: %[[K:.*]] = linalg.dim %[[A]], 1 : !linalg.view<?x?xf32>
// CHECK: %[[N:.*]] = linalg.dim %[[B]], 1 : !linalg.view<?x?xf32>
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
// CHECK: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
// CHECK: %[[M:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?x?xf32>
// CHECK: %[[K:.*]] = linalg.dim %[[A]], 1 : !linalg.view<?x?xf32>
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}] : !linalg.view<?xf32>
// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
// CHECK: %[[B:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
// CHECK: %[[C:.*]] = linalg.view %arg0[] : !linalg.buffer<?xf32> -> !linalg.view<f32>
// CHECK: %[[K:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?xf32>
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}] : !linalg.view<?xf32>
// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}] : !linalg.view<?xf32>
// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
}
// CHECK-LABEL: func @dot_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
// CHECK: %[[K:.*]] = linalg.dim %arg0, 0 : !linalg.view<?xf32>
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
// CHECK-DAG: %[[a:.*]] = linalg.load %arg0[%{{.*}}] : !linalg.view<?xf32>
// CHECK-DAG: %[[b:.*]] = linalg.load %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
return
}
// CHECK-LABEL: func @fill_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: f32) {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
func @fill_view0(%arg0: !linalg.view<f32>, %arg1: f32) {
return
}
// CHECK-LABEL: func @fill_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: f32) {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
func @copy_view(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>) {
return
}
// CHECK-LABEL: func @copy_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
// CHECK: %[[L:.*]] = linalg.load %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
// CHECK: linalg.store %[[L]], %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
return
}
// CHECK-LABEL: func @copy_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
// CHECK: %[[L:.*]] = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
// CHECK: linalg.store %[[L]], %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
// CHECK: %[[K:.*]] = linalg.dim %arg0, 2 : !linalg.view<?x?x?xf32>
// CHECK: %[[B:.*]] = linalg.dim %arg1, 0 : !linalg.view<?x?x?xf32>
// CHECK: %[[X0:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?x?xf32>
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
// CHECK: %[[SUM:.*]] = affine.apply #[[S2D1]](%{{.*}}, %{{.*}})
// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %[[SUM]], %{{.*}}] : !linalg.view<?x?x?xf32>
// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
// CHECK: %[[B:.*]] = linalg.dim %arg1, 0 : !linalg.view<?x?x?x?xf32>
// CHECK: %[[X0:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?x?x?xf32>
// CHECK: %[[X1:.*]] = linalg.dim %arg2, 2 : !linalg.view<?x?x?x?xf32>
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[X1]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
-// CHECK: linalg.for %{{.*}} = %{{.*}} to %[[Z1]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X1]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z1]] step %{{.*}} {
// CHECK: %[[SUM0:.*]] = affine.apply #map1(%{{.*}}, %{{.*}})
// CHECK: %[[SUM1:.*]] = affine.apply #map2(%{{.*}}, %{{.*}})
// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %[[SUM0]], %[[SUM1]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
return
}
// TILE-1D-LABEL: func @matmul(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// TILE-1D: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// TILE-1D: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// TILE-1D: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
// TILE-1D: %[[vA:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
// TILE-1D: %[[vB:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
// TILE-1D: %[[vC:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
// CHECK-NEXT: return %{{.*}} : !linalg.range
func @linalg_for(%arg0 : index, %arg1 : index, %arg2 : index) {
- linalg.for %i0 = %arg0 to %arg1 step %arg2 {
- linalg.for %i1 = %arg0 to %arg1 step %arg2 {
+ loop.for %i0 = %arg0 to %arg1 step %arg2 {
+ loop.for %i1 = %arg0 to %arg1 step %arg2 {
%min_cmp = cmpi "slt", %i0, %i1 : index
%min = select %min_cmp, %i0, %i1 : index
%max_cmp = cmpi "sge", %i0, %i1 : index
%max = select %max_cmp, %i0, %i1 : index
- linalg.for %i2 = %min to %max step %i1 {
+ loop.for %i2 = %min to %max step %i1 {
}
}
}
return
}
// CHECK-LABEL: func @linalg_for(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// CHECK-NEXT: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK-NEXT: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK-NEXT: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK-NEXT: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
// CHECK-NEXT: %{{.*}} = cmpi "slt", %{{.*}}, %{{.*}} : index
// CHECK-NEXT: %{{.*}} = select %{{.*}}, %{{.*}}, %{{.*}} : index
// CHECK-NEXT: %{{.*}} = cmpi "sge", %{{.*}}, %{{.*}} : index
// CHECK-NEXT: %{{.*}} = select %{{.*}}, %{{.*}}, %{{.*}} : index
-// CHECK-NEXT: linalg.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK-NEXT: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
func @fill_view(%arg0: !linalg.view<?xf32>, %arg1: f32) {
linalg.fill(%arg0, %arg1) : !linalg.view<?xf32>, f32
}
// TILE-2-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-2: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-2: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}, %{{.*}}, %[[K]], %{{.*}}] : !linalg.view<?x?xf32>
// TILE-02-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
// TILE-02: %[[N:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
-// TILE-02: linalg.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
+// TILE-02: loop.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
// TILE-02: %[[K:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
// TILE-02: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-02: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[K]], %{{.*}}, %{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?x?xf32>
// TILE-002-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
// TILE-002: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-002: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-002: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
// TILE-002: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
// TILE-002: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-002: %[[sAj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?x?xf32>
// TILE-234: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
// TILE-234: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-234: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
-// TILE-234: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[N]] step %{{.*}} {
-// TILE-234: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[N]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
// TILE-234: %[[ai:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-234: %[[ak:.*]] = affine.apply #[[UB2]](%{{.*}})
// TILE-234: %[[sAik:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ai]], %{{.*}}, %{{.*}}, %[[ak]], %{{.*}}] : !linalg.view<?x?xf32>
}
// TILE-2-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-2: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-2: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}, %{{.*}}, %[[N]], %{{.*}}] : !linalg.view<?x?xf32>
// TILE-02-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
// TILE-02: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-02: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-02: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
// TILE-02: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
// TILE-02: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-02: %[[sAj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?x?xf32>
// TILE-02: linalg.matvec(%[[sAj]], %[[sBj]], %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
// TILE-002-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// TILE-002-NOT: linalg.for
+// TILE-002-NOT: loop.for
// TILE-234-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
// TILE-234: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-234: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
-// TILE-234: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
// TILE-234: %[[ai:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-234: %[[aj:.*]] = affine.apply #[[UB1]](%{{.*}})
// TILE-234: %[[sAij:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ai]], %{{.*}}, %{{.*}}, %[[aj]], %{{.*}}] : !linalg.view<?x?xf32>
}
// TILE-2-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?xf32>
-// TILE-2: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?xf32>
// TILE-2: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-2: linalg.dot(%[[sAi]], %[[sBi]], {{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
// TILE-02-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// TILE-02-NOT: linalg.for
+// TILE-02-NOT: loop.for
// TILE-002-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// TILE-002-NOT: linalg.for
+// TILE-002-NOT: loop.for
// TILE-234-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?xf32>
-// TILE-234: linalg.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
// TILE-234: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-234: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?xf32>
// TILE-234: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
// TILE-23004: %[[B:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?x?x?xf32>
// TILE-23004: %[[PaddedInput0:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
// TILE-23004: %[[X0:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: linalg.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
-// TILE-23004: linalg.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
-// TILE-23004: linalg.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
+// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
+// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
+// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
// TILE-23004: %[[Z0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?x?x?xf32>
// TILE-23004: %[[Z1:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
// TILE-23004: %[[I2p4:.*]] = affine.apply #[[UB2]](%{{.*}})
%s = linalg.buffer_size %arg0 : !linalg.buffer<?xf32>
%R = linalg.range %c0:%s:%c1 : !linalg.range
%V = linalg.view %arg0[%R] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
- linalg.for %i0 = %c0 to %s step %c1 {
+ loop.for %i0 = %c0 to %s step %c1 {
linalg.store %f, %V[%i0] : !linalg.view<?xf32>
}
return