19#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
20#include "mlir/Conversion/LLVMCommon/Pattern.h"
21#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
22#include "mlir/Dialect/Math/IR/Math.h"
23#include "mlir/Dialect/UB/IR/UBOps.h"
24#include "mlir/IR/TypeUtilities.h"
30#define GEN_PASS_DEF_CONVERTAIEVECTOLLVM
31#include "aie/Conversion/Passes.h.inc"
38inline static Value bitcastValueToType(OpBuilder &builder, Location loc,
39 Value val, Type dstTy) {
40 return LLVM::BitcastOp::create(builder, loc, dstTy, val).getResult();
46inline static Value widen128bVectorValueTo512b(OpBuilder &builder, Location loc,
48 return xllvm::VectorSetI512I128IntrOp::create(
49 builder, loc, VectorType::get({16}, builder.getI32Type()),
50 bitcastValueToType(builder, loc, val,
51 VectorType::get({4}, builder.getI32Type())))
59inline static Value widen256bVectorValueTo512b(OpBuilder &builder, Location loc,
62 LLVM::ConstantOp::create(builder, loc, builder.getI32Type(), (int32_t)0);
63 return xllvm::VectorSetI512I256IntrOp::create(
64 builder, loc, VectorType::get({16}, builder.getI32Type()),
65 bitcastValueToType(builder, loc, val,
66 VectorType::get({8}, builder.getI32Type())),
74static Value forceCastValueToType(OpBuilder &builder, Location loc, Value val,
76 auto valTy = val.getType();
79 auto srcVecTy = dyn_cast<VectorType>(valTy);
80 auto dstVecTy = dyn_cast<VectorType>(type);
83 assert(dstVecTy &&
"vector values cannot be forced into a non-vector type");
87 if (srcVecTy != flatSrcVecTy)
88 val = vector::ShapeCastOp::create(builder, loc, flatSrcVecTy, val);
93 int64_t dstVecLength =
94 flatDstVecTy.getElementTypeBitWidth() * flatDstVecTy.getShape()[0];
95 int64_t srcVecLength =
96 flatSrcVecTy.getElementTypeBitWidth() * flatSrcVecTy.getShape()[0];
97 if (srcVecLength != dstVecLength) {
98 assert(srcVecLength < dstVecLength &&
99 "only widening forced casts are supported");
100 assert(dstVecLength == 512 &&
101 (srcVecLength == 128 || srcVecLength == 256) &&
102 "only 128b to 512b and 256b to 512b forced casts are supported");
103 if (srcVecLength == 128)
104 val = widen128bVectorValueTo512b(builder, loc, val);
106 val = widen256bVectorValueTo512b(builder, loc, val);
110 val = bitcastValueToType(builder, loc, val, flatDstVecTy);
113 if (flatDstVecTy != dstVecTy)
114 val = vector::ShapeCastOp::create(builder, loc, dstVecTy, val);
120 assert(!dstVecTy &&
"cannot force cast scalar to vector type");
121 return bitcastValueToType(builder, loc, val, type);
128static SmallVector<Value> forceCastOperandsToSignature(OpBuilder &builder,
131 TypeRange signature) {
132 return llvm::to_vector(llvm::map_range(
133 llvm::zip_equal(operands, signature), [&](
auto &&vt) -> Value {
134 return forceCastValueToType(builder, loc, std::get<0>(vt),
157static LLVM::LLVMFuncOp getOrCreateScalarHelperFunc(
158 ModuleOp module, OpBuilder &rewriter, StringRef opName, StringRef device,
159 TypeRange argTypes, Type resultType,
160 const std::function<
void(OpBuilder &, Location, ValueRange)> &bodyBuilder) {
163 std::string funcName =
"__" + device.str() +
"_scalar_" + opName.str();
166 auto helperFunc =
module.lookupSymbol<LLVM::LLVMFuncOp>(funcName);
171 OpBuilder::InsertionGuard guard(rewriter);
172 rewriter.setInsertionPointToStart(module.getBody());
175 SmallVector<Type> argTypesVec(argTypes.begin(), argTypes.end());
177 helperFunc = LLVM::LLVMFuncOp::create(
178 rewriter, rewriter.getUnknownLoc(), funcName,
179 LLVM::LLVMFunctionType::get(resultType, argTypesVec));
182 helperFunc->setAttr(
"passthrough", rewriter.getArrayAttr(
183 {rewriter.getStringAttr(
"noinline")}));
186 auto *entryBlock = helperFunc.addEntryBlock(rewriter);
187 OpBuilder::InsertionGuard bodyGuard(rewriter);
188 rewriter.setInsertionPointToStart(entryBlock);
191 SmallVector<Value> args;
192 for (
unsigned i = 0; i < argTypes.size(); ++i)
193 args.push_back(entryBlock->getArgument(i));
196 bodyBuilder(rewriter, rewriter.getUnknownLoc(), args);
223static inline int aiev2_vmac_compute_control(
int sgn_x,
int sgn_y,
int amode,
224 int bmode,
int variant,
225 int zero_acc,
int shift16,
226 int sub_mul,
int sub_acc1,
227 int sub_acc2,
int sub_mask) {
228 return ((
unsigned)sub_mask << 16) | ((unsigned)shift16 << 10) |
229 ((
unsigned)sub_mul << 11) | ((unsigned)sub_acc1 << 12) |
230 ((
unsigned)sub_acc2 << 13) | ((unsigned)amode << 1) |
231 ((
unsigned)bmode << 3) | ((unsigned)variant << 5) |
232 (((
unsigned)sgn_x << 9) | ((
unsigned)sgn_y << 8)) |
233 ((unsigned)zero_acc << 0);
236static std::string getVectorTypeString(VectorType type,
bool abbrev =
false,
238 std::stringstream ss;
241 if (
auto intType = dyn_cast<IntegerType>(type.getElementType())) {
242 ss << (acc ?
"acc" : abbrev ?
"i" :
"int") << intType.getWidth();
243 }
else if (dyn_cast<FloatType>(type.getElementType())) {
244 ss << (abbrev ?
"f" :
"float");
249static std::string getMulOrFMAIntrinsicName(Operation *op) {
250 std::string baseName;
252 if (
auto mulOp = dyn_cast<aievec::aie1::MulOp>(op)) {
254 lhs = mulOp.getLhs();
255 result = mulOp.getResult();
256 }
else if (
auto fmaOp = dyn_cast<aievec::aie1::FMAOp>(op)) {
258 lhs = fmaOp.getLhs();
259 result = fmaOp.getResult();
261 VectorType resultType = cast<VectorType>(result.getType());
263 std::stringstream ss;
265 if (dyn_cast<IntegerType>(resultType.getElementType())) {
267 ss << resultSize <<
"."
268 << getVectorTypeString(cast<VectorType>(lhs.getType()));
269 }
else if (dyn_cast<FloatType>(resultType.getElementType())) {
270 ss <<
"vfp" << baseName;
277static uint32_t encodeSquare(uint32_t square) {
279 out |= ((square >> 0) & 0x3) << 0;
280 out |= ((square >> 4) & 0x3) << 2;
281 out |= ((square >> 8) & 0x3) << 4;
282 out |= ((square >> 12) & 0x3) << 6;
288static void encodeConf(uint32_t conf[2],
const BufferParams &x,
290 conf[0] |= ((x.step & 0x3F) << 0) | ((z.step & 0x3F) << 8);
291 conf[1] |= (encodeSquare(x.square) << 0) | (encodeSquare(z.square) << 8);
292 conf[1] |= sub << 17;
296 :
public mlir::ConvertOpToLLVMPattern<aievec::aie1::AddOp> {
298 using ConvertOpToLLVMPattern<aievec::aie1::AddOp>::ConvertOpToLLVMPattern;
302 ConversionPatternRewriter &rewriter)
const override {
303 op.emitWarning() <<
"aie.add conversion is not implemented\n";
310 :
public mlir::ConvertOpToLLVMPattern<aievec::AddElemOp> {
312 using ConvertOpToLLVMPattern<aievec::AddElemOp>::ConvertOpToLLVMPattern;
321 auto lhs = op.getLhs();
322 auto lhsVecTy = cast<VectorType>(lhs.getType());
323 auto lhsScaTy = lhsVecTy.getElementType();
324 unsigned lhsBitWidth = lhsScaTy.getIntOrFloatBitWidth();
327 if (llvm::isa<IntegerType>(lhsScaTy)) {
330 if (lhsBitWidth == 32) {
340 ConversionPatternRewriter &rewriter)
const override {
341 Location loc = op.getLoc();
345 op.emitWarning() <<
"aievec.add_elem conversion is not supported.\n";
350 if (decodedAddElemOp.kind ==
352 auto confCst = LLVM::ConstantOp::create(
353 rewriter, loc, rewriter.getI32Type(),
354 rewriter.getI32IntegerAttr(decodedAddElemOp.conf));
355 SmallVector<Value> operands(
356 {adaptor.getLhs(), adaptor.getRhs(), confCst});
358 auto addElemOp = xllvm::AddAccFloatAIE2IntrOp::create(
359 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
360 forceCastOperandsToSignature(
361 rewriter, loc, operands,
362 {VectorType::get({8}, rewriter.getI64Type()),
363 VectorType::get({8}, rewriter.getI64Type()),
364 rewriter.getI32Type()}));
367 auto resultVal = forceCastValueToType(rewriter, loc, addElemOp,
368 op.getResult().getType());
369 rewriter.replaceOp(op, resultVal);
373 op.emitWarning() <<
"aievec.add_elem conversion is not supported.\n";
380 :
public mlir::ConvertOpToLLVMPattern<aievec::SubElemOp> {
382 using ConvertOpToLLVMPattern<aievec::SubElemOp>::ConvertOpToLLVMPattern;
391 auto lhs = op.getLhs();
392 auto lhsVecTy = cast<VectorType>(lhs.getType());
393 auto lhsScaTy = lhsVecTy.getElementType();
394 unsigned lhsBitWidth = lhsScaTy.getIntOrFloatBitWidth();
397 if (llvm::isa<IntegerType>(lhsScaTy)) {
400 if (lhsBitWidth == 32) {
410 ConversionPatternRewriter &rewriter)
const override {
411 Location loc = op.getLoc();
415 op.emitWarning() <<
"aievec.sub_elem conversion is not supported.\n";
420 if (decodedSubElemOp.kind ==
422 auto confCst = LLVM::ConstantOp::create(
423 rewriter, loc, rewriter.getI32Type(),
424 rewriter.getI32IntegerAttr(decodedSubElemOp.conf));
425 SmallVector<Value> operands(
426 {adaptor.getLhs(), adaptor.getRhs(), confCst});
428 auto subElemOp = xllvm::SubAccFloatAIE2IntrOp::create(
429 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
430 forceCastOperandsToSignature(
431 rewriter, loc, operands,
432 {VectorType::get({8}, rewriter.getI64Type()),
433 VectorType::get({8}, rewriter.getI64Type()),
434 rewriter.getI32Type()}));
437 auto resultVal = forceCastValueToType(rewriter, loc, subElemOp,
438 op.getResult().getType());
439 rewriter.replaceOp(op, resultVal);
443 op.emitWarning() <<
"aievec.sub_elem conversion is not supported.\n";
455template <
typename SrcOpTy,
typename IntrOpTy>
457 :
public mlir::ConvertOpToLLVMPattern<SrcOpTy> {
459 using mlir::ConvertOpToLLVMPattern<SrcOpTy>::ConvertOpToLLVMPattern;
464 ConversionPatternRewriter &rewriter)
const override {
465 constexpr int64_t accLanes = 64;
466 Location loc = op.getLoc();
467 auto type = cast<VectorType>(adaptor.getLhs().getType());
468 int64_t lanes = type.getNumElements();
469 if (!type.getElementType().isF32() || type.getRank() != 1 ||
470 accLanes % lanes != 0 || lanes % 2 != 0) {
471 op.emitWarning() << op->getName() <<
" conversion is not supported.\n";
477 auto accType = VectorType::get({accLanes}, rewriter.getF32Type());
478 auto accI64Type = VectorType::get({accLanes / 2}, rewriter.getI64Type());
479 auto i64Type = VectorType::get({lanes / 2}, rewriter.getI64Type());
480 auto lowLanes = [](int64_t n, int64_t size) {
481 SmallVector<int64_t> mask(size, -1);
482 std::iota(mask.begin(), mask.begin() + std::min(n, size), 0);
485 Value lhs = adaptor.getLhs(), rhs = adaptor.getRhs();
486 if (lanes != accLanes) {
487 lhs = LLVM::BitcastOp::create(rewriter, loc, i64Type, lhs);
488 rhs = LLVM::BitcastOp::create(rewriter, loc, i64Type, rhs);
489 SmallVector<int64_t> padMask = lowLanes(lanes / 2, accLanes / 2);
490 lhs = vector::ShuffleOp::create(rewriter, loc, lhs, lhs, padMask);
491 rhs = vector::ShuffleOp::create(rewriter, loc, rhs, rhs, padMask);
492 lhs = LLVM::BitcastOp::create(rewriter, loc, accType, lhs);
493 rhs = LLVM::BitcastOp::create(rewriter, loc, accType, rhs);
496 auto confCst = LLVM::ConstantOp::create(
497 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(60));
498 Value result = IntrOpTy::create(rewriter, loc, accType, lhs, rhs, confCst);
499 if (lanes != accLanes) {
500 result = LLVM::BitcastOp::create(rewriter, loc, accI64Type, result);
501 result = vector::ShuffleOp::create(rewriter, loc, result, result,
502 lowLanes(lanes / 2, lanes / 2));
503 result = LLVM::BitcastOp::create(rewriter, loc, type, result);
505 rewriter.replaceOp(op, result);
512 xllvm::AddACC2048AccFloatAIE2pIntrOp>;
515 xllvm::SubACC2048AccFloatAIE2pIntrOp>;
525 using ConvertOpToLLVMPattern<aievec::NegOp>::ConvertOpToLLVMPattern;
529 ConversionPatternRewriter &rewriter)
const override {
530 Location loc = op.getLoc();
531 auto srcVecTy = cast<VectorType>(adaptor.getSource().getType());
532 auto srcScaTy = srcVecTy.getElementType();
536 if (!isa<FloatType>(srcScaTy) || srcScaTy.getIntOrFloatBitWidth() != 32 ||
537 srcVecTy.getNumElements() != 16) {
538 op.emitWarning() <<
"aievec.neg conversion is not supported.\n";
542 auto v8i64Ty = VectorType::get({8}, rewriter.getI64Type());
546 auto confCst = LLVM::ConstantOp::create(
547 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(28));
548 SmallVector<Value> operands({adaptor.getSource(), confCst});
550 auto negOp = xllvm::NegACC512AccFloatAIE2IntrOp::create(
551 rewriter, loc, v8i64Ty,
552 forceCastOperandsToSignature(rewriter, loc, operands,
553 {v8i64Ty, rewriter.getI32Type()}));
556 forceCastValueToType(rewriter, loc, negOp, op.getResult().getType());
557 rewriter.replaceOp(op, resultVal);
568 :
public mlir::ConvertOpToLLVMPattern<aievec::NegOp> {
570 using ConvertOpToLLVMPattern<aievec::NegOp>::ConvertOpToLLVMPattern;
574 ConversionPatternRewriter &rewriter)
const override {
575 Location loc = op.getLoc();
576 auto srcVecTy = cast<VectorType>(adaptor.getSource().getType());
577 auto srcScaTy = srcVecTy.getElementType();
578 unsigned laneSize = srcVecTy.getNumElements();
580 if (!isa<FloatType>(srcScaTy) || srcScaTy.getIntOrFloatBitWidth() != 32 ||
581 (laneSize != 16 && laneSize != 32)) {
582 op.emitWarning() <<
"aievec.neg conversion is not supported.\n";
586 auto v64f32Ty = VectorType::get({64}, rewriter.getF32Type());
590 Value srcVal = adaptor.getSource();
592 if (srcVecTy != fltSrcVecTy)
593 srcVal = vector::ShapeCastOp::create(rewriter, loc, fltSrcVecTy, srcVal)
597 SmallVector<int64_t> expandMask;
598 for (
unsigned i = 0; i < laneSize; ++i)
599 expandMask.push_back(i);
600 for (
unsigned i = laneSize; i < 64; ++i)
601 expandMask.push_back(-1);
603 vector::ShuffleOp::create(rewriter, loc, srcVal, srcVal, expandMask);
609 auto confCst = LLVM::ConstantOp::create(
610 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(60));
611 auto negResult = xllvm::NegACC2048AccFloatAIE2pIntrOp::create(
612 rewriter, loc, v64f32Ty, srcExpanded, confCst);
614 SmallVector<int64_t> extractMask;
615 for (
unsigned i = 0; i < laneSize; ++i)
616 extractMask.push_back(i);
617 Value finalResult = vector::ShuffleOp::create(rewriter, loc, negResult,
618 negResult, extractMask)
622 if (srcVecTy != fltSrcVecTy)
624 vector::ShapeCastOp::create(rewriter, loc, srcVecTy, finalResult)
627 rewriter.replaceOp(op, finalResult);
633 :
public mlir::ConvertOpToLLVMPattern<aievec::aie1::SubOp> {
635 using ConvertOpToLLVMPattern<aievec::aie1::SubOp>::ConvertOpToLLVMPattern;
639 ConversionPatternRewriter &rewriter)
const override {
640 op.emitWarning() <<
"aie.sub conversion is not implemented\n";
646 :
public mlir::ConvertOpToLLVMPattern<aievec::aie1::FMAOp> {
648 using ConvertOpToLLVMPattern<aievec::aie1::FMAOp>::ConvertOpToLLVMPattern;
652 ConversionPatternRewriter &rewriter)
const override {
653 auto module = op->getParentOfType<ModuleOp>();
654 MLIRContext *context = rewriter.getContext();
656 auto startType = IntegerType::get(context, 32);
657 auto offsetsType = VectorType::get({2}, IntegerType::get(context, 32));
658 auto confType = VectorType::get({2}, IntegerType::get(context, 32));
661 std::string intrinsicName = getMulOrFMAIntrinsicName(op);
662 auto func =
module.lookupSymbol<LLVM::LLVMFuncOp>(
663 StringAttr::get(context, intrinsicName));
666 OpBuilder::InsertionGuard guard(rewriter);
667 rewriter.setInsertionPointToStart(module.getBody());
668 func = LLVM::LLVMFuncOp::create(
669 rewriter, rewriter.getUnknownLoc(), intrinsicName,
670 LLVM::LLVMFunctionType::get(
671 op.getResult().getType(),
672 {op.getLhs().getType(), op.getRhs().getType(),
673 op.getAcc().getType(), startType,
684 op.getXstart().getAsInteger(0, x.
start);
685 op.getXoffsets().getAsInteger(0, x.
offsets);
686 op.getXoffsetsHi().getAsInteger(0, x.
offsets_hi);
687 op.getXstep().getAsInteger(0, x.
step);
688 op.getXsquare().getAsInteger(0, x.
square);
689 op.getZstart().getAsInteger(0, z.
start);
690 op.getZoffsets().getAsInteger(0, z.
offsets);
691 op.getZoffsetsHi().getAsInteger(0, z.
offsets_hi);
692 op.getZstep().getAsInteger(0, z.
step);
693 op.getZsquare().getAsInteger(0, z.
square);
696 uint32_t conf[2] = {0, 0};
697 encodeConf(conf, x, z, op.getFmsub());
700 auto xstartVal = LLVM::ConstantOp::create(
701 rewriter, op->getLoc(), startType, rewriter.getI32IntegerAttr(x.
start));
702 auto ystartVal = LLVM::ConstantOp::create(rewriter, op->getLoc(), startType,
703 rewriter.getI32IntegerAttr(0));
704 auto zstartVal = LLVM::ConstantOp::create(
705 rewriter, op->getLoc(), startType, rewriter.getI32IntegerAttr(z.
start));
706 auto xoffsetsVal = LLVM::ConstantOp::create(
707 rewriter, op->getLoc(), offsetsType,
708 rewriter.getI32VectorAttr({(int32_t)x.offsets, (int32_t)x.offsets_hi}));
709 auto zoffsetsVal = LLVM::ConstantOp::create(
710 rewriter, op->getLoc(), offsetsType,
711 rewriter.getI32VectorAttr({(int32_t)z.offsets, (int32_t)z.offsets_hi}));
712 auto confVal = LLVM::ConstantOp::create(
713 rewriter, op->getLoc(), confType,
714 rewriter.getI32VectorAttr({(int32_t)conf[0], (int32_t)conf[1]}));
715 rewriter.replaceOpWithNewOp<LLVM::CallOp>(
717 ValueRange{op.getLhs(), op.getRhs(), op.getAcc(), xstartVal, ystartVal,
718 zstartVal, xoffsetsVal, zoffsetsVal, confVal});
724 :
public mlir::ConvertOpToLLVMPattern<aievec::aie1::MulOp> {
726 using ConvertOpToLLVMPattern<aievec::aie1::MulOp>::ConvertOpToLLVMPattern;
730 ConversionPatternRewriter &rewriter)
const override {
731 auto module = op->getParentOfType<ModuleOp>();
732 MLIRContext *context = rewriter.getContext();
734 auto startType = IntegerType::get(context, 32);
735 auto offsetsType = VectorType::get({2}, IntegerType::get(context, 32));
736 auto confType = VectorType::get({2}, IntegerType::get(context, 32));
739 std::string intrinsicName = getMulOrFMAIntrinsicName(op);
740 auto func =
module.lookupSymbol<LLVM::LLVMFuncOp>(
741 StringAttr::get(context, intrinsicName));
744 OpBuilder::InsertionGuard guard(rewriter);
745 rewriter.setInsertionPointToStart(module.getBody());
746 func = LLVM::LLVMFuncOp::create(
747 rewriter, rewriter.getUnknownLoc(), intrinsicName,
748 LLVM::LLVMFunctionType::get(op.getResult().getType(),
749 {op.getLhs().getType(),
750 op.getRhs().getType(),
762 op.getXstart().getAsInteger(0, x.
start);
763 op.getXoffsets().getAsInteger(0, x.
offsets);
764 op.getXoffsetsHi().getAsInteger(0, x.
offsets_hi);
765 op.getXstep().getAsInteger(0, x.
step);
766 op.getXsquare().getAsInteger(0, x.
square);
767 op.getZstart().getAsInteger(0, z.
start);
768 op.getZoffsets().getAsInteger(0, z.
offsets);
769 op.getZoffsetsHi().getAsInteger(0, z.
offsets_hi);
770 op.getZstep().getAsInteger(0, z.
step);
771 op.getZsquare().getAsInteger(0, z.
square);
774 uint32_t conf[2] = {0, 0};
775 encodeConf(conf, x, z,
false);
778 auto xstartVal = LLVM::ConstantOp::create(
779 rewriter, op->getLoc(), startType, rewriter.getI32IntegerAttr(x.
start));
780 auto ystartVal = LLVM::ConstantOp::create(rewriter, op->getLoc(), startType,
781 rewriter.getI32IntegerAttr(0));
782 auto zstartVal = LLVM::ConstantOp::create(
783 rewriter, op->getLoc(), startType, rewriter.getI32IntegerAttr(z.
start));
784 auto xoffsetsVal = LLVM::ConstantOp::create(
785 rewriter, op->getLoc(), offsetsType,
786 rewriter.getI32VectorAttr({(int32_t)x.offsets, (int32_t)x.offsets_hi}));
787 auto zoffsetsVal = LLVM::ConstantOp::create(
788 rewriter, op->getLoc(), offsetsType,
789 rewriter.getI32VectorAttr({(int32_t)z.offsets, (int32_t)z.offsets_hi}));
790 auto confVal = LLVM::ConstantOp::create(
791 rewriter, op->getLoc(), confType,
792 rewriter.getI32VectorAttr({(int32_t)conf[0], (int32_t)conf[1]}));
793 rewriter.replaceOpWithNewOp<LLVM::CallOp>(
795 ValueRange{op.getLhs(), op.getRhs(), xstartVal, ystartVal, zstartVal,
796 xoffsetsVal, zoffsetsVal, confVal});
802 :
public mlir::ConvertOpToLLVMPattern<aievec::MulElemOp> {
804 using ConvertOpToLLVMPattern<aievec::MulElemOp>::ConvertOpToLLVMPattern;
808 : ConvertOpToLLVMPattern(typeConverter),
830 auto lhs = op.getLhs();
831 auto lhsVecTy = cast<VectorType>(lhs.getType());
832 auto lhsScaTy = lhsVecTy.getElementType();
833 unsigned lhsBitWidth = lhsScaTy.getIntOrFloatBitWidth();
836 if (llvm::isa<IntegerType>(lhsScaTy)) {
837 if (lhsBitWidth == 8) {
839 aiev2_vmac_compute_control(
845 if (lhsBitWidth == 16) {
847 aiev2_vmac_compute_control(
853 if (lhsBitWidth == 32) {
859 if (lhsBitWidth == 16) {
861 aiev2_vmac_compute_control(
867 if (lhsBitWidth == 32) {
908 ConversionPatternRewriter &rewriter)
const {
910 Location loc = op.getLoc();
911 auto zeroCst = LLVM::ConstantOp::create(
912 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(0));
913 auto a0 = adaptor.getLhs();
914 auto a1 = xllvm::VectorBroadcast32I512IntrOp::create(
915 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()), zeroCst);
916 auto b0 = adaptor.getRhs();
917 auto b1 = xllvm::UndefV16I32IntrOp::create(
918 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()));
921 auto a_lo = xllvm::VectorShuffleIntrOp::create(
922 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()), a0, a1,
923 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
924 rewriter.getI32IntegerAttr(2)));
925 auto a_hi = xllvm::VectorShuffleIntrOp::create(
926 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()), a0, a1,
927 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
928 rewriter.getI32IntegerAttr(3)));
929 auto b_lo = xllvm::VectorShuffleIntrOp::create(
930 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()), b0, b1,
931 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
932 rewriter.getI32IntegerAttr(2)));
933 auto b_hi = xllvm::VectorShuffleIntrOp::create(
934 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()), b0, b1,
935 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
936 rewriter.getI32IntegerAttr(3)));
938 auto mulConfCst = LLVM::ConstantOp::create(
939 rewriter, loc, rewriter.getI32Type(),
940 rewriter.getI32IntegerAttr(aiev2_vmac_compute_control(
944 auto mulConfOp = xllvm::MulConfAcc64IntrOp::create(
945 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
946 forceCastOperandsToSignature(
948 {a_hi, b_hi, mulConfCst},
950 {VectorType::get({64}, rewriter.getI8Type()),
951 VectorType::get({16}, rewriter.getI32Type()),
952 rewriter.getI32Type()}));
954 auto createMacConfOp = [&](SmallVector<Value> operands,
955 int macConf) -> Value {
957 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
958 rewriter.getI32IntegerAttr(macConf)));
959 return xllvm::MacConfAcc64IntrOp::create(
960 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
961 forceCastOperandsToSignature(
965 {VectorType::get({64}, rewriter.getI8Type()),
966 VectorType::get({16}, rewriter.getI32Type()),
967 VectorType::get({16}, rewriter.getI64Type()),
968 rewriter.getI32Type()}))
971 auto acc64Val = mulConfOp.getResult();
972 acc64Val = createMacConfOp(
973 SmallVector<Value>{a_hi, b_lo, acc64Val},
974 aiev2_vmac_compute_control(
978 acc64Val = createMacConfOp(
979 SmallVector<Value>{a_lo, b_hi, acc64Val},
980 aiev2_vmac_compute_control(
984 acc64Val = createMacConfOp(
985 SmallVector<Value>{a_lo, b_lo, acc64Val},
986 aiev2_vmac_compute_control(
993 forceCastValueToType(rewriter, loc, acc64Val, op.getResult().getType());
994 rewriter.replaceOp(op, resultVal);
1036 ConversionPatternRewriter &rewriter)
const {
1037 Location loc = op.getLoc();
1039 LLVM::ConstantOp::create(rewriter, loc, rewriter.getBF16Type(),
1040 rewriter.getZeroAttr(rewriter.getBF16Type()));
1041 auto aZeros = xllvm::VectorBroadcast16BF512IntrOp::create(
1042 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), zeroCst);
1043 auto bZeros = xllvm::VectorBroadcast16BF512IntrOp::create(
1044 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), zeroCst);
1045 auto cZeros = xllvm::VectorBroadcast16BF512IntrOp::create(
1046 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), zeroCst);
1047 auto dZeros = xllvm::VectorBroadcast16BF512IntrOp::create(
1048 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), zeroCst);
1049 auto eZeros = xllvm::VectorBroadcast16BF512IntrOp::create(
1050 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), zeroCst);
1051 auto fZeros = xllvm::VectorBroadcast16BF512IntrOp::create(
1052 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), zeroCst);
1054 LLVM::ConstantOp::create(rewriter, loc, rewriter.getBF16Type(),
1055 rewriter.getOneAttr(rewriter.getBF16Type()));
1056 auto dummy0 = xllvm::VectorBroadcast16BF512IntrOp::create(
1057 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), oneCst);
1058 auto zeroCstI32 = LLVM::ConstantOp::create(
1059 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(0));
1060 auto mscMacMulConfCst = LLVM::ConstantOp::create(
1061 rewriter, loc, rewriter.getI32Type(),
1062 rewriter.getI32IntegerAttr(aiev2_vmac_compute_control(
1067 auto extractV16FP32ToThreeV16BF16 =
1068 [&](Value inputV16FP32, Value aZeros, Value bZeros,
1069 Value cZeros) -> std::tuple<Value, Value, Value> {
1071 auto inputBitCasted =
1072 forceCastValueToType(rewriter, loc, inputV16FP32,
1073 VectorType::get({8}, rewriter.getI64Type()));
1074 auto v1ToBF16 = xllvm::Vector16AccFloatToV16BF16AIE2IntrOp::create(
1075 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()),
1077 auto a = xllvm::UpdBF512BF256IntrOp::create(
1078 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), aZeros,
1079 v1ToBF16, zeroCstI32);
1082 auto acc0 = xllvm::MscConfBF16IntrOp::create(
1083 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()), a, dummy0,
1084 inputBitCasted, mscMacMulConfCst);
1087 auto acc0ToBF16 = xllvm::Vector16AccFloatToV16BF16AIE2IntrOp::create(
1088 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()), acc0);
1089 auto b = xllvm::UpdBF512BF256IntrOp::create(
1090 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), bZeros,
1091 acc0ToBF16, zeroCstI32);
1094 auto acc0Mscb = xllvm::MscConfBF16IntrOp::create(
1095 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()), b, dummy0,
1096 acc0, mscMacMulConfCst);
1097 auto acc0MscbToBF16 = xllvm::Vector16AccFloatToV16BF16AIE2IntrOp::create(
1098 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()),
1100 auto c = xllvm::UpdBF512BF256IntrOp::create(
1101 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), cZeros,
1102 acc0MscbToBF16, zeroCstI32);
1103 return std::make_tuple(a.getResult(), b.getResult(), c.getResult());
1108 extractV16FP32ToThreeV16BF16(adaptor.getLhs(), aZeros, bZeros, cZeros);
1111 extractV16FP32ToThreeV16BF16(adaptor.getRhs(), dZeros, eZeros, fZeros);
1114 auto createMacOps = [&](Value lhs, Value rhs, Value acc) -> Value {
1115 return xllvm::MacConfBF16IntrOp::create(
1116 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
1117 lhs, rhs, acc, mscMacMulConfCst)
1131 auto afMul = xllvm::MulConfBF16IntrOp::create(
1132 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()), a, f,
1134 finalMacVal = createMacOps(
1139 createMacOps(d, c, createMacOps(b, e, afMul)))));
1149 auto bdMul = xllvm::MulConfBF16IntrOp::create(
1150 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()), b, d,
1152 finalMacVal = createMacOps(a, d, createMacOps(a, e, bdMul));
1158 auto cfMul = xllvm::MulConfBF16IntrOp::create(
1159 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()), c, f,
1161 finalMacVal = createMacOps(
1174 createMacOps(c, e, cfMul))))))));
1178 auto resultVal = forceCastValueToType(rewriter, loc, finalMacVal,
1179 op.getResult().getType());
1180 rewriter.replaceOp(op, resultVal);
1186 ConversionPatternRewriter &rewriter)
const override {
1187 Location loc = op.getLoc();
1191 op.emitWarning() <<
"aievec.mul_elem conversion is not supported.\n";
1199 if (decodedMulElemOp.kind ==
1205 auto confCst = LLVM::ConstantOp::create(
1206 rewriter, loc, rewriter.getI32Type(),
1207 rewriter.getI32IntegerAttr(decodedMulElemOp.conf));
1208 Value mulElemOp =
nullptr;
1209 SmallVector<Value> operands({adaptor.getLhs(), adaptor.getRhs(), confCst});
1214 mulElemOp = xllvm::MulConfAcc32IntrOp::create(
1215 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
1216 forceCastOperandsToSignature(
1217 rewriter, loc, operands,
1218 {VectorType::get({64}, rewriter.getI8Type()),
1219 VectorType::get({16}, rewriter.getI32Type()),
1220 rewriter.getI32Type()}));
1221 }
else if (decodedMulElemOp.kind ==
1225 auto zero32 = LLVM::ConstantOp::create(
1226 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(0));
1227 auto zeros_i16 = xllvm::VectorBroadcast16I512IntrOp::create(
1228 rewriter, loc, VectorType::get({32}, rewriter.getI16Type()), zero32);
1229 auto zeros_bf16 = LLVM::BitcastOp::create(
1230 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()),
1232 auto zeroVec = xllvm::ExtBF256BF512IntrOp::create(
1233 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()),
1234 zeros_bf16, zero32);
1237 auto idx1 = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1238 rewriter.getI32IntegerAttr(1));
1241 auto lhsSet = xllvm::VectorSetBF512BF256IntrOp::create(
1242 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()),
1243 adaptor.getLhs(), zero32);
1244 auto lhsConcat = xllvm::UpdBF512BF256IntrOp::create(
1245 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), lhsSet,
1249 auto rhsSet = xllvm::VectorSetBF512BF256IntrOp::create(
1250 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()),
1251 adaptor.getRhs(), zero32);
1252 auto rhsConcat = xllvm::UpdBF512BF256IntrOp::create(
1253 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()), rhsSet,
1257 mulElemOp = xllvm::MulConfBF16IntrOp::create(
1258 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()), lhsConcat,
1259 rhsConcat, confCst);
1263 auto resultVal = forceCastValueToType(rewriter, loc, mulElemOp,
1264 op.getResult().getType());
1265 rewriter.replaceOp(op, resultVal);
1272 :
public mlir::ConvertOpToLLVMPattern<aievec::MulElemOp> {
1274 using ConvertOpToLLVMPattern<aievec::MulElemOp>::ConvertOpToLLVMPattern;
1288 auto lhs = op.getLhs();
1289 auto lhsVecTy = cast<VectorType>(lhs.getType());
1290 auto lhsScaTy = lhsVecTy.getElementType();
1291 unsigned lhsBitWidth = lhsScaTy.getIntOrFloatBitWidth();
1295 if (llvm::isa<IntegerType>(lhsScaTy)) {
1298 if (lhsBitWidth == 16) {
1300 if (lhsLanes == 16) {
1304 if (lhsLanes == 32) {
1308 if (lhsLanes == 64) {
1319 ConversionPatternRewriter &rewriter)
const override {
1320 Location loc = op.getLoc();
1324 op.emitWarning() <<
"aievec.mul_elem conversion is not supported for "
1330 auto confCst = LLVM::ConstantOp::create(
1331 rewriter, loc, rewriter.getI32Type(),
1332 rewriter.getI32IntegerAttr(decodedMulElemOp.conf));
1334 Value mulElemOp =
nullptr;
1337 if (decodedMulElemOp.kind ==
1343 SmallVector<int64_t> padMask;
1344 for (
int i = 0; i < 16; ++i)
1345 padMask.push_back(i);
1346 for (
int i = 16; i < 32; ++i)
1347 padMask.push_back(-1);
1349 auto lhsPadded = vector::ShuffleOp::create(
1350 rewriter, loc, adaptor.getLhs(), adaptor.getLhs(), padMask);
1351 auto rhsPadded = vector::ShuffleOp::create(
1352 rewriter, loc, adaptor.getRhs(), adaptor.getRhs(), padMask);
1354 SmallVector<Value> operands({lhsPadded, rhsPadded, confCst});
1357 mulElemOp = xllvm::MulConfBF16I512ACC512AIE2pIntrOp::create(
1358 rewriter, loc, VectorType::get({16}, rewriter.getF32Type()),
1359 forceCastOperandsToSignature(
1360 rewriter, loc, operands,
1361 {VectorType::get({32}, rewriter.getBF16Type()),
1362 VectorType::get({32}, rewriter.getBF16Type()),
1363 rewriter.getI32Type()}));
1364 }
else if (decodedMulElemOp.kind ==
1367 SmallVector<Value> operands(
1368 {adaptor.getLhs(), adaptor.getRhs(), confCst});
1369 mulElemOp = xllvm::MulConfBF16I512ACC1024AIE2pIntrOp::create(
1370 rewriter, loc, VectorType::get({32}, rewriter.getF32Type()),
1371 forceCastOperandsToSignature(
1372 rewriter, loc, operands,
1373 {VectorType::get({32}, rewriter.getBF16Type()),
1374 VectorType::get({32}, rewriter.getBF16Type()),
1375 rewriter.getI32Type()}));
1376 }
else if (decodedMulElemOp.kind ==
1379 SmallVector<Value> operands(
1380 {adaptor.getLhs(), adaptor.getRhs(), confCst});
1381 mulElemOp = xllvm::MulConfBF16I1024ACC2048AIE2pIntrOp::create(
1382 rewriter, loc, VectorType::get({64}, rewriter.getF32Type()),
1383 forceCastOperandsToSignature(
1384 rewriter, loc, operands,
1385 {VectorType::get({64}, rewriter.getBF16Type()),
1386 VectorType::get({64}, rewriter.getBF16Type()),
1387 rewriter.getI32Type()}));
1391 auto resultVal = forceCastValueToType(rewriter, loc, mulElemOp,
1392 op.getResult().getType());
1393 rewriter.replaceOp(op, resultVal);
1401 :
public mlir::ConvertOpToLLVMPattern<aievec::FMAElemOp> {
1403 using ConvertOpToLLVMPattern<aievec::FMAElemOp>::ConvertOpToLLVMPattern;
1407 ConversionPatternRewriter &rewriter)
const override {
1408 auto loc = fmaOp.getLoc();
1409 auto lhs = adaptor.getLhs();
1410 auto rhs = adaptor.getRhs();
1411 auto acc = adaptor.getAcc();
1412 auto lhsTy = cast<VectorType>(lhs.getType());
1413 auto accTy = cast<VectorType>(acc.getType());
1418 if (lhsTy != flatLhsTy)
1419 lhs = vector::ShapeCastOp::create(rewriter, loc, flatLhsTy, lhs);
1420 if (cast<VectorType>(rhs.getType()) != flatLhsTy)
1421 rhs = vector::ShapeCastOp::create(rewriter, loc, flatLhsTy, rhs);
1422 if (accTy != flatAccTy)
1423 acc = vector::ShapeCastOp::create(rewriter, loc, flatAccTy, acc);
1425 if (!flatLhsTy.getElementType().isBF16()) {
1427 <<
"aievec.mac_elem AIE2p conversion only supports bf16 inputs.\n";
1431 Type i32ty = rewriter.getI32Type();
1432 auto confCst = LLVM::ConstantOp::create(
1433 rewriter, loc, i32ty,
1434 rewriter.getI32IntegerAttr(aiev2_vmac_compute_control(
1440 unsigned lhsLanes = flatLhsTy.getNumElements();
1441 Value macIntrOp =
nullptr;
1443 if (lhsLanes == 16) {
1445 SmallVector<int64_t> padMask;
1446 for (
int i = 0; i < 16; ++i)
1447 padMask.push_back(i);
1448 for (
int i = 16; i < 32; ++i)
1449 padMask.push_back(-1);
1452 vector::ShuffleOp::create(rewriter, loc, lhs, lhs, padMask);
1454 vector::ShuffleOp::create(rewriter, loc, rhs, rhs, padMask);
1456 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
1457 auto v16f32Ty = VectorType::get({16}, rewriter.getF32Type());
1458 macIntrOp = xllvm::MacConfBF16I512ACC512AIE2pIntrOp::create(
1459 rewriter, loc, v16f32Ty,
1460 forceCastOperandsToSignature(
1461 rewriter, loc, {lhsPadded, rhsPadded, acc, confCst},
1462 {v32bf16Ty, v32bf16Ty, v16f32Ty, i32ty}));
1463 }
else if (lhsLanes == 32) {
1465 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
1466 auto v32f32Ty = VectorType::get({32}, rewriter.getF32Type());
1467 macIntrOp = xllvm::MacConfBF16I512ACC1024AIE2pIntrOp::create(
1468 rewriter, loc, v32f32Ty,
1469 forceCastOperandsToSignature(
1470 rewriter, loc, {lhs, rhs, acc, confCst},
1471 {v32bf16Ty, v32bf16Ty, v32f32Ty, i32ty}));
1474 <<
"aievec.mac_elem AIE2p conversion: unsupported lane count "
1475 << lhsLanes <<
".\n";
1480 auto resVal = forceCastValueToType(rewriter, loc, macIntrOp, flatAccTy);
1481 if (flatAccTy != accTy)
1482 resVal = vector::ShapeCastOp::create(rewriter, loc, accTy, resVal);
1484 rewriter.replaceOp(fmaOp, resVal);
1497 using ConvertOpToLLVMPattern<aievec::UPSOp>::ConvertOpToLLVMPattern;
1501 ConversionPatternRewriter &rewriter)
const override {
1502 Location loc = op.getLoc();
1504 Value result = op.getResult();
1505 VectorType resultType = cast<VectorType>(result.getType());
1507 Type resultScaTy = resultType.getElementType();
1508 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
1510 int resultVectorSize = resultBitWidth * resultLanes;
1512 Value opSrcVal = adaptor.getSource();
1513 auto srcVecTy = cast<VectorType>(opSrcVal.getType());
1515 if (srcVecTy != fltSrcVecTy)
1516 opSrcVal = vector::ShapeCastOp::create(rewriter, op.getLoc(), fltSrcVecTy,
1522 Value upsIntrOp =
nullptr;
1523 if (llvm::isa<IntegerType>(resultScaTy)) {
1525 auto signCst = LLVM::ConstantOp::create(
1526 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(1));
1528 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1529 rewriter.getI32IntegerAttr(op.getShift()));
1531 SmallVector<Value> operands({opSrcVal, shiftCst, signCst});
1532 if (resultVectorSize == 512) {
1533 if (resultBitWidth == 32) {
1535 upsIntrOp = xllvm::Acc32V16I256UpsAIE2IntrOp::create(
1536 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
1537 forceCastOperandsToSignature(
1538 rewriter, loc, operands,
1539 {VectorType::get({16}, rewriter.getI16Type()),
1540 rewriter.getI32Type(), rewriter.getI32Type()}));
1541 }
else if (resultBitWidth == 64) {
1543 upsIntrOp = xllvm::Acc64V8I256UpsAIE2IntrOp::create(
1544 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
1545 forceCastOperandsToSignature(
1546 rewriter, loc, operands,
1547 {VectorType::get({8}, rewriter.getI32Type()),
1548 rewriter.getI32Type(), rewriter.getI32Type()}));
1550 }
else if (resultVectorSize == 1024) {
1551 Value src = opSrcVal;
1552 VectorType srcType = cast<VectorType>(src.getType());
1553 Type srcScaType = srcType.getElementType();
1554 unsigned srcBitWidth = srcScaType.getIntOrFloatBitWidth();
1556 if (resultBitWidth == 32 && srcBitWidth == 16) {
1558 upsIntrOp = xllvm::Acc32V32I512UpsAIE2IntrOp::create(
1559 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
1560 forceCastOperandsToSignature(
1561 rewriter, loc, operands,
1562 {VectorType::get({32}, rewriter.getI16Type()),
1563 rewriter.getI32Type(), rewriter.getI32Type()}));
1564 }
else if (resultBitWidth == 64 && srcBitWidth == 32) {
1566 upsIntrOp = xllvm::Acc64V16I512UpsAIE2IntrOp::create(
1567 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
1568 forceCastOperandsToSignature(
1569 rewriter, loc, operands,
1570 {VectorType::get({16}, rewriter.getI32Type()),
1571 rewriter.getI32Type(), rewriter.getI32Type()}));
1572 }
else if (resultBitWidth == 64 && srcBitWidth == 16) {
1574 upsIntrOp = xllvm::Acc64V16I256UpsAIE2IntrOp::create(
1575 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
1576 forceCastOperandsToSignature(
1577 rewriter, loc, operands,
1578 {VectorType::get({16}, rewriter.getI16Type()),
1579 rewriter.getI32Type(), rewriter.getI32Type()}));
1580 }
else if (resultBitWidth == 32 && srcBitWidth == 8) {
1582 upsIntrOp = xllvm::Acc32V32I256UpsAIE2IntrOp::create(
1583 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
1584 forceCastOperandsToSignature(
1585 rewriter, loc, operands,
1586 {VectorType::get({32}, rewriter.getI8Type()),
1587 rewriter.getI32Type(), rewriter.getI32Type()}));
1593 if (resultVectorSize == 512) {
1595 upsIntrOp = xllvm::Vector16BF16ToV16AccFloatAIE2IntrOp::create(
1596 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
1597 forceCastOperandsToSignature(
1598 rewriter, loc, {opSrcVal},
1599 {VectorType::get({16}, rewriter.getBF16Type())}));
1600 }
else if (resultVectorSize == 1024) {
1609 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1610 rewriter.getI32IntegerAttr(0));
1612 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1613 rewriter.getI32IntegerAttr(1));
1614 auto extractUps = [&](Value source, Value index) -> Value {
1615 auto extOp = xllvm::ExtI256I512IntrOp::create(
1616 rewriter, loc, VectorType::get({8}, rewriter.getI32Type()),
1617 forceCastOperandsToSignature(
1618 rewriter, loc, {source, index},
1619 {VectorType::get({16}, rewriter.getI32Type()),
1620 rewriter.getI32Type()}));
1621 return xllvm::Vector16BF16ToV16AccFloatAIE2IntrOp::create(
1622 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
1623 forceCastOperandsToSignature(
1624 rewriter, loc, {extOp},
1625 {VectorType::get({16}, rewriter.getBF16Type())}));
1627 auto resLo = extractUps(opSrcVal, indexZeroCst);
1628 auto resHi = extractUps(opSrcVal, indexOneCst);
1631 upsIntrOp = xllvm::ConcatI1024I512IntrOp::create(
1632 rewriter, loc, VectorType::get({32}, rewriter.getI32Type()),
1633 forceCastOperandsToSignature(
1634 rewriter, loc, {resLo, resHi},
1635 {VectorType::get({16}, rewriter.getI32Type()),
1636 VectorType::get({16}, rewriter.getI32Type())}));
1641 op.emitWarning() <<
"aievec.ups is not supported.\n";
1646 if (flatResTy != upsIntrOp.getType())
1647 upsIntrOp = LLVM::BitcastOp::create(rewriter, loc, flatResTy, upsIntrOp);
1649 if (flatResTy != resultType)
1651 vector::ShapeCastOp::create(rewriter, loc, resultType, upsIntrOp);
1653 rewriter.replaceOp(op, upsIntrOp);
1661 :
public mlir::ConvertOpToLLVMPattern<aievec::UPSOp> {
1663 using ConvertOpToLLVMPattern<aievec::UPSOp>::ConvertOpToLLVMPattern;
1667 ConversionPatternRewriter &rewriter)
const override {
1668 Location loc = op.getLoc();
1670 Value result = op.getResult();
1671 VectorType resultType = cast<VectorType>(result.getType());
1673 Type resultScaTy = resultType.getElementType();
1674 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
1676 int resultVectorSize = resultBitWidth * resultLanes;
1678 Value opSrcVal = adaptor.getSource();
1679 auto srcVecTy = cast<VectorType>(opSrcVal.getType());
1681 if (srcVecTy != fltSrcVecTy)
1682 opSrcVal = vector::ShapeCastOp::create(rewriter, op.getLoc(), fltSrcVecTy,
1688 Value upsIntrOp =
nullptr;
1689 if (llvm::isa<IntegerType>(resultScaTy)) {
1691 auto signCst = LLVM::ConstantOp::create(
1692 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(1));
1694 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1695 rewriter.getI32IntegerAttr(op.getShift()));
1697 SmallVector<Value> operands({opSrcVal, shiftCst, signCst});
1698 if (resultVectorSize == 512) {
1699 if (resultBitWidth == 32) {
1701 upsIntrOp = xllvm::Acc32V16I256UpsAIE2pIntrOp::create(
1702 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
1703 forceCastOperandsToSignature(
1704 rewriter, loc, operands,
1705 {VectorType::get({16}, rewriter.getI16Type()),
1706 rewriter.getI32Type(), rewriter.getI32Type()}));
1707 }
else if (resultBitWidth == 64) {
1709 upsIntrOp = xllvm::Acc64V8I256UpsAIE2pIntrOp::create(
1710 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
1711 forceCastOperandsToSignature(
1712 rewriter, loc, operands,
1713 {VectorType::get({8}, rewriter.getI32Type()),
1714 rewriter.getI32Type(), rewriter.getI32Type()}));
1716 }
else if (resultVectorSize == 1024) {
1717 Value src = opSrcVal;
1718 VectorType srcType = cast<VectorType>(src.getType());
1719 Type srcScaType = srcType.getElementType();
1720 unsigned srcBitWidth = srcScaType.getIntOrFloatBitWidth();
1722 int srcVectorSize = srcBitWidth * srcLanes;
1724 if (resultBitWidth == 32 && srcBitWidth == 16 && srcVectorSize == 512) {
1726 upsIntrOp = xllvm::Acc32V32I512UpsAIE2pIntrOp::create(
1727 rewriter, loc, VectorType::get({32}, rewriter.getI32Type()),
1728 forceCastOperandsToSignature(
1729 rewriter, loc, operands,
1730 {VectorType::get({32}, rewriter.getI16Type()),
1731 rewriter.getI32Type(), rewriter.getI32Type()}));
1732 }
else if (resultBitWidth == 64 && srcBitWidth == 32 &&
1733 srcVectorSize == 512) {
1735 upsIntrOp = xllvm::Acc64V16I512UpsAIE2pIntrOp::create(
1736 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
1737 forceCastOperandsToSignature(
1738 rewriter, loc, operands,
1739 {VectorType::get({16}, rewriter.getI32Type()),
1740 rewriter.getI32Type(), rewriter.getI32Type()}));
1741 }
else if (resultBitWidth == 64 && srcBitWidth == 16 &&
1742 srcVectorSize == 256) {
1744 upsIntrOp = xllvm::Acc64V16I256UpsAIE2pIntrOp::create(
1745 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()),
1746 forceCastOperandsToSignature(
1747 rewriter, loc, operands,
1748 {VectorType::get({16}, rewriter.getI16Type()),
1749 rewriter.getI32Type(), rewriter.getI32Type()}));
1750 }
else if (resultBitWidth == 32 && srcBitWidth == 8 &&
1751 srcVectorSize == 256) {
1753 upsIntrOp = xllvm::Acc32V32I256UpsAIE2pIntrOp::create(
1754 rewriter, loc, VectorType::get({32}, rewriter.getI32Type()),
1755 forceCastOperandsToSignature(
1756 rewriter, loc, operands,
1757 {VectorType::get({32}, rewriter.getI8Type()),
1758 rewriter.getI32Type(), rewriter.getI32Type()}));
1760 }
else if (resultVectorSize == 2048) {
1761 Value src = opSrcVal;
1762 VectorType srcType = cast<VectorType>(src.getType());
1763 Type srcScaType = srcType.getElementType();
1764 unsigned srcBitWidth = srcScaType.getIntOrFloatBitWidth();
1766 int srcVectorSize = srcBitWidth * srcLanes;
1768 if (resultBitWidth == 32 && srcBitWidth == 8 && srcVectorSize == 512) {
1770 upsIntrOp = xllvm::Acc32V64I512UpsAIE2pIntrOp::create(
1771 rewriter, loc, VectorType::get({64}, rewriter.getI32Type()),
1772 forceCastOperandsToSignature(
1773 rewriter, loc, operands,
1774 {VectorType::get({64}, rewriter.getI8Type()),
1775 rewriter.getI32Type(), rewriter.getI32Type()}));
1776 }
else if (resultBitWidth == 64 && srcBitWidth == 16 &&
1777 srcVectorSize == 512) {
1779 upsIntrOp = xllvm::Acc64V32I512UpsAIE2pIntrOp::create(
1780 rewriter, loc, VectorType::get({32}, rewriter.getI64Type()),
1781 forceCastOperandsToSignature(
1782 rewriter, loc, operands,
1783 {VectorType::get({32}, rewriter.getI16Type()),
1784 rewriter.getI32Type(), rewriter.getI32Type()}));
1785 }
else if (resultBitWidth == 32 && srcBitWidth == 16 &&
1786 srcVectorSize == 1024) {
1790 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1791 rewriter.getI32IntegerAttr(0));
1793 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1794 rewriter.getI32IntegerAttr(1));
1796 auto extractUps2048 = [&](Value source, Value index, Value shiftCst,
1797 Value signCst) -> Value {
1800 auto v32i32Source = forceCastValueToType(
1801 rewriter, loc, source,
1802 VectorType::get({32}, rewriter.getI32Type()));
1807 SmallVector<int64_t> shuffleMask;
1808 if (
auto constIndex = index.getDefiningOp<LLVM::ConstantOp>()) {
1809 auto indexAttr = cast<IntegerAttr>(constIndex.getValue());
1810 int64_t idxVal = indexAttr.getInt();
1811 int startIdx = idxVal * 16;
1812 for (
int i = 0; i < 16; ++i) {
1813 shuffleMask.push_back(startIdx + i);
1817 for (
int i = 0; i < 16; ++i) {
1818 shuffleMask.push_back(i);
1822 auto extOp = vector::ShuffleOp::create(rewriter, loc, v32i32Source,
1823 v32i32Source, shuffleMask);
1825 return xllvm::Acc32V32I512UpsAIE2pIntrOp::create(
1826 rewriter, loc, VectorType::get({32}, rewriter.getI32Type()),
1827 forceCastOperandsToSignature(
1828 rewriter, loc, {extOp, shiftCst, signCst},
1829 {VectorType::get({32}, rewriter.getI16Type()),
1830 rewriter.getI32Type(), rewriter.getI32Type()}));
1833 auto res0 = extractUps2048(opSrcVal, index0Cst, shiftCst, signCst);
1834 auto res1 = extractUps2048(opSrcVal, index1Cst, shiftCst, signCst);
1838 SmallVector<int64_t> concatMask;
1839 for (
int i = 0; i < 64; ++i) {
1840 concatMask.push_back(i);
1843 vector::ShuffleOp::create(rewriter, loc, res0, res1, concatMask);
1849 if (resultVectorSize == 512) {
1851 upsIntrOp = xllvm::Vector16BF16ToV16AccFloatAIE2pIntrOp::create(
1852 rewriter, loc, VectorType::get({16}, rewriter.getF32Type()),
1853 forceCastOperandsToSignature(
1854 rewriter, loc, {opSrcVal},
1855 {VectorType::get({16}, rewriter.getBF16Type())}));
1856 }
else if (resultVectorSize == 1024) {
1858 upsIntrOp = xllvm::Vector32BF16ToV32AccFloatAIE2pIntrOp::create(
1859 rewriter, loc, VectorType::get({32}, rewriter.getF32Type()),
1860 forceCastOperandsToSignature(
1861 rewriter, loc, {opSrcVal},
1862 {VectorType::get({32}, rewriter.getBF16Type())}));
1863 }
else if (resultVectorSize == 2048) {
1867 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1868 rewriter.getI32IntegerAttr(0));
1870 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1871 rewriter.getI32IntegerAttr(1));
1873 auto extractUps2048 = [&](Value source, Value index) -> Value {
1876 auto v32i32Source = forceCastValueToType(
1877 rewriter, loc, source,
1878 VectorType::get({32}, rewriter.getI32Type()));
1883 SmallVector<int64_t> shuffleMask;
1884 if (
auto constIndex = index.getDefiningOp<LLVM::ConstantOp>()) {
1885 auto indexAttr = cast<IntegerAttr>(constIndex.getValue());
1886 int64_t idxVal = indexAttr.getInt();
1887 int startIdx = idxVal * 16;
1888 for (
int i = 0; i < 16; ++i) {
1889 shuffleMask.push_back(startIdx + i);
1893 for (
int i = 0; i < 16; ++i) {
1894 shuffleMask.push_back(i);
1898 auto extOp = vector::ShuffleOp::create(rewriter, loc, v32i32Source,
1899 v32i32Source, shuffleMask);
1901 return xllvm::Vector32BF16ToV32AccFloatAIE2pIntrOp::create(
1902 rewriter, loc, VectorType::get({32}, rewriter.getF32Type()),
1903 forceCastOperandsToSignature(
1904 rewriter, loc, {extOp},
1905 {VectorType::get({32}, rewriter.getBF16Type())}));
1908 auto res0 = extractUps2048(opSrcVal, index0Cst);
1909 auto res1 = extractUps2048(opSrcVal, index1Cst);
1913 auto v32i32Res0 = forceCastValueToType(
1914 rewriter, loc, res0, VectorType::get({32}, rewriter.getI32Type()));
1915 auto v32i32Res1 = forceCastValueToType(
1916 rewriter, loc, res1, VectorType::get({32}, rewriter.getI32Type()));
1918 SmallVector<int64_t> concatMask;
1919 for (
int i = 0; i < 64; ++i) {
1920 concatMask.push_back(i);
1922 upsIntrOp = vector::ShuffleOp::create(rewriter, loc, v32i32Res0,
1923 v32i32Res1, concatMask);
1928 op.emitWarning() <<
"aievec.ups is not supported.\n";
1933 if (flatResTy != upsIntrOp.getType())
1934 upsIntrOp = LLVM::BitcastOp::create(rewriter, loc, flatResTy, upsIntrOp);
1936 if (flatResTy != resultType)
1938 vector::ShapeCastOp::create(rewriter, loc, resultType, upsIntrOp);
1940 rewriter.replaceOp(op, upsIntrOp);
1948 using ConvertOpToLLVMPattern<aievec::SRSOp>::ConvertOpToLLVMPattern;
1952 ConversionPatternRewriter &rewriter)
const override {
1953 Location loc = op.getLoc();
1955 Value result = op.getResult();
1956 VectorType resultType = cast<VectorType>(result.getType());
1957 Type resultScaTy = resultType.getElementType();
1958 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
1960 int resultVectorSize = resultBitWidth * resultLanes;
1963 Value srsIntrOp =
nullptr;
1964 if (llvm::isa<IntegerType>(resultScaTy)) {
1967 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
1968 rewriter.getI32IntegerAttr(op.getSign()));
1971 SmallVector<Value> operands(
1972 {adaptor.getSource(), adaptor.getShift(), signCst});
1973 if (resultVectorSize == 512) {
1974 if (resultBitWidth == 16) {
1975 srsIntrOp = xllvm::I512V32Acc32SrsAIE2IntrOp::create(
1976 rewriter, loc, VectorType::get({32}, rewriter.getI16Type()),
1977 forceCastOperandsToSignature(
1978 rewriter, loc, operands,
1979 {VectorType::get({16}, rewriter.getI64Type()),
1980 rewriter.getI32Type(), rewriter.getI32Type()}));
1981 }
else if (resultBitWidth == 32) {
1982 srsIntrOp = xllvm::I512V16Acc64SrsAIE2IntrOp::create(
1983 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
1984 forceCastOperandsToSignature(
1985 rewriter, loc, operands,
1986 {VectorType::get({16}, rewriter.getI64Type()),
1987 rewriter.getI32Type(), rewriter.getI32Type()}));
1989 }
else if (resultVectorSize == 256) {
1990 Value src = adaptor.getSource();
1991 VectorType srcType = cast<VectorType>(src.getType());
1992 Type srcScaType = srcType.getElementType();
1993 unsigned srcBitWidth = srcScaType.getIntOrFloatBitWidth();
1995 if (resultBitWidth == 16 && srcBitWidth == 32) {
1996 srsIntrOp = xllvm::I256V16Acc32SrsAIE2IntrOp::create(
1997 rewriter, loc, VectorType::get({16}, rewriter.getI16Type()),
1998 forceCastOperandsToSignature(
1999 rewriter, loc, operands,
2000 {VectorType::get({8}, rewriter.getI64Type()),
2001 rewriter.getI32Type(), rewriter.getI32Type()}));
2002 }
else if (resultBitWidth == 8 && srcBitWidth == 32) {
2003 srsIntrOp = xllvm::I256V32Acc32SrsAIE2IntrOp::create(
2004 rewriter, loc, VectorType::get({32}, rewriter.getI8Type()),
2005 forceCastOperandsToSignature(
2006 rewriter, loc, operands,
2007 {VectorType::get({16}, rewriter.getI64Type()),
2008 rewriter.getI32Type(), rewriter.getI32Type()}));
2009 }
else if (resultBitWidth == 16 && srcBitWidth == 64) {
2010 srsIntrOp = xllvm::I256V16Acc64SrsAIE2IntrOp::create(
2011 rewriter, loc, VectorType::get({16}, rewriter.getI16Type()),
2012 forceCastOperandsToSignature(
2013 rewriter, loc, operands,
2014 {VectorType::get({16}, rewriter.getI64Type()),
2015 rewriter.getI32Type(), rewriter.getI32Type()}));
2016 }
else if (resultBitWidth == 32 && srcBitWidth == 64) {
2017 srsIntrOp = xllvm::I256V8Acc64SrsAIE2IntrOp::create(
2018 rewriter, loc, VectorType::get({8}, rewriter.getI32Type()),
2019 forceCastOperandsToSignature(
2020 rewriter, loc, operands,
2021 {VectorType::get({8}, rewriter.getI64Type()),
2022 rewriter.getI32Type(), rewriter.getI32Type()}));
2027 if (resultVectorSize == 256) {
2028 srsIntrOp = xllvm::Vector16AccFloatToV16BF16AIE2IntrOp::create(
2029 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()),
2030 forceCastOperandsToSignature(
2031 rewriter, loc, {adaptor.getSource()},
2032 {VectorType::get({8}, rewriter.getI64Type())}));
2033 }
else if (resultVectorSize == 512) {
2042 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2043 rewriter.getI32IntegerAttr(0));
2045 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2046 rewriter.getI32IntegerAttr(1));
2047 auto extractSrs = [&](Value source, Value index) -> Value {
2048 auto extOp = xllvm::ExtI512I1024IntrOp::create(
2049 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
2050 forceCastOperandsToSignature(
2051 rewriter, loc, {source, index},
2052 {VectorType::get({32}, rewriter.getI32Type()),
2053 rewriter.getI32Type()}));
2054 return xllvm::Vector16AccFloatToV16BF16AIE2IntrOp::create(
2055 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()),
2056 forceCastOperandsToSignature(
2057 rewriter, loc, {extOp},
2058 {VectorType::get({8}, rewriter.getI64Type())}));
2060 auto resLo = extractSrs(adaptor.getSource(), indexZeroCst);
2061 auto resHi = extractSrs(adaptor.getSource(), indexOneCst);
2064 srsIntrOp = xllvm::ConcatI512I256IntrOp::create(
2065 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
2066 forceCastOperandsToSignature(
2067 rewriter, loc, {resLo, resHi},
2068 {VectorType::get({8}, rewriter.getI32Type()),
2069 VectorType::get({8}, rewriter.getI32Type())}));
2074 op.emitWarning() <<
"aievec.srs is not supported.\n";
2079 auto resultVal = forceCastValueToType(rewriter, loc, srsIntrOp,
2080 op.getResult().getType());
2081 rewriter.replaceOp(op, resultVal);
2089 :
public mlir::ConvertOpToLLVMPattern<aievec::SRSOp> {
2091 using ConvertOpToLLVMPattern<aievec::SRSOp>::ConvertOpToLLVMPattern;
2095 ConversionPatternRewriter &rewriter)
const override {
2096 Location loc = op.getLoc();
2098 Value result = op.getResult();
2099 VectorType resultType = cast<VectorType>(result.getType());
2100 Type resultScaTy = resultType.getElementType();
2101 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
2103 int resultVectorSize = resultBitWidth * resultLanes;
2106 Value srsIntrOp =
nullptr;
2107 if (llvm::isa<IntegerType>(resultScaTy)) {
2110 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2111 rewriter.getI32IntegerAttr(op.getSign()));
2114 SmallVector<Value> operands(
2115 {adaptor.getSource(), adaptor.getShift(), signCst});
2116 if (resultVectorSize == 512) {
2117 Value src = adaptor.getSource();
2118 VectorType srcType = cast<VectorType>(src.getType());
2119 Type srcScaType = srcType.getElementType();
2120 unsigned srcBitWidth = srcScaType.getIntOrFloatBitWidth();
2122 if (resultBitWidth == 16 && srcBitWidth == 32) {
2124 srsIntrOp = xllvm::I512V32Acc32SrsAIE2pIntrOp::create(
2125 rewriter, loc, VectorType::get({32}, rewriter.getI16Type()),
2126 forceCastOperandsToSignature(
2127 rewriter, loc, operands,
2128 {VectorType::get({32}, rewriter.getI32Type()),
2129 rewriter.getI32Type(), rewriter.getI32Type()}));
2130 }
else if (resultBitWidth == 16 && srcBitWidth == 64) {
2132 srsIntrOp = xllvm::I512V32Acc64SrsAIE2pIntrOp::create(
2133 rewriter, loc, VectorType::get({32}, rewriter.getI16Type()),
2134 forceCastOperandsToSignature(
2135 rewriter, loc, operands,
2136 {VectorType::get({32}, rewriter.getI64Type()),
2137 rewriter.getI32Type(), rewriter.getI32Type()}));
2138 }
else if (resultBitWidth == 32 && srcBitWidth == 64) {
2140 srsIntrOp = xllvm::I512V16Acc64SrsAIE2pIntrOp::create(
2141 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
2142 forceCastOperandsToSignature(
2143 rewriter, loc, operands,
2144 {VectorType::get({16}, rewriter.getI64Type()),
2145 rewriter.getI32Type(), rewriter.getI32Type()}));
2146 }
else if (resultBitWidth == 8 && srcBitWidth == 32) {
2148 srsIntrOp = xllvm::I512V64Acc32SrsAIE2pIntrOp::create(
2149 rewriter, loc, VectorType::get({64}, rewriter.getI8Type()),
2150 forceCastOperandsToSignature(
2151 rewriter, loc, operands,
2152 {VectorType::get({64}, rewriter.getI32Type()),
2153 rewriter.getI32Type(), rewriter.getI32Type()}));
2155 }
else if (resultVectorSize == 256) {
2156 Value src = adaptor.getSource();
2157 VectorType srcType = cast<VectorType>(src.getType());
2158 Type srcScaType = srcType.getElementType();
2159 unsigned srcBitWidth = srcScaType.getIntOrFloatBitWidth();
2161 if (resultBitWidth == 16 && srcBitWidth == 32) {
2163 srsIntrOp = xllvm::I256V16Acc32SrsAIE2pIntrOp::create(
2164 rewriter, loc, VectorType::get({16}, rewriter.getI16Type()),
2165 forceCastOperandsToSignature(
2166 rewriter, loc, operands,
2167 {VectorType::get({16}, rewriter.getI32Type()),
2168 rewriter.getI32Type(), rewriter.getI32Type()}));
2169 }
else if (resultBitWidth == 8 && srcBitWidth == 32) {
2171 srsIntrOp = xllvm::I256V32Acc32SrsAIE2pIntrOp::create(
2172 rewriter, loc, VectorType::get({32}, rewriter.getI8Type()),
2173 forceCastOperandsToSignature(
2174 rewriter, loc, operands,
2175 {VectorType::get({32}, rewriter.getI32Type()),
2176 rewriter.getI32Type(), rewriter.getI32Type()}));
2177 }
else if (resultBitWidth == 16 && srcBitWidth == 64) {
2179 srsIntrOp = xllvm::I256V16Acc64SrsAIE2pIntrOp::create(
2180 rewriter, loc, VectorType::get({16}, rewriter.getI16Type()),
2181 forceCastOperandsToSignature(
2182 rewriter, loc, operands,
2183 {VectorType::get({16}, rewriter.getI64Type()),
2184 rewriter.getI32Type(), rewriter.getI32Type()}));
2185 }
else if (resultBitWidth == 32 && srcBitWidth == 64) {
2187 srsIntrOp = xllvm::I256V8Acc64SrsAIE2pIntrOp::create(
2188 rewriter, loc, VectorType::get({8}, rewriter.getI32Type()),
2189 forceCastOperandsToSignature(
2190 rewriter, loc, operands,
2191 {VectorType::get({8}, rewriter.getI64Type()),
2192 rewriter.getI32Type(), rewriter.getI32Type()}));
2194 }
else if (resultVectorSize == 1024) {
2195 Value src = adaptor.getSource();
2196 VectorType srcType = cast<VectorType>(src.getType());
2197 Type srcScaType = srcType.getElementType();
2198 unsigned srcBitWidth = srcScaType.getIntOrFloatBitWidth();
2200 if (resultBitWidth == 16 && srcBitWidth == 32) {
2204 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2205 rewriter.getI32IntegerAttr(0));
2207 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2208 rewriter.getI32IntegerAttr(1));
2210 auto extractSrs1024 = [&](Value source, Value index, Value shiftCst,
2211 Value signCst) -> Value {
2214 auto v64i32Source = forceCastValueToType(
2215 rewriter, loc, source,
2216 VectorType::get({64}, rewriter.getI32Type()));
2221 SmallVector<int64_t> shuffleMask;
2222 if (
auto constIndex = index.getDefiningOp<LLVM::ConstantOp>()) {
2223 auto indexAttr = cast<IntegerAttr>(constIndex.getValue());
2224 int64_t idxVal = indexAttr.getInt();
2225 int startIdx = idxVal * 32;
2226 for (
int i = 0; i < 32; ++i) {
2227 shuffleMask.push_back(startIdx + i);
2231 for (
int i = 0; i < 32; ++i) {
2232 shuffleMask.push_back(i);
2236 auto extOp = vector::ShuffleOp::create(rewriter, loc, v64i32Source,
2237 v64i32Source, shuffleMask);
2239 return xllvm::I512V32Acc32SrsAIE2pIntrOp::create(
2240 rewriter, loc, VectorType::get({32}, rewriter.getI16Type()),
2241 forceCastOperandsToSignature(
2242 rewriter, loc, {extOp, shiftCst, signCst},
2243 {VectorType::get({32}, rewriter.getI32Type()),
2244 rewriter.getI32Type(), rewriter.getI32Type()}));
2248 extractSrs1024(src, index0Cst, adaptor.getShift(), signCst);
2250 extractSrs1024(src, index1Cst, adaptor.getShift(), signCst);
2254 auto v16i32Res0 = forceCastValueToType(
2255 rewriter, loc, res0,
2256 VectorType::get({16}, rewriter.getI32Type()));
2257 auto v16i32Res1 = forceCastValueToType(
2258 rewriter, loc, res1,
2259 VectorType::get({16}, rewriter.getI32Type()));
2261 SmallVector<int64_t> concatMask;
2262 for (
int i = 0; i < 32; ++i) {
2263 concatMask.push_back(i);
2265 srsIntrOp = vector::ShuffleOp::create(rewriter, loc, v16i32Res0,
2266 v16i32Res1, concatMask);
2272 if (resultVectorSize == 256) {
2274 srsIntrOp = xllvm::Vector16AccFloatToV16BF16AIE2pIntrOp::create(
2275 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()),
2276 forceCastOperandsToSignature(
2277 rewriter, loc, {adaptor.getSource()},
2278 {VectorType::get({16}, rewriter.getF32Type())}));
2279 }
else if (resultVectorSize == 512) {
2281 srsIntrOp = xllvm::Vector32AccFloatToV32BF16AIE2pIntrOp::create(
2282 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()),
2283 forceCastOperandsToSignature(
2284 rewriter, loc, {adaptor.getSource()},
2285 {VectorType::get({32}, rewriter.getF32Type())}));
2286 }
else if (resultVectorSize == 1024) {
2290 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2291 rewriter.getI32IntegerAttr(0));
2293 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2294 rewriter.getI32IntegerAttr(1));
2296 auto extractSrs1024 = [&](Value source, Value index) -> Value {
2299 auto v64i32Source = forceCastValueToType(
2300 rewriter, loc, source,
2301 VectorType::get({64}, rewriter.getI32Type()));
2306 SmallVector<int64_t> shuffleMask;
2307 if (
auto constIndex = index.getDefiningOp<LLVM::ConstantOp>()) {
2308 auto indexAttr = cast<IntegerAttr>(constIndex.getValue());
2309 int64_t idxVal = indexAttr.getInt();
2310 int startIdx = idxVal * 32;
2311 for (
int i = 0; i < 32; ++i) {
2312 shuffleMask.push_back(startIdx + i);
2316 for (
int i = 0; i < 32; ++i) {
2317 shuffleMask.push_back(i);
2321 auto extOp = vector::ShuffleOp::create(rewriter, loc, v64i32Source,
2322 v64i32Source, shuffleMask);
2324 return xllvm::Vector32AccFloatToV32BF16AIE2pIntrOp::create(
2325 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()),
2326 forceCastOperandsToSignature(
2327 rewriter, loc, {extOp},
2328 {VectorType::get({32}, rewriter.getF32Type())}));
2331 auto res0 = extractSrs1024(adaptor.getSource(), index0Cst);
2332 auto res1 = extractSrs1024(adaptor.getSource(), index1Cst);
2336 auto v16i32Res0 = forceCastValueToType(
2337 rewriter, loc, res0, VectorType::get({16}, rewriter.getI32Type()));
2338 auto v16i32Res1 = forceCastValueToType(
2339 rewriter, loc, res1, VectorType::get({16}, rewriter.getI32Type()));
2341 SmallVector<int64_t> concatMask;
2342 for (
int i = 0; i < 32; ++i) {
2343 concatMask.push_back(i);
2345 srsIntrOp = vector::ShuffleOp::create(rewriter, loc, v16i32Res0,
2346 v16i32Res1, concatMask);
2351 op.emitWarning() <<
"aievec.srs is not supported.\n";
2356 auto resultVal = forceCastValueToType(rewriter, loc, srsIntrOp,
2357 op.getResult().getType());
2358 rewriter.replaceOp(op, resultVal);
2366 using ConvertOpToLLVMPattern<aievec::UPDOp>::ConvertOpToLLVMPattern;
2369 auto resultType = cast<VectorType>(op.getResult().getType());
2370 std::stringstream ss;
2371 ss <<
"llvm.aie.upd.";
2372 ss << (loadSize == 128 ?
'v' : loadSize == 256 ?
'w' :
'x') <<
".";
2373 ss << getVectorTypeString(resultType) <<
".";
2375 ss << (op.getIndex() == 0 ?
"lo" :
"hi");
2381 ConversionPatternRewriter &rewriter)
const override {
2382 auto module = op->getParentOfType<ModuleOp>();
2383 MLIRContext *context = rewriter.getContext();
2391 auto ptr = this->getStridedElementPtr(
2392 rewriter, op->getLoc(), cast<MemRefType>(op.getSource().getType()),
2393 adaptor.getSource(), adaptor.getIndices());
2397 if (vecSizeInBits <= 256) {
2401 auto vectorPtrType = LLVM::LLVMPointerType::get(
2403 cast<MemRefType>(op.getSource().getType()).getMemorySpaceAsInt());
2405 LLVM::BitcastOp::create(rewriter, op->getLoc(), vectorPtrType, ptr);
2406 auto vecType = cast<VectorType>(op.getResult().getType());
2407 rewriter.replaceOpWithNewOp<LLVM::LoadOp>(op, vecType, castedPtr, 1);
2415 int loadSize = vecSizeInBits == 256 ? 128
2416 : vecSizeInBits == 512 ? 256
2421 auto resultType = cast<VectorType>(op.getResult().getType());
2424 VectorType::get({(int64_t)lanes / 2}, resultType.getElementType());
2427 auto vectorPtrType = LLVM::LLVMPointerType::get(
2429 cast<MemRefType>(op.getSource().getType()).getMemorySpaceAsInt());
2431 LLVM::BitcastOp::create(rewriter, op->getLoc(), vectorPtrType, ptr);
2433 LLVM::LoadOp::create(rewriter, op->getLoc(), loadType, castedPtr, 1);
2439 auto func =
module.lookupSymbol<LLVM::LLVMFuncOp>(
2440 StringAttr::get(context, intrinsicName));
2443 OpBuilder::InsertionGuard guard(rewriter);
2444 rewriter.setInsertionPointToStart(module.getBody());
2445 func = LLVM::LLVMFuncOp::create(
2446 rewriter, rewriter.getUnknownLoc(), intrinsicName,
2447 LLVM::LLVMFunctionType::get(resultType, {resultType, loadType}));
2452 if (adaptor.getVector()) {
2454 destValue = adaptor.getVector();
2463 std::stringstream ss;
2464 ss <<
"llvm.aie." << getVectorTypeString(resultType) <<
".undef";
2465 std::string intrinsicName = ss.str();
2467 auto func =
module.lookupSymbol<LLVM::LLVMFuncOp>(
2468 StringAttr::get(rewriter.getContext(), intrinsicName));
2471 OpBuilder::InsertionGuard guard(rewriter);
2472 rewriter.setInsertionPointToStart(module.getBody());
2473 func = LLVM::LLVMFuncOp::create(
2474 rewriter, rewriter.getUnknownLoc(), intrinsicName,
2475 LLVM::LLVMFunctionType::get(resultType, {}));
2478 LLVM::CallOp::create(rewriter, op->getLoc(),
func, ValueRange{})
2483 rewriter.replaceOpWithNewOp<LLVM::CallOp>(
2484 op,
func, ValueRange{destValue, loadValue});
2492 :
public mlir::ConvertOpToLLVMPattern<aievec::ConcatOp> {
2494 using ConvertOpToLLVMPattern<aievec::ConcatOp>::ConvertOpToLLVMPattern;
2498 ConversionPatternRewriter &rewriter)
const override {
2499 Location loc = op.getLoc();
2501 SmallVector<Value> sources = adaptor.getSources();
2502 Value src = sources.front();
2503 VectorType srcType = cast<VectorType>(src.getType());
2504 Type srcScalarType = srcType.getElementType();
2505 unsigned srcBitWidth = srcScalarType.getIntOrFloatBitWidth();
2507 int srcVectorSize = srcBitWidth * srcLanes;
2509 Value result = op.getResult();
2510 VectorType resultType = cast<VectorType>(result.getType());
2511 Type resultScaTy = resultType.getElementType();
2512 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
2514 int resultVectorSize = resultBitWidth * resultLanes;
2516 if (sources.size() != 2 && sources.size() != 4) {
2517 op.emitWarning() <<
"aievec.concat with " << sources.size()
2518 <<
" operands is not supported.\n";
2523 Value concatOp =
nullptr;
2524 if (srcVectorSize == 256 && resultVectorSize == 512) {
2525 concatOp = xllvm::ConcatI512I256IntrOp::create(
2526 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
2527 forceCastOperandsToSignature(
2528 rewriter, loc, adaptor.getSources(),
2529 {VectorType::get({8}, rewriter.getI32Type()),
2530 VectorType::get({8}, rewriter.getI32Type())}));
2531 }
else if (srcVectorSize == 256 && resultVectorSize == 1024) {
2532 concatOp = xllvm::ConcatI1024I256IntrOp::create(
2533 rewriter, loc, VectorType::get({32}, rewriter.getI32Type()),
2534 forceCastOperandsToSignature(
2535 rewriter, loc, adaptor.getSources(),
2536 {VectorType::get({8}, rewriter.getI32Type()),
2537 VectorType::get({8}, rewriter.getI32Type()),
2538 VectorType::get({8}, rewriter.getI32Type()),
2539 VectorType::get({8}, rewriter.getI32Type())}));
2540 }
else if (srcVectorSize == 512 && resultVectorSize == 1024) {
2541 concatOp = xllvm::ConcatI1024I512IntrOp::create(
2542 rewriter, loc, VectorType::get({32}, rewriter.getI32Type()),
2543 forceCastOperandsToSignature(
2544 rewriter, loc, adaptor.getSources(),
2545 {VectorType::get({16}, rewriter.getI32Type()),
2546 VectorType::get({16}, rewriter.getI32Type())}));
2548 op.emitWarning() <<
"aievec.concat with " << srcVectorSize
2549 <<
"-bit operands, and " << resultVectorSize
2550 <<
"-bit result is not supported.\n";
2556 forceCastValueToType(rewriter, loc, concatOp, op.getResult().getType());
2557 rewriter.replaceOp(op, resultVal);
2565 using ConvertOpToLLVMPattern<aievec::ExtOp>::ConvertOpToLLVMPattern;
2569 ConversionPatternRewriter &rewriter)
const override {
2570 Location loc = op.getLoc();
2572 Value src = adaptor.getSource();
2573 VectorType srcType = cast<VectorType>(src.getType());
2574 Type srcScalarType = srcType.getElementType();
2575 unsigned srcBitWidth = srcScalarType.getIntOrFloatBitWidth();
2577 int srcVectorSize = srcBitWidth * srcLanes;
2579 Value result = op.getResult();
2580 VectorType resultType = cast<VectorType>(result.getType());
2581 Type resultScaTy = resultType.getElementType();
2582 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
2584 int resultVectorSize = resultBitWidth * resultLanes;
2588 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2589 rewriter.getI32IntegerAttr(op.getIndex()));
2592 SmallVector<Value> operands({adaptor.getSource(), indexCst});
2593 Value extOp =
nullptr;
2595 if (resultVectorSize == 256 && srcVectorSize == 512) {
2596 extOp = xllvm::ExtI256I512IntrOp::create(
2597 rewriter, loc, VectorType::get({8}, rewriter.getI32Type()),
2598 forceCastOperandsToSignature(
2599 rewriter, loc, operands,
2600 {VectorType::get({16}, rewriter.getI32Type()),
2601 rewriter.getI32Type()}));
2602 }
else if (resultVectorSize == 512 && srcVectorSize == 1024) {
2603 extOp = xllvm::ExtI512I1024IntrOp::create(
2604 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
2605 forceCastOperandsToSignature(
2606 rewriter, loc, operands,
2607 {VectorType::get({32}, rewriter.getI32Type()),
2608 rewriter.getI32Type()}));
2609 }
else if (resultVectorSize == 256 && srcVectorSize == 1024) {
2610 extOp = xllvm::ExtI256I1024IntrOp::create(
2611 rewriter, loc, VectorType::get({8}, rewriter.getI32Type()),
2612 forceCastOperandsToSignature(
2613 rewriter, loc, operands,
2614 {VectorType::get({32}, rewriter.getI32Type()),
2615 rewriter.getI32Type()}));
2616 }
else if (resultVectorSize == 128 && srcVectorSize == 512) {
2617 auto shiftOp = adaptor.getSource();
2618 if (op.getIndex() > 0) {
2619 auto undefOp = xllvm::UndefV16I32IntrOp::create(
2620 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()));
2622 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
2623 rewriter.getI32IntegerAttr(0));
2624 auto shiftCst = LLVM::ConstantOp::create(
2625 rewriter, loc, rewriter.getI32Type(),
2626 rewriter.getI32IntegerAttr(op.getIndex() * 16));
2627 SmallVector<Value> shiftOperands{adaptor.getSource(), undefOp, stepCst,
2631 shiftOp = xllvm::VectorShiftI512I512IntrOp::create(
2632 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
2633 forceCastOperandsToSignature(
2634 rewriter, loc, shiftOperands,
2635 {VectorType::get({16}, rewriter.getI32Type()),
2636 VectorType::get({16}, rewriter.getI32Type()),
2637 rewriter.getI32Type(), rewriter.getI32Type()}));
2641 extOp = xllvm::ExtI128I512IntrOp::create(
2642 rewriter, loc, VectorType::get({4}, rewriter.getI32Type()),
2643 forceCastOperandsToSignature(
2644 rewriter, loc, {shiftOp},
2645 {VectorType::get({16}, rewriter.getI32Type())}));
2647 op.emitWarning() <<
"aievec.ext with " << srcVectorSize
2648 <<
"-bit source, and " << resultVectorSize
2649 <<
"-bit result is not supported.\n";
2655 forceCastValueToType(rewriter, loc, extOp, op.getResult().getType());
2656 rewriter.replaceOp(op, resultVal);
2664 :
public mlir::ConvertOpToLLVMPattern<aievec::ExtOp> {
2666 using ConvertOpToLLVMPattern<aievec::ExtOp>::ConvertOpToLLVMPattern;
2670 ConversionPatternRewriter &rewriter)
const override {
2671 Location loc = op.getLoc();
2673 Value src = adaptor.getSource();
2674 VectorType srcType = cast<VectorType>(src.getType());
2675 VectorType resultType = cast<VectorType>(op.getResult().getType());
2681 if (srcLanes % resultLanes != 0) {
2682 op.emitWarning() <<
"aievec.ext of a part that does not divide the "
2683 "source is not supported for AIE2p.\n";
2688 SmallVector<int64_t> shuffleMask;
2689 int startIdx = op.getIndex() * resultLanes;
2690 for (
int i = 0; i < resultLanes; ++i) {
2691 shuffleMask.push_back(startIdx + i);
2695 vector::ShuffleOp::create(rewriter, loc, src, src, shuffleMask);
2697 rewriter.replaceOp(op, extracted);
2703 :
public mlir::ConvertOpToLLVMPattern<aievec::aie1::SelectOp> {
2705 using ConvertOpToLLVMPattern<aievec::aie1::SelectOp>::ConvertOpToLLVMPattern;
2708 auto xbuffType = cast<VectorType>(op.getXbuff().getType());
2709 std::stringstream ss;
2710 ss <<
"llvm.aie.prim." << getVectorTypeString(xbuffType) <<
".select";
2716 ConversionPatternRewriter &rewriter)
const override {
2717 auto module = op->getParentOfType<ModuleOp>();
2718 MLIRContext *context = rewriter.getContext();
2720 auto selectType = IntegerType::get(context, 32);
2721 auto startType = IntegerType::get(context, 32);
2722 auto offsetsType = VectorType::get({2}, IntegerType::get(context, 32));
2723 auto confType = VectorType::get({2}, IntegerType::get(context, 32));
2727 auto func =
module.lookupSymbol<LLVM::LLVMFuncOp>(
2728 StringAttr::get(context, intrinsicName));
2731 OpBuilder::InsertionGuard guard(rewriter);
2732 rewriter.setInsertionPointToStart(module.getBody());
2733 func = LLVM::LLVMFuncOp::create(
2734 rewriter, rewriter.getUnknownLoc(), intrinsicName,
2735 LLVM::LLVMFunctionType::get(op.getResult().getType(),
2736 {op.getXbuff().getType(), selectType,
2745 uint32_t select = 0;
2750 op.getSelect().getAsInteger(0, select);
2751 op.getXstart().getAsInteger(0, x.
start);
2752 op.getXoffsets().getAsInteger(0, x.
offsets);
2753 op.getXoffsetsHi().getAsInteger(0, x.
offsets_hi);
2754 op.getXsquare().getAsInteger(0, x.
square);
2755 op.getYstart().getAsInteger(0, y.
start);
2756 op.getYoffsets().getAsInteger(0, y.
offsets);
2757 op.getYoffsetsHi().getAsInteger(0, y.
offsets_hi);
2758 op.getYsquare().getAsInteger(0, y.
square);
2761 uint32_t conf[2] = {0, 0};
2762 encodeConf(conf, x, z,
false);
2763 conf[1] |= encodeSquare(y.
square) << 21;
2766 auto selectVal = LLVM::ConstantOp::create(
2767 rewriter, op->getLoc(), selectType, rewriter.getI32IntegerAttr(select));
2768 auto xstartVal = LLVM::ConstantOp::create(
2769 rewriter, op->getLoc(), startType, rewriter.getI32IntegerAttr(x.
start));
2770 auto ystartVal = LLVM::ConstantOp::create(
2771 rewriter, op->getLoc(), startType, rewriter.getI32IntegerAttr(y.
start));
2772 auto xoffsetsVal = LLVM::ConstantOp::create(
2773 rewriter, op->getLoc(), offsetsType,
2774 rewriter.getI32VectorAttr({(int32_t)x.offsets, (int32_t)x.offsets_hi}));
2775 auto yoffsetsVal = LLVM::ConstantOp::create(
2776 rewriter, op->getLoc(), offsetsType,
2777 rewriter.getI32VectorAttr({(int32_t)y.offsets, (int32_t)y.offsets_hi}));
2778 auto confVal = LLVM::ConstantOp::create(
2779 rewriter, op->getLoc(), confType,
2780 rewriter.getI32VectorAttr({(int32_t)conf[0], (int32_t)conf[1]}));
2781 rewriter.replaceOpWithNewOp<LLVM::CallOp>(
2783 ValueRange{op.getXbuff(), selectVal, xstartVal, ystartVal, xoffsetsVal,
2784 yoffsetsVal, confVal});
2791 using ConvertOpToLLVMPattern<aievec::PackOp>::ConvertOpToLLVMPattern;
2794 auto sourceType = cast<VectorType>(op.getSource().getType());
2795 std::stringstream ss;
2796 ss <<
"llvm.aie.pack." << getVectorTypeString(sourceType);
2802 ConversionPatternRewriter &rewriter)
const override {
2803 auto module = op->getParentOfType<ModuleOp>();
2804 MLIRContext *context = rewriter.getContext();
2808 auto func =
module.lookupSymbol<LLVM::LLVMFuncOp>(
2809 StringAttr::get(context, intrinsicName));
2812 OpBuilder::InsertionGuard guard(rewriter);
2813 rewriter.setInsertionPointToStart(module.getBody());
2814 func = LLVM::LLVMFuncOp::create(
2815 rewriter, rewriter.getUnknownLoc(), intrinsicName,
2816 LLVM::LLVMFunctionType::get(op.getResult().getType(),
2817 {op.getSource().getType()}));
2820 rewriter.replaceOpWithNewOp<LLVM::CallOp>(op,
func,
2821 ValueRange{op.getSource()});
2827 :
public mlir::ConvertOpToLLVMPattern<aievec::UnpackOp> {
2829 using ConvertOpToLLVMPattern<aievec::UnpackOp>::ConvertOpToLLVMPattern;
2833 ConversionPatternRewriter &rewriter)
const override {
2834 op.emitWarning() <<
"aie.unpack conversion is not implemented\n";
2845 :
public mlir::ConvertOpToLLVMPattern<aievec::UnpackOp> {
2847 using ConvertOpToLLVMPattern<aievec::UnpackOp>::ConvertOpToLLVMPattern;
2851 ConversionPatternRewriter &rewriter)
const override {
2852 Location loc = op.getLoc();
2853 auto srcTy = cast<VectorType>(op.getSource().getType());
2854 auto dstTy = cast<VectorType>(op.getResult().getType());
2855 if (!srcTy.getElementType().isInteger(8) ||
2856 !dstTy.getElementType().isInteger(8))
2861 if (dstLanes != 2 * srcLanes)
2863 if (dstLanes != 64 && dstLanes != 128)
2866 auto signCst = LLVM::ConstantOp::create(
2867 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(0));
2870 if (dstLanes == 64) {
2871 unpacked = xllvm::UnpackI512I8I4AIE2pIntrOp::create(
2872 rewriter, loc, VectorType::get({64}, rewriter.getI8Type()),
2873 adaptor.getSource(), signCst)
2877 xllvm::UnpackI1024I8I4AIE2pIntrOp::create(
2878 rewriter, loc, VectorType::get({128}, rewriter.getI8Type()),
2879 adaptor.getSource(), signCst)
2882 rewriter.replaceOp(op, unpacked);
2888 :
public mlir::ConvertOpToLLVMPattern<aievec::BroadcastOp> {
2890 using ConvertOpToLLVMPattern<aievec::BroadcastOp>::ConvertOpToLLVMPattern;
2894 ConversionPatternRewriter &rewriter)
const override {
2895 op.emitWarning() <<
"aie.broadcast conversion is not implemented\n";
2902static Value padVectorWithPoison(ConversionPatternRewriter &rewriter,
2903 Location loc, Value vec,
int srcLanes,
2905 SmallVector<int64_t> padMask;
2906 for (
int i = 0; i < srcLanes; ++i)
2907 padMask.push_back(i);
2908 for (
int i = srcLanes; i < dstLanes; ++i)
2909 padMask.push_back(-1);
2910 return vector::ShuffleOp::create(rewriter, loc, vec, vec, padMask);
2915static Value extractLowerLanes(ConversionPatternRewriter &rewriter,
2916 Location loc, Value vec,
int lanes) {
2917 SmallVector<int64_t> extractMask;
2918 for (
int i = 0; i < lanes; ++i)
2919 extractMask.push_back(i);
2920 return vector::ShuffleOp::create(rewriter, loc, vec, vec, extractMask);
2925 using ConvertOpToLLVMPattern<aievec::MaxOp>::ConvertOpToLLVMPattern;
2929 ConversionPatternRewriter &rewriter)
const override {
2930 Location loc = op.getLoc();
2932 VectorType resultType = cast<VectorType>(op.getResult().getType());
2933 Type resultScaTy = resultType.getElementType();
2934 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
2936 int resultVectorSize = resultBitWidth * resultLanes;
2939 if (resultVectorSize != 512 && resultVectorSize != 256) {
2940 op.emitWarning() <<
"aievec.max conversion with " << resultVectorSize
2941 <<
"-bit result is not supported.\n";
2946 Value maxOp =
nullptr;
2947 if (llvm::isa<IntegerType>(resultScaTy)) {
2950 auto cmpCst = LLVM::ConstantOp::create(
2951 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(1));
2952 SmallVector<Value> operands{adaptor.getLhs(), adaptor.getRhs(), cmpCst};
2953 if (resultBitWidth == 8) {
2954 maxOp = xllvm::VectorMaxLt8IntrOp::create(
2956 mlir::LLVM::LLVMStructType::getLiteral(
2957 rewriter.getContext(),
2958 {VectorType::get({64}, rewriter.getI8Type()),
2959 VectorType::get({2}, rewriter.getI32Type())}),
2960 forceCastOperandsToSignature(
2961 rewriter, loc, operands,
2962 {VectorType::get({64}, rewriter.getI8Type()),
2963 VectorType::get({64}, rewriter.getI8Type()),
2964 rewriter.getI32Type()}));
2965 }
else if (resultBitWidth == 16) {
2966 maxOp = xllvm::VectorMaxLt16IntrOp::create(
2968 mlir::LLVM::LLVMStructType::getLiteral(
2969 rewriter.getContext(),
2970 {VectorType::get({32}, rewriter.getI16Type()),
2971 rewriter.getI32Type()}),
2972 forceCastOperandsToSignature(
2973 rewriter, loc, operands,
2974 {VectorType::get({32}, rewriter.getI16Type()),
2975 VectorType::get({32}, rewriter.getI16Type()),
2976 rewriter.getI32Type()}));
2977 }
else if (resultBitWidth == 32) {
2978 maxOp = xllvm::VectorMaxLt32IntrOp::create(
2980 mlir::LLVM::LLVMStructType::getLiteral(
2981 rewriter.getContext(),
2982 {VectorType::get({16}, rewriter.getI32Type()),
2983 rewriter.getI32Type()}),
2984 forceCastOperandsToSignature(
2985 rewriter, loc, operands,
2986 {VectorType::get({16}, rewriter.getI32Type()),
2987 VectorType::get({16}, rewriter.getI32Type()),
2988 rewriter.getI32Type()}));
2991 if (resultBitWidth == 16) {
2992 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
2993 Value lhs = adaptor.getLhs(), rhs = adaptor.getRhs();
2996 if (resultLanes == 16) {
2997 lhs = padVectorWithPoison(rewriter, loc, lhs, 16, 32);
2998 rhs = padVectorWithPoison(rewriter, loc, rhs, 16, 32);
3001 maxOp = xllvm::VectorMaxLtBf16IntrOp::create(
3003 mlir::LLVM::LLVMStructType::getLiteral(
3004 rewriter.getContext(), {v32bf16Ty, rewriter.getI32Type()}),
3005 forceCastOperandsToSignature(rewriter, loc, {lhs, rhs},
3006 {v32bf16Ty, v32bf16Ty}));
3011 op.emitWarning() <<
"aievec.max conversion fails due to unsupported "
3012 "element data type.\n";
3017 Value resultVec = LLVM::ExtractValueOp::create(rewriter, loc, maxOp,
3020 if (resultLanes == 16 && !llvm::isa<IntegerType>(resultScaTy))
3021 resultVec = extractLowerLanes(rewriter, loc, resultVec, 16);
3023 rewriter.replaceOp(op, resultVec);
3031 using ConvertOpToLLVMPattern<aievec::MinOp>::ConvertOpToLLVMPattern;
3035 ConversionPatternRewriter &rewriter)
const override {
3036 Location loc = op.getLoc();
3038 VectorType resultType = cast<VectorType>(op.getResult().getType());
3039 Type resultScaTy = resultType.getElementType();
3040 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
3042 int resultVectorSize = resultBitWidth * resultLanes;
3045 if (resultVectorSize != 512 && resultVectorSize != 256) {
3046 op.emitWarning() <<
"aievec.min conversion with " << resultVectorSize
3047 <<
"-bit result is not supported.\n";
3052 Value minOp =
nullptr;
3053 if (llvm::isa<IntegerType>(resultScaTy)) {
3056 auto cmpCst = LLVM::ConstantOp::create(
3057 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(1));
3058 SmallVector<Value> operands{adaptor.getLhs(), adaptor.getRhs(), cmpCst};
3059 if (resultBitWidth == 8) {
3060 minOp = xllvm::VectorMinGe8IntrOp::create(
3062 mlir::LLVM::LLVMStructType::getLiteral(
3063 rewriter.getContext(),
3064 {VectorType::get({64}, rewriter.getI8Type()),
3065 VectorType::get({2}, rewriter.getI32Type())}),
3066 forceCastOperandsToSignature(
3067 rewriter, loc, operands,
3068 {VectorType::get({64}, rewriter.getI8Type()),
3069 VectorType::get({64}, rewriter.getI8Type()),
3070 rewriter.getI32Type()}));
3071 }
else if (resultBitWidth == 16) {
3072 minOp = xllvm::VectorMinGe16IntrOp::create(
3074 mlir::LLVM::LLVMStructType::getLiteral(
3075 rewriter.getContext(),
3076 {VectorType::get({32}, rewriter.getI16Type()),
3077 rewriter.getI32Type()}),
3078 forceCastOperandsToSignature(
3079 rewriter, loc, operands,
3080 {VectorType::get({32}, rewriter.getI16Type()),
3081 VectorType::get({32}, rewriter.getI16Type()),
3082 rewriter.getI32Type()}));
3083 }
else if (resultBitWidth == 32) {
3084 minOp = xllvm::VectorMinGe32IntrOp::create(
3086 mlir::LLVM::LLVMStructType::getLiteral(
3087 rewriter.getContext(),
3088 {VectorType::get({16}, rewriter.getI32Type()),
3089 rewriter.getI32Type()}),
3090 forceCastOperandsToSignature(
3091 rewriter, loc, operands,
3092 {VectorType::get({16}, rewriter.getI32Type()),
3093 VectorType::get({16}, rewriter.getI32Type()),
3094 rewriter.getI32Type()}));
3097 if (resultBitWidth == 16) {
3098 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
3099 Value lhs = adaptor.getLhs(), rhs = adaptor.getRhs();
3102 if (resultLanes == 16) {
3103 lhs = padVectorWithPoison(rewriter, loc, lhs, 16, 32);
3104 rhs = padVectorWithPoison(rewriter, loc, rhs, 16, 32);
3107 minOp = xllvm::VectorMinGeBf16IntrOp::create(
3109 mlir::LLVM::LLVMStructType::getLiteral(
3110 rewriter.getContext(), {v32bf16Ty, rewriter.getI32Type()}),
3111 forceCastOperandsToSignature(rewriter, loc, {lhs, rhs},
3112 {v32bf16Ty, v32bf16Ty}));
3117 op.emitWarning() <<
"aievec.min conversion fails due to unsupported "
3118 "element data type.\n";
3123 Value resultVec = LLVM::ExtractValueOp::create(rewriter, loc, minOp,
3126 if (resultLanes == 16 && !llvm::isa<IntegerType>(resultScaTy))
3127 resultVec = extractLowerLanes(rewriter, loc, resultVec, 16);
3129 rewriter.replaceOp(op, resultVec);
3137 :
public mlir::ConvertOpToLLVMPattern<aievec::MaxOp> {
3139 using ConvertOpToLLVMPattern<aievec::MaxOp>::ConvertOpToLLVMPattern;
3143 ConversionPatternRewriter &rewriter)
const override {
3144 Location loc = op.getLoc();
3146 VectorType resultType = cast<VectorType>(op.getResult().getType());
3147 Type resultScaTy = resultType.getElementType();
3148 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
3150 int resultVectorSize = resultBitWidth * resultLanes;
3153 if (resultVectorSize != 512 && resultVectorSize != 256) {
3154 op.emitWarning() <<
"aievec.max conversion with " << resultVectorSize
3155 <<
"-bit result is not supported.\n";
3160 Value maxOp =
nullptr;
3161 if (llvm::isa<IntegerType>(resultScaTy)) {
3164 auto cmpCst = LLVM::ConstantOp::create(
3165 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(1));
3166 SmallVector<Value> operands{adaptor.getLhs(), adaptor.getRhs(), cmpCst};
3167 if (resultBitWidth == 8) {
3168 maxOp = xllvm::VectorMaxLt8AIE2pIntrOp::create(
3170 mlir::LLVM::LLVMStructType::getLiteral(
3171 rewriter.getContext(),
3172 {VectorType::get({64}, rewriter.getI8Type()),
3173 VectorType::get({2}, rewriter.getI32Type())}),
3174 forceCastOperandsToSignature(
3175 rewriter, loc, operands,
3176 {VectorType::get({64}, rewriter.getI8Type()),
3177 VectorType::get({64}, rewriter.getI8Type()),
3178 rewriter.getI32Type()}));
3179 }
else if (resultBitWidth == 16) {
3180 maxOp = xllvm::VectorMaxLt16AIE2pIntrOp::create(
3182 mlir::LLVM::LLVMStructType::getLiteral(
3183 rewriter.getContext(),
3184 {VectorType::get({32}, rewriter.getI16Type()),
3185 rewriter.getI32Type()}),
3186 forceCastOperandsToSignature(
3187 rewriter, loc, operands,
3188 {VectorType::get({32}, rewriter.getI16Type()),
3189 VectorType::get({32}, rewriter.getI16Type()),
3190 rewriter.getI32Type()}));
3191 }
else if (resultBitWidth == 32) {
3192 maxOp = xllvm::VectorMaxLt32AIE2pIntrOp::create(
3194 mlir::LLVM::LLVMStructType::getLiteral(
3195 rewriter.getContext(),
3196 {VectorType::get({16}, rewriter.getI32Type()),
3197 rewriter.getI32Type()}),
3198 forceCastOperandsToSignature(
3199 rewriter, loc, operands,
3200 {VectorType::get({16}, rewriter.getI32Type()),
3201 VectorType::get({16}, rewriter.getI32Type()),
3202 rewriter.getI32Type()}));
3205 if (resultBitWidth == 16) {
3206 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
3207 Value lhs = adaptor.getLhs(), rhs = adaptor.getRhs();
3209 if (resultLanes == 16) {
3210 lhs = padVectorWithPoison(rewriter, loc, lhs, 16, 32);
3211 rhs = padVectorWithPoison(rewriter, loc, rhs, 16, 32);
3214 maxOp = xllvm::VectorMaxLtBf16AIE2pIntrOp::create(
3216 mlir::LLVM::LLVMStructType::getLiteral(
3217 rewriter.getContext(), {v32bf16Ty, rewriter.getI32Type()}),
3218 forceCastOperandsToSignature(rewriter, loc, {lhs, rhs},
3219 {v32bf16Ty, v32bf16Ty}));
3224 op.emitWarning() <<
"aievec.max conversion fails due to unsupported "
3225 "element data type.\n";
3229 Value resultVec = LLVM::ExtractValueOp::create(rewriter, loc, maxOp,
3231 if (resultLanes == 16 && !llvm::isa<IntegerType>(resultScaTy))
3232 resultVec = extractLowerLanes(rewriter, loc, resultVec, 16);
3234 rewriter.replaceOp(op, resultVec);
3242 :
public mlir::ConvertOpToLLVMPattern<aievec::MinOp> {
3244 using ConvertOpToLLVMPattern<aievec::MinOp>::ConvertOpToLLVMPattern;
3248 ConversionPatternRewriter &rewriter)
const override {
3249 Location loc = op.getLoc();
3251 VectorType resultType = cast<VectorType>(op.getResult().getType());
3252 Type resultScaTy = resultType.getElementType();
3253 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
3255 int resultVectorSize = resultBitWidth * resultLanes;
3258 if (resultVectorSize != 512 && resultVectorSize != 256) {
3259 op.emitWarning() <<
"aievec.min conversion with " << resultVectorSize
3260 <<
"-bit result is not supported.\n";
3265 Value minOp =
nullptr;
3266 if (llvm::isa<IntegerType>(resultScaTy)) {
3269 auto cmpCst = LLVM::ConstantOp::create(
3270 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(1));
3271 SmallVector<Value> operands{adaptor.getLhs(), adaptor.getRhs(), cmpCst};
3272 if (resultBitWidth == 8) {
3273 minOp = xllvm::VectorMinGe8AIE2pIntrOp::create(
3275 mlir::LLVM::LLVMStructType::getLiteral(
3276 rewriter.getContext(),
3277 {VectorType::get({64}, rewriter.getI8Type()),
3278 VectorType::get({2}, rewriter.getI32Type())}),
3279 forceCastOperandsToSignature(
3280 rewriter, loc, operands,
3281 {VectorType::get({64}, rewriter.getI8Type()),
3282 VectorType::get({64}, rewriter.getI8Type()),
3283 rewriter.getI32Type()}));
3284 }
else if (resultBitWidth == 16) {
3285 minOp = xllvm::VectorMinGe16AIE2pIntrOp::create(
3287 mlir::LLVM::LLVMStructType::getLiteral(
3288 rewriter.getContext(),
3289 {VectorType::get({32}, rewriter.getI16Type()),
3290 rewriter.getI32Type()}),
3291 forceCastOperandsToSignature(
3292 rewriter, loc, operands,
3293 {VectorType::get({32}, rewriter.getI16Type()),
3294 VectorType::get({32}, rewriter.getI16Type()),
3295 rewriter.getI32Type()}));
3296 }
else if (resultBitWidth == 32) {
3297 minOp = xllvm::VectorMinGe32AIE2pIntrOp::create(
3299 mlir::LLVM::LLVMStructType::getLiteral(
3300 rewriter.getContext(),
3301 {VectorType::get({16}, rewriter.getI32Type()),
3302 rewriter.getI32Type()}),
3303 forceCastOperandsToSignature(
3304 rewriter, loc, operands,
3305 {VectorType::get({16}, rewriter.getI32Type()),
3306 VectorType::get({16}, rewriter.getI32Type()),
3307 rewriter.getI32Type()}));
3310 if (resultBitWidth == 16) {
3311 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
3312 Value lhs = adaptor.getLhs(), rhs = adaptor.getRhs();
3314 if (resultLanes == 16) {
3315 lhs = padVectorWithPoison(rewriter, loc, lhs, 16, 32);
3316 rhs = padVectorWithPoison(rewriter, loc, rhs, 16, 32);
3319 minOp = xllvm::VectorMinGeBf16AIE2pIntrOp::create(
3321 mlir::LLVM::LLVMStructType::getLiteral(
3322 rewriter.getContext(), {v32bf16Ty, rewriter.getI32Type()}),
3323 forceCastOperandsToSignature(rewriter, loc, {lhs, rhs},
3324 {v32bf16Ty, v32bf16Ty}));
3329 op.emitWarning() <<
"aievec.min conversion fails due to unsupported "
3330 "element data type.\n";
3334 Value resultVec = LLVM::ExtractValueOp::create(rewriter, loc, minOp,
3336 if (resultLanes == 16 && !llvm::isa<IntegerType>(resultScaTy))
3337 resultVec = extractLowerLanes(rewriter, loc, resultVec, 16);
3339 rewriter.replaceOp(op, resultVec);
3350template <
typename LtOp,
typename GeOp>
3351static Value buildCmpBitmask(OpBuilder &builder, Location loc, StringRef rel,
3352 Value lhs, Value rhs, ValueRange extraOperands) {
3353 auto structTy = LLVM::LLVMStructType::getLiteral(
3354 builder.getContext(), {lhs.getType(), builder.getI32Type()});
3355 auto compare = [&](
bool lessThan, Value a, Value b) -> Value {
3356 SmallVector<Value> operands{a, b};
3357 llvm::append_range(operands, extraOperands);
3358 Value result = lessThan
3359 ? Value(LtOp::create(builder, loc, structTy, operands))
3360 : Value(GeOp::create(builder, loc, structTy, operands));
3361 return LLVM::ExtractValueOp::create(builder, loc, result, 1);
3364 return compare(
true, lhs, rhs);
3366 return compare(
false, lhs, rhs);
3368 return compare(
true, rhs, lhs);
3370 return compare(
false, rhs, lhs);
3371 assert((rel ==
"eq" || rel ==
"ne") &&
"unexpected compare predicate");
3373 bool isEq = rel ==
"eq";
3374 Value forward = compare(!isEq, lhs, rhs);
3375 Value backward = compare(!isEq, rhs, lhs);
3377 return LLVM::AndOp::create(builder, loc, forward, backward);
3378 return LLVM::OrOp::create(builder, loc, forward, backward);
3385template <
typename MaxLtBf16IntrOp,
typename MinGeBf16IntrOp,
3386 typename MaxLt32IntrOp,
typename MinGe32IntrOp,
3387 typename MaxLt16IntrOp,
typename MinGe16IntrOp>
3390 using ConvertOpToLLVMPattern<aievec::CmpOp>::ConvertOpToLLVMPattern;
3394 ConversionPatternRewriter &rewriter)
const override {
3395 Location loc = op.getLoc();
3396 auto vecTy = cast<VectorType>(op.getLhs().getType());
3397 auto elTy = vecTy.getElementType();
3398 unsigned elWidth = elTy.getIntOrFloatBitWidth();
3400 StringRef pred = op.getPred();
3402 bool isUnsigned = llvm::is_contained({
"ult",
"uge",
"ugt",
"ule"}, pred);
3404 !llvm::is_contained({
"slt",
"sge",
"sgt",
"sle",
"eq",
"ne"}, pred))
3407 StringRef rel = pred.size() == 3 ? pred.drop_front() : pred;
3409 Value lhs = adaptor.getLhs(), rhs = adaptor.getRhs();
3411 if (elWidth == 16 && isa<FloatType>(elTy) && (lanes == 16 || lanes == 32)) {
3413 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
3415 lhs = padVectorWithPoison(rewriter, loc, lhs, 16, 32);
3416 rhs = padVectorWithPoison(rewriter, loc, rhs, 16, 32);
3418 SmallVector<Value> operands = forceCastOperandsToSignature(
3419 rewriter, loc, {lhs, rhs}, {v32bf16Ty, v32bf16Ty});
3420 bitmask = buildCmpBitmask<MaxLtBf16IntrOp, MinGeBf16IntrOp>(
3421 rewriter, loc, rel, operands[0], operands[1], {});
3425 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
3426 rewriter.getI32IntegerAttr(0xFFFF));
3427 bitmask = LLVM::AndOp::create(rewriter, loc, bitmask, mask);
3429 }
else if (isa<IntegerType>(elTy) && elWidth * lanes == 512 &&
3430 (elWidth == 32 || elWidth == 16)) {
3434 VectorType::get({lanes}, rewriter.getIntegerType(elWidth));
3435 Value sign = LLVM::ConstantOp::create(
3436 rewriter, loc, rewriter.getI32Type(),
3437 rewriter.getI32IntegerAttr(isUnsigned ? 0 : 1));
3438 SmallVector<Value> operands = forceCastOperandsToSignature(
3439 rewriter, loc, {lhs, rhs}, {intVecTy, intVecTy});
3440 bitmask = elWidth == 32
3441 ? buildCmpBitmask<MaxLt32IntrOp, MinGe32IntrOp>(
3442 rewriter, loc, rel, operands[0], operands[1], sign)
3443 : buildCmpBitmask<MaxLt16IntrOp, MinGe16IntrOp>(
3444 rewriter, loc, rel, operands[0], operands[1], sign);
3450 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
3451 op, op.getResult().getType(), bitmask);
3458 xllvm::VectorMinGeBf16IntrOp,
3459 xllvm::VectorMaxLt32IntrOp, xllvm::VectorMinGe32IntrOp,
3460 xllvm::VectorMaxLt16IntrOp, xllvm::VectorMinGe16IntrOp>;
3463 xllvm::VectorMaxLtBf16AIE2pIntrOp, xllvm::VectorMinGeBf16AIE2pIntrOp,
3464 xllvm::VectorMaxLt32AIE2pIntrOp, xllvm::VectorMinGe32AIE2pIntrOp,
3465 xllvm::VectorMaxLt16AIE2pIntrOp, xllvm::VectorMinGe16AIE2pIntrOp>;
3470template <
typename Sel16IntrOp,
typename Sel32IntrOp>
3473 using ConvertOpToLLVMPattern<aievec::SelOp>::ConvertOpToLLVMPattern;
3477 ConversionPatternRewriter &rewriter)
const override {
3478 Location loc = op.getLoc();
3479 auto resultType = cast<VectorType>(op.getResult().getType());
3480 auto elTy = resultType.getElementType();
3481 unsigned elWidth = elTy.getIntOrFloatBitWidth();
3483 auto i32Ty = rewriter.getI32Type();
3486 Value selMask = adaptor.getSel();
3487 if (selMask.getType() != i32Ty)
3489 UnrealizedConversionCastOp::create(rewriter, loc, i32Ty, selMask)
3493 if (elWidth == 16 && isa<FloatType>(elTy)) {
3494 auto v32i16Ty = VectorType::get({32}, rewriter.getI16Type());
3495 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
3497 Value lhs = adaptor.getLhs(), rhs = adaptor.getRhs();
3498 bool needExtract =
false;
3501 lhs = padVectorWithPoison(rewriter, loc, lhs, 16, 32);
3502 rhs = padVectorWithPoison(rewriter, loc, rhs, 16, 32);
3504 }
else if (lanes != 32) {
3509 auto lhsCast = forceCastValueToType(rewriter, loc, lhs, v32bf16Ty);
3510 auto lhsI16 = LLVM::BitcastOp::create(rewriter, loc, v32i16Ty, lhsCast);
3511 auto rhsCast = forceCastValueToType(rewriter, loc, rhs, v32bf16Ty);
3512 auto rhsI16 = LLVM::BitcastOp::create(rewriter, loc, v32i16Ty, rhsCast);
3514 auto selResult = Sel16IntrOp::create(
3515 rewriter, loc, v32i16Ty,
3516 forceCastOperandsToSignature(rewriter, loc, {lhsI16, rhsI16, selMask},
3517 {v32i16Ty, v32i16Ty, i32Ty}));
3521 LLVM::BitcastOp::create(rewriter, loc, v32bf16Ty, selResult);
3524 result = extractLowerLanes(rewriter, loc, result, 16);
3526 rewriter.replaceOp(op, result);
3531 if (elWidth == 32 && isa<IntegerType>(elTy) && lanes == 16) {
3532 auto v16i32Ty = VectorType::get({16}, rewriter.getI32Type());
3533 auto selResult = Sel32IntrOp::create(
3534 rewriter, loc, v16i32Ty,
3535 forceCastOperandsToSignature(
3536 rewriter, loc, {adaptor.getLhs(), adaptor.getRhs(), selMask},
3537 {v16i32Ty, v16i32Ty, i32Ty}));
3538 rewriter.replaceOp(op, selResult->getResult(0));
3543 if (elWidth == 16 && isa<IntegerType>(elTy) && lanes == 32) {
3544 auto v32i16Ty = VectorType::get({32}, rewriter.getI16Type());
3545 auto selResult = Sel16IntrOp::create(
3546 rewriter, loc, v32i16Ty,
3547 forceCastOperandsToSignature(
3548 rewriter, loc, {adaptor.getLhs(), adaptor.getRhs(), selMask},
3549 {v32i16Ty, v32i16Ty, i32Ty}));
3550 rewriter.replaceOp(op, selResult->getResult(0));
3562 xllvm::VectorSel32AIE2pIntrOp>;
3565 :
public mlir::ConvertOpToLLVMPattern<aievec::BroadcastScalarOp> {
3567 using ConvertOpToLLVMPattern<
3568 aievec::BroadcastScalarOp>::ConvertOpToLLVMPattern;
3572 ConversionPatternRewriter &rewriter)
const override {
3573 Location loc = op.getLoc();
3575 Value result = op.getResult();
3576 VectorType resultType = cast<VectorType>(result.getType());
3577 Type resultScaTy = resultType.getElementType();
3578 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
3580 int resultVectorSize = resultBitWidth * resultLanes;
3582 if (resultVectorSize != 512) {
3584 <<
"aievec.broadcast_scalar conversion with result vector size "
3585 << resultVectorSize <<
" is not implemented.\n";
3590 if (llvm::isa<IntegerType>(resultScaTy)) {
3591 Value src = adaptor.getSource();
3592 Type srcType = src.getType();
3593 unsigned srcBitWidth = srcType.getIntOrFloatBitWidth();
3595 if (srcBitWidth < 32) {
3596 src = LLVM::SExtOp::create(rewriter, loc, rewriter.getI32Type(), src);
3599 if (resultBitWidth == 8) {
3600 rewriter.replaceOpWithNewOp<xllvm::VectorBroadcast8I512IntrOp>(
3601 op, VectorType::get({64}, rewriter.getI8Type()), src);
3602 }
else if (resultBitWidth == 16) {
3603 rewriter.replaceOpWithNewOp<xllvm::VectorBroadcast16I512IntrOp>(
3604 op, VectorType::get({32}, rewriter.getI16Type()), src);
3605 }
else if (resultBitWidth == 32) {
3606 rewriter.replaceOpWithNewOp<xllvm::VectorBroadcast32I512IntrOp>(
3607 op, VectorType::get({16}, rewriter.getI32Type()), src);
3610 <<
"aievec.broadcast_scalar conversion with result bitwidth "
3611 << resultBitWidth <<
" is not implemented.\n";
3616 if (resultBitWidth == 16) {
3617 rewriter.replaceOpWithNewOp<xllvm::VectorBroadcast16BF512IntrOp>(
3618 op, VectorType::get({32}, rewriter.getBF16Type()),
3619 adaptor.getSource());
3620 }
else if (resultBitWidth == 32) {
3626 auto srcAsI32 = bitcastValueToType(rewriter, loc, adaptor.getSource(),
3627 rewriter.getI32Type());
3628 auto broadcastI32 = xllvm::VectorBroadcast32I512IntrOp::create(
3629 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
3632 bitcastValueToType(rewriter, loc, broadcastI32,
3633 VectorType::get({16}, rewriter.getF32Type()));
3634 rewriter.replaceOp(op, resultF32);
3637 <<
"aievec.broadcast_scalar conversion with result bitwidth "
3638 << resultBitWidth <<
" is not implemented.\n";
3650 :
public mlir::ConvertOpToLLVMPattern<aievec::BroadcastScalarOp> {
3652 using ConvertOpToLLVMPattern<
3653 aievec::BroadcastScalarOp>::ConvertOpToLLVMPattern;
3657 ConversionPatternRewriter &rewriter)
const override {
3658 Location loc = op.getLoc();
3660 Value result = op.getResult();
3661 VectorType resultType = cast<VectorType>(result.getType());
3662 Type resultScaTy = resultType.getElementType();
3663 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
3665 int resultVectorSize = resultBitWidth * resultLanes;
3668 if (resultVectorSize != 256 && resultVectorSize != 512) {
3670 <<
"aievec.broadcast_scalar conversion with result vector size "
3671 << resultVectorSize <<
" is not implemented for AIE2p.\n";
3675 Value src = adaptor.getSource();
3676 Type srcType = src.getType();
3679 if (llvm::isa<IntegerType>(resultScaTy)) {
3680 unsigned srcBitWidth = srcType.getIntOrFloatBitWidth();
3681 if (srcBitWidth < resultBitWidth) {
3682 src = LLVM::SExtOp::create(rewriter, loc, resultScaTy, src);
3683 }
else if (srcBitWidth > resultBitWidth) {
3684 src = LLVM::TruncOp::create(rewriter, loc, resultScaTy, src);
3689 auto poisonVec = LLVM::PoisonOp::create(rewriter, loc, resultType);
3692 auto idx0 = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(),
3693 rewriter.getI64IntegerAttr(0));
3694 auto insertedVec = LLVM::InsertElementOp::create(rewriter, loc, resultType,
3695 poisonVec, src, idx0);
3699 SmallVector<int64_t> broadcastMask(resultLanes, 0);
3700 auto broadcastVec = vector::ShuffleOp::create(rewriter, loc, insertedVec,
3701 insertedVec, broadcastMask);
3703 rewriter.replaceOp(op, broadcastVec);
3710 using ConvertOpToLLVMPattern<aievec::ShiftOp>::ConvertOpToLLVMPattern;
3714 ConversionPatternRewriter &rewriter)
const override {
3715 Location loc = op.getLoc();
3717 Value result = op.getResult();
3718 VectorType resultType = cast<VectorType>(result.getType());
3719 Type resultScaTy = resultType.getElementType();
3720 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
3722 int resultVectorSize = resultBitWidth * resultLanes;
3724 if (resultVectorSize != 512) {
3725 op.emitWarning() <<
"aievec.shift conversion with result vector size "
3726 << resultVectorSize <<
" is not implemented.\n";
3731 auto stepCst = LLVM::ConstantOp::create(
3732 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(0));
3735 Value shiftOp =
nullptr;
3736 SmallVector<Value> operands(
3737 {adaptor.getLhs(), adaptor.getRhs(), stepCst, adaptor.getShift()});
3738 if (llvm::isa<IntegerType>(resultScaTy)) {
3740 shiftOp = xllvm::VectorShiftI512I512IntrOp::create(
3741 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
3742 forceCastOperandsToSignature(
3743 rewriter, loc, operands,
3744 {VectorType::get({16}, rewriter.getI32Type()),
3745 VectorType::get({16}, rewriter.getI32Type()),
3746 rewriter.getI32Type(), rewriter.getI32Type()}));
3749 shiftOp = xllvm::VectorShiftBF512BF512IntrOp::create(
3750 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()),
3751 forceCastOperandsToSignature(
3752 rewriter, loc, operands,
3753 {VectorType::get({32}, rewriter.getBF16Type()),
3754 VectorType::get({32}, rewriter.getBF16Type()),
3755 rewriter.getI32Type(), rewriter.getI32Type()}));
3760 forceCastValueToType(rewriter, loc, shiftOp, op.getResult().getType());
3761 rewriter.replaceOp(op, resultVal);
3769 :
public mlir::ConvertOpToLLVMPattern<aievec::ShiftOp> {
3771 using ConvertOpToLLVMPattern<aievec::ShiftOp>::ConvertOpToLLVMPattern;
3775 ConversionPatternRewriter &rewriter)
const override {
3776 Location loc = op.getLoc();
3778 Value result = op.getResult();
3779 VectorType resultType = cast<VectorType>(result.getType());
3780 Type resultScaTy = resultType.getElementType();
3781 unsigned resultBitWidth = resultScaTy.getIntOrFloatBitWidth();
3783 int resultVectorSize = resultBitWidth * resultLanes;
3785 if (resultVectorSize != 512) {
3786 op.emitWarning() <<
"aievec.shift conversion with result vector size "
3787 << resultVectorSize <<
" is not implemented.\n";
3792 auto stepCst = LLVM::ConstantOp::create(
3793 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(0));
3796 Value shiftOp =
nullptr;
3797 SmallVector<Value> operands(
3798 {adaptor.getLhs(), adaptor.getRhs(), stepCst, adaptor.getShift()});
3799 if (llvm::isa<IntegerType>(resultScaTy)) {
3801 shiftOp = xllvm::VectorShiftI512I512AIE2pIntrOp::create(
3802 rewriter, loc, VectorType::get({16}, rewriter.getI32Type()),
3803 forceCastOperandsToSignature(
3804 rewriter, loc, operands,
3805 {VectorType::get({16}, rewriter.getI32Type()),
3806 VectorType::get({16}, rewriter.getI32Type()),
3807 rewriter.getI32Type(), rewriter.getI32Type()}));
3810 shiftOp = xllvm::VectorShiftBF512BF512AIE2pIntrOp::create(
3811 rewriter, loc, VectorType::get({32}, rewriter.getBF16Type()),
3812 forceCastOperandsToSignature(
3813 rewriter, loc, operands,
3814 {VectorType::get({32}, rewriter.getBF16Type()),
3815 VectorType::get({32}, rewriter.getBF16Type()),
3816 rewriter.getI32Type(), rewriter.getI32Type()}));
3821 forceCastValueToType(rewriter, loc, shiftOp, op.getResult().getType());
3822 rewriter.replaceOp(op, resultVal);
3829 :
public mlir::ConvertOpToLLVMPattern<aievec::ExtElemOp> {
3831 using ConvertOpToLLVMPattern<aievec::ExtElemOp>::ConvertOpToLLVMPattern;
3835 ConversionPatternRewriter &rewriter)
const override {
3836 Location loc = op.getLoc();
3838 Type resultType = op.getResult().getType();
3839 unsigned resultBitWidth = resultType.getIntOrFloatBitWidth();
3841 Value src = adaptor.getSource();
3842 VectorType srcType = cast<VectorType>(src.getType());
3843 Type srcScalarType = srcType.getElementType();
3844 unsigned srcBitWidth = srcScalarType.getIntOrFloatBitWidth();
3846 int srcVectorSize = srcBitWidth * srcLanes;
3848 if (srcVectorSize != 512) {
3849 op.emitWarning() <<
"aievec.ext_elem conversion with source vector size "
3850 << srcVectorSize <<
" is not supported.\n";
3855 auto signCst = LLVM::ConstantOp::create(
3856 rewriter, loc, rewriter.getI32Type(), rewriter.getI32IntegerAttr(1));
3859 Value extElemOp =
nullptr;
3860 SmallVector<Value> operands(
3861 {adaptor.getSource(), adaptor.getIndex(), signCst});
3862 if (resultBitWidth == 8) {
3863 extElemOp = xllvm::VectorExtractElem8I512IntrOp::create(
3864 rewriter, loc, rewriter.getI32Type(),
3865 forceCastOperandsToSignature(
3866 rewriter, loc, operands,
3867 {VectorType::get({64}, rewriter.getI8Type()),
3868 rewriter.getI32Type(), rewriter.getI32Type()}));
3869 }
else if (resultBitWidth == 16) {
3870 extElemOp = xllvm::VectorExtractElem16I512IntrOp::create(
3871 rewriter, loc, rewriter.getI32Type(),
3872 forceCastOperandsToSignature(
3873 rewriter, loc, operands,
3874 {VectorType::get({32}, rewriter.getI16Type()),
3875 rewriter.getI32Type(), rewriter.getI32Type()}));
3876 }
else if (resultBitWidth == 32) {
3877 extElemOp = xllvm::VectorExtractElem32I512IntrOp::create(
3878 rewriter, loc, rewriter.getI32Type(),
3879 forceCastOperandsToSignature(
3880 rewriter, loc, operands,
3881 {VectorType::get({16}, rewriter.getI32Type()),
3882 rewriter.getI32Type(), rewriter.getI32Type()}));
3884 op.emitWarning() <<
"aievec.ext_elem conversion with result bit width "
3885 << resultBitWidth <<
" is not implemented.\n";
3890 if (llvm::isa<IntegerType>(resultType)) {
3891 if (resultBitWidth < 32) {
3894 if (resultBitWidth < 16) {
3895 auto i16Ty = rewriter.getI16Type();
3896 auto trunc16 = LLVM::TruncOp::create(rewriter, loc, i16Ty, extElemOp);
3897 rewriter.replaceOpWithNewOp<LLVM::TruncOp>(op, resultType,
3898 trunc16.getResult());
3900 rewriter.replaceOpWithNewOp<LLVM::TruncOp>(op, resultType, extElemOp);
3903 rewriter.replaceOp(op, extElemOp);
3907 if (resultBitWidth == 16) {
3908 extElemOp = LLVM::TruncOp::create(rewriter, loc, rewriter.getI16Type(),
3911 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(op, resultType, extElemOp);
3919 :
public mlir::ConvertOpToLLVMPattern<aievec::FMAElemOp> {
3921 using ConvertOpToLLVMPattern<aievec::FMAElemOp>::ConvertOpToLLVMPattern;
3925 ConversionPatternRewriter &rewriter)
const override {
3926 auto loc = fmaOp.getLoc();
3927 auto lhs = adaptor.getLhs();
3928 auto rhs = adaptor.getRhs();
3929 auto acc = adaptor.getAcc();
3930 auto lhsTy = cast<VectorType>(lhs.getType());
3931 auto rhsTy = cast<VectorType>(rhs.getType());
3932 auto accTy = cast<VectorType>(acc.getType());
3938 if (lhsTy != flatLhsTy)
3939 lhs = vector::ShapeCastOp::create(rewriter, loc, flatLhsTy, lhs);
3940 if (rhsTy != flatRhsTy)
3941 rhs = vector::ShapeCastOp::create(rewriter, loc, flatRhsTy, rhs);
3942 if (accTy != flatAccTy)
3943 acc = vector::ShapeCastOp::create(rewriter, loc, flatAccTy, acc);
3946 Type i32ty = rewriter.getI32Type();
3947 auto confCst = LLVM::ConstantOp::create(
3948 rewriter, loc, i32ty,
3949 rewriter.getI32IntegerAttr(aiev2_vmac_compute_control(
3959 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
3960 if (flatLhsTy.getElementType().isBF16() &&
3961 flatLhsTy.getNumElements() < 32) {
3962 auto zero32 = LLVM::ConstantOp::create(rewriter, loc, i32ty,
3963 rewriter.getI32IntegerAttr(0));
3964 auto zeros_i16 = xllvm::VectorBroadcast16I512IntrOp::create(
3965 rewriter, loc, VectorType::get({32}, rewriter.getI16Type()), zero32);
3967 LLVM::BitcastOp::create(rewriter, loc, v32bf16Ty, zeros_i16);
3968 auto zeroVec = xllvm::ExtBF256BF512IntrOp::create(
3969 rewriter, loc, VectorType::get({16}, rewriter.getBF16Type()),
3970 zeros_bf16, zero32);
3972 auto idx1 = LLVM::ConstantOp::create(rewriter, loc, i32ty,
3973 rewriter.getI32IntegerAttr(1));
3975 auto lhsSet = xllvm::VectorSetBF512BF256IntrOp::create(
3976 rewriter, loc, v32bf16Ty, lhs, zero32);
3977 lhs = xllvm::UpdBF512BF256IntrOp::create(rewriter, loc, v32bf16Ty, lhsSet,
3980 auto rhsSet = xllvm::VectorSetBF512BF256IntrOp::create(
3981 rewriter, loc, v32bf16Ty, rhs, zero32);
3982 rhs = xllvm::UpdBF512BF256IntrOp::create(rewriter, loc, v32bf16Ty, rhsSet,
3987 auto v8i64Ty = VectorType::get({8}, rewriter.getI64Type());
3988 auto macIntrOp = xllvm::MacConfBF16IntrOp::create(
3989 rewriter, loc, v8i64Ty,
3990 forceCastOperandsToSignature(rewriter, loc, {lhs, rhs, acc, confCst},
3991 {v32bf16Ty, v32bf16Ty, v8i64Ty, i32ty}));
3995 forceCastValueToType(rewriter, loc, macIntrOp.getResult(), flatAccTy);
3996 if (flatAccTy != accTy)
3997 resVal = vector::ShapeCastOp::create(rewriter, loc, accTy, resVal);
3999 rewriter.replaceOp(fmaOp, resVal);
4007static Value lookThroughShapeCasts(Value v) {
4008 while (
auto castOp = v.getDefiningOp<vector::ShapeCastOp>())
4009 v = castOp.getSource();
4022static std::optional<bool> peelSignednessCast(Value &v) {
4023 auto castOp = v.getDefiningOp<UnrealizedConversionCastOp>();
4025 return std::nullopt;
4026 auto vecTy = dyn_cast<VectorType>(v.getType());
4028 vecTy ? dyn_cast<IntegerType>(vecTy.getElementType()) : IntegerType();
4029 if (!intTy || intTy.isSignless())
4030 return std::nullopt;
4031 v = castOp.getInputs()[0];
4032 return intTy.isSigned();
4065 std::optional<bool> castSigned = peelSignednessCast(v);
4067 Value orig = lookThroughShapeCasts(v);
4068 if (
auto extSIOp = orig.getDefiningOp<arith::ExtSIOp>())
4069 return {lookThroughShapeCasts(extSIOp.getIn()),
true};
4070 if (
auto extUIOp = orig.getDefiningOp<arith::ExtUIOp>())
4071 return {lookThroughShapeCasts(extUIOp.getIn()),
false};
4073 return {v, *castSigned};
4075 auto vecTy = dyn_cast<VectorType>(v.getType());
4077 vecTy ? dyn_cast<IntegerType>(vecTy.getElementType()) : IntegerType();
4078 return {v, !(intTy && intTy.isUnsigned())};
4085static Value transposeTile(OpBuilder &b, Location loc, Value v, int64_t rows,
4086 int64_t cols,
bool aie2p) {
4087 auto vecTy = cast<VectorType>(v.getType());
4088 std::optional<SmallVector<aievec::ShuffleMode, 2>> modes =
4089 aievec::getTileTransposeModes(aie2p, vecTy.getElementType(), rows, cols);
4090 assert(modes &&
"the matmul verifier admits only transposable tiles");
4093 Type i32ty = b.getI32Type();
4094 auto v16i32Ty = VectorType::get({16}, i32ty);
4095 SmallVector<Value, 2> modeCsts;
4096 auto createModeConstants = [&]() {
4097 for (aievec::ShuffleMode mode : *modes)
4098 modeCsts.push_back(LLVM::ConstantOp::create(
4099 b, loc, i32ty, b.getI32IntegerAttr(
static_cast<int32_t
>(mode))));
4101 auto shuffle = [&](Value x, Value y, Value modeCst) -> Value {
4103 return xllvm::VectorShuffleAIE2pIntrOp::create(b, loc, v16i32Ty, x, y,
4105 return xllvm::VectorShuffleIntrOp::create(b, loc, v16i32Ty, x, y, modeCst);
4107 int64_t numElems = vecTy.getNumElements();
4108 if (modes->size() == 2) {
4109 auto halves = forceCastValueToType(b, loc, v, VectorType::get({32}, i32ty));
4110 auto lo = vector::ShuffleOp::create(
4111 b, loc, halves, halves, llvm::to_vector(llvm::seq<int64_t>(0, 16)));
4112 auto hi = vector::ShuffleOp::create(
4113 b, loc, halves, halves, llvm::to_vector(llvm::seq<int64_t>(16, 32)));
4114 createModeConstants();
4115 Value resLo = shuffle(lo, hi, modeCsts[0]);
4116 Value resHi = shuffle(lo, hi, modeCsts[1]);
4117 auto res = vector::ShuffleOp::create(
4118 b, loc, resLo, resHi, llvm::to_vector(llvm::seq<int64_t>(0, 32)));
4119 return forceCastValueToType(b, loc, res, vecTy);
4121 bool half = numElems * vecTy.getElementTypeBitWidth() == 256;
4124 SmallVector<int64_t> padMask =
4125 llvm::to_vector(llvm::seq<int64_t>(0, numElems));
4126 padMask.append(numElems, vector::ShuffleOp::kPoisonIndex);
4127 x = vector::ShuffleOp::create(b, loc, v, v, padMask);
4129 Value xi = forceCastValueToType(b, loc, x, v16i32Ty);
4132 : xllvm::UndefV16I32IntrOp::create(b, loc, v16i32Ty).getResult();
4133 createModeConstants();
4135 forceCastValueToType(b, loc, shuffle(xi, y, modeCsts[0]), x.getType());
4137 res = vector::ShuffleOp::create(
4138 b, loc, res, res, llvm::to_vector(llvm::seq<int64_t>(0, numElems)));
4144static Value materializeOperandLayout(OpBuilder &b, Location loc, Value flat,
4145 VectorType storedTy,
bool stored,
4146 bool native,
bool aie2p) {
4147 if (stored == native)
4149 return transposeTile(b, loc, flat, storedTy.getDimSize(0),
4150 storedTy.getDimSize(1), aie2p);
4154 :
public mlir::ConvertOpToLLVMPattern<aievec::MatMulOp> {
4155 using ConvertOpToLLVMPattern<aievec::MatMulOp>::ConvertOpToLLVMPattern;
4157 enum class Accumulator { I32, I64, BF16 };
4160 static std::tuple<Accumulator, int, int, int>
4164 case K::AIE2_I8xI4_4x16x8:
4165 return {Accumulator::I32, 0, 0, 0};
4166 case K::AIE2_I8xI8_4x8x8:
4167 return {Accumulator::I32, 0, 1, 0};
4168 case K::AIE2_I16xI8_4x4x8:
4169 return {Accumulator::I32, 0, 2, 0};
4170 case K::AIE2_I16xI16_4x2x8:
4171 return {Accumulator::I32, 0, 3, 0};
4172 case K::AIE2_I16xI8_2x8x8_Acc64:
4173 return {Accumulator::I64, 1, 2, 0};
4174 case K::AIE2_I16xI8_4x8x4_Acc64:
4175 return {Accumulator::I64, 1, 2, 1};
4176 case K::AIE2_I16xI16_2x4x8_Acc64:
4177 return {Accumulator::I64, 1, 3, 0};
4178 case K::AIE2_I16xI16_4x4x4_Acc64:
4179 return {Accumulator::I64, 1, 3, 1};
4180 case K::AIE2_I32xI16_4x2x4_Acc64:
4181 return {Accumulator::I64, 1, 0, 0};
4182 case K::AIE2_BF16_4x8x4:
4183 return {Accumulator::BF16, 2, 3, 0};
4185 llvm_unreachable(
"not an AIE2 recipe");
4190 matchAndRewrite(aievec::MatMulOp op, OpAdaptor adaptor,
4191 ConversionPatternRewriter &rewriter)
const override {
4192 auto lhsTy = cast<VectorType>(op.getLhs().getType());
4193 auto rhsTy = cast<VectorType>(op.getRhs().getType());
4194 auto accTy = cast<VectorType>(op.getAcc().getType());
4195 std::optional<aievec::MatMulRecipe> recipe =
4197 op.getLhsTransposed(), op.getRhsTransposed());
4199 return rewriter.notifyMatchFailure(op,
"not an AIE2 matmul tile");
4200 auto [accKind, amode, bmode, variant] = getAccAndModes(recipe->kind);
4205 Value lhs = adaptor.getLhs();
4206 Value rhs = adaptor.getRhs();
4207 int signX = 0, signY = 0;
4208 if (accKind != Accumulator::BF16) {
4209 auto narrow = [](Value v, VectorType ty,
int &sign) {
4212 if (getElementTypeOrSelf(resolved.
narrowed).getIntOrFloatBitWidth() ==
4213 ty.getElementTypeBitWidth())
4217 lhs = narrow(lhs, lhsTy, signX);
4218 rhs = narrow(rhs, rhsTy, signY);
4220 int conf = aiev2_vmac_compute_control(
4221 signX, signY, amode, bmode, variant,
4225 Location loc = op.getLoc();
4228 auto flatten = [&](Value v) -> Value {
4230 if (v.getType() == flatTy)
4232 return vector::ShapeCastOp::create(rewriter, loc, flatTy, v);
4237 Value acc = vector::ShapeCastOp::create(rewriter, loc, accFlattenedVecTy,
4239 lhs = materializeOperandLayout(rewriter, loc, lhs, lhsTy,
4240 op.getLhsTransposed(), recipe->lhsKM,
4242 rhs = materializeOperandLayout(rewriter, loc, rhs, rhsTy,
4243 op.getRhsTransposed(), recipe->rhsNK,
4246 Type i32ty = rewriter.getI32Type();
4247 auto confCst = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4248 rewriter.getI32IntegerAttr(conf));
4249 SmallVector<Value> operands({lhs, rhs, acc, confCst});
4251 if (accKind == Accumulator::BF16)
4253 xllvm::MacConfBF16IntrOp::create(
4254 rewriter, loc, VectorType::get({8}, rewriter.getI64Type()),
4255 forceCastOperandsToSignature(
4256 rewriter, loc, operands,
4257 {VectorType::get({32}, rewriter.getBF16Type()),
4258 VectorType::get({32}, rewriter.getBF16Type()),
4259 VectorType::get({8}, rewriter.getI64Type()), i32ty}))
4262 SmallVector<Type> intrFuncSig(
4263 {VectorType::get({64}, rewriter.getI8Type()),
4264 VectorType::get({16}, i32ty),
4265 VectorType::get({16}, rewriter.getI64Type()), i32ty});
4266 VectorType v16xi64ty = VectorType::get({16}, rewriter.getI64Type());
4267 if (accKind == Accumulator::I32)
4268 matMulResVal = xllvm::MacConfAcc32IntrOp::create(
4269 rewriter, loc, v16xi64ty,
4270 forceCastOperandsToSignature(rewriter, loc, operands,
4274 matMulResVal = xllvm::MacConfAcc64IntrOp::create(
4275 rewriter, loc, v16xi64ty,
4276 forceCastOperandsToSignature(rewriter, loc, operands,
4282 bitcastValueToType(rewriter, loc, matMulResVal, accFlattenedVecTy);
4284 rewriter.replaceOpWithNewOp<vector::ShapeCastOp>(op, op.getType(),
4293static Value widenBF16ToAccFloat(OpBuilder &rewriter, Location loc, Type i32ty,
4295 auto v64bf16Ty = VectorType::get({64}, rewriter.getBF16Type());
4296 auto ones = LLVM::ConstantOp::create(
4297 rewriter, loc, v64bf16Ty,
4298 DenseElementsAttr::get(
4299 v64bf16Ty, rewriter.getFloatAttr(rewriter.getBF16Type(), 1.0)));
4301 auto conf = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4302 rewriter.getI32IntegerAttr(60));
4303 return xllvm::MulConfBF16I1024ACC2048AIE2pIntrOp::create(
4304 rewriter, loc, VectorType::get({64}, rewriter.getF32Type()), v64bf16,
4311static Value performBFP16_8x8MatMul(OpBuilder &rewriter, Location loc,
4312 Type i32ty, Value lhs64f32,
4313 Value rhs64f32Transposed, Value acc64i32,
4315 auto v64i32Ty = VectorType::get({64}, rewriter.getI32Type());
4318 auto bfpStructTy = mlir::LLVM::LLVMStructType::getLiteral(
4319 rewriter.getContext(), {VectorType::get({64}, rewriter.getI8Type()),
4320 VectorType::get({8}, rewriter.getI8Type())});
4322 auto lhsBFP = xllvm::Vector64AccFloatToV64BFP16EBS8AIE2pIntrOp::create(
4323 rewriter, loc, bfpStructTy, lhs64f32);
4324 auto rhsBFP = xllvm::Vector64AccFloatToV64BFP16EBS8AIE2pIntrOp::create(
4325 rewriter, loc, bfpStructTy, rhs64f32Transposed);
4328 auto lhsData = LLVM::ExtractValueOp::create(rewriter, loc, lhsBFP, 0);
4329 auto lhsExp = LLVM::ExtractValueOp::create(rewriter, loc, lhsBFP, 1);
4330 auto rhsData = LLVM::ExtractValueOp::create(rewriter, loc, rhsBFP, 0);
4331 auto rhsExp = LLVM::ExtractValueOp::create(rewriter, loc, rhsBFP, 1);
4334 return xllvm::MacConfBFP576ACC2048AIE2pIntrOp::create(
4335 rewriter, loc, v64i32Ty, lhsData, lhsExp, rhsData, rhsExp, acc64i32,
4342static Value perform8x8x4MatMul(OpBuilder &rewriter, Location loc, Type i32ty,
4343 Value lhsKM64bf16, Value rhs32bf16,
4345 auto v32bf16Ty = VectorType::get({32}, rewriter.getBF16Type());
4346 auto v32f32Ty = VectorType::get({32}, rewriter.getF32Type());
4350 vector::ShuffleOp::create(rewriter, loc, lhsKM64bf16, lhsKM64bf16,
4351 llvm::to_vector(llvm::seq<int64_t>(0, 32)));
4353 vector::ShuffleOp::create(rewriter, loc, lhsKM64bf16, lhsKM64bf16,
4354 llvm::to_vector(llvm::seq<int64_t>(32, 64)));
4357 auto extractBroadcastShuffle = [&](Value src,
int idx) -> Value {
4358 SmallVector<int64_t> extractMask;
4359 int startIdx = idx * 8;
4360 for (
int i = 0; i < 8; ++i)
4361 extractMask.push_back(startIdx + i);
4363 for (
int rep = 0; rep < 3; ++rep) {
4364 for (
int i = 0; i < 8; ++i)
4365 extractMask.push_back(startIdx + i);
4368 vector::ShuffleOp::create(rewriter, loc, src, src, extractMask);
4371 auto broadI32 = forceCastValueToType(rewriter, loc, broadcasted,
4372 VectorType::get({16}, i32ty));
4373 auto shuffleMode4x8 = LLVM::ConstantOp::create(
4374 rewriter, loc, i32ty, rewriter.getI32IntegerAttr(29));
4375 auto shuffled = xllvm::VectorShuffleAIE2pIntrOp::create(
4376 rewriter, loc, VectorType::get({16}, i32ty), broadI32, broadI32,
4379 return forceCastValueToType(rewriter, loc, shuffled, v32bf16Ty);
4383 SmallVector<Value> rowVectors;
4384 for (
int i = 0; i < 4; ++i)
4385 rowVectors.push_back(extractBroadcastShuffle(xaBF16, i));
4386 for (
int i = 0; i < 4; ++i)
4387 rowVectors.push_back(extractBroadcastShuffle(xbBF16, i));
4390 auto extractBroadcast4 = [&](Value src,
int idx) -> Value {
4391 SmallVector<int64_t> mask;
4392 int startIdx = idx * 4;
4394 for (
int rep = 0; rep < 8; ++rep) {
4395 for (
int i = 0; i < 4; ++i)
4396 mask.push_back(startIdx + i);
4398 return vector::ShuffleOp::create(rewriter, loc, src, src, mask);
4402 SmallVector<Value> colVectors;
4403 for (
int i = 0; i < 8; ++i)
4404 colVectors.push_back(extractBroadcast4(rhs32bf16, i));
4407 auto conf60 = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4408 rewriter.getI32IntegerAttr(60));
4410 Value acc = acc32f32;
4411 for (
int i = 0; i < 8; ++i) {
4412 acc = xllvm::MacConfBF16I512ACC1024AIE2pIntrOp::create(
4413 rewriter, loc, v32f32Ty, rowVectors[i], colVectors[i], acc, conf60);
4420 :
public mlir::ConvertOpToLLVMPattern<aievec::MatMulOp_AIE2P> {
4421 using ConvertOpToLLVMPattern<aievec::MatMulOp_AIE2P>::ConvertOpToLLVMPattern;
4424 matchAndRewrite(aievec::MatMulOp_AIE2P op, OpAdaptor adaptor,
4425 ConversionPatternRewriter &rewriter)
const override {
4427 auto lhsTy = cast<VectorType>(op.getLhs().getType());
4428 auto rhsTy = cast<VectorType>(op.getRhs().getType());
4429 auto accTy = cast<VectorType>(op.getAcc().getType());
4430 std::optional<aievec::MatMulRecipe> recipe =
4432 op.getLhsTransposed(), op.getRhsTransposed());
4434 return rewriter.notifyMatchFailure(op,
"not an AIE2P matmul tile");
4440 Value lhsOperand = adaptor.getLhs();
4441 Value rhsOperand = adaptor.getRhs();
4442 bool lhsIsSigned = resolveMatMulOperand(lhsOperand).isSigned;
4443 bool rhsIsSigned = resolveMatMulOperand(rhsOperand).isSigned;
4444 peelSignednessCast(lhsOperand);
4445 peelSignednessCast(rhsOperand);
4447 Location loc = op.getLoc();
4450 Value lhsFlat = vector::ShapeCastOp::create(
4454 Value rhsFlat = vector::ShapeCastOp::create(
4459 Value acc = vector::ShapeCastOp::create(rewriter, loc, accFlattenedVecTy,
4461 auto getLhs = [&]() {
4462 return materializeOperandLayout(rewriter, loc, lhsFlat, lhsTy,
4463 op.getLhsTransposed(), recipe->lhsKM,
4466 auto getRhs = [&]() {
4467 return materializeOperandLayout(rewriter, loc, rhsFlat, rhsTy,
4468 op.getRhsTransposed(), recipe->rhsNK,
4471 Type i32ty = rewriter.getI32Type();
4474 switch (recipe->kind) {
4475 case K::AIE2P_I8_8x8x8: {
4482 8 | ((lhsIsSigned ? 1 : 0) << 9) | ((rhsIsSigned ? 1 : 0) << 8);
4483 auto confCst = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4484 rewriter.getI32IntegerAttr(conf));
4486 xllvm::MacConfI512ACC2048AIE2pIntrOp::create(
4487 rewriter, loc, VectorType::get({32}, rewriter.getI64Type()),
4488 forceCastOperandsToSignature(
4489 rewriter, loc, {getLhs(), getRhs(), acc, confCst},
4490 {VectorType::get({16}, rewriter.getI32Type()),
4491 VectorType::get({32}, rewriter.getI16Type()),
4492 VectorType::get({32}, rewriter.getI64Type()), i32ty}))
4496 case K::AIE2P_I16_8x2x8: {
4501 SmallVector<int64_t> padMask = llvm::to_vector(llvm::seq<int64_t>(0, 16));
4502 padMask.append(48, vector::ShuffleOp::kPoisonIndex);
4503 Value lhs = getLhs(), rhs = getRhs();
4505 vector::ShuffleOp::create(rewriter, loc, lhs, lhs, padMask);
4507 vector::ShuffleOp::create(rewriter, loc, rhs, rhs, padMask);
4508 auto confCst = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4509 rewriter.getI32IntegerAttr(24));
4511 xllvm::MacConfI1024ACC2048AIE2pIntrOp::create(
4512 rewriter, loc, VectorType::get({32}, rewriter.getI64Type()),
4513 forceCastOperandsToSignature(
4514 rewriter, loc, {lhsPadded, rhsPadded, acc, confCst},
4515 {VectorType::get({32}, rewriter.getI32Type()),
4516 VectorType::get({64}, rewriter.getI16Type()),
4517 VectorType::get({32}, rewriter.getI64Type()), i32ty}))
4521 case K::AIE2P_BFP16_8x8x8: {
4525 auto v32f32Ty = VectorType::get({32}, rewriter.getF32Type());
4528 Value lhs = getLhs();
4529 auto lhs32bf16_lo = vector::ShuffleOp::create(
4530 rewriter, loc, lhs, lhs, llvm::to_vector(llvm::seq<int64_t>(0, 32)));
4531 auto lhs32bf16_hi = vector::ShuffleOp::create(
4532 rewriter, loc, lhs, lhs, llvm::to_vector(llvm::seq<int64_t>(32, 64)));
4533 auto lhs32f32_lo = xllvm::Vector32BF16ToV32AccFloatAIE2pIntrOp::create(
4534 rewriter, loc, v32f32Ty, lhs32bf16_lo);
4535 auto lhs32f32_hi = xllvm::Vector32BF16ToV32AccFloatAIE2pIntrOp::create(
4536 rewriter, loc, v32f32Ty, lhs32bf16_hi);
4540 vector::ShuffleOp::create(rewriter, loc, lhs32f32_lo, lhs32f32_hi,
4541 llvm::to_vector(llvm::seq<int64_t>(0, 64)));
4544 auto rhsNK = widenBF16ToAccFloat(rewriter, loc, i32ty, getRhs());
4547 auto conf780 = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4548 rewriter.getI32IntegerAttr(780));
4549 matMulResVal = performBFP16_8x8MatMul(
4550 rewriter, loc, i32ty, lhs64f32, rhsNK,
4551 forceCastValueToType(rewriter, loc, acc,
4552 VectorType::get({64}, rewriter.getI32Type())),
4556 case K::AIE2P_BFP16_4x8x8: {
4560 auto v32f32Ty = VectorType::get({32}, rewriter.getF32Type());
4561 SmallVector<int64_t> padMask = llvm::to_vector(llvm::seq<int64_t>(0, 32));
4562 padMask.append(32, vector::ShuffleOp::kPoisonIndex);
4565 auto lhs32f32 = xllvm::Vector32BF16ToV32AccFloatAIE2pIntrOp::create(
4566 rewriter, loc, v32f32Ty, getLhs());
4568 vector::ShuffleOp::create(rewriter, loc, lhs32f32, lhs32f32, padMask);
4571 auto rhsNK = widenBF16ToAccFloat(rewriter, loc, i32ty, getRhs());
4574 auto acc32i32 = forceCastValueToType(
4575 rewriter, loc, acc, VectorType::get({32}, rewriter.getI32Type()));
4577 vector::ShuffleOp::create(rewriter, loc, acc32i32, acc32i32, padMask);
4580 auto confCst = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4581 rewriter.getI32IntegerAttr(780));
4582 auto result64i32 = performBFP16_8x8MatMul(rewriter, loc, i32ty, lhs64f32,
4583 rhsNK, acc64i32, confCst);
4587 vector::ShuffleOp::create(rewriter, loc, result64i32, result64i32,
4588 llvm::to_vector(llvm::seq<int64_t>(0, 32)));
4591 case K::AIE2P_BF16Outer_8x1x8: {
4595 auto v64f32Ty = VectorType::get({64}, rewriter.getF32Type());
4598 SmallVector<int64_t> replicateMask;
4599 for (
int rep = 0; rep < 8; ++rep)
4600 for (
int i = 0; i < 8; ++i)
4601 replicateMask.push_back(i);
4602 Value lhs = lhsFlat, rhs = rhsFlat;
4604 vector::ShuffleOp::create(rewriter, loc, lhs, lhs, replicateMask);
4607 SmallVector<int64_t> transposeMask;
4608 for (
int c = 0; c < 8; ++c)
4609 for (
int r = 0; r < 8; ++r)
4610 transposeMask.push_back(r * 8 + c);
4611 auto lhs64bf16Transposed = vector::ShuffleOp::create(
4612 rewriter, loc, lhs64bf16, lhs64bf16, transposeMask);
4614 vector::ShuffleOp::create(rewriter, loc, rhs, rhs, replicateMask);
4617 auto confCst = LLVM::ConstantOp::create(rewriter, loc, i32ty,
4618 rewriter.getI32IntegerAttr(60));
4619 matMulResVal = xllvm::MacConfBF16I1024ACC2048AIE2pIntrOp::create(
4620 rewriter, loc, v64f32Ty, lhs64bf16Transposed, rhs64bf16, acc,
4624 case K::AIE2P_BF16Elem_4x8x4: {
4630 SmallVector<int64_t> lhsPadMask =
4631 llvm::to_vector(llvm::seq<int64_t>(0, 32));
4632 lhsPadMask.append(32, vector::ShuffleOp::kPoisonIndex);
4633 Value lhs = getLhs();
4635 vector::ShuffleOp::create(rewriter, loc, lhs, lhs, lhsPadMask);
4636 lhsPadded = transposeTile(rewriter, loc, lhsPadded, 8, 8,
4639 SmallVector<int64_t> accPadMask =
4640 llvm::to_vector(llvm::seq<int64_t>(0, 16));
4641 accPadMask.append(16, vector::ShuffleOp::kPoisonIndex);
4643 vector::ShuffleOp::create(rewriter, loc, acc, acc, accPadMask);
4645 Value acc32 = perform8x8x4MatMul(rewriter, loc, i32ty, lhsPadded,
4646 getRhs(), accPadded);
4649 vector::ShuffleOp::create(rewriter, loc, acc32, acc32,
4650 llvm::to_vector(llvm::seq<int64_t>(0, 16)));
4653 case K::AIE2P_BF16Elem_8x8x4: {
4655 Value lhs = getLhs();
4656 Value rhs = getRhs();
4657 matMulResVal = perform8x8x4MatMul(rewriter, loc, i32ty, lhs, rhs, acc);
4661 return rewriter.notifyMatchFailure(op,
"not an AIE2P recipe");
4666 forceCastValueToType(rewriter, loc, matMulResVal, accFlattenedVecTy);
4668 rewriter.replaceOpWithNewOp<vector::ShapeCastOp>(op, op.getType(),
4680 using ConvertOpToLLVMPattern<aievec::CastOp>::ConvertOpToLLVMPattern;
4683 static bool isConstantZero(Value val) {
4684 DenseElementsAttr denseAttr;
4687 if (
auto arithConstOp = val.getDefiningOp<arith::ConstantOp>()) {
4688 denseAttr = dyn_cast<DenseElementsAttr>(arithConstOp.getValue());
4689 }
else if (
auto llvmConstOp = val.getDefiningOp<LLVM::ConstantOp>()) {
4690 denseAttr = dyn_cast<DenseElementsAttr>(llvmConstOp.getValue());
4693 if (!denseAttr || !denseAttr.isSplat())
4696 auto splatAttr = denseAttr.getSplatValue<Attribute>();
4697 if (
auto floatAttr = dyn_cast<FloatAttr>(splatAttr))
4698 return floatAttr.getValue().isZero();
4699 if (
auto intAttr = dyn_cast<IntegerAttr>(splatAttr))
4700 return intAttr.getValue().isZero();
4706 matchAndRewrite(aievec::CastOp castOp, OpAdaptor adaptor,
4707 ConversionPatternRewriter &rewriter)
const override {
4711 if (!castOp.getIsResAcc() || !isConstantZero(adaptor.getSource())) {
4713 rewriter.replaceOp(castOp, adaptor.getSource());
4717 Location loc = castOp.getLoc();
4718 auto srcVecType = cast<VectorType>(castOp.getSource().getType());
4719 Type srcElemType = srcVecType.getElementType();
4723 if (srcElemType.isF32() && lanes == 16) {
4725 auto zeroAcc1024 = xllvm::VectorBroadcastZeroAcc1024IntrOp::create(
4726 rewriter, loc, VectorType::get({16}, rewriter.getI64Type()));
4729 SmallVector<int64_t> extractMask = {0, 1, 2, 3, 4, 5, 6, 7};
4730 auto zeroAcc512 = vector::ShuffleOp::create(rewriter, loc, zeroAcc1024,
4731 zeroAcc1024, extractMask);
4734 auto result = LLVM::BitcastOp::create(
4735 rewriter, loc, VectorType::get({16}, rewriter.getF32Type()),
4738 rewriter.replaceOp(castOp, result);
4743 rewriter.replaceOp(castOp, adaptor.getSource());
4756 :
public mlir::ConvertOpToLLVMPattern<aievec::CastOp> {
4757 using ConvertOpToLLVMPattern<aievec::CastOp>::ConvertOpToLLVMPattern;
4760 matchAndRewrite(aievec::CastOp castOp, OpAdaptor adaptor,
4761 ConversionPatternRewriter &rewriter)
const override {
4762 Value src = adaptor.getSource();
4763 Type srcTy = src.getType();
4764 Type dstTy = getTypeConverter()->convertType(castOp.getResult().getType());
4765 if (srcTy == dstTy) {
4766 rewriter.replaceOp(castOp, src);
4769 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(castOp, dstTy, src);
4775 :
public mlir::ConvertOpToLLVMPattern<aievec::ShuffleOp> {
4776 using ConvertOpToLLVMPattern<aievec::ShuffleOp>::ConvertOpToLLVMPattern;
4779 matchAndRewrite(aievec::ShuffleOp shuffleOp, OpAdaptor adaptor,
4780 ConversionPatternRewriter &rewriter)
const override {
4782 return shuffleOp.emitOpError()
4783 <<
"shuffle mode '" << stringifyShuffleMode(shuffleOp.getMode())
4784 <<
"' is not available on AIE2";
4785 auto loc = shuffleOp.getLoc();
4786 auto lhs = adaptor.getLhs();
4787 auto rhs = adaptor.getRhs();
4788 auto i32ty = rewriter.getI32Type();
4789 auto v16xi32ty = VectorType::get({16}, i32ty);
4791 rhs = xllvm::UndefV16I32IntrOp::create(rewriter, loc, v16xi32ty);
4794 LLVM::ConstantOp::create(rewriter, loc, i32ty,
4795 static_cast<int32_t
>(shuffleOp.getMode()))
4797 auto vShuffleVal = xllvm::VectorShuffleIntrOp::create(
4798 rewriter, loc, v16xi32ty,
4799 forceCastOperandsToSignature(
4801 {lhs, rhs, modeAttrVal},
4802 {v16xi32ty, v16xi32ty, i32ty}))
4805 vShuffleVal = forceCastValueToType(rewriter, loc, vShuffleVal,
4806 shuffleOp.getResult().getType());
4808 rewriter.replaceOp(shuffleOp, vShuffleVal);
4817 :
public mlir::ConvertOpToLLVMPattern<aievec::ShuffleOp> {
4818 using ConvertOpToLLVMPattern<aievec::ShuffleOp>::ConvertOpToLLVMPattern;
4821 matchAndRewrite(aievec::ShuffleOp shuffleOp, OpAdaptor adaptor,
4822 ConversionPatternRewriter &rewriter)
const override {
4823 auto loc = shuffleOp.getLoc();
4824 auto i32ty = rewriter.getI32Type();
4825 auto v16xi32ty = VectorType::get({16}, i32ty);
4826 Value lhs = adaptor.getLhs();
4827 Value rhs = adaptor.getRhs();
4830 auto mode = LLVM::ConstantOp::create(
4831 rewriter, loc, i32ty,
static_cast<int32_t
>(shuffleOp.getMode()));
4832 Value v = xllvm::VectorShuffleAIE2pIntrOp::create(
4833 rewriter, loc, v16xi32ty,
4834 forceCastOperandsToSignature(rewriter, loc, {lhs, rhs, mode},
4835 {v16xi32ty, v16xi32ty, i32ty}))
4837 rewriter.replaceOp(shuffleOp,
4838 forceCastValueToType(rewriter, loc, v,
4839 shuffleOp.getResult().getType()));
4848 :
public mlir::ConvertOpToLLVMPattern<aievec::InvOp> {
4850 using ConvertOpToLLVMPattern<aievec::InvOp>::ConvertOpToLLVMPattern;
4854 ConversionPatternRewriter &rewriter)
const override {
4855 auto loc = invOp.getLoc();
4856 auto operandType = adaptor.getSource().getType();
4859 if (operandType.isF32()) {
4860 auto invResult = xllvm::InvAIE2pIntrOp::create(
4861 rewriter, loc, rewriter.getF32Type(), adaptor.getSource());
4862 rewriter.replaceOp(invOp, invResult);
4867 auto vecType = dyn_cast<VectorType>(operandType);
4868 if (!vecType || !vecType.getElementType().isF32())
4873 Value result = LLVM::PoisonOp::create(rewriter, loc, vecType);
4875 for (
int i = 0; i < numElements; ++i) {
4877 auto indexCst = LLVM::ConstantOp::create(
4878 rewriter, loc, rewriter.getI64Type(), rewriter.getI64IntegerAttr(i));
4879 auto extractedElem = LLVM::ExtractElementOp::create(
4880 rewriter, loc, adaptor.getSource(), indexCst);
4883 auto invResult = xllvm::InvAIE2pIntrOp::create(
4884 rewriter, loc, rewriter.getF32Type(), extractedElem);
4887 result = LLVM::InsertElementOp::create(rewriter, loc, vecType, result,
4888 invResult, indexCst);
4891 rewriter.replaceOp(invOp, result);
4901template <
typename IntrOpTy>
4902static Value applyAccFloatUnaryIntrinsic(ConversionPatternRewriter &rewriter,
4903 Location loc, Value source,
4904 Type resultElemType) {
4905 auto srcType = cast<VectorType>(source.getType());
4906 unsigned laneSize = getVectorLaneSize(srcType);
4907 auto v16bf16Ty = VectorType::get({16}, rewriter.getBF16Type());
4908 auto v16f32Ty = VectorType::get({16}, rewriter.getF32Type());
4909 auto toF32 = [&](Value v16bf16) -> Value {
4910 return xllvm::Vector16BF16ToV16AccFloatAIE2pIntrOp::create(
4911 rewriter, loc, v16f32Ty, v16bf16);
4914 SmallVector<Value, 2> parts;
4915 if (laneSize == 16) {
4916 parts.push_back(source);
4918 for (int64_t half = 0; half < 2; ++half) {
4919 SmallVector<int64_t> mask =
4920 llvm::to_vector(llvm::seq<int64_t>(16 * half, 16 * (half + 1)));
4922 vector::ShuffleOp::create(rewriter, loc, source, source, mask));
4925 if (srcType.getElementType().isBF16())
4926 for (Value &part : parts)
4928 for (Value &part : parts)
4929 part = IntrOpTy::create(rewriter, loc, v16bf16Ty, part);
4930 if (resultElemType.isF32())
4931 for (Value &part : parts)
4934 if (parts.size() == 1)
4935 return parts.front();
4936 SmallVector<int64_t> combineMask = llvm::to_vector(llvm::seq<int64_t>(0, 32));
4937 return vector::ShuffleOp::create(rewriter, loc, parts[0], parts[1],
4945 :
public mlir::ConvertOpToLLVMPattern<aievec::ExpOp> {
4947 using ConvertOpToLLVMPattern<aievec::ExpOp>::ConvertOpToLLVMPattern;
4951 ConversionPatternRewriter &rewriter)
const override {
4952 auto loc = expOp.getLoc();
4953 auto srcType = cast<VectorType>(adaptor.getSource().getType());
4954 auto srcElemType = srcType.getElementType();
4958 if ((laneSize != 16 && laneSize != 32) || !srcElemType.isBF16())
4959 return expOp.emitWarning()
4960 <<
"aievec.exp conversion only supports v16bfloat16 and "
4964 auto log2eBF16Const = LLVM::ConstantOp::create(
4965 rewriter, loc, rewriter.getBF16Type(),
4966 rewriter.getFloatAttr(rewriter.getBF16Type(), 1.442695));
4969 SmallVector<int64_t> broadcastMask;
4970 for (
unsigned i = 0; i < laneSize; ++i)
4971 broadcastMask.push_back(0);
4973 auto v1bf16 = LLVM::UndefOp::create(
4974 rewriter, loc, VectorType::get({1}, rewriter.getBF16Type()));
4975 auto v1bf16Inserted = LLVM::InsertElementOp::create(
4976 rewriter, loc, v1bf16, log2eBF16Const,
4977 LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 0));
4979 auto log2eVec = vector::ShuffleOp::create(rewriter, loc, v1bf16Inserted,
4980 v1bf16Inserted, broadcastMask);
4986 VectorType::get({(int64_t)laneSize}, rewriter.getF32Type());
4987 auto mulResult = aievec::MulElemOp::create(rewriter, loc, resultF32Ty,
4988 adaptor.getSource(), log2eVec);
4991 Value exp2Result = applyAccFloatUnaryIntrinsic<xllvm::Exp2AIE2pIntrOp>(
4992 rewriter, loc, mulResult, rewriter.getBF16Type());
4994 rewriter.replaceOp(expOp, exp2Result);
5002template <
typename SrcOpTy,
typename IntrOpTy>
5004 :
public mlir::ConvertOpToLLVMPattern<SrcOpTy> {
5006 using ConvertOpToLLVMPattern<SrcOpTy>::ConvertOpToLLVMPattern;
5011 ConversionPatternRewriter &rewriter)
const override {
5012 auto srcType = cast<VectorType>(adaptor.getSource().getType());
5013 Type srcElemType = srcType.getElementType();
5016 if ((laneSize != 16 && laneSize != 32) ||
5017 (!srcElemType.isBF16() && !srcElemType.isF32()))
5018 return op.emitWarning()
5020 <<
" conversion only supports v16 and v32 of bfloat16 or float.\n";
5023 op, applyAccFloatUnaryIntrinsic<IntrOpTy>(
5024 rewriter, op.getLoc(), adaptor.getSource(), srcElemType));
5033 :
public mlir::ConvertOpToLLVMPattern<math::RsqrtOp> {
5035 using ConvertOpToLLVMPattern<math::RsqrtOp>::ConvertOpToLLVMPattern;
5039 ConversionPatternRewriter &rewriter)
const override {
5040 auto loc = rsqrtOp.getLoc();
5041 auto operandType = adaptor.getOperand().getType();
5044 if (operandType.isF32()) {
5045 auto rsqrtResult = xllvm::InvsqrtAIE2pIntrOp::create(
5046 rewriter, loc, rewriter.getF32Type(), adaptor.getOperand());
5047 rewriter.replaceOp(rsqrtOp, rsqrtResult);
5052 auto vecType = dyn_cast<VectorType>(operandType);
5053 if (!vecType || !vecType.getElementType().isF32())
5058 Value result = LLVM::PoisonOp::create(rewriter, loc, vecType);
5060 for (
int i = 0; i < numElements; ++i) {
5062 auto indexCst = LLVM::ConstantOp::create(
5063 rewriter, loc, rewriter.getI64Type(), rewriter.getI64IntegerAttr(i));
5064 auto extractedElem = LLVM::ExtractElementOp::create(
5065 rewriter, loc, adaptor.getOperand(), indexCst);
5068 auto rsqrtResult = xllvm::InvsqrtAIE2pIntrOp::create(
5069 rewriter, loc, rewriter.getF32Type(), extractedElem);
5072 result = LLVM::InsertElementOp::create(rewriter, loc, vecType, result,
5073 rsqrtResult, indexCst);
5076 rewriter.replaceOp(rsqrtOp, result);
5084static bool isOneLaneVectorOfScalar(Type resultType, Type sourceType) {
5085 auto vecType = dyn_cast<VectorType>(resultType);
5086 return vecType && !vecType.isScalable() && vecType.getRank() == 1 &&
5087 vecType.getNumElements() == 1 && !isa<VectorType>(sourceType);
5090static bool isOneLaneBroadcastOfScalar(vector::BroadcastOp op) {
5091 return isOneLaneVectorOfScalar(op.getType(), op.getSourceType());
5094static bool isOneLaneInsertOfScalar(vector::InsertOp op) {
5095 return isOneLaneVectorOfScalar(op.getType(),
5096 op.getValueToStore().getType()) &&
5097 !op.hasDynamicPosition();
5101 :
public mlir::ConvertOpToLLVMPattern<vector::BroadcastOp> {
5103 using ConvertOpToLLVMPattern<vector::BroadcastOp>::ConvertOpToLLVMPattern;
5107 ConversionPatternRewriter &rewriter)
const override {
5108 if (!isOneLaneBroadcastOfScalar(bcastOp))
5110 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(bcastOp, bcastOp.getType(),
5111 adaptor.getSource());
5117 :
public mlir::ConvertOpToLLVMPattern<vector::InsertOp> {
5119 using ConvertOpToLLVMPattern<vector::InsertOp>::ConvertOpToLLVMPattern;
5123 ConversionPatternRewriter &rewriter)
const override {
5124 if (!isOneLaneInsertOfScalar(insertOp))
5126 rewriter.replaceOpWithNewOp<LLVM::BitcastOp>(insertOp, insertOp.getType(),
5127 adaptor.getValueToStore());
5137 using ConvertOpToLLVMPattern<arith::DivFOp>::ConvertOpToLLVMPattern;
5140 : ConvertOpToLLVMPattern(typeConverter),
deviceName(device.str()) {}
5146 ConversionPatternRewriter &rewriter)
const override {
5147 auto loc = divOp.getLoc();
5148 auto lhsType = adaptor.getLhs().getType();
5152 auto vecType = dyn_cast<VectorType>(lhsType);
5153 if (!vecType || !vecType.getElementType().isF32())
5156 auto rhsType = adaptor.getRhs().getType();
5157 auto rhsVecType = dyn_cast<VectorType>(rhsType);
5158 if (!rhsVecType || rhsVecType != vecType)
5163 auto module = divOp->getParentOfType<ModuleOp>();
5164 auto f32Ty = rewriter.getF32Type();
5169 std::function<void(OpBuilder &, Location, ValueRange)> bodyBuilder;
5171 bodyBuilder = [](OpBuilder &builder, Location loc, ValueRange
args) {
5172 auto invResult = xllvm::InvAIE2pIntrOp::create(
5173 builder, loc, builder.getF32Type(),
args[1]);
5175 arith::MulFOp::create(builder, loc,
args[0], invResult);
5176 LLVM::ReturnOp::create(builder, loc, ValueRange{mulResult});
5179 bodyBuilder = [](OpBuilder &builder, Location loc, ValueRange
args) {
5180 auto divResult = arith::DivFOp::create(builder, loc,
args[0],
args[1]);
5181 LLVM::ReturnOp::create(builder, loc, ValueRange{divResult});
5188 getOrCreateScalarHelperFunc(module, rewriter,
"fdiv",
deviceName,
5190 f32Ty, bodyBuilder);
5194 Value result = LLVM::PoisonOp::create(rewriter, loc, vecType);
5196 for (
int i = 0; i < numElements; ++i) {
5197 auto indexCst = LLVM::ConstantOp::create(
5198 rewriter, loc, rewriter.getI64Type(), rewriter.getI64IntegerAttr(i));
5199 auto lhsElem = LLVM::ExtractElementOp::create(rewriter, loc,
5200 adaptor.getLhs(), indexCst);
5201 auto rhsElem = LLVM::ExtractElementOp::create(rewriter, loc,
5202 adaptor.getRhs(), indexCst);
5204 auto divResult = LLVM::CallOp::create(rewriter, loc, helperFunc,
5205 ValueRange{lhsElem, rhsElem})
5208 result = LLVM::InsertElementOp::create(rewriter, loc, vecType, result,
5209 divResult, indexCst);
5212 rewriter.replaceOp(divOp, result);
5218 mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns) {
5236static void populateAIEVecToLLVMAIE2ConversionPatterns(
5237 mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns,
5238 Aie2Fp32Emulation aie2Fp32EmulationOption) {
5240 patterns.add<AddElemOpAIE2Conversion, SubElemOpAIE2Conversion>(converter);
5241 patterns.add<NegOpAIE2Conversion>(converter);
5242 patterns.add<MulElemOpConversion>(converter, aie2Fp32EmulationOption);
5243 patterns.add<UPSOpAIE2Conversion, SRSOpAIE2Conversion>(converter);
5244 patterns.add<ShiftOpConversion>(converter);
5245 patterns.add<MaxOpConversion, MinOpConversion>(converter);
5246 patterns.add<CmpOpConversion, SelOpConversion>(converter);
5247 patterns.add<ExtOpConversion>(converter);
5248 patterns.add<ExtractElemOpConversion>(converter);
5249 patterns.add<ConcatOpConversion>(converter);
5250 patterns.add<FMAElemOpConversion>(converter);
5251 patterns.add<FoldAIECastOps>(converter);
5252 patterns.add<FdivOpConversion>(converter,
"aie2");
5253 patterns.add<OneLaneBroadcastOpConversion, OneLaneInsertOpConversion>(
5259 :
public mlir::ConvertOpToLLVMPattern<aievec::ExtElemOp> {
5261 using ConvertOpToLLVMPattern<aievec::ExtElemOp>::ConvertOpToLLVMPattern;
5265 ConversionPatternRewriter &rewriter)
const override {
5266 Location loc = op.getLoc();
5270 Value extracted = LLVM::ExtractElementOp::create(
5271 rewriter, loc, adaptor.getSource(), adaptor.getIndex());
5273 rewriter.replaceOp(op, extracted);
5280 :
public mlir::ConvertOpToLLVMPattern<aievec::ConcatOp> {
5282 using ConvertOpToLLVMPattern<aievec::ConcatOp>::ConvertOpToLLVMPattern;
5289 ConversionPatternRewriter &rewriter)
const override {
5290 Location loc = op.getLoc();
5291 SmallVector<Value> parts(adaptor.getSources());
5292 if (parts.empty()) {
5293 op.emitWarning() <<
"aievec.concat with no sources is not supported.\n";
5296 auto lanesOf = [](Value v) {
5297 return cast<VectorType>(v.getType()).getNumElements();
5299 while (parts.size() > 1) {
5300 SmallVector<Value> next;
5301 for (
size_t i = 0; i + 1 < parts.size(); i += 2) {
5302 Value lhs = parts[i], rhs = parts[i + 1];
5303 int64_t lhsLanes = lanesOf(lhs), rhsLanes = lanesOf(rhs);
5304 if (rhsLanes < lhsLanes) {
5305 SmallVector<int64_t> padMask(lhsLanes, -1);
5306 std::iota(padMask.begin(), padMask.begin() + rhsLanes, 0);
5307 rhs = vector::ShuffleOp::create(rewriter, loc, rhs, rhs, padMask);
5309 SmallVector<int64_t> mask(lhsLanes + rhsLanes);
5310 std::iota(mask.begin(), mask.end(), 0);
5312 vector::ShuffleOp::create(rewriter, loc, lhs, rhs, mask));
5314 if (parts.size() % 2)
5315 next.push_back(parts.back());
5316 parts = std::move(next);
5318 rewriter.replaceOp(op, parts.front());
5324 mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns) {
5358 mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns,
5359 Aie2Fp32Emulation aie2Fp32EmulationOption, StringRef aieTarget) {
5361 if (aieTarget ==
"aie2p")
5365 aie2Fp32EmulationOption);
5369static void configureAIEVecToLLVMLegalizations(LLVMConversionTarget &target) {
5372 target.addDynamicallyLegalOp<arith::DivFOp>([](arith::DivFOp divOp) {
5373 auto resultType = divOp.getType();
5374 if (
auto vecType = dyn_cast<VectorType>(resultType)) {
5376 return !vecType.getElementType().isF32();
5383 target.addDynamicallyLegalOp<vector::BroadcastOp>(
5384 [](vector::BroadcastOp op) {
return !isOneLaneBroadcastOfScalar(op); });
5385 target.addDynamicallyLegalOp<vector::InsertOp>(
5386 [](vector::InsertOp op) {
return !isOneLaneInsertOfScalar(op); });
5393 aieTarget = options.aieTarget;
5394 aie2Fp32Emulation = options.aie2Fp32Emulation;
5398 RewritePatternSet patterns(&getContext());
5399 LLVMTypeConverter converter(&getContext());
5403 converter.addConversion(
5404 [&](VectorType type) -> std::optional<Type> {
return type; });
5407 aie2Fp32Emulation, aieTarget);
5409 LLVMConversionTarget target(getContext());
5410 target.addIllegalDialect<xilinx::aievec::AIEVecDialect,
5411 xilinx::aievec::aie1::AIEVecAIE1Dialect>();
5412 target.addLegalDialect<arith::ArithDialect, vector::VectorDialect,
5413 xilinx::xllvm::XLLVMDialect, ub::UBDialect>();
5416 configureAIEVecToLLVMLegalizations(target);
5418 if (failed(applyPartialConversion(getOperation(), target,
5419 std::move(patterns))))
5420 signalPassFailure();
5424std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
5426 return std::make_unique<ConvertAIEVecToLLVMPass>();
5429std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
5431 const xilinx::ConvertAIEVecToLLVMOptions &options) {
5432 return std::make_unique<ConvertAIEVecToLLVMPass>(options);
typename SrcOpTy::Adaptor OpAdaptor
LogicalResult matchAndRewrite(SrcOpTy op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
typename SrcOpTy::Adaptor OpAdaptor
LogicalResult matchAndRewrite(SrcOpTy op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
static DecodedAddElemOp decodeAddElemOp(OpAdaptor op)
LogicalResult matchAndRewrite(aievec::AddElemOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::aie1::AddOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::BroadcastOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::BroadcastScalarOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::BroadcastScalarOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::CmpOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::ConcatOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::ConcatOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::ExpOp expOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::ExtOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::ExtOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::FMAElemOp fmaOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::FMAElemOp fmaOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::aie1::FMAOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(arith::DivFOp divOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
FdivOpConversion(const LLVMTypeConverter &typeConverter, StringRef device)
LogicalResult matchAndRewrite(aievec::InvOp invOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::MaxOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::MaxOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::MinOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::MinOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
static DecodedMulElemOp decodeMulElemOp(OpAdaptor op)
LogicalResult matchAndRewrite(aievec::MulElemOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult convertToEmulatedFP32MulElem(aievec::MulElemOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const
LogicalResult convertToEmulatedI32MulElem(aievec::MulElemOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const
MulElemOpConversion(const LLVMTypeConverter &typeConverter, Aie2Fp32Emulation aie2Fp32EmulationOption)
Aie2Fp32Emulation aie2Fp32EmulationOption
LogicalResult matchAndRewrite(aievec::MulElemOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
static DecodedMulElemOp decodeMulElemOp(OpAdaptor op)
LogicalResult matchAndRewrite(aievec::aie1::MulOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::NegOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::NegOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(vector::BroadcastOp bcastOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(vector::InsertOp insertOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::PackOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
static std::string getIntrinsicName(aievec::PackOp op)
LogicalResult matchAndRewrite(math::RsqrtOp rsqrtOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::SRSOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::SRSOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::SelOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
static std::string getIntrinsicName(aievec::aie1::SelectOp op)
LogicalResult matchAndRewrite(aievec::aie1::SelectOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::ShiftOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::ShiftOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::SubElemOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
static DecodedSubElemOp decodeSubElemOp(OpAdaptor op)
LogicalResult matchAndRewrite(aievec::aie1::SubOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
static std::string getIntrinsicName(aievec::UPDOp op, int loadSize)
LogicalResult matchAndRewrite(aievec::UPDOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::UPSOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::UPSOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::UnpackOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(aievec::UnpackOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
mlir::VectorType getFlattenedVectorType(mlir::VectorType vecTy)
std::optional< MatMulRecipe > checkMatMulTile(bool aie2p, mlir::VectorType lhsTy, mlir::VectorType rhsTy, mlir::VectorType accTy, bool lhsTransposed, bool rhsTransposed, llvm::function_ref< mlir::InFlightDiagnostic()> emitError=nullptr)
int32_t getVectorSizeInBits(mlir::VectorType type)
unsigned getVectorLaneSize(mlir::VectorType type)
bool isAIE2POnlyShuffleMode(ShuffleMode mode)
void populateAIEVecToLLVMCommonConversionPatterns(mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns)
SelOpConversionBase< xllvm::VectorSel16AIE2pIntrOp, xllvm::VectorSel32AIE2pIntrOp > SelOpAIE2pConversion
AccFloatAddSubAIE2pConversion< aievec::AddElemOp, xllvm::AddACC2048AccFloatAIE2pIntrOp > AddElemOpAIE2pConversion
CmpOpConversionBase< xllvm::VectorMaxLtBf16AIE2pIntrOp, xllvm::VectorMinGeBf16AIE2pIntrOp, xllvm::VectorMaxLt32AIE2pIntrOp, xllvm::VectorMinGe32AIE2pIntrOp, xllvm::VectorMaxLt16AIE2pIntrOp, xllvm::VectorMinGe16AIE2pIntrOp > CmpOpAIE2pConversion
void populateAIEVecToLLVMAIE2ConversionPatterns(mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns)
void populateAIEVecToLLVMAIE2pConversionPatterns(mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns)
SelOpConversionBase< xllvm::VectorSel16IntrOp, xllvm::VectorSel32IntrOp > SelOpConversion
CmpOpConversionBase< xllvm::VectorMaxLtBf16IntrOp, xllvm::VectorMinGeBf16IntrOp, xllvm::VectorMaxLt32IntrOp, xllvm::VectorMinGe32IntrOp, xllvm::VectorMaxLt16IntrOp, xllvm::VectorMinGe16IntrOp > CmpOpConversion
AccFloatAddSubAIE2pConversion< aievec::SubElemOp, xllvm::SubACC2048AccFloatAIE2pIntrOp > SubElemOpAIE2pConversion
std::unique_ptr< mlir::OperationPass< mlir::ModuleOp > > createConvertAIEVecToLLVMPass()
void populateAIEVecToLLVMConversionPatterns(mlir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns, Aie2Fp32Emulation aie2Fp32EmulationOption, llvm::StringRef aieTarget)
@ FP32_FP32_FP32_16x1x1x1
ConvertAIEVecToLLVMPass(const xilinx::ConvertAIEVecToLLVMOptions &options)
void runOnOperation() override
ConvertAIEVecToLLVMPass()=default
@ BF16_BF16_FP32_32x1x2x1
@ BF16_BF16_FP32_64x1x2x1
@ BF16_BF16_FP32_16x1x1x1
@ FP32_FP32_FP32_16x1x1x1
@ BF16_BF16_FP32_16x1x2x1
@ FP32_FP32_FP32_16x1x1x1