@@ -29,6 +29,16 @@ using namespace clang;
2929using namespace clang ::CIRGen;
3030using namespace llvm ;
3131
32+ static mlir::Value tryUseTestFPKind (CIRGenFunction &cgf, unsigned BuiltinID,
33+ mlir::Value V) {
34+ if (cgf.getBuilder ().getIsFPConstrained () &&
35+ cgf.getBuilder ().getDefaultConstrainedExcept () != cir::fp::ebIgnore) {
36+ if (mlir::Value Result = cgf.getTargetHooks ().testFPKind (
37+ V, BuiltinID, cgf.getBuilder (), cgf.cgm ))
38+ return Result;
39+ }
40+ return nullptr ;
41+ }
3242static RValue emitLibraryCall (CIRGenFunction &cgf, const FunctionDecl *fd,
3343 const CallExpr *e, mlir::Operation *calleeValue) {
3444 CIRGenCallee callee = CIRGenCallee::forDirect (calleeValue, GlobalDecl (fd));
@@ -454,14 +464,117 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
454464 assert (!cir::MissingFeatures::coroSizeBuiltinCall ());
455465 return getUndefRValue (e->getType ());
456466 }
467+ // From https://clang.llvm.org/docs/LanguageExtensions.html#builtin-isfpclass
468+ // :
469+ //
470+ // The `__builtin_isfpclass()` builtin is a generalization of functions
471+ // isnan, isinf, isfinite and some others defined by the C standard. It tests
472+ // if the floating-point value, specified by the first argument, falls into
473+ // any of data classes, specified by the second argument.
474+ case Builtin::BI__builtin_isnan: {
475+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
476+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
477+ if (mlir::Value result = tryUseTestFPKind (*this , builtinID, v))
478+ return RValue::get (result);
479+ mlir::Location loc = getLoc (e->getBeginLoc ());
480+ // FIXME: We should use builder.createZExt once createZExt is available.
481+ return RValue::get (builder.createZExtOrBitCast (
482+ loc, builder.createIsFPClass (loc, v, FPClassTest::fcNan),
483+ convertType (e->getType ())));
484+ }
485+
486+ case Builtin::BI__builtin_issignaling: {
487+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
488+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
489+ mlir::Location loc = getLoc (e->getBeginLoc ());
490+ // FIXME: We should use builder.createZExt once createZExt is available.
491+ return RValue::get (builder.createZExtOrBitCast (
492+ loc, builder.createIsFPClass (loc, v, FPClassTest::fcSNan),
493+ convertType (e->getType ())));
494+ }
495+
496+ case Builtin::BI__builtin_isinf: {
497+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
498+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
499+ if (mlir::Value result = tryUseTestFPKind (*this , builtinID, v))
500+ return RValue::get (result);
501+ mlir::Location loc = getLoc (e->getBeginLoc ());
502+ // FIXME: We should use builder.createZExt once createZExt is available.
503+ return RValue::get (builder.createZExtOrBitCast (
504+ loc, builder.createIsFPClass (loc, v, FPClassTest::fcInf),
505+ convertType (e->getType ())));
506+ }
507+
508+ case Builtin::BIfinite:
509+ case Builtin::BI__finite:
510+ case Builtin::BIfinitef:
511+ case Builtin::BI__finitef:
512+ case Builtin::BIfinitel:
513+ case Builtin::BI__finitel:
514+ case Builtin::BI__builtin_isfinite: {
515+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
516+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
517+ if (mlir::Value result = tryUseTestFPKind (*this , builtinID, v))
518+ return RValue::get (result);
519+ mlir::Location loc = getLoc (e->getBeginLoc ());
520+ // FIXME: We should use builder.createZExt once createZExt is available.
521+ return RValue::get (builder.createZExtOrBitCast (
522+ loc, builder.createIsFPClass (loc, v, FPClassTest::fcFinite),
523+ convertType (e->getType ())));
524+ }
525+
526+ case Builtin::BI__builtin_isnormal: {
527+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
528+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
529+ mlir::Location loc = getLoc (e->getBeginLoc ());
530+ // FIXME: We should use builder.createZExt once createZExt is available.
531+ return RValue::get (builder.createZExtOrBitCast (
532+ loc, builder.createIsFPClass (loc, v, FPClassTest::fcNormal),
533+ convertType (e->getType ())));
534+ }
535+
536+ case Builtin::BI__builtin_issubnormal: {
537+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
538+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
539+ mlir::Location loc = getLoc (e->getBeginLoc ());
540+ // FIXME: We should use builder.createZExt once createZExt is available.
541+ return RValue::get (builder.createZExtOrBitCast (
542+ loc, builder.createIsFPClass (loc, v, FPClassTest::fcSubnormal),
543+ convertType (e->getType ())));
544+ }
545+
546+ case Builtin::BI__builtin_iszero: {
547+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
548+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
549+ mlir::Location loc = getLoc (e->getBeginLoc ());
550+ // FIXME: We should use builder.createZExt once createZExt is available.
551+ return RValue::get (builder.createZExtOrBitCast (
552+ loc, builder.createIsFPClass (loc, v, FPClassTest::fcZero),
553+ convertType (e->getType ())));
554+ }
555+ case Builtin::BI__builtin_isfpclass: {
556+ Expr::EvalResult result;
557+ if (!e->getArg (1 )->EvaluateAsInt (result, cgm.getASTContext ()))
558+ break ;
559+
560+ CIRGenFunction::CIRGenFPOptionsRAII fpOptsRaii (*this , e);
561+ mlir::Value v = emitScalarExpr (e->getArg (0 ));
562+ uint64_t test = result.Val .getInt ().getLimitedValue ();
563+ mlir::Location loc = getLoc (e->getBeginLoc ());
564+ //
565+ // // FIXME: We should use builder.createZExt once createZExt is available.
566+ return RValue::get (builder.createZExtOrBitCast (
567+ loc, builder.createIsFPClass (loc, v, test), convertType (e->getType ())));
568+ }
457569 }
458570
459571 // If this is an alias for a lib function (e.g. __builtin_sin), emit
460572 // the call using the normal call path, but using the unmangled
461573 // version of the function name.
462- if (getContext ().BuiltinInfo .isLibFunction (builtinID))
574+ if (getContext ().BuiltinInfo .isLibFunction (builtinID)) {
463575 return emitLibraryCall (*this , fd, e,
464576 cgm.getBuiltinLibFunction (fd, builtinID));
577+ }
465578
466579 // Some target-specific builtins can have aggregate return values, e.g.
467580 // __builtin_arm_mve_vld2q_u32. So if the result is an aggregate, force
0 commit comments