Skip to content
This repository was archived by the owner on Nov 27, 2025. It is now read-only.

Commit 80862df

Browse files
Jacenty-And-Intelermilindwalekar
authored andcommitted
Enable quantization for FP4 type
1 parent f68d9eb commit 80862df

File tree

7 files changed

+117
-49
lines changed

7 files changed

+117
-49
lines changed

mlir/include/mlir/Dialect/Quant/IR/QuantTypes.h

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ class QuantizedType : public Type {
9797
return -getDefaultMaximumForF8E5M2();
9898
}
9999

100+
static constexpr int64_t getDefaultMaximumForF4E2M1FN() { return 6; }
101+
102+
static constexpr int64_t getDefaultMinimumForF4E2M1FN() {
103+
return -getDefaultMaximumForF4E2M1FN();
104+
}
105+
100106
/// Gets the original expressed type that this quantized type approximates.
101107
/// Note that this presumes that the quantized type was always derived from
102108
/// a floating point type, which in the broadest definition, is not true (i.e.
@@ -267,7 +273,7 @@ class AnyQuantizedType
267273
/// Per-layer, optional parameters omitted:
268274
/// !quant<uniform[StorageType]{Scale}>
269275
///
270-
/// StorageType: 'i'|'u' NumBits
276+
/// StorageType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8'
271277
/// ExpressedType: 'f16', 'f32', 'bf16', 'f64'
272278
/// Scale: A legal double value
273279
/// ZeroPoint: An integer value
@@ -327,7 +333,7 @@ class UniformQuantizedType
327333
/// Per-axis, optional parameters omitted:
328334
/// !quant<uniform[StorageType]{Scale}>
329335
///
330-
/// StorageType: 'i'|'u' NumBits
336+
/// StorageType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8'
331337
/// ExpressedType: 'f16', 'f32', 'bf16', 'f64'
332338
/// QuantizedDim: An integer value
333339
/// QuantParams: (Scale ':' ZeroPoint)+
@@ -414,7 +420,7 @@ class UniformQuantizedPerAxisType
414420
/// ScaleZeroList ::= ScaleZero (',' ScaleZero)*
415421
/// ScaleZero ::= Scale (':' ZeroPoint)?
416422
///
417-
/// StorageType: 'i'|'u' NumBits
423+
/// StorageType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8'
418424
/// ExpressedType: 'f16', 'f32', 'bf16', 'f64'
419425
/// AxisSpec: An integer value
420426
/// BlockSizeSpec: An integer value
@@ -534,18 +540,17 @@ class UniformQuantizedSubChannelType
534540
/// QuantileQuantizedType derives from UniformQuantizedType and adds to it a
535541
/// look up table array of quantile values. The type of the data in the look up
536542
/// table is determined by the quantileType member: supported quantileType types
537-
/// are integer/unsigned/hf8/bf8/f16/bf16/f32/f64.
543+
/// are integer/unsigned/f4/hf8/bf8/f16/bf16/f32/f64.
538544
///
539545
/// Syntax synopsis:
540546
/// Per-layer, all parameters expressed:
541547
/// !quant<quantile[StorageType:QuantileType:ExpressedType]{Quantiles}:{Scale:ZeroPoint}>
542548
/// Per-layer, optional parameters omitted:
543549
/// !quant<quantile[StorageType:QuantileType]{Quantiles}:{Scale}>
544550
///
545-
/// StorageType: 'i'|'u' NumBits
546-
/// QuantileType: 'i'|'u' NumBits, 'hf8', 'bf8', 'f16', 'bf16', 'f32', 'f64'
547-
/// ExpressedType: 'f16', 'f32', 'bf16', 'f64'
548-
/// Quantiles: Quantile+
551+
/// StorageType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8'
552+
/// QuantileType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8', 'f16', 'bf16', 'f32',
553+
/// 'f64' ExpressedType: 'f16', 'f32', 'bf16', 'f64' Quantiles: Quantile+
549554
/// Quantile: A legal double value
550555
/// Scale: A legal double value
551556
/// ZeroPoint: An integer value
@@ -601,23 +606,20 @@ class QuantileQuantizedType
601606
/// Represents per-axis QuantileQuantizedType (also known as per-channel
602607
/// quantization). The type of the data in the look up table is determined by
603608
/// the quantileType member: supported quantileType types are
604-
/// integer/unsigned/hf8/bf8/f16/bf16/f32/f64.
609+
/// integer/unsigned/f4/hf8/bf8/f16/bf16/f32/f64.
605610
///
606611
/// Syntax synopsis:
607612
/// Per-axis, all parameters expressed:
608613
/// !quant<quantile[StorageType:QuantileType:ExpressedType:QuantizedDim]{Quantiles}:{QuantParams}>
609614
/// Per-axis, optional parameters omitted:
610615
/// !quant<quantile[StorageType:QuantileType]{Quantiles}:{Scale}>
611616
///
612-
/// StorageType: 'i'|'u' NumBits
613-
/// QuantileType: 'i'|'u' NumBits, 'hf8', 'bf8', 'f16', 'bf16', 'f32', 'f64'
614-
/// ExpressedType: 'f16', 'f32', 'bf16', 'f64'
615-
/// QuantizedDim: An integer value
616-
/// Quantiles: Quantile+
617-
/// Quantile: A legal double value
618-
/// QuantParams: (Scale ':' ZeroPoint)+
619-
/// Scale: A legal double value
620-
/// ZeroPoint: An integer value
617+
/// StorageType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8'
618+
/// QuantileType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8', 'f16', 'bf16', 'f32',
619+
/// 'f64' ExpressedType: 'f16', 'f32', 'bf16', 'f64' QuantizedDim: An integer
620+
/// value Quantiles: Quantile+ Quantile: A legal double value QuantParams:
621+
/// (Scale ':' ZeroPoint)+ Scale: A legal double value ZeroPoint: An integer
622+
/// value
621623
class QuantileQuantizedPerAxisType
622624
: public Type::TypeBase<QuantileQuantizedPerAxisType,
623625
UniformQuantizedPerAxisType,

