17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/TypeSwitch.h"
20#include "llvm/Support/DebugLog.h"
25#define DEBUG_TYPE "vector-to-gpu-common"
30 auto vecType = dyn_cast<VectorType>(constantOp.getType());
31 if (!vecType || vecType.getRank() != 2)
33 return isa<SplatElementsAttr>(constantOp.getValue());
37 return broadcastOp.getResultVectorType().getRank() == 2;
40template <
typename ExtOpTy>
43 extOp.getOperand().template getDefiningOp<vector::TransferReadOp>();
46 return llvm::all_of(extOp->getUsers(), llvm::IsaPred<vector::ContractionOp>);
55std::optional<gpu::MMAElementwiseOp>
57 using MMAEwO = gpu::MMAElementwiseOp;
59 .Case([](arith::AddFOp) {
return MMAEwO::ADDF; })
60 .Case([](arith::AddIOp) {
return MMAEwO::ADDI; })
61 .Case([](arith::DivFOp) {
return MMAEwO::DIVF; })
62 .Case([](arith::DivSIOp) {
return MMAEwO::DIVS; })
63 .Case([](arith::DivUIOp) {
return MMAEwO::DIVU; })
64 .Case([](arith::ExtFOp) {
return MMAEwO::EXTF; })
65 .Case([](arith::MaximumFOp) {
return MMAEwO::MAXF; })
66 .Case([](arith::MinimumFOp) {
return MMAEwO::MINF; })
67 .Case([](arith::MulFOp) {
return MMAEwO::MULF; })
68 .Case([](arith::MulIOp) {
return MMAEwO::MULI; })
69 .Case([](arith::NegFOp) {
return MMAEwO::NEGATEF; })
70 .Case([](arith::SubFOp) {
return MMAEwO::SUBF; })
71 .Case([](arith::SubIOp) {
return MMAEwO::SUBI; })
72 .Case([](arith::TruncFOp) {
return MMAEwO::TRUNCF; })
73 .Default(std::nullopt);
89 auto operands = llvm::to_vector<4>(loop.getInitArgs());
90 llvm::append_range(operands, newInitArgs);
92 scf::ForOp::create(rewriter, loop.getLoc(), loop.getLowerBound(),
93 loop.getUpperBound(), loop.getStep(), operands);
96 newLoop.getRegion().getBlocks().splice(
97 newLoop.getRegion().getBlocks().begin(), loop.getRegion().getBlocks());
98 for (
Value operand : newInitArgs)
99 newLoop.getBody()->addArgument(operand.getType(), operand.getLoc());
101 for (
auto it : llvm::zip(loop.getResults(), newLoop.getResults().take_front(
102 loop.getNumResults())))
105 LDBG() <<
"newLoop now: " << newLoop;
106 LDBG() <<
"stripped scf.for: " << loop;
107 LDBG() <<
"erase: " << loop;
121 for (
const auto &operand : llvm::enumerate(op.getInitArgs())) {
122 auto it = valueMapping.find(operand.value());
123 if (it == valueMapping.end()) {
124 LDBG() <<
"no value mapping for: " << operand.value();
127 argMapping.push_back(std::make_pair(
128 operand.index(), op.getInitArgs().size() + newOperands.size()));
129 newOperands.push_back(it->second);
133 Block &loopBody = *newForOp.getBody();
134 for (
auto mapping : argMapping) {
135 valueMapping[newForOp.getResult(mapping.first)] =
136 newForOp.getResult(mapping.second);
138 newForOp.getNumInductionVars())] =
139 loopBody.
getArgument(mapping.second + newForOp.getNumInductionVars());
142 LDBG() <<
"scf.for to: " << newForOp;
152 auto loop = cast<scf::ForOp>(op->getParentOp());
153 auto yieldOperands = llvm::to_vector<4>(op.getOperands());
154 for (
const auto &operand : llvm::enumerate(op.getOperands())) {
155 auto it = valueMapping.find(operand.value());
156 if (it == valueMapping.end())
160 yieldOperands[operand.index()] = loop.getInitArgs()[operand.index()];
161 yieldOperands.push_back(it->second);
163 scf::YieldOp::create(rewriter, op.getLoc(), yieldOperands);
165 LDBG() <<
"erase: " << op;
173struct CombineTransferReadOpTranspose final
177 LogicalResult matchAndRewrite(vector::TransposeOp op,
180 Value source = op.getVector();
181 Type resultType = op.getType();
188 VectorType::get(cast<VectorType>(resultType).
getShape(),
189 cast<VectorType>(source.
getType()).getElementType());
192 auto transferReadOp = source.
getDefiningOp<vector::TransferReadOp>();
197 if (transferReadOp.getTransferRank() == 0)
200 if (transferReadOp.getMask() || transferReadOp.hasOutOfBoundsDim())
203 AffineMap permutationMap =
206 permutationMap.
compose(transferReadOp.getPermutationMap());
208 auto loc = op.getLoc();
209 Value
result = vector::TransferReadOp::create(
210 rewriter, loc, resultType, transferReadOp.getBase(),
211 transferReadOp.getIndices(), AffineMapAttr::get(newMap),
212 transferReadOp.getPadding(), transferReadOp.getMask(),
213 transferReadOp.getInBoundsAttr())
218 if (isa<arith::ExtSIOp>(extOp))
219 result = arith::ExtSIOp::create(rewriter, loc, op.getType(),
result)
221 else if (isa<arith::ExtUIOp>(extOp))
222 result = arith::ExtUIOp::create(rewriter, loc, op.getType(),
result)
227 arith::ExtFOp::Properties{})
239 patterns.
add<CombineTransferReadOpTranspose>(patterns.
getContext());
static ArrayRef< int64_t > getShape(Type type)
Returns the shape of the given type.
static scf::ForOp replaceForOpWithNewSignature(RewriterBase &rewriter, scf::ForOp loop, ValueRange newInitArgs)
AffineExpr getResult(unsigned idx) const
static AffineMap getPermutationMap(ArrayRef< unsigned > permutation, MLIRContext *context)
Returns an AffineMap representing a permutation.
AffineMap compose(AffineMap map) const
Returns the AffineMap resulting from composing this with map.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
RAII guard to reset the insertion point of the builder when destroyed.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
virtual void eraseBlock(Block *block)
This method erases all operations in a block.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
virtual void replaceAllUsesWith(Value from, Value to)
Find uses of from and replace them with to.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Include the generated interface declarations.
LogicalResult convertYieldOpForMMA(RewriterBase &rewriter, scf::YieldOp op, llvm::DenseMap< Value, Value > &valueMapping)
Update a yield operation to yield the converted values.
bool broadcastSupportsMMAMatrixType(vector::BroadcastOp broadcastOp)
Return true if this is a broadcast from scalar to a 2D vector.
bool elementwiseSupportsMMAMatrixType(Operation *op)
Return true if the operation is supported as elementwise on an MMA matrix.
LogicalResult convertForOpForMMA(RewriterBase &rewriter, scf::ForOp op, llvm::DenseMap< Value, Value > &valueMapping)
Extend loop-carried values with their converted counterparts.
std::optional< gpu::MMAElementwiseOp > convertElementwiseOpToMMA(Operation *op)
Return the MMA elementwise enum associated with the operation if supported.
bool constantSupportsMMAMatrixType(arith::ConstantOp constantOp)
Return true if the constant is a splat to a 2D vector so that it can be converted to an MMA constant ...
void populateVectorTransferReadTransposePatterns(RewritePatternSet &patterns)
Populate patterns that fold vector.transpose into vector.transfer_read, including through arithmetic ...
llvm::TypeSwitch< T, ResultT > TypeSwitch
template bool integerExtendSupportsMMAMatrixType< arith::ExtSIOp >(arith::ExtSIOp)
bool integerExtendSupportsMMAMatrixType(ExtOpTy extOp)
Return true if this integer extend op can be folded into a contract op.
template bool integerExtendSupportsMMAMatrixType< arith::ExtUIOp >(arith::ExtUIOp)
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...