Simplify and enable pretty-parsing/printing of the uniform quantized types.

The per-layer format is now like:
      !quant.uniform<i8<-8:7>:f32, 9.987200e-01:127>
    and per-axis is:
      !quant.uniform<i8:f32:1, {2.0e+2,0.99872:120}>

    I used the following sed script to update the unit tests (invoked with commands like `sed -i -r -f fix_quant.sed $(find . -name '*.mlir')`).
    ---
    # Per-layer
    s|\!quant<"uniform\[([iu][0-9]+):([fb]+[0-9]+)\]\{([^\}]+)\}\s*">|!quant.uniform<\1:\2, \3>|g
    s|\!quant<"uniform\[([iu][0-9]+)\(([^\)]+)\):([fb]+[0-9]+)\]\{([^\}]+)\}\s*">|!quant.uniform<\1<\2>:\3, \4>|g

    # Per-axis
    s|\!quant<"uniform\[([iu][0-9]+):([fb]+[0-9]+)(:[0-9]+)?\]\{([^\}]+)\}\s*">|!quant.uniform<\1:\2\3, {\4}>|g
    s|\!quant<"uniform\[([iu][0-9]+)\(([^\)]+)\):([fb]+[0-9]+)(:[0-9]+)?\]\{([^\}]+)\}\s*">|!quant.uniform<\1<\2>:\3\4, {\5}>|g
    ---
    I fixed up the one file of error cases manually.
    Since this is a one time syntax fix, I am not persisting the script anywhere.

--

PiperOrigin-RevId: 244425331
This commit is contained in:
Stella Laurenzo 2019-04-19 14:41:31 -07:00 committed by Mehdi Amini
parent 0b47f74037
commit 4292294a65
9 changed files with 192 additions and 204 deletions

View File

