Automated rollback of commit fc194a4f22

PiperOrigin-RevId: 260037115
This commit is contained in:
Mehdi Amini 2019-07-25 15:50:54 -07:00 committed by jpienaar
parent 6552025736
commit 387638f9c2
5 changed files with 13 additions and 169 deletions

View File

@ -840,26 +840,10 @@ Syntax:
``` {.ebnf}
float-attribute ::= float-literal (`:` float-type)?
| hexadecimal-literal `:` float-type
```
A float attribute is a literal attribute that represents a floating point value
of the specified [float type](#floating-point-types). It can be represented in
the hexadecimal form where the hexadecimal value is interpreted as bits of the
underlying binary representation. This form is useful for representing infinity
and NaN floating point values. To avoid confusion with integer attributes,
hexadecimal literals _must_ be followed by a float type to define a float
attribute.
Examples:
``` {.mlir}
42.0 // float attribute defaults to f64 type
42.0 : f32 // float attribute of f32 type
0x7C00 : f16 // positive infinity
0x7CFF : f16 // NaN (one of possible values)
42 : f32 // Error: expected integer type
```
of the specified [float type](#floating-point-types).
#### String Attribute

View File

@ -478,12 +478,8 @@ static void printFloatValue(const APFloat &apValue, raw_ostream &os) {
}
}
// Print special values in hexadecimal format. The sign bit should be
// included in the literal.
SmallVector<char, 16> str;
APInt apInt = apValue.bitcastToAPInt();
apInt.toString(str, /*Radix=*/16, /*Signed=*/false,
/*formatAsCLiteral=*/true);
apValue.toString(str);
os << str;
}

View File

