Skip to content

Commit b2c4084

Browse files
committed
Initial experiments (with integer regs for fp16).
Experiment with soft-promotion in FP regs (not working). Try to make f16 legal instead Atomic loads/stores, spill/reload, tests for __fp16 and half vectors. strict f16 with tests. Review Make use of vector facility if present.
1 parent 76b5fcb commit b2c4084

36 files changed

+2590
-57
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ to ``float``; see below for more information on this emulation.
10001000
* SPIR (natively)
10011001
* X86 (if SSE2 is available; natively if AVX512-FP16 is also available)
10021002
* RISC-V (natively if Zfh or Zhinx is available)
1003+
* SystemZ (emulated)
10031004

10041005
* ``__bf16`` is supported on the following targets (currently never natively):
10051006

clang/lib/Basic/Targets/SystemZ.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,26 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
9393
"-v128:64-a:8:16-n32:64");
9494
}
9595
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 128;
96+
97+
// True if the backend supports operations on the half LLVM IR type.
98+
// By setting this to false, conversions will happen for _Float16 around
99+
// a statement by default, with operations done in float. However, if
100+
// -ffloat16-excess-precision=none is given, no conversions will be made
101+
// and instead the backend will promote each half operation to float
102+
// individually.
103+
HasLegalHalfType = false;
104+
// Support _Float16.
105+
HasFloat16 = true;
106+
96107
HasStrictFP = true;
97108
}
98109

99110
unsigned getMinGlobalAlign(uint64_t Size, bool HasNonWeakDef) const override;
100111

112+
bool useFP16ConversionIntrinsics() const override {
113+
return false;
114+
}
115+
101116
void getTargetDefines(const LangOptions &Opts,
102117
MacroBuilder &Builder) const override;
103118

clang/lib/CodeGen/Targets/SystemZ.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ bool SystemZABIInfo::isFPArgumentType(QualType Ty) const {
185185

186186
if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
187187
switch (BT->getKind()) {
188+
case BuiltinType::Float16: // _Float16
188189
case BuiltinType::Float:
189190
case BuiltinType::Double:
190191
return true;
@@ -277,7 +278,8 @@ RValue SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
277278
} else {
278279
if (AI.getCoerceToType())
279280
ArgTy = AI.getCoerceToType();
280-
InFPRs = (!IsSoftFloatABI && (ArgTy->isFloatTy() || ArgTy->isDoubleTy()));
281+
InFPRs = (!IsSoftFloatABI &&
282+
(ArgTy->isHalfTy() || ArgTy->isFloatTy() || ArgTy->isDoubleTy()));
281283
IsVector = ArgTy->isVectorTy();
282284
UnpaddedSize = TyInfo.Width;
283285
DirectAlign = TyInfo.Align;
@@ -449,10 +451,11 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
449451

450452
// The structure is passed as an unextended integer, a float, or a double.
451453
if (isFPArgumentType(SingleElementTy)) {
452-
assert(Size == 32 || Size == 64);
454+
assert(Size == 16 || Size == 32 || Size == 64);
453455
return ABIArgInfo::getDirect(
454-
Size == 32 ? llvm::Type::getFloatTy(getVMContext())
455-
: llvm::Type::getDoubleTy(getVMContext()));
456+
Size == 16 ? llvm::Type::getHalfTy(getVMContext())
457+
: Size == 32 ? llvm::Type::getFloatTy(getVMContext())
458+
: llvm::Type::getDoubleTy(getVMContext()));
456459
} else {
457460
llvm::IntegerType *PassTy = llvm::IntegerType::get(getVMContext(), Size);
458461
return Size <= 32 ? ABIArgInfo::getNoExtend(PassTy)

clang/test/CodeGen/SystemZ/Float16.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %clang_cc1 -triple s390x-linux-gnu \
2+
// RUN: -ffloat16-excess-precision=standard -emit-llvm -o - %s \
3+
// RUN: | FileCheck %s -check-prefix=STANDARD
4+
5+
// RUN: %clang_cc1 -triple s390x-linux-gnu \
6+
// RUN: -ffloat16-excess-precision=none -emit-llvm -o - %s \
7+
// RUN: | FileCheck %s -check-prefix=NONE
8+
9+
// RUN: %clang_cc1 -triple s390x-linux-gnu \
10+
// RUN: -ffloat16-excess-precision=fast -emit-llvm -o - %s \
11+
// RUN: | FileCheck %s -check-prefix=FAST
12+
13+
_Float16 f(_Float16 a, _Float16 b, _Float16 c, _Float16 d) {
14+
return a * b + c * d;
15+
}
16+
17+
// STANDARD-LABEL: define dso_local half @f(half noundef %a, half noundef %b, half noundef %c, half noundef %d) #0 {
18+
// STANDARD-NEXT: entry:
19+
// STANDARD-NEXT: %a.addr = alloca half, align 2
20+
// STANDARD-NEXT: %b.addr = alloca half, align 2
21+
// STANDARD-NEXT: %c.addr = alloca half, align 2
22+
// STANDARD-NEXT: %d.addr = alloca half, align 2
23+
// STANDARD-NEXT: store half %a, ptr %a.addr, align 2
24+
// STANDARD-NEXT: store half %b, ptr %b.addr, align 2
25+
// STANDARD-NEXT: store half %c, ptr %c.addr, align 2
26+
// STANDARD-NEXT: store half %d, ptr %d.addr, align 2
27+
// STANDARD-NEXT: %0 = load half, ptr %a.addr, align 2
28+
// STANDARD-NEXT: %ext = fpext half %0 to float
29+
// STANDARD-NEXT: %1 = load half, ptr %b.addr, align 2
30+
// STANDARD-NEXT: %ext1 = fpext half %1 to float
31+
// STANDARD-NEXT: %mul = fmul float %ext, %ext1
32+
// STANDARD-NEXT: %2 = load half, ptr %c.addr, align 2
33+
// STANDARD-NEXT: %ext2 = fpext half %2 to float
34+
// STANDARD-NEXT: %3 = load half, ptr %d.addr, align 2
35+
// STANDARD-NEXT: %ext3 = fpext half %3 to float
36+
// STANDARD-NEXT: %mul4 = fmul float %ext2, %ext3
37+
// STANDARD-NEXT: %add = fadd float %mul, %mul4
38+
// STANDARD-NEXT: %unpromotion = fptrunc float %add to half
39+
// STANDARD-NEXT: ret half %unpromotion
40+
// STANDARD-NEXT: }
41+
42+
// NONE-LABEL: define dso_local half @f(half noundef %a, half noundef %b, half noundef %c, half noundef %d) #0 {
43+
// NONE-NEXT: entry:
44+
// NONE-NEXT: %a.addr = alloca half, align 2
45+
// NONE-NEXT: %b.addr = alloca half, align 2
46+
// NONE-NEXT: %c.addr = alloca half, align 2
47+
// NONE-NEXT: %d.addr = alloca half, align 2
48+
// NONE-NEXT: store half %a, ptr %a.addr, align 2
49+
// NONE-NEXT: store half %b, ptr %b.addr, align 2
50+
// NONE-NEXT: store half %c, ptr %c.addr, align 2
51+
// NONE-NEXT: store half %d, ptr %d.addr, align 2
52+
// NONE-NEXT: %0 = load half, ptr %a.addr, align 2
53+
// NONE-NEXT: %1 = load half, ptr %b.addr, align 2
54+
// NONE-NEXT: %mul = fmul half %0, %1
55+
// NONE-NEXT: %2 = load half, ptr %c.addr, align 2
56+
// NONE-NEXT: %3 = load half, ptr %d.addr, align 2
57+
// NONE-NEXT: %mul1 = fmul half %2, %3
58+
// NONE-NEXT: %add = fadd half %mul, %mul1
59+
// NONE-NEXT: ret half %add
60+
// NONE-NEXT: }
61+
62+
// FAST-LABEL: define dso_local half @f(half noundef %a, half noundef %b, half noundef %c, half noundef %d) #0 {
63+
// FAST-NEXT: entry:
64+
// FAST-NEXT: %a.addr = alloca half, align 2
65+
// FAST-NEXT: %b.addr = alloca half, align 2
66+
// FAST-NEXT: %c.addr = alloca half, align 2
67+
// FAST-NEXT: %d.addr = alloca half, align 2
68+
// FAST-NEXT: store half %a, ptr %a.addr, align 2
69+
// FAST-NEXT: store half %b, ptr %b.addr, align 2
70+
// FAST-NEXT: store half %c, ptr %c.addr, align 2
71+
// FAST-NEXT: store half %d, ptr %d.addr, align 2
72+
// FAST-NEXT: %0 = load half, ptr %a.addr, align 2
73+
// FAST-NEXT: %ext = fpext half %0 to float
74+
// FAST-NEXT: %1 = load half, ptr %b.addr, align 2
75+
// FAST-NEXT: %ext1 = fpext half %1 to float
76+
// FAST-NEXT: %mul = fmul float %ext, %ext1
77+
// FAST-NEXT: %2 = load half, ptr %c.addr, align 2
78+
// FAST-NEXT: %ext2 = fpext half %2 to float
79+
// FAST-NEXT: %3 = load half, ptr %d.addr, align 2
80+
// FAST-NEXT: %ext3 = fpext half %3 to float
81+
// FAST-NEXT: %mul4 = fmul float %ext2, %ext3
82+
// FAST-NEXT: %add = fadd float %mul, %mul4
83+
// FAST-NEXT: %unpromotion = fptrunc float %add to half
84+
// FAST-NEXT: ret half %unpromotion
85+
// FAST-NEXT: }

clang/test/CodeGen/SystemZ/fp16.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -triple s390x-linux-gnu -emit-llvm -o - %s \
2+
// RUN: | FileCheck %s
3+
4+
void f(__fp16 *a, __fp16 *b, __fp16 *c, __fp16 *d, __fp16 *e) {
5+
*e = (*a) * (*b) + (*c) * (*d);
6+
}
7+
8+
// CHECK-LABEL: define dso_local void @f(ptr noundef %a, ptr noundef %b, ptr noundef %c, ptr noundef %d, ptr noundef %e) #0 {
9+
// CHECK-NEXT: entry:
10+
// CHECK-NEXT: %a.addr = alloca ptr, align 8
11+
// CHECK-NEXT: %b.addr = alloca ptr, align 8
12+
// CHECK-NEXT: %c.addr = alloca ptr, align 8
13+
// CHECK-NEXT: %d.addr = alloca ptr, align 8
14+
// CHECK-NEXT: %e.addr = alloca ptr, align 8
15+
// CHECK-NEXT: store ptr %a, ptr %a.addr, align 8
16+
// CHECK-NEXT: store ptr %b, ptr %b.addr, align 8
17+
// CHECK-NEXT: store ptr %c, ptr %c.addr, align 8
18+
// CHECK-NEXT: store ptr %d, ptr %d.addr, align 8
19+
// CHECK-NEXT: store ptr %e, ptr %e.addr, align 8
20+
// CHECK-NEXT: %0 = load ptr, ptr %a.addr, align 8
21+
// CHECK-NEXT: %1 = load half, ptr %0, align 2
22+
// CHECK-NEXT: %conv = fpext half %1 to float
23+
// CHECK-NEXT: %2 = load ptr, ptr %b.addr, align 8
24+
// CHECK-NEXT: %3 = load half, ptr %2, align 2
25+
// CHECK-NEXT: %conv1 = fpext half %3 to float
26+
// CHECK-NEXT: %mul = fmul float %conv, %conv1
27+
// CHECK-NEXT: %4 = load ptr, ptr %c.addr, align 8
28+
// CHECK-NEXT: %5 = load half, ptr %4, align 2
29+
// CHECK-NEXT: %conv2 = fpext half %5 to float
30+
// CHECK-NEXT: %6 = load ptr, ptr %d.addr, align 8
31+
// CHECK-NEXT: %7 = load half, ptr %6, align 2
32+
// CHECK-NEXT: %conv3 = fpext half %7 to float
33+
// CHECK-NEXT: %mul4 = fmul float %conv2, %conv3
34+
// CHECK-NEXT: %add = fadd float %mul, %mul4
35+
// CHECK-NEXT: %8 = fptrunc float %add to half
36+
// CHECK-NEXT: %9 = load ptr, ptr %e.addr, align 8
37+
// CHECK-NEXT: store half %8, ptr %9, align 2
38+
// CHECK-NEXT: ret void
39+
// CHECK-NEXT: }

clang/test/CodeGen/SystemZ/systemz-abi.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ long long pass_longlong(long long arg) { return arg; }
5252
__int128 pass_int128(__int128 arg) { return arg; }
5353
// CHECK-LABEL: define{{.*}} void @pass_int128(ptr dead_on_unwind noalias writable sret(i128) align 8 %{{.*}}, ptr %0)
5454

55+
_Float16 pass__Float16(_Float16 arg) { return arg; }
56+
// CHECK-LABEL: define{{.*}} half @pass__Float16(half %{{.*}})
57+
5558
float pass_float(float arg) { return arg; }
5659
// CHECK-LABEL: define{{.*}} float @pass_float(float %{{.*}})
5760

@@ -79,6 +82,9 @@ _Complex long pass_complex_long(_Complex long arg) { return arg; }
7982
_Complex long long pass_complex_longlong(_Complex long long arg) { return arg; }
8083
// CHECK-LABEL: define{{.*}} void @pass_complex_longlong(ptr dead_on_unwind noalias writable sret({ i64, i64 }) align 8 %{{.*}}, ptr %{{.*}}arg)
8184

85+
_Complex _Float16 pass_complex__Float16(_Complex _Float16 arg) { return arg; }
86+
// CHECK-LABEL: define{{.*}} void @pass_complex__Float16(ptr dead_on_unwind noalias writable sret({ half, half }) align 2 %{{.*}}, ptr %{{.*}}arg)
87+
8288
_Complex float pass_complex_float(_Complex float arg) { return arg; }
8389
// CHECK-LABEL: define{{.*}} void @pass_complex_float(ptr dead_on_unwind noalias writable sret({ float, float }) align 4 %{{.*}}, ptr %{{.*}}arg)
8490

@@ -130,6 +136,11 @@ struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; }
130136

131137
// Float-like aggregate types
132138

139+
struct agg__Float16 { _Float16 a; };
140+
struct agg__Float16 pass_agg__Float16(struct agg__Float16 arg) { return arg; }
141+
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, half %{{.*}})
142+
// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
143+
133144
struct agg_float { float a; };
134145
struct agg_float pass_agg_float(struct agg_float arg) { return arg; }
135146
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, float %{{.*}})
@@ -144,6 +155,11 @@ struct agg_longdouble { long double a; };
144155
struct agg_longdouble pass_agg_longdouble(struct agg_longdouble arg) { return arg; }
145156
// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}})
146157

