Skip to content

Commit e1862ca

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 7661526 commit e1862ca

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
@@ -984,6 +984,7 @@ to ``float``; see below for more information on this emulation.
984984
* SPIR (natively)
985985
* X86 (if SSE2 is available; natively if AVX512-FP16 is also available)
986986
* RISC-V (natively if Zfh or Zhinx is available)
987+
* SystemZ (emulated)
987988

988989
* ``__bf16`` is supported on the following targets (currently never natively):
989990

clang/lib/Basic/Targets/SystemZ.h

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

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

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

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
@@ -50,6 +50,9 @@ long long pass_longlong(long long arg) { return arg; }
5050
__int128 pass_int128(__int128 arg) { return arg; }
5151
// CHECK-LABEL: define{{.*}} void @pass_int128(ptr dead_on_unwind noalias writable sret(i128) align 8 %{{.*}}, ptr %0)
5252

53+
_Float16 pass__Float16(_Float16 arg) { return arg; }
54+
// CHECK-LABEL: define{{.*}} half @pass__Float16(half %{{.*}})
55+
5356
float pass_float(float arg) { return arg; }
5457
// CHECK-LABEL: define{{.*}} float @pass_float(float %{{.*}})
5558

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

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

@@ -128,6 +134,11 @@ struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; }
128134

129135
// Float-like aggregate types
130136

137+
struct agg__Float16 { _Float16 a; };
138+
struct agg__Float16 pass_agg__Float16(struct agg__Float16 arg) { return arg; }
139+
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, half %{{.*}})
140+
// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
141+
131142
struct agg_float { float a; };
132143
struct agg_float pass_agg_float(struct agg_float arg) { return arg; }
133144
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, float %{{.*}})
@@ -142,6 +153,11 @@ struct agg_longdouble { long double a; };
142153
struct agg_longdouble pass_agg_longdouble(struct agg_longdouble arg) { return arg; }
143154
// CHECK-LABEL: define{{.*}} void @pass_agg_longdouble(ptr dead_on_unwind noalias writable sret(%struct.agg_longdouble) align 8 %{{.*}}, ptr %{{.*}})
144155

156+
struct agg__Float16_a8 { _Float16 a __attribute__((aligned (8))); };
157+
struct agg__Float16_a8 pass_agg__Float16_a8(struct agg__Float16_a8 arg) { return arg; }
158+
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, double %{{.*}})
159+
// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg__Float16_a8(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16_a8) align 8 %{{.*}}, i64 %{{.*}})
160+
145161
struct agg_float_a8 { float a __attribute__((aligned (8))); };
146162
struct agg_float_a8 pass_agg_float_a8(struct agg_float_a8 arg) { return arg; }
147163
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float_a8(ptr dead_on_unwind noalias writable sret(%struct.agg_float_a8) align 8 %{{.*}}, double %{{.*}})
@@ -169,6 +185,10 @@ struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; }
169185

170186
// Union types likewise are *not* float-like aggregate types
171187

