Skip to content

Commit 738500f

Browse files
authored
[llvm] [DFP] Add support for decimal floating point IR types. (#33)
* Add support for DFP IR type. * Fixed BitCodeFormat.rst format. * Addressed review comments. * Addressed review comments. * Addressed review comments. * Addressed review comments. * Put all the Decimal* code together. * Put all the Decimal* code together and removed unrelated changes. * Fixed comment. * Addressed review comments. * Addressed review comments. * Addressed review comments. * Fixed reference. * Fixed format.
1 parent 3b2cb1f commit 738500f

File tree

17 files changed

+185
-10
lines changed

17 files changed

+185
-10
lines changed

clang/lib/CodeGen/CodeGenTypes.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,13 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
419419
break;
420420

421421
case BuiltinType::DecimalFloat32:
422+
ResultType = llvm::Type::getDecimal32Ty(getLLVMContext());
423+
break;
422424
case BuiltinType::DecimalFloat64:
425+
ResultType = llvm::Type::getDecimal64Ty(getLLVMContext());
426+
break;
423427
case BuiltinType::DecimalFloat128:
424-
llvm::report_fatal_error("LLVM type support for decimal floating point "
425-
"is not yet implemented");
428+
ResultType = llvm::Type::getDecimal128Ty(getLLVMContext());
426429
break;
427430

428431
case BuiltinType::NullPtr:

llvm/docs/BitCodeFormat.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,30 @@ The operand fields are
13581358

13591359
* *int_params*: Numbers that correspond to the integer parameters.
13601360

1361+
TYPE_CODE_DECIMAL32 Record
1362+
^^^^^^^^^^^^^^^^^^^^^^^^^^
1363+
1364+
``[DECIMAL32]``
1365+
1366+
The ``DECIMAL32`` record (code 27) adds a ``decimal32`` (32-bit
1367+
decimal floating point) type to the type table.
1368+
1369+
TYPE_CODE_DECIMAL64 Record
1370+
^^^^^^^^^^^^^^^^^^^^^^^^^^
1371+
1372+
``[DECIMAL64]``
1373+
1374+
The ``DECIMAL64`` record (code 28) adds a ``decimal64`` (64-bit
1375+
decimal floating point) type to the type table.
1376+
1377+
TYPE_CODE_DECIMAL128 Record
1378+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
1379+
1380+
``[DECIMAL128]``
1381+
1382+
The ``DECIMAL128`` record (code 29) adds a ``decimal128`` (128-bit
1383+
decimal floating point) type to the type table.
1384+
13611385
.. _CONSTANTS_BLOCK:
13621386

13631387
CONSTANTS_BLOCK Contents

llvm/docs/LangRef.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3672,6 +3672,15 @@ Floating-Point Types
36723672
* - ``ppc_fp128``
36733673
- 128-bit floating-point value (two 64-bits)
36743674

3675+
* - ``decimal32``
3676+
- 32-bit decimal floating-point value
3677+
3678+
* - ``decimal64``
3679+
- 64-bit decimal floating-point value
3680+
3681+
* - ``decimal128``
3682+
- 128-bit decimal floating-point value
3683+
36753684
The binary format of half, float, double, and fp128 correspond to the
36763685
IEEE-754-2008 specifications for binary16, binary32, binary64, and binary128
36773686
respectively.

llvm/include/llvm-c/Core.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,12 @@ typedef enum {
164164
LLVMX86_MMXTypeKind, /**< X86 MMX */
165165
LLVMTokenTypeKind, /**< Tokens */
166166
LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */
167-
LLVMBFloatTypeKind, /**< 16 bit brain floating point type */
168-
LLVMX86_AMXTypeKind, /**< X86 AMX */
169-
LLVMTargetExtTypeKind, /**< Target extension type */
167+
LLVMBFloatTypeKind, /**< 16 bit brain floating point type */
168+
LLVMX86_AMXTypeKind, /**< X86 AMX */
169+
LLVMTargetExtTypeKind, /**< Target extension type */
170+
LLVMDecimal32TypeKind, /**< 32 bit decimal floating point type */
171+
LLVMDecimal64TypeKind, /**< 64 bit decimal floating point type */
172+
LLVMDecimal128TypeKind, /**< 128 bit decimal floating point type */
170173
} LLVMTypeKind;
171174

172175
typedef enum {
@@ -1290,6 +1293,21 @@ LLVMTypeRef LLVMFP128TypeInContext(LLVMContextRef C);
12901293
*/
12911294
LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C);
12921295

1296+
/**
1297+
* Obtain a 32-bit decimal floating point type from a context.
1298+
*/
1299+
LLVMTypeRef LLVMDecimal32TypeInContext(LLVMContextRef C);
1300+
1301+
/**
1302+
* Obtain a 64-bit decimal floating point type from a context.
1303+
*/
1304+
LLVMTypeRef LLVMDecimal64TypeInContext(LLVMContextRef C);
1305+
1306+
/**
1307+
* Obtain a 128-bit decimal floating point type from a context.
1308+
*/
1309+
LLVMTypeRef LLVMDecimal128TypeInContext(LLVMContextRef C);
1310+
12931311
/**
12941312
* Obtain a floating point type from the global context.
12951313
*
@@ -1302,6 +1320,9 @@ LLVMTypeRef LLVMDoubleType(void);
13021320
LLVMTypeRef LLVMX86FP80Type(void);
13031321
LLVMTypeRef LLVMFP128Type(void);
13041322
LLVMTypeRef LLVMPPCFP128Type(void);
1323+
LLVMTypeRef LLVMDecimal32Type(void);
1324+
LLVMTypeRef LLVMDecimal64Type(void);
1325+
LLVMTypeRef LLVMDecimal128Type(void);
13051326

13061327
/**
13071328
* @}

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ enum TypeCodes {
177177
TYPE_CODE_OPAQUE_POINTER = 25, // OPAQUE_POINTER: [addrspace]
178178

179179
TYPE_CODE_TARGET_TYPE = 26, // TARGET_TYPE
180+
181+
TYPE_CODE_DECIMAL32 = 27, // 32-bit decimal floating point
182+
TYPE_CODE_DECIMAL64 = 28, // 64-bit decimal floating point
183+
TYPE_CODE_DECIMAL128 = 29 // 128-bit decimal floating point
180184
};
181185

182186
enum OperandBundleTagCode {

llvm/include/llvm/IR/DataLayout.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,12 @@ inline TypeSize DataLayout::getTypeSizeInBits(Type *Ty) const {
715715
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
716716
return getTypeSizeInBits(LayoutTy);
717717
}
718+
case Type::Decimal32TyID:
719+
return TypeSize::Fixed(32);
720+
case Type::Decimal64TyID:
721+
return TypeSize::Fixed(64);
722+
case Type::Decimal128TyID:
723+
return TypeSize::Fixed(128);
718724
default:
719725
llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type");
720726
}

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,21 @@ class IRBuilderBase {
546546
return Type::getDoubleTy(Context);
547547
}
548548

549+
/// Fetch the type representing a 32-bit decimal floating point value.
550+
Type *getDecimal32Ty() {
551+
return Type::getDecimal32Ty(Context);
552+
}
553+
554+
/// Fetch the type representing a 64-bit decimal floating point value.
555+
Type *getDecimal64Ty() {
556+
return Type::getDecimal64Ty(Context);
557+
}
558+
559+
/// Fetch the type representing a 128-bit decimal floating point value.
560+
Type *getDecimal128Ty() {
561+
return Type::getDecimal128Ty(Context);
562+
}
563+
549564
/// Fetch the type representing void.
550565
Type *getVoidTy() {
551566
return Type::getVoidTy(Context);

llvm/include/llvm/IR/Type.h

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ class Type {
6767
X86_AMXTyID, ///< AMX vectors (8192 bits, X86 specific)
6868
TokenTyID, ///< Tokens
6969

70+
// Decimal floating-point types.
71+
Decimal32TyID, ///< 32-bit decimal floating point type
72+
Decimal64TyID, ///< 64-bit decimal floating point type
73+
Decimal128TyID, ///< 128-bit decimal floating point type
74+
7075
// Derived types... see DerivedTypes.h file.
7176
IntegerTyID, ///< Arbitrary bit width integers
7277
FunctionTyID, ///< Functions
@@ -165,6 +170,21 @@ class Type {
165170
/// Return true if this is powerpc long double.
166171
bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; }
167172

173+
/// Return true if this is 'decimal32'.
174+
bool isDecimal32Ty() const { return getTypeID() == Decimal32TyID; }
175+
176+
/// Return true if this is 'decimal64'.
177+
bool isDecimal64Ty() const { return getTypeID() == Decimal64TyID; }
178+
179+
/// Return true if this is 'decimal128'.
180+
bool isDecimal128Ty() const { return getTypeID() == Decimal128TyID; }
181+
182+
/// Return true if this is a decimal floating point.
183+
bool isDecimalFloatingPointTy() const {
184+
return getTypeID() == Decimal32TyID || getTypeID() == Decimal64TyID ||
185+
getTypeID() == Decimal128TyID;
186+
}
187+
168188
/// Return true if this is a well-behaved IEEE-like type, which has a IEEE
169189
/// compatible layout as defined by isIEEE(), and does not have unnormal
170190
/// values
@@ -184,7 +204,7 @@ class Type {
184204
/// Return true if this is one of the floating-point types
185205
bool isFloatingPointTy() const {
186206
return isIEEELikeFPTy() || getTypeID() == X86_FP80TyID ||
187-
getTypeID() == PPC_FP128TyID;
207+
getTypeID() == PPC_FP128TyID || isDecimalFloatingPointTy();
188208
}
189209

190210
/// Returns true if this is a floating-point type that is an unevaluated sum
@@ -334,11 +354,16 @@ class Type {
334354
/// type.
335355
unsigned getScalarSizeInBits() const LLVM_READONLY;
336356

337-
/// Return the width of the mantissa of this type. This is only valid on
338-
/// floating-point types. If the FP type does not have a stable mantissa (e.g.
339-
/// ppc long double), this method returns -1.
357+
/// Return the width of the mantissa of this type, in bits. This is only valid
358+
/// on floating-point types. If the FP type does not have a stable mantissa
359+
/// (e.g. ppc long double), this method returns -1.
340360
int getFPMantissaWidth() const;
341361

362+
/// Return the precision in digits of a decimal floating-point type
363+
/// per the "Decimal interchange format parameters" table of
364+
/// C23 annex H.2.1, "Interchange floating types".
365+
int getDFPPrecisionInDigits() const;
366+
342367
/// Return whether the type is IEEE compatible, as defined by the eponymous
343368
/// method in APFloat.
344369
bool isIEEE() const;
@@ -463,6 +488,9 @@ class Type {
463488
static IntegerType *getInt32Ty(LLVMContext &C);
464489
static IntegerType *getInt64Ty(LLVMContext &C);
465490
static IntegerType *getInt128Ty(LLVMContext &C);
491+
static Type *getDecimal32Ty(LLVMContext &C);
492+
static Type *getDecimal64Ty(LLVMContext &C);
493+
static Type *getDecimal128Ty(LLVMContext &C);
466494
template <typename ScalarTy> static Type *getScalarTy(LLVMContext &C) {
467495
int noOfBits = sizeof(ScalarTy) * CHAR_BIT;
468496
if (std::is_integral<ScalarTy>::value) {

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,9 @@ lltok::Kind LLLexer::LexIdentifier() {
826826
TYPEKEYWORD("x86_amx", Type::getX86_AMXTy(Context));
827827
TYPEKEYWORD("token", Type::getTokenTy(Context));
828828
TYPEKEYWORD("ptr", PointerType::getUnqual(Context));
829+
TYPEKEYWORD("decimal32", Type::getDecimal32Ty(Context));
830+
TYPEKEYWORD("decimal64", Type::getDecimal64Ty(Context));
831+
TYPEKEYWORD("decimal128", Type::getDecimal128Ty(Context));
829832

830833
#undef TYPEKEYWORD
831834

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,15 @@ Error BitcodeReader::parseTypeTableBody() {
25082508
TypeName.clear();
25092509
break;
25102510
}
2511+
case bitc::TYPE_CODE_DECIMAL32: // 32-bit DFP
2512+
ResultTy = Type::getDecimal32Ty(Context);
2513+
break;
2514+
case bitc::TYPE_CODE_DECIMAL64: // 64-bit DFP
2515+
ResultTy = Type::getDecimal64Ty(Context);
2516+
break;
2517+
case bitc::TYPE_CODE_DECIMAL128: // 128-bit DFP
2518+
ResultTy = Type::getDecimal128Ty(Context);
2519+
break;
25112520
case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
25122521
if (Record.size() < 2)
25132522
return error("Invalid array type record");

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,9 @@ void ModuleBitcodeWriter::writeTypeTable() {
976976
case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
977977
case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
978978
case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break;
979+
case Type::Decimal32TyID: Code = bitc::TYPE_CODE_DECIMAL32; break;
980+
case Type::Decimal64TyID: Code = bitc::TYPE_CODE_DECIMAL64; break;
981+
case Type::Decimal128TyID: Code = bitc::TYPE_CODE_DECIMAL128; break;
979982
case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
980983
case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
981984
case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;

llvm/lib/IR/AsmWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,9 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
561561
case Type::IntegerTyID:
562562
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
563563
return;
564+
case Type::Decimal32TyID: OS << "decimal32"; return;
565+
case Type::Decimal64TyID: OS << "decimal64"; return;
566+
case Type::Decimal128TyID: OS << "decimal128"; return;
564567

565568
case Type::FunctionTyID: {
566569
FunctionType *FTy = cast<FunctionType>(Ty);

llvm/lib/IR/Core.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,12 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
563563
return LLVMFP128TypeKind;
564564
case Type::PPC_FP128TyID:
565565
return LLVMPPC_FP128TypeKind;
566+
case Type::Decimal32TyID:
567+
return LLVMDecimal32TypeKind;
568+
case Type::Decimal64TyID:
569+
return LLVMDecimal64TypeKind;
570+
case Type::Decimal128TyID:
571+
return LLVMDecimal128TypeKind;
566572
case Type::LabelTyID:
567573
return LLVMLabelTypeKind;
568574
case Type::MetadataTyID:

llvm/lib/IR/LLVMContextImpl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
4242
X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID),
4343
PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_MMXTy(C, Type::X86_MMXTyID),
4444
X86_AMXTy(C, Type::X86_AMXTyID), Int1Ty(C, 1), Int8Ty(C, 8),
45-
Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128) {}
45+
Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128),
46+
Decimal32Ty(C, Type::Decimal32TyID), Decimal64Ty(C, Type::Decimal64TyID),
47+
Decimal128Ty(C, Type::Decimal128TyID) {}
4648

4749
LLVMContextImpl::~LLVMContextImpl() {
4850
// NOTE: We need to delete the contents of OwnedModules, but Module's dtor

llvm/lib/IR/LLVMContextImpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,7 @@ class LLVMContextImpl {
15241524
TokenTy;
15251525
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy, X86_AMXTy;
15261526
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty;
1527+
Type Decimal32Ty, Decimal64Ty, Decimal128Ty;
15271528

15281529
std::unique_ptr<ConstantTokenNone> TheNoneToken;
15291530

llvm/lib/IR/Type.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
4848
case X86_MMXTyID : return getX86_MMXTy(C);
4949
case X86_AMXTyID : return getX86_AMXTy(C);
5050
case TokenTyID : return getTokenTy(C);
51+
case Decimal32TyID : return getDecimal32Ty(C);
52+
case Decimal64TyID : return getDecimal64Ty(C);
53+
case Decimal128TyID: return getDecimal128Ty(C);
5154
default:
5255
return nullptr;
5356
}
@@ -179,6 +182,9 @@ TypeSize Type::getPrimitiveSizeInBits() const {
179182
case Type::X86_FP80TyID: return TypeSize::Fixed(80);
180183
case Type::FP128TyID: return TypeSize::Fixed(128);
181184
case Type::PPC_FP128TyID: return TypeSize::Fixed(128);
185+
case Decimal32TyID: return TypeSize::Fixed(32);
186+
case Decimal64TyID: return TypeSize::Fixed(64);
187+
case Decimal128TyID: return TypeSize::Fixed(128);
182188
case Type::X86_MMXTyID: return TypeSize::Fixed(64);
183189
case Type::X86_AMXTyID: return TypeSize::Fixed(8192);
184190
case Type::IntegerTyID:
@@ -214,6 +220,18 @@ int Type::getFPMantissaWidth() const {
214220
return -1;
215221
}
216222

223+
int Type::getDFPPrecisionInDigits() const {
224+
if (auto *VTy = dyn_cast<VectorType>(this))
225+
return VTy->getElementType()->getDFPPrecisionInDigits();
226+
assert(isDecimalFloatingPointTy() && "Not a decimal floating point type!");
227+
// Precision values per the "Decimal interchange format parameters" table of
228+
/// C23 annex H.2.1, "Interchange floating types".
229+
if (getTypeID() == Decimal32TyID) return 7;
230+
if (getTypeID() == Decimal64TyID) return 16;
231+
if (getTypeID() == Decimal128TyID) return 34;
232+
report_fatal_error("unknown decimal floating point type");
233+
}
234+
217235
bool Type::isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited) const {
218236
if (auto *ATy = dyn_cast<ArrayType>(this))
219237
return ATy->getElementType()->isSized(Visited);
@@ -245,6 +263,10 @@ Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; }
245263
Type *Type::getX86_MMXTy(LLVMContext &C) { return &C.pImpl->X86_MMXTy; }
246264
Type *Type::getX86_AMXTy(LLVMContext &C) { return &C.pImpl->X86_AMXTy; }
247265

266+
Type *Type::getDecimal32Ty(LLVMContext &C) { return &C.pImpl->Decimal32Ty; }
267+
Type *Type::getDecimal64Ty(LLVMContext &C) { return &C.pImpl->Decimal64Ty; }
268+
Type *Type::getDecimal128Ty(LLVMContext &C) { return &C.pImpl->Decimal128Ty; }
269+
248270
IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; }
249271
IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; }
250272
IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; }

llvm/test/Assembler/dfp.ll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: llvm-as < %s | llvm-dis | FileCheck %s --check-prefix=ASSEM-DISASS
2+
3+
define decimal32 @check_decimal32(decimal32 %A) {
4+
; ASSEM-DISASS: ret decimal32 %A
5+
ret decimal32 %A
6+
}
7+
8+
define decimal64 @check_decimal64(decimal64 %A) {
9+
; ASSEM-DISASS: ret decimal64 %A
10+
ret decimal64 %A
11+
}
12+
13+
define decimal128 @check_decimal128(decimal128 %A) {
14+
; ASSEM-DISASS: ret decimal128 %A
15+
ret decimal128 %A
16+
}

0 commit comments

Comments
 (0)