-
Notifications
You must be signed in to change notification settings - Fork 0
Decimal float impl #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
… us to lex and parse. This include stubbing out APDecimalFloat to represent decimal float in the AST and for calculations. This also includes decFltSemantics which we need to represent the semantics of decimal float types.
…oat constants and math working
|
||
set(CLANG_INSTALL_LIBDIR_BASENAME "lib${CLANG_LIBDIR_SUFFIX}") | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated change. The one below too.
public: | ||
// llvm::APDecimalFloat | ||
llvm::APInt getValue(const llvm::decFltSemantics &Semantics) const { | ||
// return llvm::APDecimalFloat(getIntValue(),Semantics); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this anymore, right? Same below.
|
||
public: | ||
DecimalFloatLiteral(const ASTContext &C, const llvm::APDecimalFloat &V, QualType type, | ||
SourceLocation l, unsigned width = 32 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to have width to be default?
|
||
void setWidth(unsigned Width) { width = Width;} | ||
unsigned getWidth() { return width; } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will need here get/set scale too.
I made a first pass through the patch, mostly looking at APDecimalFloat and decFltSemantics and this seems to be moving in the right direction. I think using the integer type is the way to go. This is also the way ICC implements it. For the arithmetic operations I suppose we would need to have the 64 and 128 flavors for them, right? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got about half way through the changes today. Overall, the direction looks good to me; I'm just finding more nit-picky detail concerns.
CanQualType DecimalFloat32Ty, DecimalFloat64Ty, DecimalFloat128Ty; // ISO/IEC TS 18661-2:2015 C23 conditionally supported | ||
// ISO/IEC TR 24733:2011 C++ support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per https://llvm.org/docs/CodingStandards.html#source-code-width, limit line length to 80 characters.
CAST_OPERATION(IntegralToFixedPoint) | ||
|
||
/// CK_FixedPointToBoolean - Fixed point to boolean. | ||
/// CK_FixedPointToBoolean - Decimal Float to boolean. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change to this comment doesn't seem right.
/// CK_FloatingToDecimalFloat - Floating to Decimal Float. | ||
/// _Accum a = f; | ||
CAST_OPERATION(FloatingToDecimalFloat) | ||
|
||
/// CK_DecimalFloatToFloating - Decimal Float to floating. | ||
/// (float) 2.5k | ||
CAST_OPERATION(DecimalFloatToFloating) | ||
|
||
/// CK_DecimalFloatCast - Decimal Float to Decimal Float. | ||
/// (_Accum) 0.5r | ||
CAST_OPERATION(DecimalFloatCast) | ||
|
||
/// CK_DecimalFloatToIntegral - Decimal Float to integral. | ||
/// (int) 2.0k | ||
CAST_OPERATION(DecimalFloatToIntegral) | ||
|
||
/// CK_IntegralToDecimalFloat - Integral to a Decimal Float. | ||
/// (_Accum) 2 | ||
CAST_OPERATION(IntegralToDecimalFloat) | ||
|
||
/// CK_DecimalFloatToBoolean - Decimal Float to boolean. | ||
/// (bool) 0.5r | ||
CAST_OPERATION(DecimalFloatToBoolean) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example cast operations in the comments are still for fixed point types and should be switched to operations on DFP types and literals.
/// Return true if this is a fixed point or integer type. | ||
bool isFixedPointOrIntegerType() const; | ||
|
||
/// Return true if this is a decinal float or integer type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Return true if this is a decinal float or integer type. | |
/// Return true if this is a decimal float or integer type. |
APSInt AsInt(Val.bitcastToAPInt()); | ||
return visitInt(AsInt, Ty, Offset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to worry about the availability of 128-bit integer support here? I don't think that concern exists for fixed-point types.
if (OpOverflow || ConversionOverflow) { | ||
if (Info.checkingForUndefinedBehavior()) | ||
Info.Ctx.getDiagnostics().Report(E->getExprLoc(), | ||
diag::warn_fixedpoint_constant_overflow) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The referenced diagnostic is for fixed-point, so we presumably need to use the right one (if one for DFP already exists), introduce a new one or, if the existing one is sufficiently generic, rename it. Additional occurrences can be found below.
break; | ||
|
||
case Expr::DecimalFloatLiteralClass: | ||
mangleType(E->getType()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The literal value will need to be mangled here as well; not just the type. See https://godbolt.org/z/Yd8a9ofGn for an example (and a chance to chuckle at the icc behavior).
break; | ||
|
||
case APValue::DecimalFloat: | ||
mangleType(T); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mangling of the value will be necessary here as well. See https://godbolt.org/z/3Edvh7xa4.
// literal types. | ||
if (BaseTy->isScalarType() || BaseTy->isVectorType() || | ||
BaseTy->isAnyComplexType()) | ||
BaseTy->isAnyComplexType() || BaseTy->isDecimalFloatType()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think DFP types should be considered scalar types; the check for isScalarType()
should therefore suffice here.
(note for myself: this is as far as I got with review before running out of time for the day)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I completed my first pass through all of the changes.
I need to spend some time looking at APFloat
before weighing in on whether we should try using it first before concluding that an APDecimalFloat
is needed. Likewise for fltSemantics
vs decFltSemantics
.
If you haven't already, can you think about how we can break this up into smaller, but still logically contained, reviews?
DecimalFloat64Width = 64; | ||
DecimalFloat64Align = 64; | ||
DecimalFloat128Width = 128; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DecimalFloat64Width = 64; | |
DecimalFloat64Align = 64; | |
DecimalFloat128Width = 128; | |
DecimalFloat64Width = 64; | |
DecimalFloat64Align = 64; | |
DecimalFloat128Width = 128; |
Indentation is off.
case BuiltinType::DecimalFloat32: | ||
case BuiltinType::DecimalFloat64: | ||
case BuiltinType::DecimalFloat128: | ||
Encoding = llvm::dwarf::DW_ATE_unsigned; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Encoding = llvm::dwarf::DW_ATE_unsigned; | |
Encoding = llvm::dwarf::DW_ATE_decimal_float; |
The DWARF specification already defines an encoding value for the IEEE 754R DFP types and an identifier is present in llvm/include/llvm/BinaryFormat/Dwarf.def
, so we can set the right encoding now. I'm not sure if differentiation is required for BID vs DPD encoding here, but we can revisit that as part of tahonermann#20 later.
if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) { | ||
QualType LHSType = BinOp->getLHS()->getType(); | ||
QualType RHSType = BinOp->getRHS()->getType(); | ||
return LHSType->isDecimalFloatType() || RHSType->isDecimalFloatType(); | ||
} | ||
if (const auto *UnOp = dyn_cast<UnaryOperator>(E)) | ||
return UnOp->getSubExpr()->getType()->isDecimalFloatType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to use getAs()
instead of dyn_cast()
to look through sugared types like TypedefType
. Or do I have that backwards?
} | ||
|
||
Value *VisitDecimalFloatLiteral(const DecimalFloatLiteral *E) { | ||
return Builder.getInt(E->getValue()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm reading the code right, this will return a llvm::ConstantInt
and thereby lose track of the fact that the value corresponds to a DFP representation. Do we not need to keep track of that somehow so that the constant value gets associated with a DFP IR type? That seems important if we're going to utilize the fadd
IR instruction/operator.
// Convert to the result type. | ||
return FPBuilder.CreateFixedToFixed( | ||
Result, IsShift ? LHSFixedSema : CommonFixedSema, ResultFixedSema); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Fixed/Decimal/ throughout.
llvm::APDecimalFloat Val(llvm::decFltSemantics( | ||
32u, /*Scale=*/1u, /*IsSigned=*/0u, /*IsSaturated=*/false, | ||
/*HasUnsignedPadding=*/false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will presumably need to be generalized for 64-bit and 128-bit literal support.
// S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported); | ||
// Result = Context.IntTy; | ||
// declarator.setInvalidType(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported); | |
// Result = Context.IntTy; | |
// declarator.setInvalidType(true); |
Remove.
if (getTypeID() == IntegerTyID || isFloatingPointTy() || | ||
getTypeID() == PointerTyID || getTypeID() == X86_MMXTyID || | ||
getTypeID() == X86_AMXTyID) | ||
getTypeID() == X86_AMXTyID || getTypeID() == DecimalFloat32TyID || getTypeID() == DecimalFloat64TyID || getTypeID() == DecimalFloat128TyID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Zahira added a isDecimalFloatingPointTy()
that can be used here.
case Type::DecimalFloat32TyID: | ||
return getIntegerVT(32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will presumably need to be generalized for 64-bit and 128-bit support.
decFltSemantics(unsigned Width, unsigned Scale, bool IsSigned, | ||
bool IsSaturated, bool HasUnsignedPadding) | ||
: Width(Width), LsbWeight(-static_cast<int>(Scale)), IsSigned(IsSigned), | ||
IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can omit the saturation properties; we don't need to worry about saturating and non-saturating types like fixed-point does.
This is basis for some discussions about
APDecimalFloat
,APDecimalFloatLiteral
,APDecimalFloatStorage
andDecimalFloatExprEvaluator
as well as support classes.You will see that I made the type as integer type because during codegen I could not get it to work any other way. I spent a while trying to disentangle a way to make it work otherwise without success. Floating point type seems to be deeply embedded in the codegen and taking the same path FixedPoint took felt like a much easier row.
There is a lot of hacky code to get the intel decimal float library integrated and you can see in some of the reading of decimal float literals and math I am using the library. You can see that underneath the type used for BID are all integral types.
I could compile code like this:
and dump the ast: