Author: Ayokunle Amodu Date: 2026-02-17T16:10:26-08:00 New Revision: 260f6fedc78bc6d3019d57c2afc5e5c99b8f00ea
URL: https://github.com/llvm/llvm-project/commit/260f6fedc78bc6d3019d57c2afc5e5c99b8f00ea DIFF: https://github.com/llvm/llvm-project/commit/260f6fedc78bc6d3019d57c2afc5e5c99b8f00ea.diff LOG: [CIR][NFC] Upstream support for FP environments and RAII options (#179121) This adds support for FP environment descriptions and RAII options for FP operations, i.e.,`CIRGenFPOptionsRAII`). Added: Modified: clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h clang/include/clang/CIR/MissingFeatures.h clang/lib/CIR/CodeGen/CIRGenBuilder.h clang/lib/CIR/CodeGen/CIRGenFunction.cpp clang/lib/CIR/CodeGen/CIRGenFunction.h Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 19de9b120887a..dd9dc7f0fe0f5 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -16,6 +16,7 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/ADT/STLForwardCompat.h" +#include "llvm/IR/FPEnv.h" #include "llvm/Support/ErrorHandling.h" #include "mlir/IR/Builders.h" diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 1e9b4f425cec5..59d0482d37f15 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -279,7 +279,14 @@ struct MissingFeatures { static bool emitNullabilityCheck() { return false; } static bool emitTypeCheck() { return false; } static bool emitTypeMetadataCodeForVCall() { return false; } + + // Fast math. + static bool fastMathGuard() { return false; } + // Should be implemented with a moduleOp level attribute and directly + // mapped to LLVM - those can be set directly for every relevant LLVM IR + // dialect operation (log10, ...). static bool fastMathFlags() { return false; } + static bool fastMathFuncAttributes() { return false; } static bool fpConstraints() { return false; } static bool generateDebugInfo() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index debd2faa29ef3..cd13c9578adf7 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -22,11 +22,16 @@ #include "clang/CIR/MissingFeatures.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/IR/FPEnv.h" namespace clang::CIRGen { class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { const CIRGenTypeCache &typeCache; + bool isFPConstrained = false; + llvm::fp::ExceptionBehavior defaultConstrainedExcept = llvm::fp::ebStrict; + llvm::RoundingMode defaultConstrainedRounding = llvm::RoundingMode::Dynamic; + llvm::StringMap<unsigned> recordNames; llvm::StringMap<unsigned> globalsVersioning; @@ -106,6 +111,43 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return baseName + "." + std::to_string(recordNames[baseName]++); } + // + // Floating point specific helpers + // ------------------------------- + // + + /// Enable/Disable use of constrained floating point math. When enabled the + /// CreateF<op>() calls instead create constrained floating point intrinsic + /// calls. Fast math flags are unaffected by this setting. + void setIsFPConstrained(bool isCon) { isFPConstrained = isCon; } + + /// Query for the use of constrained floating point math + bool getIsFPConstrained() const { return isFPConstrained; } + + /// Set the exception handling to be used with constrained floating point + void setDefaultConstrainedExcept(llvm::fp::ExceptionBehavior newExcept) { + assert(llvm::convertExceptionBehaviorToStr(newExcept) && + "Garbage strict exception behavior!"); + defaultConstrainedExcept = newExcept; + } + + /// Get the exception handling used with constrained floating point + llvm::fp::ExceptionBehavior getDefaultConstrainedExcept() const { + return defaultConstrainedExcept; + } + + /// Set the rounding mode handling to be used with constrained floating point + void setDefaultConstrainedRounding(llvm::RoundingMode newRounding) { + assert(llvm::convertRoundingModeToStr(newRounding) && + "Garbage strict rounding mode!"); + defaultConstrainedRounding = newRounding; + } + + /// Get the rounding mode handling used with constrained floating point + llvm::RoundingMode getDefaultConstrainedRounding() const { + return defaultConstrainedRounding; + } + cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const { if (&format == &llvm::APFloat::IEEEdouble()) return cir::LongDoubleType::get(getContext(), typeCache.doubleTy); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index c900797e54c81..f8f674c4d2c21 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -20,6 +20,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/GlobalDecl.h" #include "clang/CIR/MissingFeatures.h" +#include "llvm/IR/FPEnv.h" #include <cassert> @@ -956,6 +957,23 @@ LValue CIRGenFunction::makeNaturalAlignAddrLValue(mlir::Value val, return makeAddrLValue(addr, ty, baseInfo); } +// Map the LangOption for exception behavior into the corresponding enum in +// the IR. +static llvm::fp::ExceptionBehavior +toConstrainedExceptMd(LangOptions::FPExceptionModeKind kind) { + switch (kind) { + case LangOptions::FPE_Ignore: + return llvm::fp::ebIgnore; + case LangOptions::FPE_MayTrap: + return llvm::fp::ebMayTrap; + case LangOptions::FPE_Strict: + return llvm::fp::ebStrict; + case LangOptions::FPE_Default: + llvm_unreachable("expected explicitly initialized exception behavior"); + } + llvm_unreachable("unsupported FP exception behavior"); +} + clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd, FunctionArgList &args) { const auto *fd = cast<FunctionDecl>(gd.getDecl()); @@ -1119,6 +1137,59 @@ void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr, builder.createStore(loc, zeroValue, destPtr); } +CIRGenFunction::CIRGenFPOptionsRAII::CIRGenFPOptionsRAII(CIRGenFunction &cgf, + const clang::Expr *e) + : cgf(cgf) { + ConstructorHelper(e->getFPFeaturesInEffect(cgf.getLangOpts())); +} + +CIRGenFunction::CIRGenFPOptionsRAII::CIRGenFPOptionsRAII(CIRGenFunction &cgf, + FPOptions fpFeatures) + : cgf(cgf) { + ConstructorHelper(fpFeatures); +} + +void CIRGenFunction::CIRGenFPOptionsRAII::ConstructorHelper( + FPOptions fpFeatures) { + oldFPFeatures = cgf.curFPFeatures; + cgf.curFPFeatures = fpFeatures; + + oldExcept = cgf.builder.getDefaultConstrainedExcept(); + oldRounding = cgf.builder.getDefaultConstrainedRounding(); + + if (oldFPFeatures == fpFeatures) + return; + + // TODO(cir): create guard to restore fast math configurations. + assert(!cir::MissingFeatures::fastMathGuard()); + + llvm::RoundingMode newRoundingBehavior = fpFeatures.getRoundingMode(); + // TODO(cir): override rounding behaviour once FM configs are guarded. + llvm::fp::ExceptionBehavior newExceptionBehavior = + toConstrainedExceptMd(static_cast<LangOptions::FPExceptionModeKind>( + fpFeatures.getExceptionMode())); + // TODO(cir): override exception behaviour once FM configs are guarded. + + // TODO(cir): override FP flags once FM configs are guarded. + assert(!cir::MissingFeatures::fastMathFlags()); + + assert((cgf.curFuncDecl == nullptr || cgf.builder.getIsFPConstrained() || + isa<CXXConstructorDecl>(cgf.curFuncDecl) || + isa<CXXDestructorDecl>(cgf.curFuncDecl) || + (newExceptionBehavior == llvm::fp::ebIgnore && + newRoundingBehavior == llvm::RoundingMode::NearestTiesToEven)) && + "FPConstrained should be enabled on entire function"); + + // TODO(cir): mark CIR function with fast math attributes. + assert(!cir::MissingFeatures::fastMathFuncAttributes()); +} + +CIRGenFunction::CIRGenFPOptionsRAII::~CIRGenFPOptionsRAII() { + cgf.curFPFeatures = oldFPFeatures; + cgf.builder.setDefaultConstrainedExcept(oldExcept); + cgf.builder.setDefaultConstrainedRounding(oldRounding); +} + // TODO(cir): should be shared with LLVM codegen. bool CIRGenFunction::shouldNullCheckClassCastValue(const CastExpr *ce) { const Expr *e = ce->getSubExpr(); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index cc0087ba2d6bd..a21697ef8f1d4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -186,6 +186,21 @@ class CIRGenFunction : public CIRGenTypeCache { /// Sanitizers enabled for this function. clang::SanitizerSet sanOpts; + class CIRGenFPOptionsRAII { + public: + CIRGenFPOptionsRAII(CIRGenFunction &cgf, FPOptions FPFeatures); + CIRGenFPOptionsRAII(CIRGenFunction &cgf, const clang::Expr *E); + ~CIRGenFPOptionsRAII(); + + private: + void ConstructorHelper(clang::FPOptions FPFeatures); + CIRGenFunction &cgf; + clang::FPOptions oldFPFeatures; + llvm::fp::ExceptionBehavior oldExcept; + llvm::RoundingMode oldRounding; + }; + clang::FPOptions curFPFeatures; + /// The symbol table maps a variable name to a value in the current scope. /// Entering a function creates a new scope, and the function arguments are /// added to the mapping. When the processing of a function is terminated, _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
