Skip to content

Commit 4994051

Browse files
[CLANG][AArch64] Add the modal 8 bit floating-point scalar type (#97277)
ARM ACLE PR#323[1] adds new modal types for 8-bit floating point intrinsic. From the PR#323: ``` ACLE defines the `__mfp8` type, which can be used for the E5M2 and E4M3 8-bit floating-point formats. It is a storage and interchange only type with no arithmetic operations other than intrinsic calls. ```` The type should be an opaque type and its format in undefined in Clang. Only defined in the backend by a status/format register, for AArch64 the FPMR. This patch is an attempt to the add the mfloat8_t scalar type. It has a parser and codegen for the new scalar type. The patch it is lowering to and 8bit unsigned as it has no format. But maybe we should add another opaque type. [1] ARM-software/acle#323
1 parent 32baf29 commit 4994051

File tree

10 files changed

+189
-4
lines changed

10 files changed

+189
-4
lines changed

clang/include/clang/Basic/AArch64SVEACLETypes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@
107107
AARCH64_VECTOR_TYPE(Name, MangledName, Id, SingletonId)
108108
#endif
109109

110-
111110
//===- Vector point types -----------------------------------------------===//
112111

113112
SVE_VECTOR_TYPE_INT("__SVInt8_t", "__SVInt8_t", SveInt8, SveInt8Ty, 16, 8, 1, true)
@@ -201,6 +200,7 @@ SVE_PREDICATE_TYPE_ALL("__clang_svboolx4_t", "svboolx4_t", SveBoolx4, SveBoolx4T
201200

202201
SVE_OPAQUE_TYPE("__SVCount_t", "__SVCount_t", SveCount, SveCountTy)
203202

203+
AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8_t", "__MFloat8_t", MFloat8, MFloat8Ty, 1, 8, 1)
204204
AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8x8_t", "__MFloat8x8_t", MFloat8x8, MFloat8x8Ty, 8, 8, 1)
205205
AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8x16_t", "__MFloat8x16_t", MFloat8x16, MFloat8x16Ty, 16, 8, 1)
206206

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,7 @@ enum PredefinedTypeIDs {
11491149
///
11501150
/// Type IDs for non-predefined types will start at
11511151
/// NUM_PREDEF_TYPE_IDs.
1152-
const unsigned NUM_PREDEF_TYPE_IDS = 511;
1152+
const unsigned NUM_PREDEF_TYPE_IDS = 512;
11531153

11541154
// Ensure we do not overrun the predefined types we reserved
11551155
// in the enum PredefinedTypeIDs above.

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
783783
#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
784784
#include "clang/Basic/AArch64SVEACLETypes.def"
785785
{
786+
if (BT->getKind() == BuiltinType::MFloat8) {
787+
Encoding = llvm::dwarf::DW_ATE_unsigned_char;
788+
BTName = BT->getName(CGM.getLangOpts());
789+
// Bit size and offset of the type.
790+
uint64_t Size = CGM.getContext().getTypeSize(BT);
791+
return DBuilder.createBasicType(BTName, Size, Encoding);
792+
}
786793
ASTContext::BuiltinVectorTypeInfo Info =
787794
// For svcount_t, only the lower 2 bytes are relevant.
788795
BT->getKind() == BuiltinType::SveCount

clang/test/AST/arm-mfp8.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// RUN: %clang_cc1 -std=c++11 -triple aarch64-arm-none-eabi -target-feature -fp8 -ast-dump %s | \
2+
// RUN: FileCheck %s --strict-whitespace
3+
4+
// REQUIRES: aarch64-registered-target || arm-registered-target
5+
6+
/* Various contexts where type __mfp8 can appear. */
7+
8+
#include<arm_neon.h>
9+
/* Namespace */
10+
namespace {
11+
__mfp8 f2n;
12+
__mfp8 arr1n[10];
13+
}
14+
15+
//CHECK: |-NamespaceDecl {{.*}}
16+
//CHECK-NEXT: | |-VarDecl {{.*}} f2n '__mfp8':'__MFloat8_t'
17+
//CHECK-NEXT: | `-VarDecl {{.*}} arr1n '__mfp8[10]'
18+
19+
20+
const __mfp8 func1n(const __mfp8 mfp8) {
21+
// this should fail
22+
__mfp8 f1n;
23+
f1n = mfp8;
24+
return f1n;
25+
}
26+
//CHECK: |-FunctionDecl {{.*}} func1n 'const __mfp8 (const __mfp8)'
27+
//CHECK: | `-VarDecl {{.*}} f1n '__mfp8':'__MFloat8_t'
28+
//CHECK-NEXT: |-BinaryOperator {{.*}} '__mfp8':'__MFloat8_t' lvalue '='
29+
//CHECK-NEXT: | |-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue Var {{.*}} 'f1n' '__mfp8':'__MFloat8_t'
30+
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
31+
//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'const __mfp8':'const __MFloat8_t' lvalue ParmVar {{.*}} 'mfp8' 'const __mfp8':'const __MFloat8_t'
32+
//CHECK-NEXT: `-ReturnStmt {{.*}}
33+
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
34+
//CHECK-NEXT: `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue Var {{.*}} 'f1n' '__mfp8':'__MFloat8_t'
35+
36+
37+
/* Class */
38+
39+
class C1 {
40+
__mfp8 f1c;
41+
static const __mfp8 f2c;
42+
volatile __MFloat8_t f3c;
43+
public:
44+
C1(__mfp8 arg) : f1c(arg), f3c(arg) { }
45+
__mfp8 func1c(__mfp8 arg ) {
46+
return arg;
47+
}
48+
static __mfp8 func2c(__mfp8 arg) {
49+
return arg;
50+
}
51+
};
52+
53+
//CHECK: | |-CXXRecordDecl {{.*}} referenced class C1
54+
//CHECK-NEXT: | |-FieldDecl {{.*}} f1c '__mfp8':'__MFloat8_t'
55+
//CHECK-NEXT: | |-VarDecl {{.*}} f2c 'const __mfp8':'const __MFloat8_t' static
56+
//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile __MFloat8_t'
57+
//CHECK-NEXT: | |-AccessSpecDecl {{.*}}
58+
//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} C1 'void (__mfp8)' implicit-inline
59+
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t'
60+
//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f1c' '__mfp8':'__MFloat8_t'
61+
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
62+
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t'
63+
//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f3c' 'volatile __MFloat8_t'
64+
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
65+
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t'
66+
//CHECK-NEXT: | | `-CompoundStmt {{.*}}
67+
//CHECK-NEXT: | |-CXXMethodDecl {{.*}} func1c '__mfp8 (__mfp8)' implicit-inline
68+
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t'
69+
//CHECK-NEXT: | | `-CompoundStmt {{.*}}
70+
//CHECK-NEXT: | | `-ReturnStmt {{.*}}
71+
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
72+
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}}8 'arg' '__mfp8':'__MFloat8_t'
73+
//CHECK-NEXT: | `-CXXMethodDecl {{.*}} func2c '__mfp8 (__mfp8)' static implicit-inline
74+
//CHECK-NEXT: | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t'
75+
//CHECK-NEXT: | `-CompoundStmt {{.*}}
76+
//CHECK-NEXT: | `-ReturnStmt {{.*}}
77+
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' <LValueToRValue>
78+
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t'
79+
80+
template <class C> struct S1 {
81+
C mem1;
82+
};
83+
84+
template <> struct S1<__mfp8> {
85+
__mfp8 mem2;
86+
};
87+
88+
//CHECK: |-TemplateArgument type '__MFloat8_t'
89+
//CHECK-NEXT: | `-BuiltinType {{.*}} '__MFloat8_t'
90+
//CHECK-NEXT: |-CXXRecordDecl {{.*}} implicit struct S1
91+
//CHECK-NEXT: `-FieldDecl {{.*}} mem2 '__mfp8':'__MFloat8_t'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon -target-feature +fp8 \
2+
// RUN: -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s
3+
#include<arm_neon.h>
4+
5+
void test_locals(void) {
6+
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "__MFloat8_t", {{.*}}, baseType: ![[ELTTYU8:[0-9]+]]
7+
// CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "__MFloat8_t", size: 8, encoding: DW_ATE_unsigned_char)
8+
__MFloat8_t mfp8;
9+
}

clang/test/CodeGen/arm-mfp8.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,39 @@ mfloat8x8_t test_ret_mfloat8x8_t(mfloat8x8_t v) {
4747
return v;
4848
}
4949

50+
// CHECK-C-LABEL: define dso_local <1 x i8> @func1n(
51+
// CHECK-C-SAME: <1 x i8> [[MFP8:%.*]]) #[[ATTR0]] {
52+
// CHECK-C-NEXT: [[ENTRY:.*:]]
53+
// CHECK-C-NEXT: [[MFP8_ADDR:%.*]] = alloca <1 x i8>, align 1
54+
// CHECK-C-NEXT: [[F1N:%.*]] = alloca [10 x <1 x i8>], align 1
55+
// CHECK-C-NEXT: store <1 x i8> [[MFP8]], ptr [[MFP8_ADDR]], align 1
56+
// CHECK-C-NEXT: [[TMP0:%.*]] = load <1 x i8>, ptr [[MFP8_ADDR]], align 1
57+
// CHECK-C-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
58+
// CHECK-C-NEXT: store <1 x i8> [[TMP0]], ptr [[ARRAYIDX]], align 1
59+
// CHECK-C-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
60+
// CHECK-C-NEXT: [[TMP1:%.*]] = load <1 x i8>, ptr [[ARRAYIDX1]], align 1
61+
// CHECK-C-NEXT: ret <1 x i8> [[TMP1]]
62+
//
63+
// CHECK-CXX-LABEL: define dso_local <1 x i8> @_Z6func1nu11__MFloat8_t(
64+
// CHECK-CXX-SAME: <1 x i8> [[MFP8:%.*]]) #[[ATTR0]] {
65+
// CHECK-CXX-NEXT: [[ENTRY:.*:]]
66+
// CHECK-CXX-NEXT: [[MFP8_ADDR:%.*]] = alloca <1 x i8>, align 1
67+
// CHECK-CXX-NEXT: [[F1N:%.*]] = alloca [10 x <1 x i8>], align 1
68+
// CHECK-CXX-NEXT: store <1 x i8> [[MFP8]], ptr [[MFP8_ADDR]], align 1
69+
// CHECK-CXX-NEXT: [[TMP0:%.*]] = load <1 x i8>, ptr [[MFP8_ADDR]], align 1
70+
// CHECK-CXX-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
71+
// CHECK-CXX-NEXT: store <1 x i8> [[TMP0]], ptr [[ARRAYIDX]], align 1
72+
// CHECK-CXX-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [10 x <1 x i8>], ptr [[F1N]], i64 0, i64 2
73+
// CHECK-CXX-NEXT: [[TMP1:%.*]] = load <1 x i8>, ptr [[ARRAYIDX1]], align 1
74+
// CHECK-CXX-NEXT: ret <1 x i8> [[TMP1]]
75+
//
76+
__mfp8 func1n(__mfp8 mfp8) {
77+
__mfp8 f1n[10];
78+
f1n[2] = mfp8;
79+
return f1n[2];
80+
}
81+
82+
83+
5084
//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
5185
// CHECK: {{.*}}

clang/test/Modules/no-external-type-id.cppm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export module b;
2323
import a;
2424
export int b();
2525

26-
// CHECK: <DECL_FUNCTION {{.*}} op8=4104
26+
// CHECK: <DECL_FUNCTION {{.*}} op8=4112
2727
// CHECK: <TYPE_FUNCTION_PROTO
2828

2929
//--- a.v1.cppm

clang/test/Sema/arm-mfp8.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-arm-none-eabi -target-feature -fp8 %s
2+
3+
// REQUIRES: aarch64-registered-target
4+
#include<arm_neon.h>
5+
__mfp8 test_cast_from_float(unsigned in) {
6+
return (__mfp8)in; // expected-error {{used type '__mfp8' (aka '__MFloat8_t') where arithmetic or pointer type is required}}
7+
}
8+
9+
unsigned test_cast_to_int(__mfp8 in) {
10+
return (unsigned)in; // expected-error {{operand of type '__mfp8' (aka '__MFloat8_t') where arithmetic or pointer type is required}}
11+
}

clang/test/Sema/arm-mfp8.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify=sve,neon -triple aarch64-arm-none-eabi \
1+
// RUN: %clang_cc1 -fsyntax-only -verify=sve,neon,scalar -triple aarch64-arm-none-eabi \
22
// RUN: -target-feature -fp8 -target-feature +sve -target-feature +neon %s
33

44
// REQUIRES: aarch64-registered-target
@@ -29,3 +29,35 @@ void test_vector(mfloat8x8_t a, mfloat8x16_t b, uint8x8_t c) {
2929
c * b; // neon-error {{cannot convert between vector and non-scalar values ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x16_t' (aka '__MFloat8x16_t'))}}
3030
c / b; // neon-error {{cannot convert between vector and non-scalar values ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x16_t' (aka '__MFloat8x16_t'))}}
3131
}
32+
__mfp8 test_static_cast_from_char(char in) {
33+
return static_cast<__mfp8>(in); // scalar-error {{static_cast from 'char' to '__mfp8' (aka '__MFloat8_t') is not allowed}}
34+
}
35+
36+
char test_static_cast_to_char(__mfp8 in) {
37+
return static_cast<char>(in); // scalar-error {{static_cast from '__mfp8' (aka '__MFloat8_t') to 'char' is not allowed}}
38+
}
39+
void test(bool b) {
40+
__mfp8 mfp8;
41+
42+
mfp8 + mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
43+
mfp8 - mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
44+
mfp8 * mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
45+
mfp8 / mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}}
46+
++mfp8; // scalar-error {{cannot increment value of type '__mfp8' (aka '__MFloat8_t')}}
47+
--mfp8; // scalar-error {{cannot decrement value of type '__mfp8' (aka '__MFloat8_t')}}
48+
49+
char u8;
50+
51+
mfp8 + u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
52+
u8 + mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
53+
mfp8 - u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
54+
u8 - mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
55+
mfp8 * u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
56+
u8 * mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
57+
mfp8 / u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}}
58+
u8 / mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}}
59+
mfp8 = u8; // scalar-error {{assigning to '__mfp8' (aka '__MFloat8_t') from incompatible type 'char'}}
60+
u8 = mfp8; // scalar-error {{assigning to 'char' from incompatible type '__mfp8' (aka '__MFloat8_t')}}
61+
mfp8 + (b ? u8 : mfp8); // scalar-error {{incompatible operand types ('char' and '__mfp8' (aka '__MFloat8_t'))}}
62+
}
63+

clang/utils/TableGen/NeonEmitter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,6 +2588,7 @@ void NeonEmitter::runVectorTypes(raw_ostream &OS) {
25882588
OS << "typedef __fp16 float16_t;\n";
25892589

25902590
OS << "#if defined(__aarch64__) || defined(__arm64ec__)\n";
2591+
OS << "typedef __MFloat8_t __mfp8;\n";
25912592
OS << "typedef __MFloat8x8_t mfloat8x8_t;\n";
25922593
OS << "typedef __MFloat8x16_t mfloat8x16_t;\n";
25932594
OS << "typedef double float64_t;\n";

0 commit comments

Comments
 (0)