@@ -46,6 +46,17 @@ static RValue buildLibraryCall(CIRGenFunction &CGF, const FunctionDecl *FD,
46
46
return CGF.buildCall (E->getCallee ()->getType (), callee, E, ReturnValueSlot ());
47
47
}
48
48
49
+ static mlir::Value tryUseTestFPKind (CIRGenFunction &CGF, unsigned BuiltinID,
50
+ mlir::Value V) {
51
+ if (CGF.getBuilder ().getIsFPConstrained () &&
52
+ CGF.getBuilder ().getDefaultConstrainedExcept () != fp::ebIgnore) {
53
+ if (mlir::Value Result = CGF.getTargetHooks ().testFPKind (
54
+ V, BuiltinID, CGF.getBuilder (), CGF.CGM ))
55
+ return Result;
56
+ }
57
+ return nullptr ;
58
+ }
59
+
49
60
template <class Operation >
50
61
static RValue buildUnaryFPBuiltin (CIRGenFunction &CGF, const CallExpr &E) {
51
62
auto Arg = CGF.buildScalarExpr (E.getArg (0 ));
@@ -1191,36 +1202,6 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
1191
1202
case Builtin::BI__builtin_isunordered:
1192
1203
llvm_unreachable (" BI__builtin_isgreater and BI__builtin_isless like NYI" );
1193
1204
1194
- case Builtin::BI__builtin_isnan:
1195
- llvm_unreachable (" BI__builtin_isnan NYI" );
1196
-
1197
- case Builtin::BI__builtin_issignaling:
1198
- llvm_unreachable (" BI__builtin_issignaling NYI" );
1199
-
1200
- case Builtin::BI__builtin_isinf:
1201
- llvm_unreachable (" BI__builtin_isinf NYI" );
1202
-
1203
- case Builtin::BIfinite:
1204
- case Builtin::BI__finite:
1205
- case Builtin::BIfinitef:
1206
- case Builtin::BI__finitef:
1207
- case Builtin::BIfinitel:
1208
- case Builtin::BI__finitel:
1209
- case Builtin::BI__builtin_isfinite:
1210
- llvm_unreachable (" Builtin::BIfinite like NYI" );
1211
-
1212
- case Builtin::BI__builtin_isnormal:
1213
- llvm_unreachable (" BI__builtin_isnormal NYI" );
1214
-
1215
- case Builtin::BI__builtin_issubnormal:
1216
- llvm_unreachable (" BI__builtin_issubnormal NYI" );
1217
-
1218
- case Builtin::BI__builtin_iszero:
1219
- llvm_unreachable (" BI__builtin_iszero NYI" );
1220
-
1221
- case Builtin::BI__builtin_isfpclass:
1222
- llvm_unreachable (" BI__builtin_isfpclass NYI" );
1223
-
1224
1205
case Builtin::BI__builtin_nondeterministic_value:
1225
1206
llvm_unreachable (" BI__builtin_nondeterministic_value NYI" );
1226
1207
@@ -1328,9 +1309,6 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
1328
1309
case Builtin::BI__builtin_matrix_column_major_store:
1329
1310
llvm_unreachable (" BI__builtin_matrix_column_major_store NYI" );
1330
1311
1331
- case Builtin::BI__builtin_isinf_sign:
1332
- llvm_unreachable (" BI__builtin_isinf_sign NYI" );
1333
-
1334
1312
case Builtin::BI__builtin_flt_rounds:
1335
1313
llvm_unreachable (" BI__builtin_flt_rounds NYI" );
1336
1314
@@ -2080,6 +2058,110 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
2080
2058
llvm_unreachable (" BI__builtin_ms_va_copy NYI" );
2081
2059
case Builtin::BI__builtin_get_device_side_mangled_name:
2082
2060
llvm_unreachable (" BI__builtin_get_device_side_mangled_name NYI" );
2061
+
2062
+ // From https://clang.llvm.org/docs/LanguageExtensions.html#builtin-isfpclass
2063
+ // :
2064
+ //
2065
+ // The `__builtin_isfpclass()` builtin is a generalization of functions
2066
+ // isnan, isinf, isfinite and some others defined by the C standard. It tests
2067
+ // if the floating-point value, specified by the first argument, falls into
2068
+ // any of data classes, specified by the second argument.
2069
+ case Builtin::BI__builtin_isnan: {
2070
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2071
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2072
+ if (mlir::Value Result = tryUseTestFPKind (*this , BuiltinID, V))
2073
+ return RValue::get (Result);
2074
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2075
+ // FIXME: We should use builder.createZExt once createZExt is available.
2076
+ return RValue::get (builder.createZExtOrBitCast (
2077
+ Loc, builder.createIsFPClass (Loc, V, FPClassTest::fcNan),
2078
+ ConvertType (E->getType ())));
2079
+ }
2080
+
2081
+ case Builtin::BI__builtin_issignaling: {
2082
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2083
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2084
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2085
+ // FIXME: We should use builder.createZExt once createZExt is available.
2086
+ return RValue::get (builder.createZExtOrBitCast (
2087
+ Loc, builder.createIsFPClass (Loc, V, FPClassTest::fcSNan),
2088
+ ConvertType (E->getType ())));
2089
+ }
2090
+
2091
+ case Builtin::BI__builtin_isinf: {
2092
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2093
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2094
+ if (mlir::Value Result = tryUseTestFPKind (*this , BuiltinID, V))
2095
+ return RValue::get (Result);
2096
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2097
+ // FIXME: We should use builder.createZExt once createZExt is available.
2098
+ return RValue::get (builder.createZExtOrBitCast (
2099
+ Loc, builder.createIsFPClass (Loc, V, FPClassTest::fcInf),
2100
+ ConvertType (E->getType ())));
2101
+ }
2102
+
2103
+ case Builtin::BIfinite:
2104
+ case Builtin::BI__finite:
2105
+ case Builtin::BIfinitef:
2106
+ case Builtin::BI__finitef:
2107
+ case Builtin::BIfinitel:
2108
+ case Builtin::BI__finitel:
2109
+ case Builtin::BI__builtin_isfinite: {
2110
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2111
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2112
+ if (mlir::Value Result = tryUseTestFPKind (*this , BuiltinID, V))
2113
+ return RValue::get (Result);
2114
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2115
+ // FIXME: We should use builder.createZExt once createZExt is available.
2116
+ return RValue::get (builder.createZExtOrBitCast (
2117
+ Loc, builder.createIsFPClass (Loc, V, FPClassTest::fcFinite),
2118
+ ConvertType (E->getType ())));
2119
+ }
2120
+
2121
+ case Builtin::BI__builtin_isnormal: {
2122
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2123
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2124
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2125
+ // FIXME: We should use builder.createZExt once createZExt is available.
2126
+ return RValue::get (builder.createZExtOrBitCast (
2127
+ Loc, builder.createIsFPClass (Loc, V, FPClassTest::fcNormal),
2128
+ ConvertType (E->getType ())));
2129
+ }
2130
+
2131
+ case Builtin::BI__builtin_issubnormal: {
2132
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2133
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2134
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2135
+ // FIXME: We should use builder.createZExt once createZExt is available.
2136
+ return RValue::get (builder.createZExtOrBitCast (
2137
+ Loc, builder.createIsFPClass (Loc, V, FPClassTest::fcSubnormal),
2138
+ ConvertType (E->getType ())));
2139
+ }
2140
+
2141
+ case Builtin::BI__builtin_iszero: {
2142
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2143
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2144
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2145
+ // FIXME: We should use builder.createZExt once createZExt is available.
2146
+ return RValue::get (builder.createZExtOrBitCast (
2147
+ Loc, builder.createIsFPClass (Loc, V, FPClassTest::fcZero),
2148
+ ConvertType (E->getType ())));
2149
+ }
2150
+
2151
+ case Builtin::BI__builtin_isfpclass: {
2152
+ Expr::EvalResult Result;
2153
+ if (!E->getArg (1 )->EvaluateAsInt (Result, CGM.getASTContext ()))
2154
+ break ;
2155
+
2156
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII (*this , E);
2157
+ mlir::Value V = buildScalarExpr (E->getArg (0 ));
2158
+ uint64_t Test = Result.Val .getInt ().getLimitedValue ();
2159
+ mlir::Location Loc = getLoc (E->getBeginLoc ());
2160
+
2161
+ // FIXME: We should use builder.createZExt once createZExt is available.
2162
+ return RValue::get (builder.createZExtOrBitCast (
2163
+ Loc, builder.createIsFPClass (Loc, V, Test), ConvertType (E->getType ())));
2164
+ }
2083
2165
}
2084
2166
2085
2167
// If this is an alias for a lib function (e.g. __builtin_sin), emit
0 commit comments