27#define GEN_PASS_DEF_ARITHTOAMDGPUCONVERSIONPASS
28#include "mlir/Conversion/Passes.h.inc"
39struct ArithToAMDGPUConversionPass final
40 : impl::ArithToAMDGPUConversionPassBase<ArithToAMDGPUConversionPass> {
41 using impl::ArithToAMDGPUConversionPassBase<
42 ArithToAMDGPUConversionPass>::ArithToAMDGPUConversionPassBase;
44 void runOnOperation()
override;
51 ExtFOnFloat8RewritePattern(MLIRContext *ctx, Chipset chipset,
52 PatternBenefit benefit)
53 : OpRewritePattern::OpRewritePattern(ctx, benefit), chipset(chipset) {}
55 LogicalResult matchAndRewrite(arith::ExtFOp op,
56 PatternRewriter &rewriter)
const override;
59struct TruncFToFloat8RewritePattern final :
OpRewritePattern<arith::TruncFOp> {
60 bool saturateFP8 =
false;
61 TruncFToFloat8RewritePattern(MLIRContext *ctx,
bool saturateFP8,
62 Chipset chipset, PatternBenefit benefit)
63 : OpRewritePattern::OpRewritePattern(ctx, benefit),
64 saturateFP8(saturateFP8), chipset(chipset) {}
67 LogicalResult matchAndRewrite(arith::TruncFOp op,
68 PatternRewriter &rewriter)
const override;
71struct TruncfToFloat16RewritePattern final
76 LogicalResult matchAndRewrite(arith::TruncFOp op,
77 PatternRewriter &rewriter)
const override;
80struct ScalingExtFRewritePattern final
84 LogicalResult matchAndRewrite(arith::ScalingExtFOp op,
85 PatternRewriter &rewriter)
const override;
88struct ScalingTruncFRewritePattern final
92 LogicalResult matchAndRewrite(arith::ScalingTruncFOp op,
93 PatternRewriter &rewriter)
const override;
100 return isa<Float8E4M3FNUZType, Float8E5M2FNUZType>(elementType);
102 return isa<Float8E4M3FNType, Float8E5M2Type>(elementType);
109 if (elementType.
isF32())
112 return arith::TruncFOp::create(rewriter, loc, desType, f32);
114 return arith::ExtFOp::create(rewriter, loc,
TypeRange{desType},
115 ValueRange{f32}, arith::ExtFOp::Properties{});
116 llvm_unreachable(
"The only 32-bit float type is f32");
120ExtFOnFloat8RewritePattern::matchAndRewrite(arith::ExtFOp op,
122 Type inType = op.getIn().getType();
123 auto inVecType = dyn_cast<VectorType>(inType);
125 if (inVecType.isScalable())
127 inType = inVecType.getElementType();
132 Location loc = op.getLoc();
133 Value in = op.getIn();
135 VectorType extResType = VectorType::get(2, rewriter.
getF32Type());
137 Value asFloat = amdgpu::ExtPackedFp8Op::create(
143 int64_t numElements = inVecType.getNumElements();
145 Value zero = arith::ConstantOp::create(
146 rewriter, loc, outElemType, rewriter.
getFloatAttr(outElemType, 0.0));
147 VectorType outType = cast<VectorType>(op.getOut().getType());
149 if (inVecType.getShape().empty()) {
151 rewriter.
createOrFold<vector::BroadcastOp>(loc, outType, zero);
153 vector::ExtractOp::create(rewriter, loc, in, ArrayRef<int64_t>{});
154 Value scalarExt = arith::ExtFOp::create(
156 arith::ExtFOp::Properties{});
157 Value
result = vector::InsertOp::create(rewriter, loc, scalarExt,
158 zerodSplat, ArrayRef<int64_t>{});
163 VectorType flatTy = VectorType::get(SmallVector<int64_t>{numElements},
164 outType.getElementType());
167 if (inVecType.getRank() > 1) {
168 inVecType = VectorType::get(SmallVector<int64_t>{numElements},
169 inVecType.getElementType());
170 in = vector::ShapeCastOp::create(rewriter, loc, inVecType, in);
173 for (int64_t i = 0; i < numElements; i += 4) {
174 int64_t elemsThisOp = std::min(numElements, i + 4) - i;
175 Value inSlice = vector::ExtractStridedSliceOp::create(rewriter, loc, in, i,
177 for (int64_t j = 0; j < elemsThisOp; j += 2) {
178 if (i + j + 1 < numElements) {
179 Value asFloats = amdgpu::ExtPackedFp8Op::create(
180 rewriter, loc, extResType, inSlice, j / 2);
181 Type desType = VectorType::get(2, outElemType);
182 Value asType =
castF32To(desType, asFloats, loc, rewriter);
183 result = vector::InsertStridedSliceOp::create(rewriter, loc, asType,
186 Value asFloat = amdgpu::ExtPackedFp8Op::create(
187 rewriter, loc, rewriter.
getF32Type(), inSlice, j / 2 * 2);
188 Value asType =
castF32To(outElemType, asFloat, loc, rewriter);
189 result = vector::InsertOp::create(rewriter, loc, asType,
result, i + j);
194 if (inVecType.getRank() != outType.getRank()) {
195 result = vector::ShapeCastOp::create(rewriter, loc, outType,
result);
207 return arith::ExtFOp::create(
209 arith::ExtFOp::Properties{});
211 return arith::TruncFOp::create(rewriter, loc, rewriter.
getF32Type(), value);
212 llvm_unreachable(
"The only 32-bit float type is f32");
223 const llvm::fltSemantics &sourceSem =
225 const llvm::fltSemantics &targetSem =
226 cast<FloatType>(outElemType).getFloatSemantics();
228 APFloat
min = APFloat::getLargest(targetSem,
true);
229 APFloat
max = APFloat::getLargest(targetSem,
false);
230 bool ignoredLosesInfo =
false;
234 (
void)
min.convert(sourceSem, APFloat::rmNearestTiesToEven, &ignoredLosesInfo);
235 (
void)
max.convert(sourceSem, APFloat::rmNearestTiesToEven, &ignoredLosesInfo);
241 rewriter, loc, sourceType,
242 APFloat::getInf(sourceSem,
false));
244 rewriter, loc, sourceType, APFloat::getInf(sourceSem,
true));
246 loc, arith::CmpFPredicate::OEQ, source, inf);
248 loc, arith::CmpFPredicate::OEQ, source, negInf);
250 loc, arith::CmpFPredicate::UNO, source, source);
251 Value isNonFinite = arith::OrIOp::create(
252 rewriter, loc, arith::OrIOp::create(rewriter, loc, isInf, isNegInf),
255 Value clampedBelow = arith::MaximumFOp::create(rewriter, loc, source, minCst);
257 arith::MinimumFOp::create(rewriter, loc, clampedBelow, maxCst);
259 arith::SelectOp::create(rewriter, loc, isNonFinite, source, clamped);
264TruncFToFloat8RewritePattern::matchAndRewrite(arith::TruncFOp op,
265 PatternRewriter &rewriter)
const {
267 if (op.getRoundingmodeAttr())
269 Type outType = op.getOut().getType();
270 auto outVecType = dyn_cast<VectorType>(outType);
272 if (outVecType.isScalable())
274 outType = outVecType.getElementType();
277 if (inType && inType.getWidth() <= 8 && saturateFP8)
284 Location loc = op.getLoc();
285 Value in = op.getIn();
288 in =
clampInput(rewriter, loc, outElemType, in);
289 auto inVectorTy = dyn_cast<VectorType>(in.
getType());
290 VectorType truncResType = VectorType::get(4, outElemType);
292 Value asFloat =
castToF32(in, loc, rewriter);
293 Value asF8s = amdgpu::PackedTrunc2xFp8Op::create(
294 rewriter, loc, truncResType, asFloat,
nullptr, 0,
296 Value
result = vector::ExtractOp::create(rewriter, loc, asF8s, 0);
301 int64_t numElements = outVecType.getNumElements();
302 Value zero = arith::ConstantOp::create(
303 rewriter, loc, outElemType, rewriter.
getFloatAttr(outElemType, 0.0));
304 if (outVecType.getShape().empty()) {
306 vector::ExtractOp::create(rewriter, loc, in, ArrayRef<int64_t>{});
309 arith::TruncFOp::create(rewriter, loc, outElemType, scalarIn);
310 Value
result = vector::InsertOp::create(rewriter, loc, scalarTrunc, zero,
311 ArrayRef<int64_t>{});
316 VectorType flatTy = VectorType::get(SmallVector<int64_t>{numElements},
317 outVecType.getElementType());
320 if (inVectorTy.getRank() > 1) {
321 inVectorTy = VectorType::get(SmallVector<int64_t>{numElements},
322 inVectorTy.getElementType());
323 in = vector::ShapeCastOp::create(rewriter, loc, inVectorTy, in);
326 for (int64_t i = 0; i < numElements; i += 4) {
327 int64_t elemsThisOp = std::min(numElements, i + 4) - i;
328 Value thisResult =
nullptr;
329 for (int64_t j = 0; j < elemsThisOp; j += 2) {
330 Value elemA = vector::ExtractOp::create(rewriter, loc, in, i + j);
331 Value asFloatA =
castToF32(elemA, loc, rewriter);
332 Value asFloatB =
nullptr;
333 if (j + 1 < elemsThisOp) {
334 Value elemB = vector::ExtractOp::create(rewriter, loc, in, i + j + 1);
335 asFloatB =
castToF32(elemB, loc, rewriter);
337 thisResult = amdgpu::PackedTrunc2xFp8Op::create(
338 rewriter, loc, truncResType, asFloatA, asFloatB, j / 2, thisResult);
341 thisResult = vector::ExtractStridedSliceOp::create(
342 rewriter, loc, thisResult, 0, elemsThisOp, 1);
343 result = vector::InsertStridedSliceOp::create(rewriter, loc, thisResult,
347 if (inVectorTy.getRank() != outVecType.getRank()) {
348 result = vector::ShapeCastOp::create(rewriter, loc, outVecType,
result);
355LogicalResult TruncfToFloat16RewritePattern::matchAndRewrite(
356 arith::TruncFOp op, PatternRewriter &rewriter)
const {
357 Type outType = op.getOut().getType();
359 auto outVecType = dyn_cast<VectorType>(outType);
361 if (outVecType.isScalable())
363 outType = outVecType.getElementType();
368 Location loc = op.getLoc();
369 Value in = op.getIn();
371 VectorType truncResType = VectorType::get(2, outElemType);
372 auto inVectorTy = dyn_cast<VectorType>(in.
getType());
376 auto sourceB = LLVM::PoisonOp::create(rewriter, loc, rewriter.
getF32Type());
378 ROCDL::CvtPkRtz::create(rewriter, loc, truncResType, in, sourceB);
379 Value
result = vector::ExtractOp::create(rewriter, loc, asF16s, 0);
383 int64_t numElements = outVecType.getNumElements();
385 loc, outElemType, rewriter.
getFloatAttr(outElemType, 0.0));
387 rewriter.
createOrFold<vector::BroadcastOp>(loc, outVecType, zero);
389 if (inVectorTy.getRank() > 1) {
390 inVectorTy = VectorType::get(SmallVector<int64_t>{numElements},
391 inVectorTy.getElementType());
392 in = vector::ShapeCastOp::create(rewriter, loc, inVectorTy, in);
397 for (int64_t i = 0; i < numElements; i += 2) {
398 int64_t elemsThisOp = std::min(numElements, i + 2) - i;
399 Value thisResult =
nullptr;
400 Value elemA = vector::ExtractOp::create(rewriter, loc, in, i);
401 Value elemB = LLVM::PoisonOp::create(rewriter, loc, rewriter.
getF32Type());
403 if (elemsThisOp == 2) {
404 elemB = vector::ExtractOp::create(rewriter, loc, in, i + 1);
408 ROCDL::CvtPkRtz::create(rewriter, loc, truncResType, elemA, elemB);
411 thisResult = vector::ExtractStridedSliceOp::create(
412 rewriter, loc, thisResult, 0, elemsThisOp, 1);
413 result = vector::InsertStridedSliceOp::create(rewriter, loc, thisResult,
417 if (inVectorTy.getRank() != outVecType.getRank()) {
418 result = vector::ShapeCastOp::create(rewriter, loc, outVecType,
result);
427 Value current = value;
430 .Case([¤t](vector::ShapeCastOp op) {
431 current = op.getSource();
434 .Case([¤t](vector::BroadcastOp op) {
435 current = op.getSource();
448ScalingExtFRewritePattern::matchAndRewrite(arith::ScalingExtFOp op,
449 PatternRewriter &rewriter)
const {
450 Location loc = op.getLoc();
451 constexpr int64_t opOutWidth = 2;
453 Value in = op.getIn();
454 Value scale = op.getScale();
455 Value out = op.getOut();
464 VectorType outVecType = dyn_cast<VectorType>(out.
getType());
465 VectorType scaleVecType = dyn_cast<VectorType>(scale.
getType());
467 if (outVecType && outVecType.isScalable())
470 if (isa<RankedTensorType>(out.
getType()) ||
471 isa<RankedTensorType>(in.
getType()) ||
472 isa<RankedTensorType>(scale.
getType()))
476 scaleVecType ? VectorType::get(scaleVecType.getShape(), f32) : f32;
479 arith::ExtFOp::create(rewriter, loc,
TypeRange{scaleF32Type},
480 ValueRange{scale}, arith::ExtFOp::Properties{});
482 scale = arith::TruncFOp::create(rewriter, loc, scaleF32Type, scale);
484 VectorType extScaleResultType = VectorType::get(opOutWidth, outType);
487 Value inCast = vector::BroadcastOp::create(rewriter, loc,
488 VectorType::get(1, inType), in);
490 Value scaleExt = amdgpu::ScaledExtPackedOp::create(
491 rewriter, loc, extScaleResultType, inCast, scale, 0);
496 VectorType inVecType = cast<VectorType>(in.
getType());
498 VectorType origScaleVecType = dyn_cast<VectorType>(origScale.
getType());
500 ArrayRef<int64_t> inShape = inVecType.getShape();
501 SmallVector<int64_t> originalScaleShape;
502 if (origScaleVecType)
503 llvm::append_range(originalScaleShape, origScaleVecType.getShape());
505 originalScaleShape.insert(originalScaleShape.end(),
506 inShape.size() - originalScaleShape.size(), 1);
510 "failed to derive block size from broadcast or splat operation");
512 SmallVector<int64_t> ratio =
513 maybeRatio.value_or(SmallVector<int64_t>(inShape.size(), 1));
517 Value zero = arith::ConstantOp::create(rewriter, loc, outType,
520 rewriter.
createOrFold<vector::BroadcastOp>(loc, outVecType, zero);
522 for (SmallVector<int64_t> offsets : StaticTileOffsetRange(inShape, ratio)) {
523 SmallVector<int64_t> strides(offsets.size(), 1);
524 Value block = vector::ExtractStridedSliceOp::create(
525 rewriter, loc, in, offsets, ratio, strides);
526 VectorType block1DType = VectorType::get(blockSize, inType);
528 vector::ShapeCastOp::create(rewriter, loc, block1DType, block);
530 vector::ExtractOp::create(rewriter, loc, scale, offsets);
532 VectorType blockResultType = VectorType::get(blockSize, outType);
534 rewriter.
createOrFold<vector::BroadcastOp>(loc, blockResultType, zero);
536 for (int64_t i = 0, inSliceWidth = std::min(opInWidth, blockSize - i);
538 i += inSliceWidth, inSliceWidth = std::min(opInWidth, blockSize - i)) {
539 Value inSlice = vector::ExtractStridedSliceOp::create(
540 rewriter, loc, block1D, i, inSliceWidth, 1);
542 outSliceWidth = std::min(opOutWidth, inSliceWidth - j);
543 j < inSliceWidth; j += outSliceWidth,
544 outSliceWidth = std::min(opOutWidth, inSliceWidth - j)) {
546 Value scaleExt = amdgpu::ScaledExtPackedOp::create(
547 rewriter, loc, extScaleResultType, inSlice, uniformScale,
549 if (outSliceWidth < opOutWidth) {
550 scaleExt = vector::ExtractStridedSliceOp::create(
551 rewriter, loc, scaleExt, 0, outSliceWidth, 1);
553 blockResult = vector::InsertStridedSliceOp::create(
554 rewriter, loc, scaleExt, blockResult, i + j, 1);
558 VectorType resultType = VectorType::get(ratio, outType);
560 vector::ShapeCastOp::create(rewriter, loc, resultType, blockResult);
561 result = vector::InsertStridedSliceOp::create(rewriter, loc, cast,
result,
571ScalingTruncFRewritePattern::matchAndRewrite(arith::ScalingTruncFOp op,
572 PatternRewriter &rewriter)
const {
573 Location loc = op.getLoc();
574 constexpr int64_t opInWidth = 2;
576 Value in = op.getIn();
577 Value scale = op.getScale();
578 Value out = op.getOut();
585 VectorType outVecType = dyn_cast<VectorType>(out.
getType());
586 VectorType scaleVecType = dyn_cast<VectorType>(scale.
getType());
587 if (outVecType && outVecType.isScalable())
590 if (isa<RankedTensorType>(out.
getType()) ||
591 isa<RankedTensorType>(in.
getType()) ||
592 isa<RankedTensorType>(scale.
getType()))
596 scaleVecType ? VectorType::get(scaleVecType.getShape(), f32) : f32;
599 arith::ExtFOp::create(rewriter, loc,
TypeRange{scaleF32Type},
600 ValueRange{scale}, arith::ExtFOp::Properties{});
602 scale = arith::TruncFOp::create(rewriter, loc, scaleF32Type, scale);
604 Value zero = arith::ConstantOp::create(rewriter, loc, outType,
607 VectorType truncScaleResultType = VectorType::get(opOutWidth, outType);
610 Type inVecType = VectorType::get(1, inType);
611 Value inCast = vector::BroadcastOp::create(rewriter, loc, inVecType, in);
613 Value scaleTrunc = amdgpu::PackedScaledTruncOp::create(
614 rewriter, loc, truncScaleResultType, inCast, scale, 0,
621 VectorType inVecType = cast<VectorType>(in.
getType());
623 VectorType origScaleVecType = dyn_cast<VectorType>(origScale.
getType());
625 ArrayRef<int64_t> inShape = inVecType.getShape();
626 SmallVector<int64_t> scaleShape;
627 if (origScaleVecType)
628 llvm::append_range(scaleShape, origScaleVecType.getShape());
630 scaleShape.insert(scaleShape.end(), inShape.size() - scaleShape.size(), 1);
634 "failed to derive block size from broadcast or splat operation");
636 SmallVector<int64_t> ratio =
637 maybeRatio.value_or(SmallVector<int64_t>(inShape.size(), 1));
642 rewriter.
createOrFold<vector::BroadcastOp>(loc, outVecType, zero);
644 for (SmallVector<int64_t> offsets : StaticTileOffsetRange(inShape, ratio)) {
645 SmallVector<int64_t> strides(offsets.size(), 1);
646 Value block = vector::ExtractStridedSliceOp::create(
647 rewriter, loc, in, offsets, ratio, strides);
648 VectorType block1DType = VectorType::get(blockSize, inType);
650 vector::ShapeCastOp::create(rewriter, loc, block1DType, block);
652 vector::ExtractOp::create(rewriter, loc, scale, offsets);
654 VectorType blockResultType = VectorType::get(blockSize, outType);
656 rewriter.
createOrFold<vector::BroadcastOp>(loc, blockResultType, zero);
658 for (int64_t i = 0, outSliceWidth = std::min(opOutWidth, blockSize - i);
659 i < blockSize; i += outSliceWidth,
660 outSliceWidth = std::min(opOutWidth, blockSize - i)) {
663 if (outSliceWidth <= opInWidth) {
664 Value slice = vector::ExtractStridedSliceOp::create(
665 rewriter, loc, block1D, i, outSliceWidth, 1);
667 scaleTrunc = amdgpu::PackedScaledTruncOp::create(
668 rewriter, loc, truncScaleResultType, slice, uniformScale, 0,
671 scaleTrunc = vector::BroadcastOp::create(rewriter, loc,
672 truncScaleResultType, zero);
674 inSliceWidth = std::min(opInWidth, outSliceWidth - j);
675 j < outSliceWidth; j += opInWidth,
676 inSliceWidth = std::min(opInWidth, outSliceWidth - j)) {
677 Value slice = vector::ExtractStridedSliceOp::create(
678 rewriter, loc, block1D, i + j, inSliceWidth, 1);
679 scaleTrunc = amdgpu::PackedScaledTruncOp::create(
680 rewriter, loc, truncScaleResultType, slice, uniformScale,
681 j / opInWidth, scaleTrunc);
684 if (outSliceWidth != opOutWidth) {
685 scaleTrunc = vector::ExtractStridedSliceOp::create(
686 rewriter, loc, scaleTrunc, 0, outSliceWidth, 1);
688 blockResult = vector::InsertStridedSliceOp::create(
689 rewriter, loc, scaleTrunc, blockResult, i, 1);
692 VectorType resultType = VectorType::get(ratio, outType);
694 vector::ShapeCastOp::create(rewriter, loc, resultType, blockResult);
695 result = vector::InsertStridedSliceOp::create(rewriter, loc, cast,
result,
706 bool saturateFP8Truncf,
bool allowPackedF16Rtz,
bool supportsScaledExtTrunc,
709 if (convertFP8Arithmetic) {
710 patterns.
add<ExtFOnFloat8RewritePattern>(patterns.
getContext(), chipset,
712 patterns.
add<TruncFToFloat8RewritePattern>(
713 patterns.
getContext(), saturateFP8Truncf, chipset, benefit);
715 if (allowPackedF16Rtz)
716 patterns.
add<TruncfToFloat16RewritePattern>(patterns.
getContext(), benefit);
718 if (supportsScaledExtTrunc) {
719 patterns.
add<ScalingExtFRewritePattern>(patterns.
getContext(), benefit);
720 patterns.
add<ScalingTruncFRewritePattern>(patterns.
getContext(), benefit);
724void ArithToAMDGPUConversionPass::runOnOperation() {
729 if (failed(maybeChipset)) {
730 emitError(UnknownLoc::get(ctx),
"Invalid chipset name: " + chipset);
731 return signalPassFailure();
734 bool convertFP8Arithmetic =
736 bool supportsScaledExtTrunc = *maybeChipset ==
kGfx950;
738 patterns, convertFP8Arithmetic, saturateFP8Truncf, allowPackedF16Rtz,
739 supportsScaledExtTrunc, *maybeChipset);
741 return signalPassFailure();
constexpr Chipset kGfx942
constexpr Chipset kGfx950
static Value getOriginalVectorValue(Value value)
Get the broadcasted / splatted value for a chain of ops.
static Value castF32To(Type desType, Value f32, Location loc, PatternRewriter &rewriter)
static Value castToF32(Value value, Location loc, PatternRewriter &rewriter)
static bool isSupportedF8(Type elementType, Chipset chipset)
static Value clampInput(PatternRewriter &rewriter, Location loc, Type outElemType, Value source)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
FloatAttr getFloatAttr(Type type, double value)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
Operation is the basic unit of execution within MLIR.
MLIRContext * getContext()
Return the context this operation is associated with.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
bool hasOcpFp8(const Chipset &chipset)
void populateArithToAMDGPUConversionPatterns(RewritePatternSet &patterns, bool convertFP8Arithmetic, bool saturateFP8Truncf, bool allowPackedF16Rtz, bool supportsScaledExtTrunc, amdgpu::Chipset chipset, PatternBenefit benefit=1)
Add patterns for rewriting arith.extf and arith.truncf on FP8 types to wrappers around AMDGPU–specifi...
Include the generated interface declarations.
Value createScalarOrSplatConstant(OpBuilder &builder, Location loc, Type type, const APInt &value)
Create a constant of type type at location loc whose value is value (an APInt or APFloat whose type m...
LogicalResult applyPatternsGreedily(Region ®ion, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
int64_t computeProduct(ArrayRef< int64_t > basis)
Self-explicit.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
std::optional< SmallVector< int64_t > > computeShapeRatio(ArrayRef< int64_t > shape, ArrayRef< int64_t > subShape)
Return the multi-dimensional integral ratio of subShape to the trailing dimensions of shape.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
Represents the amdgpu gfx chipset version, e.g., gfx90a, gfx942, gfx1103.
static FailureOr< Chipset > parse(StringRef name)
Parses the chipset version string and returns the chipset on success, and failure otherwise.