@@ -46,6 +46,17 @@ static RValue buildLibraryCall(CIRGenFunction &CGF, const FunctionDecl *FD,
4646 return CGF.buildCall (E->getCallee ()->getType (), callee, E, ReturnValueSlot ());
4747}
4848
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+
4960template <class Operation >
5061static RValue buildUnaryFPBuiltin (CIRGenFunction &CGF, const CallExpr &E) {
5162 auto Arg = CGF.buildScalarExpr (E.getArg (0 ));
@@ -1191,36 +1202,6 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
11911202 case Builtin::BI__builtin_isunordered:
11921203 llvm_unreachable (" BI__builtin_isgreater and BI__builtin_isless like NYI" );
11931204
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-
12241205 case Builtin::BI__builtin_nondeterministic_value:
12251206 llvm_unreachable (" BI__builtin_nondeterministic_value NYI" );
12261207
@@ -1328,9 +1309,6 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
13281309 case Builtin::BI__builtin_matrix_column_major_store:
13291310 llvm_unreachable (" BI__builtin_matrix_column_major_store NYI" );
13301311
1331- case Builtin::BI__builtin_isinf_sign:
1332- llvm_unreachable (" BI__builtin_isinf_sign NYI" );
1333-
13341312 case Builtin::BI__builtin_flt_rounds:
13351313 llvm_unreachable (" BI__builtin_flt_rounds NYI" );
13361314
@@ -2080,6 +2058,110 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
20802058 llvm_unreachable (" BI__builtin_ms_va_copy NYI" );
20812059 case Builtin::BI__builtin_get_device_side_mangled_name:
20822060 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+ }
20832165 }
20842166
20852167 // If this is an alias for a lib function (e.g. __builtin_sin), emit
0 commit comments