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 {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 %{{.*}})