188+
union union__Float16 { _Float16 a; };
189+
union union__Float16 pass_union__Float16(union union__Float16 arg) { return arg; }
190+
// CHECK-LABEL: define{{.*}} void @pass_union__Float16(ptr dead_on_unwind noalias writable sret(%union.union__Float16) align 2 %{{.*}}, i16 noext %{{.*}})
191+
172192
union union_float { float a; };
173193
union union_float pass_union_float(union union_float arg) { return arg; }
174194
// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr dead_on_unwind noalias writable sret(%union.union_float) align 4 %{{.*}}, i32 noext %{{.*}})
@@ -446,6 +466,30 @@ struct agg_8byte va_agg_8byte(__builtin_va_list l) { return __builtin_va_arg(l,
446466
// CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
447467
// CHECK: ret void
448468

469+
struct agg__Float16 va_agg__Float16(__builtin_va_list l) { return __builtin_va_arg(l, struct agg__Float16); }
470+
// CHECK-LABEL: define{{.*}} void @va_agg__Float16(ptr dead_on_unwind noalias writable sret(%struct.agg__Float16) align 2 %{{.*}}, ptr %{{.*}}
471+
// HARD-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 1
472+
// SOFT-FLOAT: [[REG_COUNT_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 0
473+
// CHECK: [[REG_COUNT:%[^ ]+]] = load i64, ptr [[REG_COUNT_PTR]]
474+
// HARD-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 4
475+
// SOFT-FLOAT: [[FITS_IN_REGS:%[^ ]+]] = icmp ult i64 [[REG_COUNT]], 5
476+
// CHECK: br i1 [[FITS_IN_REGS]],
477+
// CHECK: [[SCALED_REG_COUNT:%[^ ]+]] = mul i64 [[REG_COUNT]], 8
478+
// HARD-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 128
479+
// SOFT-FLOAT: [[REG_OFFSET:%[^ ]+]] = add i64 [[SCALED_REG_COUNT]], 22
480+
// CHECK: [[REG_SAVE_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 3
481+
// CHECK: [[REG_SAVE_AREA:%[^ ]+]] = load ptr, ptr [[REG_SAVE_AREA_PTR:[^ ]+]]
482+
// CHECK: [[RAW_REG_ADDR:%[^ ]+]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i64 [[REG_OFFSET]]
483+
// CHECK: [[REG_COUNT1:%[^ ]+]] = add i64 [[REG_COUNT]], 1
484+
// CHECK: store i64 [[REG_COUNT1]], ptr [[REG_COUNT_PTR]]
485+
// CHECK: [[OVERFLOW_ARG_AREA_PTR:%[^ ]+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %{{.*}}, i32 0, i32 2
486+
// CHECK: [[OVERFLOW_ARG_AREA:%[^ ]+]] = load ptr, ptr [[OVERFLOW_ARG_AREA_PTR]]
487+
// CHECK: [[RAW_MEM_ADDR:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 6
488+
// CHECK: [[OVERFLOW_ARG_AREA2:%[^ ]+]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i64 8
489+
// CHECK: store ptr [[OVERFLOW_ARG_AREA2]], ptr [[OVERFLOW_ARG_AREA_PTR]]
490+
// CHECK: [[VA_ARG_ADDR:%[^ ]+]] = phi ptr [ [[RAW_REG_ADDR]], %{{.*}} ], [ [[RAW_MEM_ADDR]], %{{.*}} ]
491+
// CHECK: ret void
492+
449493
struct agg_float va_agg_float(__builtin_va_list l) { return __builtin_va_arg(l, struct agg_float); }
450494
// CHECK-LABEL: define{{.*}} void @va_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, ptr %{{.*}}
451495
// 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
@@ -252,4 +252,9 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
252252
}
253253
setLibcallName(RTLIB::MULO_I128, nullptr);
254254
}
255+
256+
if (TT.isSystemZ()) {
257+
setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
258+
setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
259+
}
255260
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@ enum RegisterKind {
6060
GRH32Reg,
6161
GR64Reg,
6262
GR128Reg,
63+
FP16Reg,
6364
FP32Reg,
6465
FP64Reg,
6566
FP128Reg,
67+
VR16Reg,
6668
VR32Reg,
6769
VR64Reg,
6870
VR128Reg,
@@ -364,9 +366,11 @@ class SystemZOperand : public MCParsedAsmOperand {
364366
bool isADDR32() const { return isReg(GR32Reg); }
365367
bool isADDR64() const { return isReg(GR64Reg); }
366368
bool isADDR128() const { return false; }
369+
bool isFP16() const { return isReg(FP16Reg); }
367370
bool isFP32() const { return isReg(FP32Reg); }
368371
bool isFP64() const { return isReg(FP64Reg); }
369372
bool isFP128() const { return isReg(FP128Reg); }
373+
bool isVR16() const { return isReg(VR16Reg); }
370374
bool isVR32() const { return isReg(VR32Reg); }
371375
bool isVR64() const { return isReg(VR64Reg); }
372376
bool isVF128() const { return false; }
@@ -543,6 +547,9 @@ class SystemZAsmParser : public MCTargetAsmParser {
543547
ParseStatus parseADDR128(OperandVector &Operands) {
544548
llvm_unreachable("Shouldn't be used as an operand");
545549
}
550+
ParseStatus parseFP16(OperandVector &Operands) {
551+
return parseRegister(Operands, FP16Reg);
552+
}
546553
ParseStatus parseFP32(OperandVector &Operands) {
547554
return parseRegister(Operands, FP32Reg);
548555
}
@@ -552,6 +559,9 @@ class SystemZAsmParser : public MCTargetAsmParser {
552559
ParseStatus parseFP128(OperandVector &Operands) {
553560
return parseRegister(Operands, FP128Reg);
554561
}
562+
ParseStatus parseVR16(OperandVector &Operands) {
563+
return parseRegister(Operands, VR16Reg);
564+
}
555565
ParseStatus parseVR32(OperandVector &Operands) {
556566
return parseRegister(Operands, VR32Reg);
557567
}
@@ -841,11 +851,13 @@ ParseStatus SystemZAsmParser::parseRegister(OperandVector &Operands,
841851
case GR128Reg:
842852
Group = RegGR;
843853
break;
854+
case FP16Reg:
844855
case FP32Reg:
845856
case FP64Reg:
846857
case FP128Reg:
847858
Group = RegFP;
848859
break;
860+
case VR16Reg:
849861
case VR32Reg:
850862
case VR64Reg:
851863
case VR128Reg:
@@ -894,9 +906,11 @@ ParseStatus SystemZAsmParser::parseRegister(OperandVector &Operands,
894906
case GRH32Reg: Regs = SystemZMC::GRH32Regs; break;
895907
case GR64Reg: Regs = SystemZMC::GR64Regs; break;
896908
case GR128Reg: Regs = SystemZMC::GR128Regs; break;
909+
case FP16Reg: Regs = SystemZMC::FP16Regs; break;
897910
case FP32Reg: Regs = SystemZMC::FP32Regs; break;
898911
case FP64Reg: Regs = SystemZMC::FP64Regs; break;
899912
case FP128Reg: Regs = SystemZMC::FP128Regs; break;
913+
case VR16Reg: Regs = SystemZMC::VR16Regs; break;
900914
case VR32Reg: Regs = SystemZMC::VR32Regs; break;
901915
case VR64Reg: Regs = SystemZMC::VR64Regs; break;
902916
case VR128Reg: Regs = SystemZMC::VR128Regs; break;

0 commit comments

Comments
 (0)