@ -227,9 +227,8 @@ public:
/// Parse a float attribute.
Attribute parseFloatAttr(Type type, bool isNegative);
/// Parse a decimal or a hexadecimal literal, which can be either an integer
/// or a float attribute.
Attribute parseDecOrHexAttr(Type type, bool isNegative);
/// Parse an integer attribute.
Attribute parseIntegerAttr(Type type, bool isSigned);
/// Parse an opaque elements attribute.
Attribute parseOpaqueElementsAttr();
@ -999,11 +998,11 @@ Attribute Parser::parseAttribute(Type type) {
case Token::floatliteral:
return parseFloatAttr(type, /*isNegative=*/false);
case Token::integer:
return parseDecOrHexAttr(type, /*isNegative=*/false);
return parseIntegerAttr(type, /*isSigned=*/false);
case Token::minus: {
consumeToken(Token::minus);
if (getToken().is(Token::integer))
return parseDecOrHexAttr(type, /*isNegative=*/true);
return parseIntegerAttr(type, /*isSigned=*/true);
if (getToken().is(Token::floatliteral))
return parseFloatAttr(type, /*isNegative=*/true);
@ -1152,17 +1151,12 @@ Attribute Parser::parseFloatAttr(Type type, bool isNegative) {
return FloatAttr::get(type, isNegative ? -val.getValue() : val.getValue());
}
/// Parse a decimal or a hexadecimal literal, which can be either an integer
/// or a float attribute.
Attribute Parser::parseDecOrHexAttr(Type type, bool isNegative) {
/// Parse an integer attribute.
Attribute Parser::parseIntegerAttr(Type type, bool isSigned) {
auto val = getToken().getUInt64IntegerValue();
if (!val.hasValue())
if (!val.hasValue() ||
(isSigned ? (int64_t)-val.getValue() >= 0 : (int64_t)val.getValue() < 0))
return (emitError("integer constant out of range for attribute"), nullptr);
// Remember if the literal is hexadecimal.
StringRef spelling = getToken().getSpelling();
bool isHex = spelling.size() > 1 && spelling[1] == 'x';
consumeToken(Token::integer);
if (!type) {
// Default to i64 if not type is specified.
@ -1171,47 +1165,14 @@ Attribute Parser::parseDecOrHexAttr(Type type, bool isNegative) {
else if (!(type = parseType()))
return nullptr;
}
// Hexadecimal representation of float literals is not supported for bfloat16.
// When supported, the literal should be unsigned.
auto floatType = type.dyn_cast<FloatType>();
if (floatType && !type.isBF16()) {
if (isNegative) {
emitError("hexadecimal float literal should not have a leading minus");
return nullptr;
}
if (!isHex) {
emitError("unexpected decimal integer literal for a float attribute")
.attachNote()
<< "add a trailing dot to make the literal a float";
return nullptr;
}
// Construct a float attribute bitwise equivalent to the integer literal.
int width = type.getIntOrFloatBitWidth();
APInt apInt(width, *val, isNegative);
if (apInt != *val) {
emitError("hexadecimal float constant out of range for attribute");
return nullptr;
}
APFloat apFloat(floatType.getFloatSemantics(), apInt);
return builder.getFloatAttr(type, apFloat);
}
if (!type.isIntOrIndex())
return (emitError("integer literal not valid for specified type"), nullptr);
return (emitError("integer value not valid for specified type"), nullptr);
// Parse the integer literal.
int width = type.isIndex() ? 64 : type.getIntOrFloatBitWidth();
APInt apInt(width, *val, isNegative);
APInt apInt(width, *val, isSigned);
if (apInt != *val)
return (emitError("integer constant out of range for attribute"), nullptr);
// Otherwise construct an integer attribute.
if (isNegative ? (int64_t)-val.getValue() >= 0 : (int64_t)val.getValue() < 0)
return (emitError("integer constant out of range for attribute"), nullptr);
return builder.getIntegerAttr(type, isNegative ? -apInt : apInt);
return builder.getIntegerAttr(type, isSigned ? -apInt : apInt);
}
/// Parse an opaque elements attribute.

View File

@ -1044,32 +1044,3 @@ func @invalid_region_dominance() {
}) : () -> ()
return
}
// -----
func @hexadecimal_bf16() {
// expected-error @+1 {{integer literal not valid for specified type}}
"foo"() {value = 0xffff : bf16} : () -> ()
}
// -----
func @hexadecimal_float_leading_minus() {
// expected-error @+1 {{hexadecimal float literal should not have a leading minus}}
"foo"() {value = -0x7fff : f16} : () -> ()
}
// -----
func @hexadecimal_float_literal_overflow() {
// expected-error @+1 {{hexadecimal float constant out of range for attribute}}
"foo"() {value = 0xffffffff : f16} : () -> ()
}
// -----
func @decimal_float_literal() {
// expected-error @+2 {{unexpected decimal integer literal for a float attribute}}
// expected-note @+1 {{add a trailing dot to make the literal a float}}
"foo"() {value = 42 : f32} : () -> ()
}

View File

@ -945,71 +945,3 @@ func @dialect_attribute_with_type() {
// CHECK-NEXT: foo = #foo.attr : i32
"foo.unknown_op"() {foo = #foo.attr : i32} : () -> ()
}
// CHECK-LABEL: @f16_special_values
func @f16_special_values() {
// F16 NaNs.
// CHECK: constant 0x7C01 : f16
%0 = constant 0x7C01 : f16
// CHECK: constant 0x7FFF : f16
%1 = constant 0x7FFF : f16
// CHECK: constant 0xFFFF : f16
%2 = constant 0xFFFF : f16
// F16 positive infinity.
// CHECK: constant 0x7C00 : f16
%3 = constant 0x7C00 : f16
// F16 negative inifinity.
// CHECK: constant 0xFC00 : f16
%4 = constant 0xFC00 : f16
return
}
// CHECK-LABEL: @f32_special_values
func @f32_special_values() {
// F32 signaling NaNs.
// CHECK: constant 0x7F800001 : f32
%0 = constant 0x7F800001 : f32
// CHECK: constant 0x7FBFFFFF : f32
%1 = constant 0x7FBFFFFF : f32
// F32 quiet NaNs.
// CHECK: constant 0x7FC00000 : f32
%2 = constant 0x7FC00000 : f32
// CHECK: constant 0xFFFFFFFF : f32
%3 = constant 0xFFFFFFFF : f32
// F32 positive infinity.
// CHECK: constant 0x7F800000 : f32
%4 = constant 0x7F800000 : f32
// F32 negative infinity.
// CHECK: constant 0xFF800000 : f32
%5 = constant 0xFF800000 : f32
return
}
// CHECK-LABEL: @f64_special_values
func @f64_special_values() {
// F64 signaling NaNs.
// CHECK: constant 0x7FF0000000000001 : f64
%0 = constant 0x7FF0000000000001 : f64
// CHECK: constant 0x7FF8000000000000 : f64
%1 = constant 0x7FF8000000000000 : f64
// F64 quiet NaNs.
// CHECK: constant 0x7FF0000001000000 : f64
%2 = constant 0x7FF0000001000000 : f64
// CHECK: constant 0xFFF0000001000000 : f64
%3 = constant 0xFFF0000001000000 : f64
// F64 positive inifinity.
// CHECK: constant 0x7FF0000000000000 : f64
%4 = constant 0x7FF0000000000000 : f64
// F64 negative infinity.
// CHECK: constant 0xFFF0000000000000 : f64
%5 = constant 0xFFF0000000000000 : f64
return
}