@ -752,11 +752,11 @@ static bool isDialectTypeSimpleEnoughForPrettyForm(StringRef typeName) {
return false;
break;
case ')':
if (nestedPunctuation.pop_back_val() != ')')
if (nestedPunctuation.pop_back_val() != '(')
return false;
break;
case '}':
if (nestedPunctuation.pop_back_val() != '}')
if (nestedPunctuation.pop_back_val() != '{')
return false;
break;
default:

View File

@ -67,12 +67,10 @@ namespace {
enum class TokenKind {
error,
eof,
l_bracket,
r_bracket,
l_brace,
r_brace,
l_paren,
r_paren,
l_angle,
r_angle,
colon,
comma,
alpha_ident,
@ -144,18 +142,14 @@ Token Lexer::lexToken() {
return emitError(tokStart, "unexpected character");
case '[':
return formToken(TokenKind::l_bracket, tokStart);
case ']':
return formToken(TokenKind::r_bracket, tokStart);
case '<':
return formToken(TokenKind::l_angle, tokStart);
case '>':
return formToken(TokenKind::r_angle, tokStart);
case '{':
return formToken(TokenKind::l_brace, tokStart);
case '}':
return formToken(TokenKind::r_brace, tokStart);
case '(':
return formToken(TokenKind::l_paren, tokStart);
case ')':
return formToken(TokenKind::r_paren, tokStart);
case ':':
return formToken(TokenKind::colon, tokStart);
case ',':
@ -312,17 +306,17 @@ Type TypeParser::parseType() {
/// Parses a UniformQuantizedType.
///
/// uniform_type ::= `uniform` type_spec quant_param_spec
///
/// type_spec ::= `[` storage-spec `:` expressed-type (quant-dim)? `]`
/// quant-dim ::= `:` integer-literal
/// storage-spec ::= storage-type (`(` storage-range `)`)?
/// uniform_type ::= uniform_per_layer
/// | uniform_per_axis
/// uniform_per_layer ::= `uniform<` storage-spec `,` scale-zero `>`
/// uniform_per_axis ::= `uniform<` storage-spec axis-spec
/// `,` scale-zero-list `>`
/// storage-spec ::= storage-type (`<` storage-range `>`)?
/// storage-range ::= integer-literal `:` integer-literal
/// storage-type ::= (`i` | `u`) integer-literal
/// expressed-type ::= (`f16` | `f32` | `f64` | `bf16`)
///
/// quant_param_spec ::= `{` scale-zero (`,` scale-zero )* `}`
/// axis-spec ::= `:` integer-literal
/// scale-zero ::= float-literal `:` integer-literal
/// scale-zero-list ::= `{` scale-zero (`,` scale-zero)* `}`
Type TypeParser::parseUniformType() {
IntegerType storageType;
FloatType expressedType;
@ -335,7 +329,7 @@ Type TypeParser::parseUniformType() {
SmallVector<int64_t, 1> zeroPoints;
// Type specification.
if (!consumeIf(TokenKind::l_bracket)) {
if (!consumeIf(TokenKind::l_angle)) {
return (emitError("unrecognized token: " + curToken.spelling), nullptr);
}
@ -354,7 +348,7 @@ Type TypeParser::parseUniformType() {
isSigned, storageType.getWidth());
int64_t defaultIntegerMax = QuantizedType::getDefaultMaxinumForInteger(
isSigned, storageType.getWidth());
if (consumeIf(TokenKind::l_paren)) {
if (consumeIf(TokenKind::l_angle)) {
// Explicit storage min and storage max.
if (curToken.kind != TokenKind::integer_literal) {
return (emitError("expected storage type minimum"), nullptr);
@ -380,7 +374,7 @@ Type TypeParser::parseUniformType() {
}
consumeToken(TokenKind::integer_literal);
if (!consumeIf(TokenKind::r_paren)) {
if (!consumeIf(TokenKind::r_angle)) {
return (emitError("unrecognized token: " + curToken.spelling), nullptr);
}
} else {
@ -410,13 +404,17 @@ Type TypeParser::parseUniformType() {
isPerAxis = true;
}
if (!consumeIf(TokenKind::r_bracket)) {
// Comma leading into range_spec.
if (!consumeIf(TokenKind::comma)) {
return (emitError("unrecognized token: " + curToken.spelling), nullptr);
}
// Parameter specification.
if (!consumeIf(TokenKind::l_brace)) {
return (emitError("unrecognized token: " + curToken.spelling), nullptr);
// For per-axis, ranges are in a {} delimitted list.
if (isPerAxis) {
if (!consumeIf(TokenKind::l_brace)) {
return (emitError("unrecognized token: " + curToken.spelling), nullptr);
}
}
// Parse scales/zeroPoints.
@ -426,9 +424,15 @@ Type TypeParser::parseUniformType() {
if (parseQuantParams(scales.back(), zeroPoints.back())) {
return nullptr;
}
} while (consumeIf(TokenKind::comma));
} while (isPerAxis && consumeIf(TokenKind::comma));
if (!consumeIf(TokenKind::r_brace)) {
if (isPerAxis) {
if (!consumeIf(TokenKind::r_brace)) {
return (emitError("unrecognized token: " + curToken.spelling), nullptr);
}
}
if (!consumeIf(TokenKind::r_angle)) {
return (emitError("unrecognized token: " + curToken.spelling), nullptr);
}
@ -567,8 +571,8 @@ static void printStorageType(QuantizedType type, raw_ostream &out) {
QuantizedType::getDefaultMaxinumForInteger(isSigned, storageWidth);
if (defaultIntegerMin != type.getStorageTypeMin() ||
defaultIntegerMax != type.getStorageTypeMax()) {
out << "(" << type.getStorageTypeMin() << ":" << type.getStorageTypeMax()
<< ")";
out << "<" << type.getStorageTypeMin() << ":" << type.getStorageTypeMax()
<< ">";
}
}
@ -599,28 +603,27 @@ static void printQuantParams(double scale, int64_t zeroPoint,
/// Helper that prints a UniformQuantizedType.
static void printUniformQuantizedType(UniformQuantizedType type,
raw_ostream &out) {
out << "uniform[";
out << "uniform<";
printStorageType(type, out);
out << ":";
printExpressedType(type, out);
out << "]";
out << ", ";
// scheme specific parameters
out << "{";
printQuantParams(type.getScale(), type.getZeroPoint(), out);
out << "}";
out << ">";
}
/// Helper that prints a UniformQuantizedPerAxisType.
static void printUniformQuantizedPerAxisType(UniformQuantizedPerAxisType type,
raw_ostream &out) {
out << "uniform[";
out << "uniform<";
printStorageType(type, out);
out << ":";
printExpressedType(type, out);
out << ":";
out << type.getQuantizedDimension();
out << "]";
out << ", ";
// scheme specific parameters
ArrayRef<double> scales = type.getScales();
@ -632,7 +635,7 @@ static void printUniformQuantizedPerAxisType(UniformQuantizedPerAxisType type,
out << ",";
}
}
out << "}";
out << "}>";
}
/// Print a type registered to this dialect.

View File

@ -3,19 +3,19 @@
// -----
// Verify lowering when operands and result have the same fixedpoint scale.
// CHECK-LABEL: real_addew_fixedpoint_isomorphic
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
func @real_addew_fixedpoint_isomorphic(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK-NEXT: %0 = "quant.scast"(%arg0) : (tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>) -> tensor<4xi8>
// CHECK-NEXT: %0 = "quant.scast"(%arg0) : (tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>) -> tensor<4xi8>
// CHECK-NEXT: %2 = "fxpmath.convertis"(%0) : (tensor<4xi8>) -> tensor<4xi16>
// CHECK-NEXT: %3 = "fxpmath.convertis"(%1) : (tensor<4xi8>) -> tensor<4xi16>
// CHECK-NEXT: %4 = addi %2, %3 : tensor<4xi16>
// CHECK-NEXT: %5 = "fxpmath.clampis"(%4) {clamp_max: 127 : i16, clamp_min: -128 : i16} : (tensor<4xi16>) -> tensor<4xi16>
// CHECK-NEXT: %6 = "fxpmath.convertis"(%5) : (tensor<4xi16>) -> tensor<4xi8>
// CHECK-NEXT: %7 = "quant.scast"(%6) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>
// CHECK-NEXT: return %7 : tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>
// CHECK-NEXT: %7 = "quant.scast"(%6) : (tensor<4xi8>) -> tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>
// CHECK-NEXT: return %7 : tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>
%0 = "fxpmath.real_add_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)
return %0 : !type_result
}
@ -24,21 +24,21 @@ func @real_addew_fixedpoint_isomorphic(%arg0 : !type_lhs, %arg1: !type_rhs) -> !
// Verify lowering when operands and result have the same fixedpoint scale
// and non-zero zero points.
// CHECK-LABEL: real_addew_affine_isomorphic
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2:-5}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2:-5}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2:-5}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2:-5>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2:-5>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2:-5>>
func @real_addew_affine_isomorphic(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK-NEXT: %cst = constant splat<tensor<4xi16>, 5> : tensor<4xi16>
// CHECK-NEXT: %0 = "quant.scast"(%arg0) : (tensor<4x!quant<"uniform[i8:f32]{6.250000e-02:-5}">>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant<"uniform[i8:f32]{6.250000e-02:-5}">>) -> tensor<4xi8>
// CHECK-NEXT: %0 = "quant.scast"(%arg0) : (tensor<4x!quant.uniform<i8:f32, 6.250000e-02:-5>>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant.uniform<i8:f32, 6.250000e-02:-5>>) -> tensor<4xi8>
// CHECK-NEXT: %2 = "fxpmath.convertis"(%0) : (tensor<4xi8>) -> tensor<4xi16>
// CHECK-NEXT: %3 = "fxpmath.convertis"(%1) : (tensor<4xi8>) -> tensor<4xi16>
// CHECK-NEXT: %4 = addi %2, %3 : tensor<4xi16>
// CHECK-NEXT: %5 = addi %4, %cst : tensor<4xi16>
// CHECK-NEXT: %6 = "fxpmath.clampis"(%5) {clamp_max: 127 : i16, clamp_min: -128 : i16} : (tensor<4xi16>) -> tensor<4xi16>
// CHECK-NEXT: %7 = "fxpmath.convertis"(%6) : (tensor<4xi16>) -> tensor<4xi8>
// CHECK-NEXT: %8 = "quant.scast"(%7) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[i8:f32]{6.250000e-02:-5}">>
// CHECK-NEXT: return %8 : tensor<4x!quant<"uniform[i8:f32]{6.250000e-02:-5}">>
// CHECK-NEXT: %8 = "quant.scast"(%7) : (tensor<4xi8>) -> tensor<4x!quant.uniform<i8:f32, 6.250000e-02:-5>>
// CHECK-NEXT: return %8 : tensor<4x!quant.uniform<i8:f32, 6.250000e-02:-5>>
%0 = "fxpmath.real_add_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)
return %0 : !type_result
}
@ -47,19 +47,19 @@ func @real_addew_affine_isomorphic(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type
// The RHS quant parameters proscribe a range of [-8..8) so an explicit clamp
// of [-4..4] should result in an integral clamp range of [-64..64].
// CHECK-LABEL: real_addew_fixedpoint_clamp
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
func @real_addew_fixedpoint_clamp(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK-NEXT: %0 = "quant.scast"(%arg0) : (tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>) -> tensor<4xi8>
// CHECK-NEXT: %0 = "quant.scast"(%arg0) : (tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>) -> tensor<4xi8>
// CHECK-NEXT: %2 = "fxpmath.convertis"(%0) : (tensor<4xi8>) -> tensor<4xi16>
// CHECK-NEXT: %3 = "fxpmath.convertis"(%1) : (tensor<4xi8>) -> tensor<4xi16>
// CHECK-NEXT: %4 = addi %2, %3 : tensor<4xi16>
// CHECK-NEXT: %5 = "fxpmath.clampis"(%4) {clamp_max: 64 : i16, clamp_min: -64 : i16} : (tensor<4xi16>) -> tensor<4xi16>
// CHECK-NEXT: %6 = "fxpmath.convertis"(%5) : (tensor<4xi16>) -> tensor<4xi8>
// CHECK-NEXT: %7 = "quant.scast"(%6) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>
// CHECK-NEXT: return %7 : tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>
// CHECK-NEXT: %7 = "quant.scast"(%6) : (tensor<4xi8>) -> tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>
// CHECK-NEXT: return %7 : tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>
%0 = "fxpmath.real_add_ew"(%arg0, %arg1) { clamp_min:-4.0, clamp_max:4.0 }
: (!type_lhs, !type_rhs) -> (!type_result)
return %0 : !type_result
@ -69,8 +69,8 @@ func @real_addew_fixedpoint_clamp(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_
// CHECK-LABEL: real_addew_unquantized_lhs
// Verifies that leaves as-is for unquantized lhs.
!type_lhs = type tensor<4xf32>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
func @real_addew_unquantized_lhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK: %0 = "fxpmath.real_add_ew"(%arg0, %arg1)
%0 = "fxpmath.real_add_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)
@ -80,9 +80,9 @@ func @real_addew_unquantized_lhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_r
// -----
// CHECK-LABEL: real_addew_unquantized_rhs
// Verifies that leaves as-is for unquantized rhs.
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4xf32>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
func @real_addew_unquantized_rhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK: %0 = "fxpmath.real_add_ew"(%arg0, %arg1)
%0 = "fxpmath.real_add_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)
@ -92,8 +92,8 @@ func @real_addew_unquantized_rhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_r
// -----
// CHECK-LABEL: real_addew_unquantized_result
// Verifies that leaves as-is for unquantized result.
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_result = type tensor<4xf32>
func @real_addew_unquantized_result(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK: %0 = "fxpmath.real_add_ew"(%arg0, %arg1)

View File

@ -3,12 +3,12 @@
// -----
// Verify lowering when operands and result have the same fixedpoint scale.
// CHECK-LABEL: real_mulew_fixedpoint
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{3.875e-2}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{1.065e-1}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 3.875e-2>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 1.065e-1>>
func @real_mulew_fixedpoint(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK: %0 = "quant.scast"(%arg0) : (tensor<4x!quant<"uniform[i8:f32]{6.250000e-02}">>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant<"uniform[i8:f32]{3.875000e-02}">>) -> tensor<4xi8>
// CHECK: %0 = "quant.scast"(%arg0) : (tensor<4x!quant.uniform<i8:f32, 6.250000e-02>>) -> tensor<4xi8>
// CHECK-NEXT: %1 = "quant.scast"(%arg1) : (tensor<4x!quant.uniform<i8:f32, 3.875000e-02>>) -> tensor<4xi8>
// CHECK-NEXT: %2 = "fxpmath.convertis"(%0) : (tensor<4xi8>) -> tensor<4xi32>
// CHECK-NEXT: %3 = "fxpmath.convertis"(%1) : (tensor<4xi8>) -> tensor<4xi32>
// CHECK-NEXT: %4 = muli %2, %3 : tensor<4xi32>
@ -16,8 +16,8 @@ func @real_mulew_fixedpoint(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result
// CHECK-NEXT: %6 = "fxpmath.rounding_divide_by_potis"(%5) {exponent: 5 : i32} : (tensor<4xi32>) -> tensor<4xi32>
// CHECK-NEXT: %7 = "fxpmath.clampis"(%6) {clamp_max: 127 : i32, clamp_min: -128 : i32} : (tensor<4xi32>) -> tensor<4xi32>
// CHECK-NEXT: %8 = "fxpmath.convertis"(%7) : (tensor<4xi32>) -> tensor<4xi8>
// CHECK-NEXT: %9 = "quant.scast"(%8) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[i8:f32]{1.065000e-01}">>
// CHECK-NEXT: return %9 : tensor<4x!quant<"uniform[i8:f32]{1.065000e-01}">>
// CHECK-NEXT: %9 = "quant.scast"(%8) : (tensor<4xi8>) -> tensor<4x!quant.uniform<i8:f32, 1.065000e-01>>
// CHECK-NEXT: return %9 : tensor<4x!quant.uniform<i8:f32, 1.065000e-01>>
%0 = "fxpmath.real_mul_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)
return %0 : !type_result
}
@ -26,9 +26,9 @@ func @real_mulew_fixedpoint(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result
// Verify lowering when operands and result have the same fixedpoint scale
// and non-zero zero points.
// CHECK-LABEL: real_mulew_affine_clamp
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2:-3}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2:-5}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2:-9}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2:-3>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2:-5>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2:-9>>
func @real_mulew_affine_clamp(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// Just verify that the affine adds/constants and clamps are present.
// CHECK: %cst = constant splat<tensor<4xi32>, 3> : tensor<4xi32>
@ -47,8 +47,8 @@ func @real_mulew_affine_clamp(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_resu
// CHECK-LABEL: real_mulew_unquantized_lhs
// Verifies that leaves as-is for unquantized lhs.
!type_lhs = type tensor<4xf32>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
func @real_mulew_unquantized_lhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK: %0 = "fxpmath.real_mul_ew"(%arg0, %arg1)
%0 = "fxpmath.real_mul_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)
@ -58,9 +58,9 @@ func @real_mulew_unquantized_lhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_r
// -----
// CHECK-LABEL: real_mulew_unquantized_rhs
// Verifies that leaves as-is for unquantized rhs.
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4xf32>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_result = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
func @real_mulew_unquantized_rhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK: %0 = "fxpmath.real_mul_ew"(%arg0, %arg1)
%0 = "fxpmath.real_mul_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)
@ -70,8 +70,8 @@ func @real_mulew_unquantized_rhs(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_r
// -----
// CHECK-LABEL: real_mulew_unquantized_result
// Verifies that leaves as-is for unquantized result.
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_result = type tensor<4xf32>
func @real_mulew_unquantized_result(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// CHECK: %0 = "fxpmath.real_mul_ew"(%arg0, %arg1)
@ -84,9 +84,9 @@ func @real_mulew_unquantized_result(%arg0 : !type_lhs, %arg1: !type_rhs) -> !typ
// Note that the multiplier = lhs_scale * rhs_scale / result_scale
// = 22.740610328638496
// CHECK-LABEL: real_mulew_multiplier_gt_1
!type_lhs = type tensor<4x!quant<"uniform[i8:f32]{6.25e-2}">>
!type_rhs = type tensor<4x!quant<"uniform[i8:f32]{3.875e-2}">>
!type_result = type tensor<4x!quant<"uniform[i8:f32]{1.065e-4}">>
!type_lhs = type tensor<4x!quant.uniform<i8:f32, 6.25e-2>>
!type_rhs = type tensor<4x!quant.uniform<i8:f32, 3.875e-2>>
!type_result = type tensor<4x!quant.uniform<i8:f32, 1.065e-4>>
func @real_mulew_multiplier_gt_1(%arg0 : !type_lhs, %arg1: !type_rhs) -> !type_result {
// expected-warning@+1 {{unimplemented: cannot multiply with multipler > 1.0}}
%0 = "fxpmath.real_mul_ew"(%arg0, %arg1) : (!type_lhs, !type_rhs) -> (!type_result)

View File

@ -6,19 +6,19 @@ func @redundant_scast() -> tensor<4xi8> {
// CHECK-NEXT: constant splat<tensor<4xi8>, 10>
// CHECK-NEXT: return
%cst = constant splat<tensor<4xi8>, 5> : tensor<4xi8>
%1 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">>
%2 = "quant.scast"(%1) : (tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">>) -> tensor<4xi8>
%1 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>>
%2 = "quant.scast"(%1) : (tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>>) -> tensor<4xi8>
%3 = addi %2, %2 : tensor<4xi8>
return %3 : tensor<4xi8>
}
// -----
// CHECK-LABEL: non_redundant_scast
func @non_redundant_scast() -> tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">> {
func @non_redundant_scast() -> tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>> {
// CHECK-NEXT: constant splat<tensor<4xi8>, 5>
// CHECK-NEXT: scast
// CHECK-NEXT: return
%cst = constant splat<tensor<4xi8>, 5> : tensor<4xi8>
%1 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">>
return %1 : tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">>
%1 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>>
return %1 : tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>>
}

View File

@ -12,10 +12,10 @@
// CHECK-LABEL: constant_splat_tensor_u8_affine
func @constant_splat_tensor_u8_affine() -> tensor<4xf32> {
// CHECK: %cst = constant splat<tensor<4xi8>, -64> : tensor<4xi8>
// CHECK-NEXT: %0 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">>
// CHECK-NEXT: %0 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>>
%cst = constant splat<tensor<4xf32>, 0.5> : tensor<4xf32>
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">>
%2 = "quant.dcast"(%1) : (tensor<4x!quant<"uniform[u8:f32]{7.812500e-03:128}">>) -> (tensor<4xf32>)
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>>
%2 = "quant.dcast"(%1) : (tensor<4x!quant.uniform<u8:f32, 7.812500e-03:128>>) -> (tensor<4xf32>)
return %2 : tensor<4xf32>
}
@ -24,10 +24,10 @@ func @constant_splat_tensor_u8_affine() -> tensor<4xf32> {
// CHECK-LABEL: constant_splat_tensor_i8_affine
func @constant_splat_tensor_i8_affine() -> tensor<4xf32> {
// CHECK: %cst = constant splat<tensor<4xi8>, 63> : tensor<4xi8>
// CHECK-NEXT: %0 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[i8:f32]{7.812500e-03:-1}">>
// CHECK-NEXT: %0 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant.uniform<i8:f32, 7.812500e-03:-1>>
%cst = constant splat<tensor<4xf32>, 0.5> : tensor<4xf32>
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant<"uniform[i8:f32]{7.812500e-03:-1}">>
%2 = "quant.dcast"(%1) : (tensor<4x!quant<"uniform[i8:f32]{7.812500e-03:-1}">>) -> (tensor<4xf32>)
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant.uniform<i8:f32, 7.812500e-03:-1>>
%2 = "quant.dcast"(%1) : (tensor<4x!quant.uniform<i8:f32, 7.812500e-03:-1>>) -> (tensor<4xf32>)
return %2 : tensor<4xf32>
}
@ -36,10 +36,10 @@ func @constant_splat_tensor_i8_affine() -> tensor<4xf32> {
// CHECK-LABEL: const_splat_tensor_i8_fixedpoint
func @const_splat_tensor_i8_fixedpoint() -> tensor<4xf32> {
// CHECK: %cst = constant splat<tensor<4xi8>, 64> : tensor<4xi8>
// CHECK-NEXT: %0 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant<"uniform[i8:f32]{7.812500e-03}">>
// CHECK-NEXT: %0 = "quant.scast"(%cst) : (tensor<4xi8>) -> tensor<4x!quant.uniform<i8:f32, 7.812500e-03>>
%cst = constant splat<tensor<4xf32>, 0.5> : tensor<4xf32>
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant<"uniform[i8:f32]{7.812500e-03}">>
%2 = "quant.dcast"(%1) : (tensor<4x!quant<"uniform[i8:f32]{7.812500e-03}">>) -> (tensor<4xf32>)
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant.uniform<i8:f32, 7.812500e-03>>
%2 = "quant.dcast"(%1) : (tensor<4x!quant.uniform<i8:f32, 7.812500e-03>>) -> (tensor<4xf32>)
return %2 : tensor<4xf32>
}
@ -49,8 +49,8 @@ func @const_splat_tensor_i8_fixedpoint() -> tensor<4xf32> {
func @const_splat_tensor_i8_fixedpoint_neg() -> tensor<4xf32> {
// CHECK: %cst = constant splat<tensor<4xi8>, -64> : tensor<4xi8>
%cst = constant splat<tensor<4xf32>, -0.5> : tensor<4xf32>
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant<"uniform[i8:f32]{7.812500e-03}">>
%2 = "quant.dcast"(%1) : (tensor<4x!quant<"uniform[i8:f32]{7.812500e-03}">>) -> (tensor<4xf32>)
%1 = "quant.qcast"(%cst) : (tensor<4xf32>) -> tensor<4x!quant.uniform<i8:f32, 7.812500e-03>>
%2 = "quant.dcast"(%1) : (tensor<4x!quant.uniform<i8:f32, 7.812500e-03>>) -> (tensor<4xf32>)
return %2 : tensor<4xf32>
}
@ -60,8 +60,8 @@ func @const_splat_tensor_i8_fixedpoint_neg() -> tensor<4xf32> {
func @const_dense_tensor_i8_fixedpoint() -> tensor<7xf32> {
// CHECK: %cst = constant dense<tensor<7xi8>, [-128, -128, -64, 0, 64, 127, 127]> : tensor<7xi8>
%cst = constant dense<tensor<7xf32>, [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]> : tensor<7xf32>
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant<"uniform[i8:f32]{7.812500e-03}">>
%2 = "quant.dcast"(%1) : (tensor<7x!quant<"uniform[i8:f32]{7.812500e-03}">>) -> (tensor<7xf32>)
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant.uniform<i8:f32, 7.812500e-03>>
%2 = "quant.dcast"(%1) : (tensor<7x!quant.uniform<i8:f32, 7.812500e-03>>) -> (tensor<7xf32>)
return %2 : tensor<7xf32>
}
@ -74,8 +74,8 @@ func @const_sparse_tensor_i8_fixedpoint() -> tensor<7x2xf32> {
%cst = constant sparse<tensor<7x2xf32>,
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6]],
[-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]> : tensor<7x2xf32>
%1 = "quant.qcast"(%cst) : (tensor<7x2xf32>) -> tensor<7x2x!quant<"uniform[i8:f32]{7.812500e-03}">>
%2 = "quant.dcast"(%1) : (tensor<7x2x!quant<"uniform[i8:f32]{7.812500e-03}">>) -> (tensor<7x2xf32>)
%1 = "quant.qcast"(%cst) : (tensor<7x2xf32>) -> tensor<7x2x!quant.uniform<i8:f32, 7.812500e-03>>
%2 = "quant.dcast"(%1) : (tensor<7x2x!quant.uniform<i8:f32, 7.812500e-03>>) -> (tensor<7x2xf32>)
return %2 : tensor<7x2xf32>
}
@ -84,10 +84,10 @@ func @const_sparse_tensor_i8_fixedpoint() -> tensor<7x2xf32> {
// CHECK-LABEL: const_primitive_float_i8_fixedpoint
func @const_primitive_float_i8_fixedpoint() -> f32 {
// CHECK: %c64_i8 = constant 64 : i8
// CHECK-NEXT: %0 = "quant.scast"(%c64_i8) : (i8) -> !quant<"uniform[i8:f32]{7.812500e-03}">
// CHECK-NEXT: %0 = "quant.scast"(%c64_i8) : (i8) -> !quant.uniform<i8:f32, 7.812500e-03>
%cst = constant 0.5 : f32
%1 = "quant.qcast"(%cst) : (f32) -> !quant<"uniform[i8:f32]{7.812500e-03}">
%2 = "quant.dcast"(%1) : (!quant<"uniform[i8:f32]{7.812500e-03}">) -> (f32)
%1 = "quant.qcast"(%cst) : (f32) -> !quant.uniform<i8:f32, 7.812500e-03>
%2 = "quant.dcast"(%1) : (!quant.uniform<i8:f32, 7.812500e-03>) -> (f32)
return %2 : f32
}
@ -98,8 +98,8 @@ func @const_dense_tensor_u4_affine() -> tensor<7xf32> {
// NOTE: Unsigned quantities printed by MLIR as signed.
// CHECK: %cst = constant dense<tensor<7xi4>, [0, 0, 4, -8, -4, -1, -1]> : tensor<7xi4>
%cst = constant dense<tensor<7xf32>, [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]> : tensor<7xf32>
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant<"uniform[u4:f32]{1.250000e-01:8}">>
%2 = "quant.dcast"(%1) : (tensor<7x!quant<"uniform[u4:f32]{1.250000e-01:8}">>) -> (tensor<7xf32>)
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant.uniform<u4:f32, 1.250000e-01:8>>
%2 = "quant.dcast"(%1) : (tensor<7x!quant.uniform<u4:f32, 1.250000e-01:8>>) -> (tensor<7xf32>)
return %2 : tensor<7xf32>
}
@ -110,8 +110,8 @@ func @const_dense_tensor_i4_affine() -> tensor<7xf32> {
// NOTE: Unsigned quantities printed by MLIR as signed.
// CHECK: %cst = constant dense<tensor<7xi4>, [-8, -8, -5, -1, 3, 7, 7]> : tensor<7xi4>
%cst = constant dense<tensor<7xf32>, [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]> : tensor<7xf32>
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant<"uniform[i4:f32]{1.250000e-01:-1}">>
%2 = "quant.dcast"(%1) : (tensor<7x!quant<"uniform[i4:f32]{1.250000e-01:-1}">>) -> (tensor<7xf32>)
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant.uniform<i4:f32, 1.250000e-01:-1>>
%2 = "quant.dcast"(%1) : (tensor<7x!quant.uniform<i4:f32, 1.250000e-01:-1>>) -> (tensor<7xf32>)
return %2 : tensor<7xf32>
}
@ -121,8 +121,8 @@ func @const_dense_tensor_i4_affine() -> tensor<7xf32> {
func @const_dense_tensor_i4_fixedpoint() -> tensor<7xf32> {
// CHECK: %cst = constant dense<tensor<7xi4>, [-8, -8, -4, 0, 4, 7, 7]> : tensor<7xi4>
%cst = constant dense<tensor<7xf32>, [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]> : tensor<7xf32>
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant<"uniform[i4:f32]{1.250000e-01}">>
%2 = "quant.dcast"(%1) : (tensor<7x!quant<"uniform[i4:f32]{1.250000e-01}">>) -> (tensor<7xf32>)
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant.uniform<i4:f32, 1.250000e-01>>
%2 = "quant.dcast"(%1) : (tensor<7x!quant.uniform<i4:f32, 1.250000e-01>>) -> (tensor<7xf32>)
return %2 : tensor<7xf32>
}
@ -134,7 +134,7 @@ func @const_dense_tensor_i4_fixedpoint() -> tensor<7xf32> {
func @const_custom_storage_range_i8_fixedpoint() -> tensor<7xf32> {
// CHECK: %cst = constant dense<tensor<7xi8>, [-100, -100, -64, 0, 64, 100, 100]> : tensor<7xi8>
%cst = constant dense<tensor<7xf32>, [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]> : tensor<7xf32>
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant<"uniform[i8(-100:100):f32]{7.812500e-03}">>
%2 = "quant.dcast"(%1) : (tensor<7x!quant<"uniform[i8(-100:100):f32]{7.812500e-03}">>) -> (tensor<7xf32>)
%1 = "quant.qcast"(%cst) : (tensor<7xf32>) -> tensor<7x!quant.uniform<i8<-100:100>:f32, 7.812500e-03>>
%2 = "quant.dcast"(%1) : (tensor<7x!quant.uniform<i8<-100:100>:f32, 7.812500e-03>>) -> (tensor<7xf32>)
return %2 : tensor<7xf32>
}

View File

@ -6,8 +6,8 @@
func @fakeQuantArgs_Quint8_0_1(tensor<8x4x3xf32>) -> tensor<8x4x3xf32> {
^bb0(%arg0: tensor<8x4x3xf32>):
// CHECK: %0 = "quant.qcast"(%arg0) : (tensor<8x4x3xf32>)
// CHECK-SAME: -> tensor<8x4x3x!quant<"uniform[u8:f32]{0.0039215686274509803}">>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant<"uniform[u8:f32]{0.0039215686274509803}">>)
// CHECK-SAME: -> tensor<8x4x3x!quant.uniform<u8:f32, 0.0039215686274509803>>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant.uniform<u8:f32, 0.0039215686274509803>>)
// CHECK-SAME: -> tensor<8x4x3xf32>
%0 = "quant.const_fake_quant"(%arg0) {
min: 0.0 : f32, max: 1.0 : f32, num_bits: 8
@ -21,8 +21,8 @@ func @fakeQuantArgs_Quint8_0_1(tensor<8x4x3xf32>) -> tensor<8x4x3xf32> {
func @fakeQuantArgs_Quint8_NarrowRange(tensor<8x4x3xf32>) -> tensor<8x4x3xf32> {
^bb0(%arg0: tensor<8x4x3xf32>):
// CHECK: %0 = "quant.qcast"(%arg0) : (tensor<8x4x3xf32>)
// CHECK-SAME: -> tensor<8x4x3x!quant<"uniform[u8(1:255):f32]{0.003937007874015748:1}">>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant<"uniform[u8(1:255):f32]{0.003937007874015748:1}">>)
// CHECK-SAME: -> tensor<8x4x3x!quant.uniform<u8<1:255>:f32, 0.003937007874015748:1>>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant.uniform<u8<1:255>:f32, 0.003937007874015748:1>>)
// CHECK-SAME: -> tensor<8x4x3xf32>
%0 = "quant.const_fake_quant"(%arg0) {
min: 0.0 : f32, max: 1.0 : f32, num_bits: 8, narrow_range: true
@ -36,8 +36,8 @@ func @fakeQuantArgs_Quint8_NarrowRange(tensor<8x4x3xf32>) -> tensor<8x4x3xf32> {
func @fakeQuantArgs_Quint8_SymmetricRange(tensor<8x4x3xf32>) -> tensor<8x4x3xf32> {
^bb0(%arg0: tensor<8x4x3xf32>):
// CHECK: %0 = "quant.qcast"(%arg0) : (tensor<8x4x3xf32>)
// CHECK-SAME: -> tensor<8x4x3x!quant<"uniform[u8:f32]{7.812500e-03:128}">>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant<"uniform[u8:f32]{7.812500e-03:128}">>)
// CHECK-SAME: -> tensor<8x4x3x!quant.uniform<u8:f32, 7.812500e-03:128>>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant.uniform<u8:f32, 7.812500e-03:128>>)
// CHECK-SAME: -> tensor<8x4x3xf32>
%0 = "quant.const_fake_quant"(%arg0) {
min: -1.0 : f32, max: 0.9921875 : f32, num_bits: 8, narrow_range: false
@ -52,8 +52,8 @@ func @fakeQuantArgs_Quint8_SymmetricRange(tensor<8x4x3xf32>) -> tensor<8x4x3xf32
func @fakeQuantArgs_Qint16_Symmetric(tensor<8x4x3xf32>) -> tensor<8x4x3xf32> {
^bb0(%arg0: tensor<8x4x3xf32>):
// CHECK: %0 = "quant.qcast"(%arg0) : (tensor<8x4x3xf32>)
// CHECK-SAME: -> tensor<8x4x3x!quant<"uniform[i16:f32]{3.0517578125E-5}">>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant<"uniform[i16:f32]{3.0517578125E-5}">>)
// CHECK-SAME: -> tensor<8x4x3x!quant.uniform<i16:f32, 3.0517578125E-5>>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<8x4x3x!quant.uniform<i16:f32, 3.0517578125E-5>>)
// CHECK-SAME: -> tensor<8x4x3xf32>
%0 = "quant.const_fake_quant"(%arg0) {
min: -1.0 : f32, max: 0.999969482 : f32, num_bits: 16
@ -67,8 +67,8 @@ func @fakeQuantArgs_Qint16_Symmetric(tensor<8x4x3xf32>) -> tensor<8x4x3xf32> {
func @fakeQuantArgs_UnrankedTensor(tensor<f32>) -> tensor<f32> {
^bb0(%arg0: tensor<f32>):
// CHECK: %0 = "quant.qcast"(%arg0) : (tensor<f32>)
// CHECK-SAME: -> tensor<!quant<"uniform[u8:f32]{0.0039215686274509803}">>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<!quant<"uniform[u8:f32]{0.0039215686274509803}">>)
// CHECK-SAME: -> tensor<!quant.uniform<u8:f32, 0.0039215686274509803>>
// CHECK-NEXT: %1 = "quant.dcast"(%0) : (tensor<!quant.uniform<u8:f32, 0.0039215686274509803>>)
// CHECK-SAME: -> tensor<f32>
%0 = "quant.const_fake_quant"(%arg0) {
min: 0.0 : f32, max: 1.0 : f32, num_bits: 8

View File

@ -3,135 +3,120 @@
// -----
// Invalid type.
// expected-error@+1 {{unknown quantized type foobar}}
!qalias = type !quant<"foobar">
!qalias = type !quant.foobar
// -----
// Unrecognized token: illegal token
// expected-error@+1 {{unrecognized token: %}}
!qalias = type !quant<"%%">
// expected-error@+1 {{unrecognized token: _}}
!qalias = type !quant.__
// -----
// Unrecognized token: trailing
// expected-error@+1 {{unrecognized token: 23}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{0.99872:127} 23">
// -----
// Unrecognized token: type open
// expected-error@+1 {{unrecognized token: (}}
!qalias = type !quant<"uniform(i8(-4:3):f32){0.99872:127}">
!qalias = type !quant.uniform<i8<-4:3>:f32, 0.99872:127 23>
// -----
// Unrecognized token: missing storage type maximum
// expected-error@+1 {{expected storage type maximum}}
!qalias = type !quant<"uniform[i8(16:f32]{0.99872:127}">
// expected-error@+1 {{unrecognized token: >}}
!qalias = type !quant.uniform<i8<16>:f32, 0.99872:127>
// -----
// Unrecognized token: missing closing paren
// Unrecognized token: missing closing angle bracket
// expected-error@+1 {{unrecognized token: :}}
!qalias = type !quant<"uniform[i8(-4:3:f32]{0.99872:127}">
!qalias = type !quant<"uniform<i8<-4:3:f32, 0.99872:127>">
// -----
// Unrecognized token: missing type colon
// expected-error@+1 {{unrecognized token: f}}
!qalias = type !quant<"uniform[i8(-4:3)f32]{0.99872:127}">
!qalias = type !quant.uniform<i8<-4:3>f32, 0.99872:127>
// -----
// Unrecognized token: missing closing bracket
// expected-error@+1 {{unrecognized token: {}}
!qalias = type !quant<"uniform[i8(-4:3):f32{0.99872:127}">
// -----
// Unrecognized token: wrong opening brace
// expected-error@+1 {{unrecognized token: (}}
!qalias = type !quant<"uniform[i8(-4:3):f32](0.99872:127}">
// Unrecognized token: missing comma
// expected-error@+1 {{unrecognized token: 0.99872}}
!qalias = type !quant.uniform<i8<-4:3>:f32 0.99872:127>
// -----
// Unrecognized storage type: illegal prefix
// expected-error@+1 {{illegal storage type prefix: int}}
!qalias = type !quant<"uniform[int8(-4:3):f32]{0.99872:127}">
!qalias = type !quant.uniform<int8<-4:3>:f32, 0.99872:127>
// -----
// Unrecognized storage type: no width
// expected-error@+1 {{expected storage type width}}
!qalias = type !quant<"uniform[i(-4:3):f32]{0.99872:127}">
!qalias = type !quant.uniform<i<-4:3>:f32, 0.99872:127>
// -----
// Unrecognized storage type: storage size > 32
// expected-error@+1 {{illegal storage type size: 33}}
!qalias = type !quant<"uniform[i33:f32]{0.99872:127}">
!qalias = type !quant.uniform<i33:f32, 0.99872:127>
// -----
// Unrecognized storage type: storage size < 0
// expected-error@+1 {{illegal storage type size: -1}}
!qalias = type !quant<"uniform[i-1(-4:3):f32]{0.99872:127}">
!qalias = type !quant.uniform<i-1<-4:3>:f32, 0.99872:127>
// -----
// Unrecognized storage type: storage size == 0
// expected-error@+1 {{illegal storage type size: 0}}
!qalias = type !quant<"uniform[i0(-4:3):f32]{0.99872:127}">
!qalias = type !quant.uniform<i0<-4:3>:f32, 0.99872:127>
// -----
// Illegal storage min/max: max - min < 0
// expected-error@+1 {{illegal storage min and storage max: (2:1)}}
!qalias = type !quant<"uniform[i8(2:1):f32]{0.99872:127}">
!qalias = type !quant.uniform<i8<2:1>:f32, 0.99872:127>
// -----
// Illegal storage min/max: max - min == 0
// expected-error@+1 {{illegal storage min and storage max: (1:1)}}
!qalias = type !quant<"uniform[i8(1:1):f32]{0.99872:127}">
!qalias = type !quant.uniform<i8<1:1>:f32, 0.99872:127>
// -----
// Illegal storage min/max: max > defaultMax
// expected-error@+1 {{illegal storage type maximum: 9}}
!qalias = type !quant<"uniform[i4(-1:9):f32]{0.99872:127}">
!qalias = type !quant.uniform<i4<-1:9>:f32, 0.99872:127>
// -----
// Illegal storage min/max: min < defaultMin
// expected-error@+1 {{illegal storage type minimum: -9}}
!qalias = type !quant<"uniform[i4(-9:1):f32]{0.99872:127}">
!qalias = type !quant.uniform<i4<-9:1>:f32, 0.99872:127>
// -----
// Illegal uniform params: invalid scale
// expected-error@+1 {{expected valid uniform scale. got: abc}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{abc:127}">
!qalias = type !quant.uniform<i8<-4:3>:f32, abc:127>
// -----
// Illegal uniform params: invalid zero point separator
// expected-error@+1 {{unrecognized token: abc}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{0.1abc}">
!qalias = type !quant.uniform<i8<-4:3>:f32, 0.1abc>
// -----
// Illegal uniform params: missing zero point
// expected-error@+1 {{expected integer uniform zero point. got: }}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{0.1:}">
// expected-error@+1 {{expected integer uniform zero point. got: >}}
!qalias = type !quant.uniform<i8<-4:3>:f32, 0.1:>
// -----
// Illegal uniform params: invalid zero point
// expected-error@+1 {{expected integer uniform zero point. got: abc}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{0.1:abc}">
// -----
// Illegal uniform params: missing closing brace
// expected-error@+1 {{unrecognized token: )}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{0.1:0)">
!qalias = type !quant.uniform<i8<-4:3>:f32, 0.1:abc>
// -----
// Illegal expressed type: f33
// expected-error@+1 {{unrecognized expressed type: f33}}
!qalias = type !quant<"uniform[i8(-4:3):f33]{0.99872:127}">
!qalias = type !quant.uniform<i8<-4:3>:f33, 0.99872:127>
// -----
// Illegal scale: negative
// expected-error@+1 {{illegal scale: -1.000000}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{-1.0:127}">
!qalias = type !quant.uniform<i8<-4:3>:f32, -1.0:127>
// -----
// Illegal uniform params: missing quantized dimension
// expected-error@+1 {{expected quantized dimension}}
!qalias = type !quant<"uniform[i8(-4:3):f32:]{2.000000e+02:-19.987200e-01:1}">
!qalias = type !quant.uniform<i8<-4:3>:f32:, {2.000000e+02:-19.987200e-01:1}>
// -----
// Illegal uniform params: unspecified quantized dimension, when multiple scales
// provided.
// expected-error@+1 {{multiple scales/zeroPoints provided, but quantizedDimension wasn't specified}}
!qalias = type !quant<"uniform[i8(-4:3):f32]{2.000000e+02,-19.987200e-01:1}">
// expected-error@+1 {{expected valid uniform scale. got: {}}
!qalias = type !quant.uniform<i8<-4:3>:f32, {2.000000e+02,-19.987200e-01:1}>

View File

@ -3,8 +3,8 @@
// -----
// All per-layer params specified:
// [signed] storageType, storageTypeMin, storageTypeMax, expressedType, scale, zeroPoint
// CHECK: !quant<"uniform[i8(-8:7):f32]{9.987200e-01:127}">
!qalias = type !quant<"uniform[i8(-8:7):f32]{0.99872:127}">
// CHECK: !quant.uniform<i8<-8:7>:f32, 9.987200e-01:127>
!qalias = type !quant.uniform<i8<-8:7>:f32, 0.99872:127>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -12,8 +12,8 @@ func @parse() -> !qalias {
// -----
// Trailing whitespace.
// CHECK: !quant<"uniform[i8(-8:7):f32]{9.987200e-01:127}">
!qalias = type !quant<"uniform[i8(-8:7):f32]{0.99872:127} ">
// CHECK: !quant.uniform<i8<-8:7>:f32, 9.987200e-01:127>
!qalias = type !quant.uniform<i8<-8:7>:f32, 0.99872:127 >
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -22,8 +22,8 @@ func @parse() -> !qalias {
// -----
// Required per-layer params specified:
// [unsigned] storageType, expressedType, scale
// CHECK: !quant<"uniform[u8:f32]{9.987200e-01}">
!qalias = type !quant<"uniform[u8:f32]{0.99872}">
// CHECK: !quant.uniform<u8:f32, 9.987200e-01>
!qalias = type !quant.uniform<u8:f32, 0.99872>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -31,8 +31,8 @@ func @parse() -> !qalias {
// -----
// Exponential scale (-)
// CHECK: !quant<"uniform[u8:f32]{2.000000e-02}">
!qalias = type !quant<"uniform[u8:f32]{2.0e-2}">
// CHECK: !quant.uniform<u8:f32, 2.000000e-02>
!qalias = type !quant.uniform<u8:f32, 2.0e-2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -40,8 +40,8 @@ func @parse() -> !qalias {
// -----
// Exponential scale (+)
// CHECK: !quant<"uniform[u8:f32]{2.000000e+02}">
!qalias = type !quant<"uniform[u8:f32]{2.0e+2}">
// CHECK: !quant.uniform<u8:f32, 2.000000e+02>
!qalias = type !quant.uniform<u8:f32, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -49,8 +49,8 @@ func @parse() -> !qalias {
// -----
// Storage type: i16
// CHECK: !quant<"uniform[i16:f32]{2.000000e+02}">
!qalias = type !quant<"uniform[i16:f32]{2.0e+2}">
// CHECK: !quant.uniform<i16:f32, 2.000000e+02>
!qalias = type !quant.uniform<i16:f32, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -58,8 +58,8 @@ func @parse() -> !qalias {
// -----
// Storage type: u16
// CHECK: !quant<"uniform[u16:f32]{2.000000e+02}">
!qalias = type !quant<"uniform[u16:f32]{2.0e+2}">
// CHECK: !quant.uniform<u16:f32, 2.000000e+02>
!qalias = type !quant.uniform<u16:f32, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -67,8 +67,8 @@ func @parse() -> !qalias {
// -----
// Storage type: i32
// CHECK: !quant<"uniform[i32:f32]{2.000000e+02}">
!qalias = type !quant<"uniform[i32:f32]{2.0e+2}">
// CHECK: !quant.uniform<i32:f32, 2.000000e+02>
!qalias = type !quant.uniform<i32:f32, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -76,8 +76,8 @@ func @parse() -> !qalias {
// -----
// Storage type: u32
// CHECK: !quant<"uniform[u32:f32]{2.000000e+02}">
!qalias = type !quant<"uniform[u32:f32]{2.0e+2}">
// CHECK: !quant.uniform<u32:f32, 2.000000e+02>
!qalias = type !quant.uniform<u32:f32, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -85,8 +85,8 @@ func @parse() -> !qalias {
// -----
// Expressed type: f32
// CHECK: !quant<"uniform[u8:f32]{2.000000e+02}">
!qalias = type !quant<"uniform[u8:f32]{2.0e+2}">
// CHECK: !quant.uniform<u8:f32, 2.000000e+02>
!qalias = type !quant.uniform<u8:f32, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -94,8 +94,8 @@ func @parse() -> !qalias {
// -----
// Expressed type: f16
// CHECK: !quant<"uniform[u8:f16]{2.000000e+02}">
!qalias = type !quant<"uniform[u8:f16]{2.0e+2}">
// CHECK: !quant.uniform<u8:f16, 2.000000e+02>
!qalias = type !quant.uniform<u8:f16, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -103,8 +103,8 @@ func @parse() -> !qalias {
// -----
// Expressed type: f64
// CHECK: !quant<"uniform[u8:f64]{2.000000e+02}">
!qalias = type !quant<"uniform[u8:f64]{2.0e+2}">
// CHECK: !quant.uniform<u8:f64, 2.000000e+02>
!qalias = type !quant.uniform<u8:f64, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -112,8 +112,8 @@ func @parse() -> !qalias {
// -----
// Expressed type: bf16
// CHECK: !quant<"uniform[u8:bf16]{2.000000e+02}">
!qalias = type !quant<"uniform[u8:bf16]{2.0e+2}">
// CHECK: !quant.uniform<u8:bf16, 2.000000e+02>
!qalias = type !quant.uniform<u8:bf16, 2.0e+2>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -121,8 +121,8 @@ func @parse() -> !qalias {
// -----
// Per-axis scales and zero points (affine)
// CHECK: !quant<"uniform[u8:f32:1]{2.000000e+02:-120,9.987200e-01:127}">
!qalias = type !quant<"uniform[u8:f32:1]{2.0e+2:-120,0.99872:127}">
// CHECK: !quant.uniform<u8:f32:1, {2.000000e+02:-120,9.987200e-01:127}>
!qalias = type !quant.uniform<u8:f32:1, {2.0e+2:-120,0.99872:127}>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -130,8 +130,8 @@ func @parse() -> !qalias {
// -----
// Per-axis scales and no zero points (fixedpoint)
// CHECK: !quant<"uniform[i8:f32:1]{2.000000e+02,9.987200e-01}">
!qalias = type !quant<"uniform[i8:f32:1]{2.0e+2,0.99872}">
// CHECK: !quant.uniform<i8:f32:1, {2.000000e+02,9.987200e-01}>
!qalias = type !quant.uniform<i8:f32:1, {2.0e+2,0.99872}>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias
@ -139,8 +139,8 @@ func @parse() -> !qalias {
// -----
// Per-axis scales and zero points (mixed affine and fixedpoint)
// CHECK: !quant<"uniform[i8:f32:1]{2.000000e+02,9.987200e-01:120}">
!qalias = type !quant<"uniform[i8:f32:1]{2.0e+2,0.99872:120}">
// CHECK: !quant.uniform<i8:f32:1, {2.000000e+02,9.987200e-01:120}>
!qalias = type !quant.uniform<i8:f32:1, {2.0e+2,0.99872:120}>
func @parse() -> !qalias {
%0 = "foo"() : () -> !qalias
return %0 : !qalias