Skip to content

Commit 632273a

Browse files
Lancernlanza
authored andcommitted
[CIR][CIRGen] Add support for __fp16 type (#950)
This PR adds support for the `__fp16` type. CIRGen and LLVM lowering is included. Resolve #900 .
1 parent 8c8b2ce commit 632273a

File tree

3 files changed

+866
-10
lines changed

3 files changed

+866
-10
lines changed

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

+56-8
Original file line numberDiff line numberDiff line change
@@ -502,16 +502,25 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
502502
// TODO(cir): CGFPOptionsRAII
503503
assert(!MissingFeatures::CGFPOptionsRAII());
504504

505-
if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType)
506-
llvm_unreachable("__fp16 type NYI");
505+
if (type->isHalfType() &&
506+
!CGF.getContext().getLangOpts().NativeHalfType) {
507+
// Another special case: half FP increment should be done via float
508+
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
509+
llvm_unreachable("cast via llvm.convert.from.fp16 is NYI");
510+
} else {
511+
value = Builder.createCast(CGF.getLoc(E->getExprLoc()),
512+
mlir::cir::CastKind::floating, input,
513+
CGF.CGM.FloatTy);
514+
}
515+
}
507516

508517
if (mlir::isa<mlir::cir::SingleType, mlir::cir::DoubleType>(
509518
value.getType())) {
510519
// Create the inc/dec operation.
511520
// NOTE(CIR): clang calls CreateAdd but folds this to a unary op
512521
auto kind =
513522
(isInc ? mlir::cir::UnaryOpKind::Inc : mlir::cir::UnaryOpKind::Dec);
514-
value = buildUnaryOp(E, kind, input);
523+
value = buildUnaryOp(E, kind, value);
515524
} else {
516525
// Remaining types are Half, Bfloat16, LongDouble, __ibm128 or
517526
// __float128. Convert from float.
@@ -537,8 +546,16 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
537546
value = Builder.createBinop(value, mlir::cir::BinOpKind::Add, amt);
538547
}
539548

540-
if (type->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType)
541-
llvm_unreachable("NYI");
549+
if (type->isHalfType() &&
550+
!CGF.getContext().getLangOpts().NativeHalfType) {
551+
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
552+
llvm_unreachable("cast via llvm.convert.to.fp16 is NYI");
553+
} else {
554+
value = Builder.createCast(CGF.getLoc(E->getExprLoc()),
555+
mlir::cir::CastKind::floating, value,
556+
input.getType());
557+
}
558+
}
542559

543560
} else if (type->isFixedPointType()) {
544561
llvm_unreachable("no fixed point inc/dec yet");
@@ -1043,7 +1060,23 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
10431060
// Cast from half through float if half isn't a native type.
10441061
if (SrcType->isHalfType() &&
10451062
!CGF.getContext().getLangOpts().NativeHalfType) {
1046-
llvm_unreachable("not implemented");
1063+
// Cast to FP using the intrinsic if the half type itself isn't supported.
1064+
if (mlir::isa<mlir::cir::CIRFPTypeInterface>(DstTy)) {
1065+
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
1066+
llvm_unreachable("cast via llvm.convert.from.fp16 is NYI");
1067+
} else {
1068+
// Cast to other types through float, using either the intrinsic or
1069+
// FPExt, depending on whether the half type itself is supported (as
1070+
// opposed to operations on half, available with NativeHalfType).
1071+
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1072+
llvm_unreachable("cast via llvm.convert.from.fp16 is NYI");
1073+
} else {
1074+
Src = Builder.createCast(
1075+
CGF.getLoc(Loc), mlir::cir::CastKind::floating, Src, CGF.FloatTy);
1076+
}
1077+
SrcType = CGF.getContext().FloatTy;
1078+
SrcTy = CGF.FloatTy;
1079+
}
10471080
}
10481081

10491082
// TODO(cir): LLVM codegen ignore conversions like int -> uint,
@@ -1098,13 +1131,28 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
10981131
// Cast to half through float if half isn't a native type.
10991132
if (DstType->isHalfType() &&
11001133
!CGF.getContext().getLangOpts().NativeHalfType) {
1101-
llvm_unreachable("NYI");
1134+
// Make sure we cast in a single step if from another FP type.
1135+
if (mlir::isa<mlir::cir::CIRFPTypeInterface>(SrcTy)) {
1136+
// Use the intrinsic if the half type itself isn't supported
1137+
// (as opposed to operations on half, available with NativeHalfType).
1138+
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics())
1139+
llvm_unreachable("cast via llvm.convert.to.fp16 is NYI");
1140+
// If the half type is supported, just use an fptrunc.
1141+
return Builder.createCast(CGF.getLoc(Loc),
1142+
mlir::cir::CastKind::floating, Src, DstTy);
1143+
}
1144+
DstTy = CGF.FloatTy;
11021145
}
11031146

11041147
Res = buildScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
11051148

11061149
if (DstTy != ResTy) {
1107-
llvm_unreachable("NYI");
1150+
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1151+
llvm_unreachable("cast via llvm.convert.to.fp16 is NYI");
1152+
} else {
1153+
Res = Builder.createCast(CGF.getLoc(Loc), mlir::cir::CastKind::floating,
1154+
Res, ResTy);
1155+
}
11081156
}
11091157

11101158
if (Opts.EmitImplicitIntegerTruncationChecks)

clang/lib/CIR/CodeGen/CIRGenTypes.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,11 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) {
470470
ResultType = CGM.FP16Ty;
471471
break;
472472
case BuiltinType::Half:
473-
// Should be the same as above?
474-
assert(0 && "not implemented");
473+
if (Context.getLangOpts().NativeHalfType ||
474+
!Context.getTargetInfo().useFP16ConversionIntrinsics())
475+
ResultType = CGM.FP16Ty;
476+
else
477+
llvm_unreachable("NYI");
475478
break;
476479
case BuiltinType::BFloat16:
477480
ResultType = CGM.BFloat16Ty;

0 commit comments

Comments
 (0)