29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/SmallVector.h"
31#include "llvm/Support/Casting.h"
50 virtual std::optional<std::tuple<TypedValue<ShapedType>,
Sharding>>
79 while (
static_cast<int64_t>(tgtShardingSplitAxes.size()) <=
84 llvm::to_vector(tgtShardingSplitAxes[splitTensorDim].asArrayRef());
85 tgtSplitAxes.push_back(splitGridAxis);
93 static std::tuple<TypedValue<ShapedType>,
Sharding>
98 AllSliceOp::create(builder, srcShard, grid,
102 tgtSharding(builder.
getContext(), std::move(srcSharding),
103 splitTensorDim, splitGridAxis);
104 return {tgtShard, resultSharding};
112 static std::optional<GridAxis> detect(
const Sharding &srcSharding,
115 if (
static_cast<size_t>(tensorDim) >= tgtSharding.getSplitAxes().size())
117 auto tgtAxes = tgtSharding.getSplitAxes()[tensorDim].asArrayRef();
118 if (srcSharding.
getSplitAxes().size() >
static_cast<size_t>(tensorDim)) {
119 auto srcAxes = srcSharding.
getSplitAxes()[tensorDim].asArrayRef();
120 if (srcAxes.size() + 1 != tgtAxes.size())
122 if (!llvm::equal(srcAxes,
123 llvm::make_range(tgtAxes.begin(), tgtAxes.end() - 1)))
126 if (tgtAxes.size() != 1)
129 return tgtAxes.back();
133 std::optional<std::tuple<TypedValue<ShapedType>,
Sharding>>
136 ShapedType srcUnshardedType,
140 if (
auto gridAxis = detect(srcSharding, tgtSharding, tensorDim))
141 return apply(builder, srcSharding, srcShard, grid, tensorDim,
153 static std::optional<SmallVector<GridAxis>>
156 if (
static_cast<size_t>(tensorDim) >= srcSharding.
getSplitAxes().size())
159 auto srcSplitAxes = srcSharding.
getSplitAxes()[tensorDim].asArrayRef();
160 if (tgtSharding.getSplitAxes().size() >
static_cast<size_t>(tensorDim)) {
161 auto tgtSplitAxes = tgtSharding.getSplitAxes()[tensorDim].asArrayRef();
164 if (srcSplitAxes.size() <= tgtSplitAxes.size())
168 if (!std::equal(tgtSplitAxes.begin(), tgtSplitAxes.end(),
169 srcSplitAxes.begin()))
171 dimOff = tgtSplitAxes.size();
175 if (srcSplitAxes.size() == 0)
189 int64_t splitTensorDim,
size_t numUnsplitAxes) {
192 assert(
static_cast<int64_t>(resSplitAxes.size()) > splitTensorDim);
194 assert(srcSplitAxes.size() >= numUnsplitAxes);
195 size_t numSplitAxes = srcSplitAxes.size() - numUnsplitAxes;
197 srcSplitAxes.begin() + numSplitAxes);
204 static ShapedType allGatherResultType(ShapedType srcType,
209 for (
GridAxis gridAxis : unsplitAxes)
210 tgtShape[splitTensorDim] =
212 return srcType.cloneWith(tgtShape, srcType.getElementType());
217 static std::tuple<TypedValue<ShapedType>,
Sharding>
224 Sharding resultSharding = tgtSharding(ctx, std::move(srcSharding),
225 splitTensorDim, unsplitAxes.size());
226 ShapedType agResultType = allGatherResultType(
227 srcShard.getType(), splitTensorDim, grid.getShape(), unsplitAxes);
228 Value allGatherResult = AllGatherOp::create(
230 RankedTensorType::get(agResultType.getShape(),
231 agResultType.getElementType()),
232 grid.getSymName(), unsplitAxes, srcShard, APInt(64, splitTensorDim));
236 tensor::CastOp::create(builder, tgtType, allGatherResult).getResult();
237 return {tgtShard, resultSharding};
241 std::optional<std::tuple<TypedValue<ShapedType>,
Sharding>>
244 ShapedType srcUnshardedType,
248 if (
auto gridAxes = detect(srcSharding, tgtSharding, tensorDim))
249 return apply(builder, srcSharding, srcUnshardedType, srcShard, grid,
250 tensorDim, gridAxes.value());
261 tgtShape[srcTensorDim] =
gatherDimension(tgtShape[srcTensorDim], splitCount);
262 tgtShape[tgtTensorDim] =
shardDimension(tgtShape[tgtTensorDim], splitCount);
263 return srcShape.cloneWith(tgtShape, srcShape.getElementType());
278 static std::optional<std::tuple<int64_t, GridAxis>>
281 if (
static_cast<size_t>(srcTensorDim) >= srcSharding.
getSplitAxes().size())
283 auto srcAxes = srcSharding.
getSplitAxes()[srcTensorDim].asArrayRef();
289 if (
static_cast<size_t>(srcTensorDim) >= tgtSharding.getSplitAxes().size())
291 auto tgtSrcAxes = tgtSharding.getSplitAxes()[srcTensorDim].asArrayRef();
292 if (tgtSrcAxes.size() + 1 != srcAxes.size())
295 if (!llvm::equal(tgtSrcAxes,
296 llvm::make_range(srcAxes.begin(), srcAxes.end() - 1)))
299 GridAxis movedAxis = srcAxes.back();
303 for (
size_t tgtTensorDim = 0;
304 tgtTensorDim < tgtSharding.getSplitAxes().size(); ++tgtTensorDim) {
305 if (
static_cast<int64_t>(tgtTensorDim) == srcTensorDim)
307 auto tgtAxes = tgtSharding.getSplitAxes()[tgtTensorDim].asArrayRef();
309 if (tgtAxes.empty() || tgtAxes.front() != movedAxis)
314 static_cast<size_t>(tgtTensorDim) < srcSharding.
getSplitAxes().size()
317 if (!llvm::equal(srcTgtAxes,
318 llvm::make_range(tgtAxes.begin() + 1, tgtAxes.end())))
320 return std::make_tuple(
static_cast<int64_t>(tgtTensorDim), movedAxis);
332 while (
static_cast<int64_t>(splitAxes.size()) <= tgtTensorDim)
336 auto srcSplitAxes = llvm::to_vector(splitAxes[srcTensorDim].asArrayRef());
337 assert(!srcSplitAxes.empty() && srcSplitAxes.back() == movedAxis);
338 srcSplitAxes.pop_back();
342 auto tgtSplitAxes = llvm::to_vector(splitAxes[tgtTensorDim].asArrayRef());
343 tgtSplitAxes.insert(tgtSplitAxes.begin(), movedAxis);
349 static std::tuple<TypedValue<ShapedType>,
Sharding>
357 tgtSharding(ctx, srcSharding, srcTensorDim, tgtTensorDim, movedAxis);
358 ShapedType a2aResultShape =
360 srcTensorDim, tgtTensorDim);
361 Value allToAllResult = AllToAllOp::create(
363 RankedTensorType::get(a2aResultShape.getShape(),
364 a2aResultShape.getElementType()),
366 APInt(64, tgtTensorDim), APInt(64, srcTensorDim));
367 ShapedType tgtShape =
370 tensor::CastOp::create(builder, tgtShape, allToAllResult).getResult();
371 return {tgtShard, resultSharding};
375 std::optional<std::tuple<TypedValue<ShapedType>,
Sharding>>
378 ShapedType srcUnshardedType,
382 if (
auto detectRes = detect(srcSharding, tgtSharding, tensorDim)) {
383 auto [tgtTensorDim, movedAxis] = detectRes.value();
384 return apply(builder, grid, srcSharding, srcUnshardedType, srcShard,
385 tensorDim, tgtTensorDim, movedAxis);
396 std::optional<std::tuple<TypedValue<ShapedType>,
Sharding>>
399 ShapedType srcUnshardedType,
414 assert(srcHaloSizes.empty() || srcHaloSizes.size() == tgtHaloSizes.size());
415 assert(((srcHaloSizes.empty() || ShapedType::isStaticShape(srcHaloSizes)) &&
416 ShapedType::isStaticShape(tgtHaloSizes) &&
417 srcShard.getType().hasStaticShape()) &&
418 "dynamic shapes/halos are not supported yet for shard-partition");
419 auto rank = srcShard.getType().getRank();
422 strides(rank, 1), outShape(srcShard.getType().getShape()),
423 coreShape(srcShard.getType().getShape());
427 for (
auto i = 0u; i < rank; ++i) {
428 if (i < splitAxes.size() && !splitAxes[i].empty()) {
429 if (!srcHaloSizes.empty()) {
430 coreShape[i] -= srcHaloSizes[i * 2] + srcHaloSizes[i * 2 + 1];
431 srcCoreOffs[i] = srcHaloSizes[i * 2];
433 tgtCoreOffs[i] = tgtHaloSizes[i * 2];
435 coreShape[i] + tgtHaloSizes[i * 2] + tgtHaloSizes[i * 2 + 1];
441 auto initVal = tensor::EmptyOp::create(builder, srcShard.
getLoc(), outShape,
442 srcShard.getType().getElementType());
443 auto core = tensor::ExtractSliceOp::create(
444 builder, srcShard.
getLoc(),
445 RankedTensorType::get(coreShape, srcShard.getType().getElementType()),
446 srcShard, noVals, noVals, noVals, srcCoreOffs, coreShape, strides);
447 auto initOprnd = tensor::InsertSliceOp::create(
448 builder, srcShard.
getLoc(), core, initVal, noVals, noVals, noVals,
449 tgtCoreOffs, coreShape, strides);
452 auto updateHaloResult =
453 UpdateHaloOp::create(builder, srcShard.
getLoc(),
454 RankedTensorType::get(
455 outShape, srcShard.getType().getElementType()),
456 initOprnd, grid.getSymName(),
470 GridOp grid,
const Sharding &srcSharding,
475 if (srcSharding == tgtSharding ||
480 assert(shardedSrc.getType() ==
482 [[maybe_unused]] ShapedType tgtShardType =
484 assert(shardedSrc.getType().getRank() == tgtShardType.getRank());
485 assert(unshardedSrc.getType().getRank() == tgtShardType.getRank());
493 &updateHaloPattern, &moveLastSplitAxisPattern, &splitLastAxisPattern,
494 &unsplitLastAxesPattern};
496 Sharding currentSharding = srcSharding;
498 dim < tgtShardType.getRank() && currentSharding != tgtSharding; ++dim) {
499 for (
auto &pattern : patterns) {
500 if (
auto tryRes = pattern->tryApply(builder, grid, dim, currentSharding,
501 tgtSharding, unshardedSrc.getType(),
503 std::tie(currentShard, currentSharding) = tryRes.value();
509 if (currentSharding != tgtSharding ||
510 currentShard.getType() != tgtShardType) {
512 <<
"Failed to reshard; probably hitting an unknown resharding pattern:"
513 <<
" got " << currentSharding <<
" expected " << tgtSharding
514 <<
" got type " << currentShard.getType() <<
" expected "
522 ShardOp srcShardOp, ShardOp tgtShardOp,
524 assert(srcShardOp.getResult() == tgtShardOp.getSrc());
525 auto srcSharding = srcShardOp.getSharding();
526 auto tgtSharding = tgtShardOp.getSharding();
528 return reshard(implicitLocOpBuilder, grid, srcSharding, tgtSharding,
529 srcShardOp.getSrc(), shardedSrc);
536 GridOp srcGrid =
getGrid(srcShardOp, symbolTableCollection);
537 assert(srcGrid && srcGrid ==
getGrid(tgtShardOp, symbolTableCollection));
538 return reshard(builder, srcGrid, srcShardOp, tgtShardOp, shardedSrc);
542 registry.
insert<shard::ShardDialect, tensor::TensorDialect>();
545#define GEN_PASS_DEF_PARTITION
546#include "mlir/Dialect/Shard/Transforms/Passes.h.inc"
560 auto rankedTensorArg = dyn_cast<TypedValue<RankedTensorType>>(arg);
561 if (!rankedTensorArg || rankedTensorArg.getType().getRank() == 0 ||
562 rankedTensorArg.use_empty()) {
563 return arg.getType();
566 assert(rankedTensorArg.hasOneUse());
568 ShardOp shardOp = llvm::dyn_cast<ShardOp>(useOp);
570 GridOp grid =
getGrid(shardOp, symbolTableCollection);
572 shardOp.getSharding()));
583 ShardingInterface shardingInterface = llvm::dyn_cast<ShardingInterface>(op);
584 if (!shardingInterface) {
588 resultShardings, partitionMap,
589 symbolTableCollection, builder);
591 if (failed(shardingInterface.partition(
592 partitionedOperands, operandShardings, resultShardings,
593 partitionMap, symbolTableCollection, builder))) {
599 return partitionMap.contains(result);
608 std::vector<Sharding> res;
610 llvm::transform(op.
getOperands(), std::back_inserter(res), [](
Value operand) {
611 TypedValue<RankedTensorType> rankedTensor =
612 dyn_cast<TypedValue<RankedTensorType>>(operand);
613 if (!rankedTensor || rankedTensor.getType().getRank() == 0) {
619 ShardOp shardOp = llvm::cast<ShardOp>(definingOp);
620 return Sharding(shardOp.getSharding());
628 std::vector<Sharding> res;
632 if (!result.hasOneUse() || result.use_empty()) {
641 ShardOp shardOp = llvm::dyn_cast<ShardOp>(userOp);
643 return Sharding(shardOp.getSharding());
645 if (rankedTensor.getType().getRank() == 0) {
650 if (
auto sharding = operand.getDefiningOp<ShardingOp>()) {
651 return Sharding(sharding.getGridAttr());
664 Value tgtPartitionValue;
668 ShardOp srcShardOp = shardOp.getSrc().
getDefiningOp<ShardOp>();
670 tgtPartitionValue = partitionMap.
lookup(shardOp.getSrc());
674 cast<TypedValue<ShapedType>>(partitionMap.
lookup(srcShardOp));
675 tgtPartitionValue =
reshard(builder, srcShardOp, shardOp, shardedSrc,
676 symbolTableCollection);
677 if (!tgtPartitionValue) {
678 return shardOp.emitError()
679 <<
"Failed to reshard from " << srcShardOp.getSharding() <<
" to "
680 << shardOp.getSharding();
684 assert(!partitionMap.
contains(shardOp.getResult()));
685 partitionMap.
map(shardOp.getResult(), tgtPartitionValue);
695 auto rankedTensorArg = dyn_cast<TypedValue<RankedTensorType>>(arg);
696 if (!rankedTensorArg || rankedTensorArg.getType().getRank() == 0 ||
697 rankedTensorArg.use_empty())
700 if (!rankedTensorArg.hasOneUse())
702 <<
"Cannot partition: expected a single use for block argument "
703 << arg.getArgNumber() <<
" in block "
707 auto shardOp = dyn_cast<ShardOp>(useOp);
710 <<
"Cannot partition: expected a shard.shard op for block "
711 <<
"argument " << arg.getArgNumber() <<
" in block "
732 auto rankedTT = dyn_cast<RankedTensorType>(operand.get().getType());
733 if (!rankedTT || rankedTT.getRank() == 0)
736 auto shard = operand.get().getDefiningOp<ShardOp>();
738 return op->
emitError() <<
"Cannot partition: tensor operand "
739 << operand.getOperandNumber()
740 <<
" must be defined by a shard.shard operation.";
741 if (!
shard.getAnnotateForUsers())
743 <<
"Cannot partition: shard.shard for operand "
744 << operand.getOperandNumber() <<
" must set 'annotate_for_users'.";
749 <<
"Cannot partition: result " <<
result.getResultNumber()
750 <<
" must have exactly one use.";
751 auto shard = dyn_cast<ShardOp>(*
result.user_begin());
754 <<
"Cannot partition: user of result " <<
result.getResultNumber()
755 <<
" must be shard.shard operation.";
756 if (
shard.getAnnotateForUsers())
757 return op->
emitError() <<
"Cannot partition: shard.shard for result "
758 <<
result.getResultNumber()
759 <<
" must not set 'annotate_for_users'.";
768 if (isa<ShardingOp>(op)) {
772 if (
auto getShardingOp = dyn_cast<GetShardingOp>(op)) {
773 auto shardOp = getShardingOp.getSource().getDefiningOp<ShardOp>();
775 return op.
emitError(
"expected a shard op as source of get_sharding");
777 auto newSharding = builder.
clone(*shardOp.getSharding().getDefiningOp());
778 partitionMap.
map(op.
getResult(0), newSharding->getResult(0));
782 ShardOp shardOp = llvm::dyn_cast<ShardOp>(op);
793 llvm::transform(op.
getOperands(), std::back_inserter(partitionedOperands),
794 [&partitionMap](
Value operand) {
795 assert(partitionMap.contains(operand));
796 return partitionMap.lookup(operand);
800 symbolTableCollection, builder);
812 llvm::transform(block.
getArguments(), std::back_inserter(argLocations),
817 for (
auto [unshardedBlockArg, partitionedBlockArg] :
819 partitionMap.
map(unshardedBlockArg, partitionedBlockArg);
842 for (
Block &
b : op.getBlocks()) {
843 if (llvm::any_of(
b.getOperations(),
844 [](
Operation &op) { return isa<ShardOp>(op); })) {
845 originalBlocks.push_back(&
b);
849 for (
Block *block : originalBlocks) {
850 if (failed(
partitionBlock(*block, partitionMap, symbolTableCollection,
856 for (
Block *block : originalBlocks) {
863 for (
Block &block : op.getFunctionBody()) {
869 returnOp = &block.back();
874 op.setType(FunctionType::get(
875 op->getContext(), op.getFunctionBody().front().getArgumentTypes(),
884struct Partition :
public impl::PartitionBase<Partition> {
885 void runOnOperation()
override {
888 if (failed(partitionFuncOp(getOperation(), partitionMap,
889 symbolTableCollection))) {
890 return signalPassFailure();
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
This class represents an argument of a Block.
Block represents an ordered list of Operations.
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
OpListType & getOperations()
BlockArgListType getArguments()
unsigned computeBlockNumber()
Compute the position of this block within its parent region using an O(N) linear scan.
MLIRContext * getContext() const
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
This is a utility class for mapping one set of IR entities to another.
auto lookup(T from) const
Lookup a mapped value within the map.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
bool contains(T from) const
Checks to see if a mapping for 'from' exists.
ImplicitLocOpBuilder maintains a 'current location', allowing use of the create<> method without spec...
Location getLoc() const
Accessors for the implied location.
mlir::InFlightDiagnostic emitError(const llvm::Twine &message=llvm::Twine())
This builder can also be used to emit diagnostics to the current location.
MLIRContext is the top-level object for a collection of MLIR operations.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
This class represents an operand of an operation.
This is a value defined by a result of an operation.
This class provides the API for a sub-set of ops that are known to be constant-like.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
MutableArrayRef< OpOperand > getOpOperands()
unsigned getNumOperands()
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
operand_type_range getOperandTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
user_range getUsers()
Returns a range of all users.
result_range getResults()
unsigned getNumResults()
Return the number of results held by this operation.
Location getLoc()
Return a location for this region.
This class represents a collection of SymbolTables.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int16_t > content)
Move the last split axis of one tensor dimension to the front of another tensor dimension's split axe...
std::optional< std::tuple< TypedValue< ShapedType >, Sharding > > tryApply(ImplicitLocOpBuilder &builder, GridOp grid, int64_t tensorDim, const Sharding &srcSharding, const Sharding &tgtSharding, ShapedType srcUnshardedType, TypedValue< ShapedType > srcShard) override
Try to apply this resharding pattern.
Base class for resharding patterns.
virtual std::optional< std::tuple< TypedValue< ShapedType >, Sharding > > tryApply(ImplicitLocOpBuilder &builder, GridOp grid, int64_t tensorDim, const Sharding &srcSharding, const Sharding &tgtSharding, ShapedType srcUnshardedType, TypedValue< ShapedType > srcShard)=0
Try to apply this resharding pattern.
static bool hasStaticOffsetsOrHalos(const Sharding &srcSharding, const Sharding &tgtSharding)
Returns true if either sharding has non-empty static sharded dims offsets or non-empty static halo si...
static bool hasStaticOffsets(const Sharding &srcSharding, const Sharding &tgtSharding)
Returns true if either sharding has non-empty static sharded dims offsets.
virtual ~ReshardingPattern()=default
static Sharding get(::mlir::FlatSymbolRefAttr grid_, ArrayRef< GridAxesAttr > split_axes_, ArrayRef< int64_t > static_halo_sizes_={}, ArrayRef< int64_t > static_sharded_dims_offsets_={}, ArrayRef< Value > dynamic_halo_sizes_={}, ArrayRef< Value > dynamic_sharded_dims_offsets_={})
bool equalSplitAxes(const Sharding &rhs) const
ArrayRef< int64_t > getStaticHaloSizes() const
::mlir::FlatSymbolRefAttr getGridAttr() const
ArrayRef< Value > getDynamicHaloSizes() const
ArrayRef< int64_t > getStaticShardedDimsOffsets() const
ArrayRef< GridAxesAttr > getSplitAxes() const
bool equalHaloSizes(const Sharding &rhs) const
Split a replicated axis: e.g. [[0, 1]] -> [[0, 1, 2]].
std::optional< std::tuple< TypedValue< ShapedType >, Sharding > > tryApply(ImplicitLocOpBuilder &builder, GridOp grid, int64_t tensorDim, const Sharding &srcSharding, const Sharding &tgtSharding, ShapedType srcUnshardedType, TypedValue< ShapedType > srcShard) override
Try to apply this resharding pattern.
Unsplit trailing axes: e.g. [[0, 1, 2]] -> [[0, 1]] or [[0, 1, 2]] -> [].
std::optional< std::tuple< TypedValue< ShapedType >, Sharding > > tryApply(ImplicitLocOpBuilder &builder, GridOp grid, int64_t tensorDim, const Sharding &srcSharding, const Sharding &tgtSharding, ShapedType srcUnshardedType, TypedValue< ShapedType > srcShard) override
Try to apply this resharding pattern.
Update halo sizes: handles cases where only the halo sizes differ between source and target sharding.
std::optional< std::tuple< TypedValue< ShapedType >, Sharding > > tryApply(ImplicitLocOpBuilder &builder, GridOp grid, int64_t tensorDim, const Sharding &srcSharding, const Sharding &tgtSharding, ShapedType srcUnshardedType, TypedValue< ShapedType > srcShard) override
Try to apply this resharding pattern.
ShapedType shardShapedType(ShapedType shape, GridOp grid, Sharding sharding)
void partitionFullyReplicatedOperation(Operation &op, ArrayRef< Value > partitionedOperands, ArrayRef< Sharding > operandShardings, ArrayRef< Sharding > resultShardings, IRMapping &partitionMap, SymbolTableCollection &symbolTable, OpBuilder &builder)
static SmallVector< Type > shardedBlockArgumentTypes(Block &block, SymbolTableCollection &symbolTableCollection)
static LogicalResult partitionFuncOp(FunctionOpInterface op, IRMapping &partitionMap, SymbolTableCollection &symbolTableCollection)
static ShapedType allToAllResultShape(ShapedType srcShape, int64_t splitCount, int64_t srcTensorDim, int64_t tgtTensorDim)
static LogicalResult checkFullyAnnotated(Block &block)
bool isFullReplication(Sharding sharding)
static LogicalResult partitionBlock(Block &block, IRMapping &partitionMap, SymbolTableCollection &symbolTableCollection, OpBuilder &builder)
static std::vector< Sharding > getOperandShardings(Operation &op)
DenseMap< Value, Value > UnshardedToShardedValueMap
static std::vector< Sharding > getResultShardings(Operation &op)
int64_t shardDimension(int64_t dimSize, int64_t shardCount)
TypedValue< ShapedType > reshard(OpBuilder &builder, GridOp grid, ShardOp source, ShardOp target, TypedValue< ShapedType > sourceShardValue)
void reshardingRegisterDependentDialects(DialectRegistry ®istry)
shard::GridOp getGrid(Operation *op, FlatSymbolRefAttr gridSymbol, SymbolTableCollection &symbolTableCollection)
static LogicalResult partitionOperation(Operation &op, ArrayRef< Value > partitionedOperands, ArrayRef< Sharding > operandShardings, ArrayRef< Sharding > resultShardings, IRMapping &partitionMap, SymbolTableCollection &symbolTableCollection, OpBuilder &builder)
int64_t gatherDimension(int64_t dimSize, int64_t shardCount)
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
This trait indicates that a terminator operation is "return-like".