[clang] 09bd12c - [CIR] Add nofpclass for fast-math flags (#191455)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 15 11:17:26 PDT 2026
Author: adams381
Date: 2026-04-15T13:17:21-05:00
New Revision: 09bd12cccbc0dc1b66d482a62f56e8ddc5aa1e7c
URL: https://github.com/llvm/llvm-project/commit/09bd12cccbc0dc1b66d482a62f56e8ddc5aa1e7c
DIFF: https://github.com/llvm/llvm-project/commit/09bd12cccbc0dc1b66d482a62f56e8ddc5aa1e7c.diff
LOG: [CIR] Add nofpclass for fast-math flags (#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)
Added:
clang/test/CIR/CodeGen/nofpclass.c
Modified:
clang/lib/CIR/CodeGen/CIRGenCall.cpp
clang/test/CIR/CodeGen/fp-math-precision-opts.c
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 10b4528ff2aac..aa40d1af68a6b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -19,6 +19,7 @@
#include "mlir/IR/Attributes.h"
#include "clang/CIR/ABIArgInfo.h"
#include "clang/CIR/MissingFeatures.h"
+#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/Support/TypeSize.h"
using namespace clang;
@@ -575,6 +576,16 @@ static bool determineNoUndef(QualType clangTy, CIRGenTypes &types,
return false;
}
+/// Compute the nofpclass mask for FP types based on language options.
+static unsigned getNoFPClassTestMask(const LangOptions &langOpts) {
+ unsigned mask = 0;
+ if (langOpts.NoHonorInfs)
+ mask |= llvm::fcInf;
+ if (langOpts.NoHonorNaNs)
+ mask |= llvm::fcNan;
+ return mask;
+}
+
void CIRGenModule::constructFunctionReturnAttributes(
const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
mlir::NamedAttrList &retAttrs) {
@@ -589,9 +600,10 @@ 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.
+ if (retTy->hasFloatingRepresentation())
+ if (unsigned mask = getNoFPClassTestMask(getLangOpts()))
+ retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
+ builder.getI64IntegerAttr(mask));
if (!isThunk) {
// TODO(cir): following comment taken from classic codegen, so if anything
@@ -700,6 +712,11 @@ void CIRGenModule::constructFunctionArgumentAttributes(
builder.getI64IntegerAttr(
getNaturalPointeeTypeAlignment(argType).getQuantity()));
}
+
+ if (argType->hasFloatingRepresentation())
+ if (unsigned mask = getNoFPClassTestMask(getLangOpts()))
+ argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
+ builder.getI64IntegerAttr(mask));
}
}
diff --git a/clang/test/CIR/CodeGen/fp-math-precision-opts.c b/clang/test/CIR/CodeGen/fp-math-precision-opts.c
index 3ba418c7278dd..4c04eb14c6309 100644
--- a/clang/test/CIR/CodeGen/fp-math-precision-opts.c
+++ b/clang/test/CIR/CodeGen/fp-math-precision-opts.c
@@ -47,9 +47,9 @@ float test_precise(float f) {
// CIR-ERRNO: cir.call @cosf
// CIR-NO-ERRNO: cir.call @cosf
// LLVM-ERRNO: call float @cosf
- // LLVM-NO-ERRNO: call float @cosf
+ // LLVM-NO-ERRNO: call nofpclass(nan inf) float @cosf
// OGCG-ERRNO: call {{.*}} float @cosf
- // OGCG-NO-ERRNO: call {{.*}} float @cosf
+ // OGCG-NO-ERRNO: call nofpclass(nan inf) float @cosf
}
float test_fast(float f) {
@@ -73,7 +73,7 @@ float test_optnone(float f) {
// CIR-ERRNO: cir.call @cosf
// CIR-NO-ERRNO: cir.call @cosf
// LLVM-ERRNO: call float @cosf
- // LLVM-NO-ERRNO: call float @cosf
+ // LLVM-NO-ERRNO: call nofpclass(nan inf) float @cosf
// OGCG-ERRNO: call {{.*}} float @cosf
- // OGCG-NO-ERRNO: call {{.*}} float @cosf
+ // OGCG-NO-ERRNO: call nofpclass(nan inf) float @cosf
}
diff --git a/clang/test/CIR/CodeGen/nofpclass.c b/clang/test/CIR/CodeGen/nofpclass.c
new file mode 100644
index 0000000000000..1d9eb1109b813
--- /dev/null
+++ b/clang/test/CIR/CodeGen/nofpclass.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -menable-no-infs -menable-no-nans -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// 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=LLVM --input-file=%t.ll %s
+
+float identity(float x) { return x; }
+// CIR: cir.func {{.*}} @identity(%arg0: !cir.float {llvm.nofpclass = 519 : i64, llvm.noundef}
+// CIR-SAME: -> (!cir.float {llvm.nofpclass = 519 : i64})
+// LLVM: define {{.*}} nofpclass(nan inf) float @identity(float noundef nofpclass(nan inf) %{{.*}})
+
+double add(double a, double b) { return a + b; }
+// CIR: cir.func {{.*}} @add(%arg0: !cir.double {llvm.nofpclass = 519 : i64, llvm.noundef}
+// CIR-SAME: %arg1: !cir.double {llvm.nofpclass = 519 : i64, llvm.noundef}
+// CIR-SAME: -> (!cir.double {llvm.nofpclass = 519 : i64})
+// LLVM: 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; }
+// CIR: cir.func {{.*}} @ret_complex() -> (!cir.complex<!cir.double> {llvm.nofpclass = 519 : i64})
+// LLVM: define {{.*}} nofpclass(nan inf) { double, double } @ret_complex()
+
+int non_fp(int x) { return x; }
+// CIR: cir.func {{.*}} @non_fp(%arg0: !s32i {llvm.noundef}{{.*}}) -> !s32i
+// LLVM: define {{.*}} i32 @non_fp(i32 noundef %{{.*}})
More information about the cfe-commits
mailing list