158+
struct agg__Float16_a8 { _Float16 a __attribute__((aligned (8))); };
159+
struct agg__Float16_a8 pass_agg__Float16_a8(struct agg__Float16_a8 arg) { return arg; }
160+
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, double %{{.*}})
161+
// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, i64 %{{.*}})
162+
147163
struct agg_float_a8 { float a __attribute__((aligned (8))); };
148164
struct agg_float_a8 pass_agg_float_a8(struct agg_float_a8 arg) { return arg; }
149165
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a8) align 8 %{{.*}}, double %{{.*}})
@@ -171,6 +187,10 @@ struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; }
171187

172188
// Union types likewise are *not* float-like aggregate types
173189

190+
union union__Float16 { _Float16 a; };
191+
union union__Float16 pass_union__Float16(union union__Float16 arg) { return arg; }
192+
// CHECK-LABEL: define{{.*}} void @pass_union__Float16(ptr dead_on_unwind noalias writable sret(%union.union__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
193+
174194
union union_float { float a; };
175195
union union_float pass_union_float(union union_float arg) { return arg; }
176196
// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr dead_on_unwind noalias writable sret(%union.union_float) align 4 %{{.*}}, i32 noext %{{.*}})
@@ -448,6 +468,30 @@ struct agg_8byte va_agg_8byte(__builtin_va_list l) { return __builtin_va_arg(l,
448468
// CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
449469
// CHECK: ret void
450470

471+
struct agg__Float16 va_agg__Float16(__builtin_va_list l) { return __builtin_va_arg(l, struct agg__Float16); }
472+
// CHECK-LABEL: define{{.*}} void @va_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, ptr %{{.*}}
473+
// HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1
474+
// SOFT-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0
475+
// CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]]
476+
// HARD-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 4
477+
// SOFT-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5
478+
// CHECK: br i1 [[FITS_IN_REGS]],
479+
// CHECK: [[SCALED_REG_COUNT:%[^ ]+]] = mul i64 [[REG_COUNT]], 8
480+
// HARD-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 128
481+
// SOFT-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 22
482+
// CHECK: [[REG_SAVE_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 3
483+
// CHECK: [[REG_SAVE_AREA:%[^ ]+]] = load ptr, ptr [[REG_SAVE_AREA_PTR:[^ ]+]]
484+
// CHECK: [[RAW_REG_ADDR:%[^ ]+]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i64 [[REG_OFFSET]]
485+
// CHECK: [[REG_COUNT1:%[^ ]+]] = add i64 [[REG_COUNT]], 1
486+
// CHECK: store i64 [[REG_COUNT1]], ptr [[REG_COUNT_PTR]]
487+
// CHECK: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2
488+
// CHECK: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]]
489+
// CHECK: [[RAW_MEM_ADDR:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 6
490+
// CHECK: [[OVERFLOW_ARG_AREA2:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8
491+
// CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]]
492+
// CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
493+
// CHECK: ret void
494+
451495
struct agg_float va_agg_float(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_float); }
452496
// CHECK-LABEL: define{{.*}} void @va_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, ptr %{{.*}}
453497
// HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1

compiler-rt/test/builtins/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ foreach(arch ${BUILTIN_TEST_ARCH})
5656
string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}")
5757
endif()
5858
else()
59-
if (${arch} MATCHES "arm|armhf|aarch64|arm64|i?86|x86_64|AMD64|riscv32|riscv64" AND COMPILER_RT_HAS_${arch}_FLOAT16)
59+
if (${arch} MATCHES "arm|armhf|aarch64|arm64|i?86|x86_64|AMD64|riscv32|riscv64|s390x" AND COMPILER_RT_HAS_${arch}_FLOAT16)
6060
list(APPEND BUILTINS_TEST_TARGET_CFLAGS -DCOMPILER_RT_HAS_FLOAT16)
6161
string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}")
6262
endif()

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,9 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
253253
}
254254
setLibcallName(RTLIB::MULO_I128, nullptr);
255255
}
256+
257+
if (TT.isSystemZ()) {
258+
setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
259+
setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
260+
}
256261
}

llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ enum RegisterKind {
6161
GRH32Reg,
6262
GR64Reg,
6363
GR128Reg,
64+
FP16Reg,
6465
FP32Reg,
6566
FP64Reg,
6667
FP128Reg,
68+
VR16Reg,
6769
VR32Reg,
6870
VR64Reg,
6971
VR128Reg,
@@ -365,9 +367,11 @@ class SystemZOperand : public MCParsedAsmOperand {
365367
bool isADDR32() const { return isReg(GR32Reg); }
366368
bool isADDR64() const { return isReg(GR64Reg); }
367369
bool isADDR128() const { return false; }
370+
bool isFP16() const { return isReg(FP16Reg); }
368371
bool isFP32() const { return isReg(FP32Reg); }
369372
bool isFP64() const { return isReg(FP64Reg); }
370373
bool isFP128() const { return isReg(FP128Reg); }
374+
bool isVR16() const { return isReg(VR16Reg); }
371375
bool isVR32() const { return isReg(VR32Reg); }
372376
bool isVR64() const { return isReg(VR64Reg); }
373377
bool isVF128() const { return false; }
@@ -544,6 +548,9 @@ class SystemZAsmParser : public MCTargetAsmParser {
544548
ParseStatus parseADDR128(OperandVector &Operands) {
545549
llvm_unreachable("Shouldn't be used as an operand");
546550
}
551+
ParseStatus parseFP16(OperandVector &Operands) {
552+
return parseRegister(Operands, FP16Reg);
553+
}
547554
ParseStatus parseFP32(OperandVector &Operands) {
548555
return parseRegister(Operands, FP32Reg);
549556
}
@@ -553,6 +560,9 @@ class SystemZAsmParser : public MCTargetAsmParser {
553560
ParseStatus parseFP128(OperandVector &Operands) {
554561
return parseRegister(Operands, FP128Reg);
555562
}
563+
ParseStatus parseVR16(OperandVector &Operands) {
564+
return parseRegister(Operands, VR16Reg);
565+
}
556566
ParseStatus parseVR32(OperandVector &Operands) {
557567
return parseRegister(Operands, VR32Reg);
558568
}
@@ -842,11 +852,13 @@ ParseStatus SystemZAsmParser::parseRegister(OperandVector &Operands,
842852
case GR128Reg:
843853
Group = RegGR;
844854
break;
855+
case FP16Reg:
845856
case FP32Reg:
846857
case FP64Reg:
847858
case FP128Reg:
848859
Group = RegFP;
849860
break;
861+
case VR16Reg:
850862
case VR32Reg:
851863
case VR64Reg:
852864
case VR128Reg:
@@ -895,9 +907,11 @@ ParseStatus SystemZAsmParser::parseRegister(OperandVector &Operands,
895907
case GRH32Reg: Regs = SystemZMC::GRH32Regs; break;
896908
case GR64Reg: Regs = SystemZMC::GR64Regs; break;
897909
case GR128Reg: Regs = SystemZMC::GR128Regs; break;
910+
case FP16Reg: Regs = SystemZMC::FP16Regs; break;
898911
case FP32Reg: Regs = SystemZMC::FP32Regs; break;
899912
case FP64Reg: Regs = SystemZMC::FP64Regs; break;
900913
case FP128Reg: Regs = SystemZMC::FP128Regs; break;
914+
case VR16Reg: Regs = SystemZMC::VR16Regs; break;
901915
case VR32Reg: Regs = SystemZMC::VR32Regs; break;
902916
case VR64Reg: Regs = SystemZMC::VR64Regs; break;
903917
case VR128Reg: Regs = SystemZMC::VR128Regs; break;

0 commit comments

Comments
 (0)