@@ -502,16 +502,26 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
502
502
// TODO(cir): CGFPOptionsRAII
503
503
assert (!MissingFeatures::CGFPOptionsRAII ());
504
504
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
+ value = Builder.createCastFromFP16 (CGF.getLoc (E->getExprLoc ()), input,
510
+ CGF.CGM .FloatTy );
511
+ } else {
512
+ value = Builder.createCast (CGF.getLoc (E->getExprLoc ()),
513
+ mlir::cir::CastKind::floating, input,
514
+ CGF.CGM .FloatTy );
515
+ }
516
+ }
507
517
508
518
if (mlir::isa<mlir::cir::SingleType, mlir::cir::DoubleType>(
509
519
value.getType ())) {
510
520
// Create the inc/dec operation.
511
521
// NOTE(CIR): clang calls CreateAdd but folds this to a unary op
512
522
auto kind =
513
523
(isInc ? mlir::cir::UnaryOpKind::Inc : mlir::cir::UnaryOpKind::Dec);
514
- value = buildUnaryOp (E, kind, input );
524
+ value = buildUnaryOp (E, kind, value );
515
525
} else {
516
526
// Remaining types are Half, Bfloat16, LongDouble, __ibm128 or
517
527
// __float128. Convert from float.
@@ -537,8 +547,16 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
537
547
value = Builder.createBinop (value, mlir::cir::BinOpKind::Add, amt);
538
548
}
539
549
540
- if (type->isHalfType () && !CGF.getContext ().getLangOpts ().NativeHalfType )
541
- llvm_unreachable (" NYI" );
550
+ if (type->isHalfType () &&
551
+ !CGF.getContext ().getLangOpts ().NativeHalfType ) {
552
+ if (CGF.getContext ().getTargetInfo ().useFP16ConversionIntrinsics ()) {
553
+ value = Builder.createCastToFP16 (CGF.getLoc (E->getExprLoc ()), value);
554
+ } else {
555
+ value = Builder.createCast (CGF.getLoc (E->getExprLoc ()),
556
+ mlir::cir::CastKind::floating, value,
557
+ input.getType ());
558
+ }
559
+ }
542
560
543
561
} else if (type->isFixedPointType ()) {
544
562
llvm_unreachable (" no fixed point inc/dec yet" );
@@ -1043,7 +1061,23 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
1043
1061
// Cast from half through float if half isn't a native type.
1044
1062
if (SrcType->isHalfType () &&
1045
1063
!CGF.getContext ().getLangOpts ().NativeHalfType ) {
1046
- llvm_unreachable (" not implemented" );
1064
+ // Cast to FP using the intrinsic if the half type itself isn't supported.
1065
+ if (mlir::isa<mlir::cir::CIRFPTypeInterface>(DstTy)) {
1066
+ if (CGF.getContext ().getTargetInfo ().useFP16ConversionIntrinsics ())
1067
+ return Builder.createCastFromFP16 (CGF.getLoc (Loc), Src, DstTy);
1068
+ } else {
1069
+ // Cast to other types through float, using either the intrinsic or
1070
+ // FPExt, depending on whether the half type itself is supported (as
1071
+ // opposed to operations on half, available with NativeHalfType).
1072
+ if (CGF.getContext ().getTargetInfo ().useFP16ConversionIntrinsics ()) {
1073
+ Src = Builder.createCastFromFP16 (CGF.getLoc (Loc), Src, DstTy);
1074
+ } else {
1075
+ Src = Builder.createCast (
1076
+ CGF.getLoc (Loc), mlir::cir::CastKind::floating, Src, CGF.FloatTy );
1077
+ }
1078
+ SrcType = CGF.getContext ().FloatTy ;
1079
+ SrcTy = CGF.FloatTy ;
1080
+ }
1047
1081
}
1048
1082
1049
1083
// TODO(cir): LLVM codegen ignore conversions like int -> uint,
@@ -1098,13 +1132,30 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
1098
1132
// Cast to half through float if half isn't a native type.
1099
1133
if (DstType->isHalfType () &&
1100
1134
!CGF.getContext ().getLangOpts ().NativeHalfType ) {
1101
- llvm_unreachable (" NYI" );
1135
+ // Make sure we cast in a single step if from another FP type.
1136
+ if (mlir::isa<mlir::cir::CIRFPTypeInterface>(SrcTy)) {
1137
+ // Use the intrinsic if the half type itself isn't supported
1138
+ // (as opposed to operations on half, available with NativeHalfType).
1139
+ if (CGF.getContext ().getTargetInfo ().useFP16ConversionIntrinsics ())
1140
+ return Builder.createCastToFP16 (CGF.getLoc (Loc), Src);
1141
+ // If the half type is supported, just use an fptrunc.
1142
+ return Builder.createCast (CGF.getLoc (Loc),
1143
+ mlir::cir::CastKind::floating, Src, DstTy);
1144
+ }
1145
+ DstTy = CGF.FloatTy ;
1102
1146
}
1103
1147
1104
1148
Res = buildScalarCast (Src, SrcType, DstType, SrcTy, DstTy, Opts);
1105
1149
1106
1150
if (DstTy != ResTy) {
1107
- llvm_unreachable (" NYI" );
1151
+ if (CGF.getContext ().getTargetInfo ().useFP16ConversionIntrinsics ()) {
1152
+ assert (mlir::cast<mlir::cir::StorageOnlyFP16Type>(ResTy) &&
1153
+ " only storage-only fp16 requires extra conversion" );
1154
+ Res = Builder.createCastToFP16 (CGF.getLoc (Loc), Res);
1155
+ } else {
1156
+ Res = Builder.createCast (CGF.getLoc (Loc), mlir::cir::CastKind::floating,
1157
+ Res, ResTy);
1158
+ }
1108
1159
}
1109
1160
1110
1161
if (Opts.EmitImplicitIntegerTruncationChecks )
0 commit comments