2022-12-20 15:42:11 -08:00
|
|
|
//===- CodegenEnv.cpp - Code generation environment class ----------------===//
|
|
|
|
|
//
|
|
|
|
|
// 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
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
#include "CodegenEnv.h"
|
2023-01-18 18:19:32 +00:00
|
|
|
|
|
|
|
|
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
|
|
|
|
|
#include "mlir/Dialect/Linalg/Utils/Utils.h"
|
[mlir][sparse] Factoring out SparseTensorType class
This change adds a new `SparseTensorType` class for making the "dim" vs "lvl" distinction more overt, and for abstracting over the differences between sparse-tensors and dense-tensors. In addition, this change also adds new type aliases `Dimension`, `Level`, and `FieldIndex` to make code more self-documenting.
Although the diff is very large, the majority of the changes are mechanical in nature (e.g., changing types to use the new aliases, updating variable names to match, etc). Along the way I also made many variables `const` when they could be; the majority of which required only adding the keyword. A few places had conditional definitions of these variables, requiring actual code changes; however, that was only done when the overall change was extremely local and easy to extract. All these changes are included in the current patch only because it would be too onerous to split them off into a separate patch.
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D143800
2023-02-14 18:20:45 -08:00
|
|
|
#include "mlir/Dialect/SparseTensor/IR/SparseTensorType.h"
|
2023-01-18 18:19:32 +00:00
|
|
|
#include "mlir/Dialect/Tensor/IR/Tensor.h"
|
[mlir][sparse] Factoring out SparseTensorType class
This change adds a new `SparseTensorType` class for making the "dim" vs "lvl" distinction more overt, and for abstracting over the differences between sparse-tensors and dense-tensors. In addition, this change also adds new type aliases `Dimension`, `Level`, and `FieldIndex` to make code more self-documenting.
Although the diff is very large, the majority of the changes are mechanical in nature (e.g., changing types to use the new aliases, updating variable names to match, etc). Along the way I also made many variables `const` when they could be; the majority of which required only adding the keyword. A few places had conditional definitions of these variables, requiring actual code changes; however, that was only done when the overall change was extremely local and easy to extract. All these changes are included in the current patch only because it would be too onerous to split them off into a separate patch.
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D143800
2023-02-14 18:20:45 -08:00
|
|
|
|
2023-01-13 21:05:06 -08:00
|
|
|
#include <optional>
|
2022-12-20 15:42:11 -08:00
|
|
|
|
|
|
|
|
using namespace mlir;
|
|
|
|
|
using namespace mlir::sparse_tensor;
|
|
|
|
|
|
2023-01-18 18:19:32 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// Code generation environment helper functions
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
/// Returns true if tensor materializes uninitialized into the computation.
|
|
|
|
|
static bool isMaterializing(Value val) {
|
|
|
|
|
return val.getDefiningOp<tensor::EmptyOp>() ||
|
|
|
|
|
val.getDefiningOp<bufferization::AllocTensorOp>();
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 22:51:26 +00:00
|
|
|
/// Makes target array's elements sorted according to the `order` array.
|
2023-08-25 21:25:00 +00:00
|
|
|
static void sortArrayBasedOnOrder(std::vector<LoopCoeffPair> &target,
|
2023-01-20 22:51:26 +00:00
|
|
|
ArrayRef<LoopId> order) {
|
2023-08-22 15:28:56 -07:00
|
|
|
std::sort(target.begin(), target.end(),
|
2023-08-25 21:25:00 +00:00
|
|
|
[&order](const LoopCoeffPair &l, const LoopCoeffPair &r) {
|
2023-08-22 15:28:56 -07:00
|
|
|
assert(std::addressof(l) == std::addressof(r) || l != r);
|
|
|
|
|
int idxL = -1, idxR = -1;
|
|
|
|
|
for (int i = 0, e = order.size(); i < e; i++) {
|
2023-08-25 21:25:00 +00:00
|
|
|
if (order[i] == l.first)
|
2023-08-22 15:28:56 -07:00
|
|
|
idxL = i;
|
2023-08-25 21:25:00 +00:00
|
|
|
if (order[i] == r.first)
|
2023-08-22 15:28:56 -07:00
|
|
|
idxR = i;
|
|
|
|
|
}
|
|
|
|
|
assert(idxL >= 0 && idxR >= 0);
|
|
|
|
|
return idxL < idxR;
|
|
|
|
|
});
|
2023-01-20 22:51:26 +00:00
|
|
|
}
|
2022-12-20 15:42:11 -08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2022-12-21 17:10:12 -08:00
|
|
|
// Code generation environment constructor and general methods
|
2022-12-20 15:42:11 -08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
CodegenEnv::CodegenEnv(linalg::GenericOp linop, SparsificationOptions opts,
|
|
|
|
|
unsigned numTensors, unsigned numLoops,
|
2023-03-21 20:47:47 +00:00
|
|
|
unsigned numFilterLoops, unsigned maxRank)
|
2022-12-21 17:10:12 -08:00
|
|
|
: linalgOp(linop), sparseOptions(opts),
|
2023-03-21 20:47:47 +00:00
|
|
|
latticeMerger(numTensors, numLoops, numFilterLoops, maxRank),
|
|
|
|
|
loopEmitter(), topSort(), sparseOut(nullptr), outerParNest(-1u),
|
|
|
|
|
insChain(), expValues(), expFilled(), expAdded(), expCount(), redVal(),
|
2023-03-24 14:46:07 -07:00
|
|
|
redExp(detail::kInvalidId), redCustom(detail::kInvalidId),
|
|
|
|
|
redValidLexInsert() {}
|
2022-12-20 15:42:11 -08:00
|
|
|
|
2023-01-18 18:19:32 +00:00
|
|
|
LogicalResult CodegenEnv::initTensorExp() {
|
|
|
|
|
// Builds the tensor expression for the Linalg operation in SSA form.
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
std::optional<ExprId> optExp = latticeMerger.buildTensorExpFromLinalg(op());
|
2023-01-18 18:19:32 +00:00
|
|
|
if (!optExp || !isAdmissibleTensorExp(*optExp))
|
|
|
|
|
return failure();
|
|
|
|
|
|
|
|
|
|
tensorExp = *optExp;
|
|
|
|
|
return success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::startEmit() {
|
|
|
|
|
assert(insChain == nullptr && "must only start emitting once");
|
2022-12-20 15:42:11 -08:00
|
|
|
if (sparseOut) {
|
|
|
|
|
insChain = sparseOut->get();
|
2022-12-21 17:10:12 -08:00
|
|
|
latticeMerger.setHasSparseOut(true);
|
2022-12-20 15:42:11 -08:00
|
|
|
}
|
2023-01-20 22:51:26 +00:00
|
|
|
|
|
|
|
|
// Sort the related loop array such that they are in the same order as they
|
|
|
|
|
// appears on the topoOrder.
|
|
|
|
|
// TODO: since we only handle affine addition for slice based codegen, and
|
|
|
|
|
// addition is assoicative, the order how we evaluate the expression does
|
|
|
|
|
// not matter. However, to support multiplication, the order of the loop
|
|
|
|
|
// index should match the evaluation order to the affine expression AST.
|
|
|
|
|
|
2022-12-27 15:47:02 -08:00
|
|
|
// Initialize loop emitter.
|
2023-01-20 22:51:26 +00:00
|
|
|
SmallVector<Value> tensors; // input tensors passed to loop emitter
|
|
|
|
|
for (OpOperand &t : linalgOp->getOpOperands()) {
|
2022-12-27 15:47:02 -08:00
|
|
|
tensors.push_back(t.get());
|
2023-03-24 16:03:56 -07:00
|
|
|
const TensorId tid = makeTensorId(t.getOperandNumber());
|
|
|
|
|
const Level lvlRank = linalgOp.getMatchingIndexingMap(&t).getNumResults();
|
|
|
|
|
const auto enc = getSparseTensorEncoding(t.get().getType());
|
|
|
|
|
(void)enc;
|
|
|
|
|
assert(!enc || lvlRank == enc.getLvlRank());
|
|
|
|
|
for (Level lvl = 0; lvl < lvlRank; lvl++)
|
|
|
|
|
sortArrayBasedOnOrder(latticeMerger.getDependentLoops(tid, lvl), topSort);
|
2023-01-20 22:51:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loopEmitter.initialize(
|
|
|
|
|
tensors,
|
|
|
|
|
StringAttr::get(linalgOp.getContext(),
|
|
|
|
|
linalg::GenericOp::getOperationName()),
|
|
|
|
|
/*hasOutput=*/true,
|
|
|
|
|
/*isSparseOut=*/sparseOut != nullptr, topSort,
|
|
|
|
|
// TODO: compute the map and pass it to loop emitter directly instead of
|
|
|
|
|
// passing in a callback.
|
2023-08-25 21:25:00 +00:00
|
|
|
/*dependentLvlGetter=*/
|
|
|
|
|
[this](TensorId t,
|
|
|
|
|
Level lvl) -> std::vector<std::pair<TensorLevel, unsigned>> {
|
|
|
|
|
// Translates from a list of loop indices to a list of [tid, lvl] pair.
|
|
|
|
|
std::vector<LoopCoeffPair> &rLoops = merger().getDependentLoops(t, lvl);
|
|
|
|
|
std::vector<std::pair<TensorLevel, unsigned>> ret;
|
2023-01-20 22:51:26 +00:00
|
|
|
ret.reserve(rLoops.size());
|
2023-08-25 21:25:00 +00:00
|
|
|
for (auto [loop, coeff] : rLoops) {
|
|
|
|
|
TensorLevel tl = makeTensorLevel(merger().getLoopDefiningLvl(loop));
|
|
|
|
|
ret.emplace_back(tl, coeff);
|
|
|
|
|
};
|
2023-01-20 22:51:26 +00:00
|
|
|
return ret;
|
|
|
|
|
});
|
2022-12-20 15:42:11 -08:00
|
|
|
}
|
|
|
|
|
|
2023-01-14 01:25:58 -08:00
|
|
|
std::optional<Operation *> CodegenEnv::genLoopBoundary(
|
|
|
|
|
function_ref<std::optional<Operation *>(MutableArrayRef<Value> parameters)>
|
2022-12-22 12:10:03 -08:00
|
|
|
callback) {
|
|
|
|
|
SmallVector<Value> params;
|
2023-02-10 13:08:49 -06:00
|
|
|
if (isReduc()) {
|
2022-12-22 12:10:03 -08:00
|
|
|
params.push_back(redVal);
|
2023-02-10 13:08:49 -06:00
|
|
|
if (redValidLexInsert)
|
|
|
|
|
params.push_back(redValidLexInsert);
|
|
|
|
|
} else {
|
|
|
|
|
assert(!redValidLexInsert);
|
|
|
|
|
}
|
2022-12-22 12:10:03 -08:00
|
|
|
if (isExpand())
|
|
|
|
|
params.push_back(expCount);
|
|
|
|
|
if (insChain != nullptr)
|
|
|
|
|
params.push_back(insChain);
|
|
|
|
|
auto r = callback(params); // may update parameters
|
|
|
|
|
unsigned i = 0;
|
2023-02-10 13:08:49 -06:00
|
|
|
if (isReduc()) {
|
2023-03-24 14:17:11 -07:00
|
|
|
// FIXME: This requires `updateExprValue` to perform updates without
|
|
|
|
|
// checking for a previous value; but it's not clear whether that's
|
|
|
|
|
// by design or might be a potential source for bugs.
|
2022-12-22 12:10:03 -08:00
|
|
|
updateReduc(params[i++]);
|
2023-02-10 13:08:49 -06:00
|
|
|
if (redValidLexInsert)
|
|
|
|
|
setValidLexInsert(params[i++]);
|
|
|
|
|
}
|
2022-12-22 12:10:03 -08:00
|
|
|
if (isExpand())
|
|
|
|
|
updateExpandCount(params[i++]);
|
|
|
|
|
if (insChain != nullptr)
|
|
|
|
|
updateInsertionChain(params[i]);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-18 18:19:32 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// Code generation environment verify functions.
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
bool CodegenEnv::isAdmissibleTensorExp(ExprId exp) {
|
2023-01-18 18:19:32 +00:00
|
|
|
// We reject any expression that makes a reduction from `-outTensor`, as those
|
|
|
|
|
// expressions create a dependency between the current iteration (i) and the
|
|
|
|
|
// previous iteration (i-1). It would require iterating over the whole
|
|
|
|
|
// coordinate space, which prevent exploiting sparsity for faster code.
|
|
|
|
|
for (utils::IteratorType it : linalgOp.getIteratorTypesArray()) {
|
|
|
|
|
if (it == utils::IteratorType::reduction) {
|
|
|
|
|
if (latticeMerger.hasNegateOnOut(exp))
|
|
|
|
|
return false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OpOperand *lhs = linalgOp.getDpsInitOperand(0);
|
2023-03-24 16:03:56 -07:00
|
|
|
const TensorId tensor = makeTensorId(lhs->getOperandNumber());
|
2023-01-18 18:19:32 +00:00
|
|
|
// An non-annotated output tensor is assumed dense, and becomes a random
|
|
|
|
|
// access n-dim memref. Admissible since insertions cannot occur.
|
[mlir][sparse] Factoring out SparseTensorType class
This change adds a new `SparseTensorType` class for making the "dim" vs "lvl" distinction more overt, and for abstracting over the differences between sparse-tensors and dense-tensors. In addition, this change also adds new type aliases `Dimension`, `Level`, and `FieldIndex` to make code more self-documenting.
Although the diff is very large, the majority of the changes are mechanical in nature (e.g., changing types to use the new aliases, updating variable names to match, etc). Along the way I also made many variables `const` when they could be; the majority of which required only adding the keyword. A few places had conditional definitions of these variables, requiring actual code changes; however, that was only done when the overall change was extremely local and easy to extract. All these changes are included in the current patch only because it would be too onerous to split them off into a separate patch.
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D143800
2023-02-14 18:20:45 -08:00
|
|
|
if (getSparseTensorType(lhs->get()).isAllDense())
|
2023-01-18 18:19:32 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// A tensor expression with a sparse output tensor that changes its values
|
|
|
|
|
// but not its nonzero structure, an operation called "simply dynamic" in
|
|
|
|
|
// [Bik96,Ch9], is also admissible without special env.
|
|
|
|
|
if (latticeMerger.isSingleCondition(tensor, exp))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// Accept "truly dynamic" if the output tensor materializes uninitialized
|
|
|
|
|
// into the computation and insertions occur in lexicographic index order.
|
|
|
|
|
sparseOut = lhs;
|
|
|
|
|
return isMaterializing(lhs->get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CodegenEnv::isAdmissibleTopoOrder() {
|
|
|
|
|
if (!hasSparseOutput())
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
OpOperand *lhs = linalgOp.getDpsInitOperand(0);
|
|
|
|
|
// Accept "truly dynamic" if the output tensor materializes uninitialized
|
|
|
|
|
// into the computation and insertions occur in lexicographic index order.
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
LoopOrd nest = 0;
|
|
|
|
|
const auto iteratorTypes = linalgOp.getIteratorTypesArray();
|
|
|
|
|
assert(topSortSize() == latticeMerger.getNumLoops());
|
|
|
|
|
for (const LoopId i : topSort) {
|
|
|
|
|
if (!latticeMerger.isFilterLoop(i)) {
|
2023-01-18 18:19:32 +00:00
|
|
|
// We only count non-filter loops as filter loops should be considered
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
// a special type of parallel loops.
|
|
|
|
|
if (linalg::isReductionIterator(iteratorTypes[i]))
|
2023-01-18 18:19:32 +00:00
|
|
|
break; // terminate at first reduction
|
|
|
|
|
nest++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Determine admissible dynamic insertion situations:
|
|
|
|
|
// (1) fully injective, since there are no reductions,
|
|
|
|
|
// (2) admissible 1-d expansion in innermost dimension.
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
if (static_cast<int64_t>(nest) >= linalgOp.getRank(lhs) - 1) {
|
2023-01-18 18:19:32 +00:00
|
|
|
outerParNest = nest;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-20 15:42:11 -08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2022-12-21 17:10:12 -08:00
|
|
|
// Code generation environment topological sort methods
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
ArrayRef<LoopId> CodegenEnv::getTopSortSlice(LoopOrd n, LoopOrd m) const {
|
|
|
|
|
return ArrayRef<LoopId>(topSort).slice(n, m);
|
2022-12-21 17:10:12 -08:00
|
|
|
}
|
|
|
|
|
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
ArrayRef<LoopId> CodegenEnv::getLoopStackUpTo(LoopOrd n) const {
|
|
|
|
|
return ArrayRef<LoopId>(topSort).take_front(n);
|
2022-12-21 17:10:12 -08:00
|
|
|
}
|
|
|
|
|
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
ArrayRef<LoopId> CodegenEnv::getCurrentLoopStack() const {
|
|
|
|
|
return getLoopStackUpTo(loopEmitter.getCurrentDepth());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Value CodegenEnv::getLoopVar(LoopId i) const {
|
|
|
|
|
// TODO: this class should store the inverse of `topSort` so that
|
|
|
|
|
// it can do this conversion directly, instead of searching through
|
|
|
|
|
// `topSort` every time. (Or else, `LoopEmitter` should handle this.)
|
|
|
|
|
for (LoopOrd n = 0, numLoops = topSortSize(); n < numLoops; n++)
|
|
|
|
|
if (topSort[n] == i)
|
|
|
|
|
return loopEmitter.getLoopIV(n);
|
|
|
|
|
llvm_unreachable("invalid loop identifier");
|
2022-12-21 17:10:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// Code generation environment sparse tensor output and expansion methods
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::updateInsertionChain(Value chain) {
|
|
|
|
|
assert(sparseOut != nullptr && insChain != nullptr);
|
|
|
|
|
insChain = chain;
|
|
|
|
|
}
|
|
|
|
|
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
// FIXME: clarify what this "rank" is really supposed to mean/be.
|
|
|
|
|
bool CodegenEnv::atExpandLevel(OpOperand *o, unsigned rank, LoopOrd n) const {
|
|
|
|
|
return sparseOut == o && outerParNest == static_cast<LoopOrd>(rank - 1) &&
|
|
|
|
|
outerParNest == n;
|
2022-12-21 17:10:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::startExpand(Value values, Value filled, Value added,
|
|
|
|
|
Value count) {
|
|
|
|
|
assert(sparseOut != nullptr && expValues == nullptr);
|
|
|
|
|
expValues = values;
|
|
|
|
|
expFilled = filled;
|
|
|
|
|
expAdded = added;
|
|
|
|
|
expCount = count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::updateExpandCount(Value count) {
|
|
|
|
|
assert(sparseOut != nullptr && expValues != nullptr);
|
|
|
|
|
expCount = count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::endExpand() {
|
|
|
|
|
assert(sparseOut != nullptr && expValues != nullptr);
|
|
|
|
|
expValues = expFilled = expAdded = expCount = Value();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// Code generation environment reduction methods
|
2022-12-20 15:42:11 -08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
void CodegenEnv::startReduc(ExprId exp, Value val) {
|
2023-03-24 14:46:07 -07:00
|
|
|
assert(!isReduc() && exp != detail::kInvalidId);
|
2022-12-20 15:42:11 -08:00
|
|
|
redExp = exp;
|
|
|
|
|
updateReduc(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::updateReduc(Value val) {
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
assert(isReduc());
|
2023-03-24 14:17:11 -07:00
|
|
|
redVal = val;
|
|
|
|
|
// NOTE: `genLoopBoundary` requires that this performs a unilateral
|
|
|
|
|
// update without checking for a previous value first. (It's not
|
|
|
|
|
// clear whether any other callsites also require that.)
|
|
|
|
|
latticeMerger.updateExprValue(redExp, val);
|
2022-12-20 15:42:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Value CodegenEnv::endReduc() {
|
2023-03-24 14:17:11 -07:00
|
|
|
assert(isReduc());
|
2022-12-20 15:42:11 -08:00
|
|
|
Value val = redVal;
|
2023-03-24 14:17:11 -07:00
|
|
|
redVal = val;
|
|
|
|
|
latticeMerger.clearExprValue(redExp);
|
2023-03-24 14:46:07 -07:00
|
|
|
redExp = detail::kInvalidId;
|
2022-12-20 15:42:11 -08:00
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 13:08:49 -06:00
|
|
|
void CodegenEnv::setValidLexInsert(Value val) {
|
|
|
|
|
assert(isReduc() && val);
|
|
|
|
|
redValidLexInsert = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::clearValidLexInsert() {
|
|
|
|
|
assert(!isReduc());
|
|
|
|
|
redValidLexInsert = Value();
|
|
|
|
|
}
|
|
|
|
|
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
void CodegenEnv::startCustomReduc(ExprId exp) {
|
2023-03-24 14:46:07 -07:00
|
|
|
assert(!isCustomReduc() && exp != detail::kInvalidId);
|
2022-12-20 15:42:11 -08:00
|
|
|
redCustom = exp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Value CodegenEnv::getCustomRedId() {
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
assert(isCustomReduc());
|
2022-12-20 15:42:11 -08:00
|
|
|
return dyn_cast<sparse_tensor::ReduceOp>(exp(redCustom).op).getIdentity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CodegenEnv::endCustomReduc() {
|
[mlir][sparse] Cleaning up names in {Merger,LoopEmitter,CodegenEnv}.{h,cpp}
This change does a bunch of renaming to clear up confusions in these files. In particular, this change:
* Renames variables and methods to clarify the "dim"/"lvl" distinction, and changes them to use the `Dimension`/`Level` types as appropriate.
* Introduces new typedefs
* `ExprId`, `LatPointId`, `LatSetId`: to clarify the interning design of the Merger.
* `LoopId`, `LoopOrd`: to clarify the distinction between arbitrary names for loop-variables, vs numeric identifiers based on the actual order of loop generation.
* `TensorId`
* (Future CLs will change these from typedefs to structs/classes, so that the typechecker can help avoid mixups.)
* Updates documentation to match the new terminology
* Adds additional assertions
* Adds `const` to local variables along the way
Reviewed By: aartbik
Differential Revision: https://reviews.llvm.org/D145756
2023-03-09 17:00:27 -08:00
|
|
|
assert(isCustomReduc());
|
2023-03-24 14:46:07 -07:00
|
|
|
redCustom = detail::kInvalidId;
|
2022-12-20 15:42:11 -08:00
|
|
|
}
|