[clang] [llvm] Clang: emit llvm.minnum and llvm.maxnum with nsz always (PR #113133)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 21 00:25:12 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: YunQiang Su (wzssyqa)
<details>
<summary>Changes</summary>
See: https://github.com/llvm/llvm-project/pull/112852
We will define llvm.minnum and llvm.maxnum with +0.0>-0.0, by default, while libc doesn't require it.
---
Full diff: https://github.com/llvm/llvm-project/pull/113133.diff
4 Files Affected:
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+20-13)
- (added) clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c (+33)
- (modified) llvm/include/llvm/IR/IRBuilder.h (+10-6)
- (modified) llvm/lib/IR/IRBuilder.cpp (+2-2)
``````````diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 28f28c70b5ae52..f2d6049908720b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -510,19 +510,20 @@ static Value *emitUnaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
// Emit an intrinsic that has 2 operands of the same type as its result.
// Depending on mode, this may be a constrained floating-point intrinsic.
-static Value *emitBinaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
- const CallExpr *E, unsigned IntrinsicID,
- unsigned ConstrainedIntrinsicID) {
+static Value *emitBinaryMaybeConstrainedFPBuiltin(
+ CodeGenFunction &CGF, const CallExpr *E, unsigned IntrinsicID,
+ unsigned ConstrainedIntrinsicID, llvm::FastMathFlags *FMF = nullptr) {
llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
if (CGF.Builder.getIsFPConstrained()) {
Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, Src0->getType());
- return CGF.Builder.CreateConstrainedFPCall(F, { Src0, Src1 });
+ return CGF.Builder.CreateConstrainedFPCall(F, {Src0, Src1}, "",
+ std::nullopt, std::nullopt, FMF);
} else {
Function *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
- return CGF.Builder.CreateCall(F, { Src0, Src1 });
+ return CGF.Builder.CreateCall(F, {Src0, Src1}, "", nullptr, FMF);
}
}
@@ -2846,10 +2847,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_fmaxf:
case Builtin::BI__builtin_fmaxf16:
case Builtin::BI__builtin_fmaxl:
- case Builtin::BI__builtin_fmaxf128:
- return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
- Intrinsic::maxnum,
- Intrinsic::experimental_constrained_maxnum));
+ case Builtin::BI__builtin_fmaxf128: {
+ llvm::FastMathFlags FMF;
+ FMF.setNoSignedZeros();
+ return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::maxnum,
+ Intrinsic::experimental_constrained_maxnum, &FMF));
+ }
case Builtin::BIfmin:
case Builtin::BIfminf:
@@ -2858,10 +2862,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_fminf:
case Builtin::BI__builtin_fminf16:
case Builtin::BI__builtin_fminl:
- case Builtin::BI__builtin_fminf128:
- return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
- Intrinsic::minnum,
- Intrinsic::experimental_constrained_minnum));
+ case Builtin::BI__builtin_fminf128: {
+ llvm::FastMathFlags FMF;
+ FMF.setNoSignedZeros();
+ return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::minnum,
+ Intrinsic::experimental_constrained_minnum, &FMF));
+ }
case Builtin::BIfmaximum_num:
case Builtin::BIfmaximum_numf:
diff --git a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
new file mode 100644
index 00000000000000..9798baf0432fea
--- /dev/null
+++ b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK
+
+float fminf (float, float);
+double fmin (double, double);
+long double fminl (long double, long double);
+float fmaxf (float, float);
+double fmax (double, double);
+long double fmaxl (long double, long double);
+
+// CHECK: call nsz float @llvm.minnum.f32
+float fmin1(float a, float b) {
+ return fminf(a, b);
+}
+// CHECK: call nsz double @llvm.minnum.f64
+float fmin2(double a, double b) {
+ return fmin(a, b);
+}
+// CHECK: call nsz x86_fp80 @llvm.minnum.f80
+float fmin3(long double a, long double b) {
+ return fminl(a, b);
+}
+// CHECK: call nsz float @llvm.maxnum.f32
+float fmax1(float a, float b) {
+ return fmaxf(a, b);
+}
+// CHECK: call nsz double @llvm.maxnum.f64
+float fmax2(double a, double b) {
+ return fmax(a, b);
+}
+// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
+float fmax3(long double a, long double b) {
+ return fmaxl(a, b);
+}
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 23fd8350a29b3d..1baca4f003cad6 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2438,12 +2438,14 @@ class IRBuilderBase {
public:
CallInst *CreateCall(FunctionType *FTy, Value *Callee,
ArrayRef<Value *> Args = {}, const Twine &Name = "",
- MDNode *FPMathTag = nullptr) {
+ MDNode *FPMathTag = nullptr,
+ FastMathFlags *uFMF = nullptr) {
CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
if (IsFPConstrained)
setConstrainedFPCallAttr(CI);
- if (isa<FPMathOperator>(CI))
- setFPAttrs(CI, FPMathTag, FMF);
+ if (isa<FPMathOperator>(CI)) {
+ setFPAttrs(CI, FPMathTag, uFMF ? (FMF | *uFMF) : FMF);
+ }
return Insert(CI, Name);
}
@@ -2459,9 +2461,10 @@ class IRBuilderBase {
}
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = {},
- const Twine &Name = "", MDNode *FPMathTag = nullptr) {
+ const Twine &Name = "", MDNode *FPMathTag = nullptr,
+ FastMathFlags *uFMF = nullptr) {
return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name,
- FPMathTag);
+ FPMathTag, uFMF);
}
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
@@ -2474,7 +2477,8 @@ class IRBuilderBase {
CallInst *CreateConstrainedFPCall(
Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "",
std::optional<RoundingMode> Rounding = std::nullopt,
- std::optional<fp::ExceptionBehavior> Except = std::nullopt);
+ std::optional<fp::ExceptionBehavior> Except = std::nullopt,
+ FastMathFlags *FMF = nullptr);
Value *CreateSelect(Value *C, Value *True, Value *False,
const Twine &Name = "", Instruction *MDFrom = nullptr);
diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index f340f7aafdc76f..5feaf956b45a97 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -1031,7 +1031,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCmp(
CallInst *IRBuilderBase::CreateConstrainedFPCall(
Function *Callee, ArrayRef<Value *> Args, const Twine &Name,
std::optional<RoundingMode> Rounding,
- std::optional<fp::ExceptionBehavior> Except) {
+ std::optional<fp::ExceptionBehavior> Except, FastMathFlags *FMF) {
llvm::SmallVector<Value *, 6> UseArgs;
append_range(UseArgs, Args);
@@ -1040,7 +1040,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCall(
UseArgs.push_back(getConstrainedFPRounding(Rounding));
UseArgs.push_back(getConstrainedFPExcept(Except));
- CallInst *C = CreateCall(Callee, UseArgs, Name);
+ CallInst *C = CreateCall(Callee, UseArgs, Name, nullptr, FMF);
setConstrainedFPCallAttr(C);
return C;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/113133
More information about the cfe-commits
mailing list