mlir/lib/Dialect/Quant/IR/QuantTypes.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,18 @@ QuantizedType::verifyInvariants(function_ref<InFlightDiagnostic()> emitError,
6464
const auto width = llvm::dyn_cast<IntegerType>(storageType).getWidth();
6565
defaultMin = QuantizedType::getDefaultMinimumForInteger(isSigned, width);
6666
defaultMax = QuantizedType::getDefaultMaximumForInteger(isSigned, width);
67-
} else if (storageType.isa<Float8E5M2Type>()) {
67+
} else if (mlir::isa<Float8E5M2Type>(storageType)) {
6868
defaultMin = QuantizedType::getDefaultMinimumForF8E5M2();
6969
defaultMax = QuantizedType::getDefaultMaximumForF8E5M2();
70-
} else if (storageType.isa<Float8E4M3FNType>()) {
70+
} else if (mlir::isa<Float8E4M3FNType>(storageType)) {
7171
defaultMin = QuantizedType::getDefaultMinimumForF8E4M3FN();
7272
defaultMax = QuantizedType::getDefaultMaximumForF8E4M3FN();
73+
} else if (mlir::isa<Float4E2M1FNType>(storageType)) {
74+
defaultMin = QuantizedType::getDefaultMinimumForF4E2M1FN();
75+
defaultMax = QuantizedType::getDefaultMaximumForF4E2M1FN();
7376
} else {
7477
return emitError() << "illegal storage type, supported types are: integral "
75-
"types, Float8E4M3FNType and Float8E5M2Type ";
78+
"types, Float8E4M3FNType, Float8E5M2Type and Float4E2M1FNType ";
7679
}
7780

