https://github.com/adams381 created https://github.com/llvm/llvm-project/pull/191455
When `-menable-no-infs` or `-menable-no-nans` is set, OGCG adds `nofpclass(nan inf)` to FP arguments and return values. CIR was missing this. Adds the check in `constructFunctionReturnAttributes` and `constructFunctionArgumentAttributes`, gated on `hasFloatingRepresentation()` (same condition classic codegen uses in `canApplyNoFPClass`). The MLIR LLVM dialect already has `llvm.nofpclass` from #188374, so only the CIRGen side is needed here. Test covers float, double, `_Complex double`, and a non-FP control case. Made with [Cursor](https://cursor.com) >From 2cf1546446e1826ff066801a3e72d12539a99d09 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Fri, 10 Apr 2026 09:23:59 -0700 Subject: [PATCH] [CIR] Add nofpclass on FP args and returns for fast-math Add nofpclass(nan inf) to floating-point arguments and return values when -menable-no-infs and/or -menable-no-nans are set, matching OGCG behavior. The nofpclass attribute is applied in constructFunctionReturnAttributes and constructFunctionArgumentAttributes using the QualType's hasFloatingRepresentation() check. The MLIR LLVM dialect support for nofpclass was previously added in PR #188374. Made-with: Cursor --- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 26 +++++++++++++++++++++++--- clang/test/CIR/CodeGen/nofpclass.c | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 clang/test/CIR/CodeGen/nofpclass.c diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 876fef687b477..4e623de96442e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -18,6 +18,7 @@ #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "clang/CIR/ABIArgInfo.h" #include "clang/CIR/MissingFeatures.h" +#include "llvm/ADT/FloatingPointMode.h" #include "llvm/Support/TypeSize.h" using namespace clang; @@ -587,9 +588,17 @@ void CIRGenModule::constructFunctionReturnAttributes( retAttrs.set(mlir::LLVM::LLVMDialect::getNoUndefAttrName(), mlir::UnitAttr::get(&getMLIRContext())); - // TODO(cir): classic codegen adds a bunch of attributes based on - // calling-convention lowering results. However, since calling conventions - // haven't happened yet, this work likely has to happen there. + // nofpclass(nan inf) when -menable-no-infs / -menable-no-nans. + if (retTy->hasFloatingRepresentation()) { + unsigned mask = 0; + if (getLangOpts().NoHonorInfs) + mask |= llvm::fcInf; + if (getLangOpts().NoHonorNaNs) + mask |= llvm::fcNan; + if (mask) + retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(), + builder.getI64IntegerAttr(mask)); + } if (!isThunk) { // TODO(cir): following comment taken from classic codegen, so if anything @@ -698,6 +707,17 @@ void CIRGenModule::constructFunctionArgumentAttributes( builder.getI64IntegerAttr( getNaturalPointeeTypeAlignment(argType).getQuantity())); } + + if (argType->hasFloatingRepresentation()) { + unsigned mask = 0; + if (getLangOpts().NoHonorInfs) + mask |= llvm::fcInf; + if (getLangOpts().NoHonorNaNs) + mask |= llvm::fcNan; + if (mask) + argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(), + builder.getI64IntegerAttr(mask)); + } } } diff --git a/clang/test/CIR/CodeGen/nofpclass.c b/clang/test/CIR/CodeGen/nofpclass.c new file mode 100644 index 0000000000000..56563173600a8 --- /dev/null +++ b/clang/test/CIR/CodeGen/nofpclass.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -menable-no-infs -menable-no-nans -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -menable-no-infs -menable-no-nans -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +float identity(float x) { return x; } +// LLVM: define {{.*}} nofpclass(nan inf) float @identity(float noundef nofpclass(nan inf) %{{.*}}) +// OGCG: define {{.*}} nofpclass(nan inf) float @identity(float noundef nofpclass(nan inf) %{{.*}}) + +double add(double a, double b) { return a + b; } +// LLVM: define {{.*}} nofpclass(nan inf) double @add(double noundef nofpclass(nan inf) %{{.*}}, double noundef nofpclass(nan inf) %{{.*}}) +// OGCG: define {{.*}} nofpclass(nan inf) double @add(double noundef nofpclass(nan inf) %{{.*}}, double noundef nofpclass(nan inf) %{{.*}}) + +_Complex double ret_complex(void) { return 1.0 + 2.0i; } +// LLVM: define {{.*}} nofpclass(nan inf) { double, double } @ret_complex() +// OGCG: define {{.*}} nofpclass(nan inf) { double, double } @ret_complex() + +int non_fp(int x) { return x; } +// LLVM: define {{.*}} i32 @non_fp(i32 noundef %{{.*}}) +// LLVM-NOT: nofpclass +// OGCG: define {{.*}} i32 @non_fp(i32 noundef %{{.*}}) +// OGCG-NOT: nofpclass _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