7881
// Verify storageTypeMin and storageTypeMax.
@@ -571,19 +574,18 @@ LogicalResult QuantileQuantizedType::verifyInvariants(
571574
unsigned typeWidth{};
572575
if (storageType.isa<IntegerType>()) {
573576
typeWidth = llvm::dyn_cast<IntegerType>(storageType).getWidth();
574-
} else if (storageType.isa<Float8E5M2Type>() ||
575-
storageType.isa<Float8E4M3FNType>()) {
576-
// Both Float8E5M2Type and Float8E4M3FNType derive from FloatType.
577+
} else if (mlir::isa<Float8E5M2Type, Float8E4M3FNType, Float4E2M1FNType>(storageType)) {
578+
// Float8E5M2Type, Float8E4M3FNType and Float4E2M1FNType derive from FloatType.
577579
typeWidth = llvm::dyn_cast<FloatType>(storageType).getWidth();
578580
} else {
579581
return emitError() << "illegal storage type, supported types are: integral "
580-
"types, Float8E4M3FNType and Float8E5M2Type ";
582+
"types, Float8E4M3FNType, Float8E5M2Type and Float4E2M1FNType ";
581583
}
582584

583585
const size_t storageTypeRange = storageTypeMax - storageTypeMin + 1;
584586
const size_t typeWidthSize = 1 << typeWidth;
585587
const size_t expectedSize =
586-
(storageTypeRange < typeWidthSize) ? storageTypeRange : typeWidthSize;
588+
(storageTypeRange < typeWidthSize) && !mlir::isa<FloatType>(storageType) ? storageTypeRange : typeWidthSize;
587589

588590
const auto quantileArraySize = quantiles.size();
589591
if (quantileArraySize != expectedSize) {
@@ -657,19 +659,18 @@ LogicalResult QuantileQuantizedPerAxisType::verifyInvariants(
657659
unsigned typeWidth{};
658660
if (storageType.isa<IntegerType>()) {
659661
typeWidth = llvm::dyn_cast<IntegerType>(storageType).getWidth();
660-
} else if (storageType.isa<Float8E5M2Type>() ||
661-
storageType.isa<Float8E4M3FNType>()) {
662-
// Both Float8E5M2Type and Float8E4M3FNType derive from FloatType.
662+
} else if (mlir::isa<Float8E5M2Type, Float8E4M3FNType, Float4E2M1FNType>(storageType)) {
663+
// Float8E5M2Type, Float8E4M3FNType and Float4E2M1FNType derive from FloatType.
663664
typeWidth = llvm::dyn_cast<FloatType>(storageType).getWidth();
664665
} else {
665666
return emitError() << "illegal storage type, supported types are: integral "
666-
"types, Float8E4M3FNType and Float8E5M2Type ";
667+
"types, Float8E4M3FNType, Float8E5M2Type and Float4E2M1FNType ";
667668
}
668669

669670
const size_t storageTypeRange = storageTypeMax - storageTypeMin + 1;
670671
const size_t typeWidthSize = 1 << typeWidth;
671672
const size_t expectedSize =
672-
(storageTypeRange < typeWidthSize) ? storageTypeRange : typeWidthSize;
673+
(storageTypeRange < typeWidthSize) && !mlir::isa<FloatType>(storageType) ? storageTypeRange : typeWidthSize;
673674

674675
const auto quantileArraySize = quantiles.size();
675676
if (quantileArraySize != expectedSize) {

mlir/lib/Dialect/Quant/IR/TypeParser.cpp

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ static Type parseStorageType(DialectAsmParser &parser, bool &isSigned) {
3535
if (auto intType = llvm::dyn_cast<IntegerType>(type)) {
3636
isSigned = !intType.isUnsigned();
3737
storageTypeWidth = intType.getWidth();
38-
} else if (llvm::dyn_cast<Float8E5M2Type>(type) ||
39-
llvm::dyn_cast<Float8E4M3FNType>(type)) {
40-
storageTypeWidth = 8;
38+
} else if (mlir::isa<Float8E5M2Type, Float8E4M3FNType, Float4E2M1FNType>(
39+
type)) {
40+
storageTypeWidth = llvm::dyn_cast<FloatType>(type).getWidth();
4141
isSigned = true;
4242
} else {
4343
parser.emitError(typeLoc, "illegal quantized storage type alias");
@@ -132,12 +132,15 @@ static ParseResult parseStorageRange(DialectAsmParser &parser, Type storageType,
132132
const auto width = llvm::dyn_cast<IntegerType>(storageType).getWidth();
133133
defaultMin = QuantizedType::getDefaultMinimumForInteger(isSigned, width);
134134
defaultMax = QuantizedType::getDefaultMaximumForInteger(isSigned, width);
135-
} else if (storageType.isa<Float8E5M2Type>()) {
135+
} else if (mlir::isa<Float8E5M2Type>(storageType)) {
136136
defaultMin = QuantizedType::getDefaultMinimumForF8E5M2();
137137
defaultMax = QuantizedType::getDefaultMaximumForF8E5M2();
138-
} else if (storageType.isa<Float8E4M3FNType>()) {
138+
} else if (mlir::isa<Float8E4M3FNType>(storageType)) {
139139
defaultMin = QuantizedType::getDefaultMinimumForF8E4M3FN();
140140
defaultMax = QuantizedType::getDefaultMaximumForF8E4M3FN();
141+
} else if (mlir::isa<Float4E2M1FNType>(storageType)) {
142+
defaultMin = QuantizedType::getDefaultMinimumForF4E2M1FN();
143+
defaultMax = QuantizedType::getDefaultMaximumForF4E2M1FN();
141144
} else {
142145
defaultMin = std::numeric_limits<int64_t>::max();
143146
defaultMax = std::numeric_limits<int64_t>::min();
@@ -150,7 +153,7 @@ static ParseResult parseStorageRange(DialectAsmParser &parser, Type storageType,
150153
}
151154

152155
// Explicit storage min and storage max.
153-
// F8 min and max values are integers, so parseInteger() is used.
156+
// F8 and F4 min and max values are integers, so parseInteger() is used.
154157
SMLoc minLoc = parser.getCurrentLocation(), maxLoc;
155158
if (parser.parseInteger(storageTypeMin) || parser.parseColon() ||
156159
parser.getCurrentLocation(&maxLoc) ||
@@ -382,15 +385,12 @@ parseQuantParamListUntilRBrace(DialectAsmParser &parser, Type expressedType,
382385
/// block-size-info `,` scale-zero-tensor `>`
383386
/// storage-spec ::= storage-type (`<` storage-range `>`)?
384387
/// storage-range ::= integer-literal `:` integer-literal
385-
/// storage-type ::= (`i` | `u`) integer-literal
386-
/// expressed-type-spec ::= `:` `f` integer-literal
387-
/// axis-spec ::= `:` integer-literal
388-
/// scale-zero ::= scale (`:` zero-point)?
389-
/// scale ::= float-literal
390-
/// zero-point ::= integer-literal
391-
/// scale-zero-list ::= scale-zero (`,` scale-zero)*
392-
/// block-size-info ::= `{` `}` | `{` axis-block `:` (`,` axis-block)* `}`
393-
/// axis-block ::= axis-spec `:` block-size-spec
388+
/// storage-type ::= (`i` | `u`) integer-literal | `f8E5M2` | `f8E4M3FN` |
389+
/// `f4E2M1FN` expressed-type-spec ::= `:` `f` integer-literal axis-spec ::=
390+
/// `:` integer-literal scale-zero ::= scale (`:` zero-point)? scale ::=
391+
/// float-literal zero-point ::= integer-literal scale-zero-list ::=
392+
/// scale-zero (`,` scale-zero)* block-size-info ::= `{` `}` | `{` axis-block
393+
/// `:` (`,` axis-block)* `}` axis-block ::= axis-spec `:` block-size-spec
394394
/// block-size-spec ::= integer-literal
395395
/// scale-zero-tensor ::= scale-zero-dense-exp | scale-zero-list
396396
/// scale-zero-dense-exp ::= `{`
@@ -407,9 +407,10 @@ parseQuantParamListUntilRBrace(DialectAsmParser &parser, Type expressedType,
407407
/// scale-zero-list `>`
408408
/// storage-spec ::= storage-type (`<` storage-range `>`)?
409409
/// storage-range ::= integer-literal `:` integer-literal
410-
/// storage-type ::= (`i` | `u`) integer-literal
411-
/// quantile-type-spec ::= `:` ((`i` | `u` | `f`) integer-literal | `f8E5M2` |
412-
/// `f8E4M3FN`)
410+
/// storage-type ::= (`i` | `u`) integer-literal | `f8E5M2` | `f8E4M3FN` |
411+
/// `f4E2M1FN` quantile-type-spec ::= `:` ((`i` | `u` | `f`) integer-literal |
412+
/// `f8E5M2` |
413+
/// `f8E4M3FN` | `f4E2M1FN`)
413414
/// expressed-type-spec ::= `:` `f` integer-literal axis-spec ::=
414415
/// `:` integer-literal quantiles-list ::= `{` quantile (`,` quantile)* `}`
415416
/// scale-zero ::= `:` float-literal `:` integer-literal
@@ -641,6 +642,8 @@ static void printStorageType(QuantizedType type, DialectAsmPrinter &out) {
641642
out << "f8E5M2";
642643
} else if (type.getStorageType().isa<Float8E4M3FNType>()) {
643644
out << "f8E4M3FN";
645+
} else if (type.getStorageType().isa<Float4E2M1FNType>()) {
646+
out << "f4E2M1FN";
644647
} else if (isSigned) {
645648
out << "i" << storageWidth;
646649
} else {
@@ -655,6 +658,8 @@ static void printStorageType(QuantizedType type, DialectAsmPrinter &out) {
655658
? QuantizedType::getDefaultMinimumForF8E5M2()
656659
: type.getStorageType().isa<Float8E4M3FNType>()
657660
? QuantizedType::getDefaultMinimumForF8E4M3FN()
661+
: type.getStorageType().isa<Float4E2M1FNType>()
662+
? QuantizedType::getDefaultMinimumForF4E2M1FN()
658663
: std::numeric_limits<int64_t>::max();
659664

660665
int64_t defaultMax =
@@ -664,6 +669,8 @@ static void printStorageType(QuantizedType type, DialectAsmPrinter &out) {
664669
? QuantizedType::getDefaultMaximumForF8E5M2()
665670
: type.getStorageType().isa<Float8E4M3FNType>()
666671
? QuantizedType::getDefaultMaximumForF8E4M3FN()
672+
: type.getStorageType().isa<Float4E2M1FNType>()
673+
? QuantizedType::getDefaultMaximumForF4E2M1FN()
667674
: std::numeric_limits<int64_t>::min();
668675

669676
if (defaultMin != type.getStorageTypeMin() ||
@@ -685,6 +692,8 @@ static void printQuantileType(Type quantileType, DialectAsmPrinter &out) {
685692
out << ":f8E5M2";
686693
} else if (quantileType.isa<Float8E4M3FNType>()) {
687694
out << ":f8E4M3FN";
695+
} else if (quantileType.isa<Float4E2M1FNType>()) {
696+
out << ":f4E2M1FN";
688697
} else {
689698
// Float types
690699
out << ":" << quantileType;

mlir/test/Dialect/Quant/parse-quantile-invalid.mlir

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ func.func @parse() -> !qalias {
126126
// expected-error@+1 {{illegal storage type minimum: -500}}
127127
!qalias = !quant.quantile<f8E4M3FN<-500:448>:f16:f32, {-1.0,1.0}:0.99872:127>
128128

129+
// -----
130+
// Illegal storage min/max: max > defaultMax
131+
// expected-error@+1 {{illegal storage type maximum: 10}}
132+
!qalias = !quant.quantile<f4E2M1FN<-6:10>:f16:f32, {-1.0,1.0}:0.99872:127>
133+
134+
// -----
135+
// Illegal storage min/max: min < defaultMin
136+
// expected-error@+1 {{illegal storage type minimum: -10}}
137+
!qalias = !quant.quantile<f4E2M1FN<-10:6>:f16:f32, {-1.0,1.0}:0.99872:127>
138+
129139
// -----
130140
// Illegal uniform params: invalid scale
131141
// expected-error@+1 {{expected floating point literal}}

mlir/test/Dialect/Quant/parse-quantile.mlir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ func.func @parse() -> !qalias {
4646
return %0 : !qalias
4747
}
4848

49+
// -----
50+
// Default min/max value optimization for f4E2M1FN.
51+
// CHECK: !quant.quantile<f4E2M1FN:f16:f32, {-1.000000e+00,-8.667000e-01,-7.333000e-01,-6.000000e-01,-4.667000e-01,-3.333000e-01,-2.000000e-01,-0.066699999999999995,0.066699999999999995,2.000000e-01,3.333000e-01,4.667000e-01,6.000000e-01,7.333000e-01,8.667000e-01,1.000000e+00}:9.987200e-01:127>
52+
!qalias = !quant.quantile<f4E2M1FN<-6:6>:f16:f32, {-1.0000,-0.8667,-0.7333,-0.6000,-0.4667,-0.3333,-0.2000,-0.0667,0.0667,0.2000,0.3333,0.4667,0.6000,0.7333,0.8667,1.0000}:0.99872:127 >
53+
func.func @parse() -> !qalias {
54+
%0 = "foo"() : () -> !qalias
55+
return %0 : !qalias
56+
}
57+
4958
// -----
5059
// Required per-layer params specified:
5160
// [unsigned] storageType, expressedType, scale
@@ -92,6 +101,15 @@ func.func @parse() -> !qalias {
92101
return %0 : !qalias
93102
}
94103

104+
// -----
105+
// Storage type: f4E2M1FN
106+
// CHECK: !quant.quantile<f4E2M1FN:f16:f32, {-1.000000e+00,-8.667000e-01,-7.333000e-01,-6.000000e-01,-4.667000e-01,-3.333000e-01,-2.000000e-01,-0.066699999999999995,0.066699999999999995,2.000000e-01,3.333000e-01,4.667000e-01,6.000000e-01,7.333000e-01,8.667000e-01,1.000000e+00}:2.000000e+02>
107+
!qalias = !quant.quantile<f4E2M1FN:f16:f32, {-1.0000,-0.8667,-0.7333,-0.6000,-0.4667,-0.3333,-0.2000,-0.0667,0.0667,0.2000,0.3333,0.4667,0.6000,0.7333,0.8667,1.0000}:2.0e+2>
108+
func.func @parse() -> !qalias {
109+
%0 = "foo"() : () -> !qalias
110+
return %0 : !qalias
111+
}
112+
95113
// -----
96114
// Expressed type: f32
97115
// CHECK: !quant.quantile<u4:f16:f32, {-1.000000e+00,-8.667000e-01,-7.333000e-01,-6.000000e-01,-4.667000e-01,-3.333000e-01,-2.000000e-01,-0.066699999999999995,0.066699999999999995,2.000000e-01,3.333000e-01,4.667000e-01,6.000000e-01,7.333000e-01,8.667000e-01,1.000000e+00}:2.000000e+02>

mlir/test/Dialect/Quant/parse-uniform-invalid.mlir

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@
100100
// expected-error@+1 {{illegal storage type minimum: -500}}
101101
!qalias = !quant.uniform<f8E4M3FN<-500:448>:f32, 0.99872:127>
102102

103+
// -----
104+
// Illegal storage min/max: max > defaultMax
105+
// expected-error@+1 {{illegal storage type maximum: 10}}
106+
!qalias = !quant.uniform<f4E2M1FN<-6:10>:f32, 0.99872:127>
107+
108+
// -----
109+
// Illegal storage min/max: min < defaultMin
110+
// expected-error@+1 {{illegal storage type minimum: -10}}
111+
!qalias = !quant.uniform<f4E2M1FN<-10:6>:f32, 0.99872:127>
112+
103113
// -----
104114
// Illegal uniform params: invalid scale
105115
// expected-error@+1 {{expected floating point literal}}

mlir/test/Dialect/Quant/parse-uniform.mlir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ func.func @parse() -> !qalias {
4646
return %0 : !qalias
4747
}
4848

49+
// -----
50+
// Default min/max value optimization for f4E2M1FN.
51+
// CHECK: !quant.uniform<f4E2M1FN:f32, 9.987200e-01:127>
52+
!qalias = !quant.uniform<f4E2M1FN<-6:6>:f32, 0.99872:127 >
53+
func.func @parse() -> !qalias {
54+
%0 = "foo"() : () -> !qalias
55+
return %0 : !qalias
56+
}
57+
4958
// -----
5059
// Required per-layer params specified:
5160
// [unsigned] storageType, expressedType, scale
@@ -92,6 +101,15 @@ func.func @parse() -> !qalias {
92101
return %0 : !qalias
93102
}
94103

104+
// -----
105+
// Storage type: f4E2M1FN
106+
// CHECK: !quant.uniform<f4E2M1FN:f32, 2.000000e+02>
107+
!qalias = !quant.uniform<f4E2M1FN:f32, 2.0e+2>
108+
func.func @parse() -> !qalias {
109+
%0 = "foo"() : () -> !qalias
110+
return %0 : !qalias
111+
}
112+
95113
// -----
96114
// Storage type: i16
97115
// CHECK: !quant.uniform<i16:f32, 2.000000e+02>

0 commit comments

Comments
 (0)