Skip to content

Commit 4f9f7a9

Browse files
committed
Clang: emit llvm.minnum and llvm.maxnum with nsz always
See: llvm#112852 We will define llvm.minnum and llvm.maxnum with +0.0>-0.0, by default, while libc doesn't require it.
1 parent 2e39533 commit 4f9f7a9

File tree

4 files changed

+65
-21
lines changed

4 files changed

+65
-21
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -689,19 +689,20 @@ static Value *emitUnaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
689689

690690
// Emit an intrinsic that has 2 operands of the same type as its result.
691691
// Depending on mode, this may be a constrained floating-point intrinsic.
692-
static Value *emitBinaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
693-
const CallExpr *E, unsigned IntrinsicID,
694-
unsigned ConstrainedIntrinsicID) {
692+
static Value *emitBinaryMaybeConstrainedFPBuiltin(
693+
CodeGenFunction &CGF, const CallExpr *E, unsigned IntrinsicID,
694+
unsigned ConstrainedIntrinsicID, llvm::FastMathFlags *FMF = nullptr) {
695695
llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
696696
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
697697

698698
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
699699
if (CGF.Builder.getIsFPConstrained()) {
700700
Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, Src0->getType());
701-
return CGF.Builder.CreateConstrainedFPCall(F, { Src0, Src1 });
701+
return CGF.Builder.CreateConstrainedFPCall(F, {Src0, Src1}, "",
702+
std::nullopt, std::nullopt, FMF);
702703
} else {
703704
Function *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
704-
return CGF.Builder.CreateCall(F, { Src0, Src1 });
705+
return CGF.Builder.CreateCall(F, {Src0, Src1}, "", nullptr, FMF);
705706
}
706707
}
707708

@@ -3221,10 +3222,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
32213222
case Builtin::BI__builtin_fmaxf:
32223223
case Builtin::BI__builtin_fmaxf16:
32233224
case Builtin::BI__builtin_fmaxl:
3224-
case Builtin::BI__builtin_fmaxf128:
3225-
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
3226-
Intrinsic::maxnum,
3227-
Intrinsic::experimental_constrained_maxnum));
3225+
case Builtin::BI__builtin_fmaxf128: {
3226+
llvm::FastMathFlags FMF;
3227+
FMF.setNoSignedZeros();
3228+
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
3229+
*this, E, Intrinsic::maxnum,
3230+
Intrinsic::experimental_constrained_maxnum, &FMF));
3231+
}
32283232

32293233
case Builtin::BIfmin:
32303234
case Builtin::BIfminf:
@@ -3233,10 +3237,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
32333237
case Builtin::BI__builtin_fminf:
32343238
case Builtin::BI__builtin_fminf16:
32353239
case Builtin::BI__builtin_fminl:
3236-
case Builtin::BI__builtin_fminf128:
3237-
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
3238-
Intrinsic::minnum,
3239-
Intrinsic::experimental_constrained_minnum));
3240+
case Builtin::BI__builtin_fminf128: {
3241+
llvm::FastMathFlags FMF;
3242+
FMF.setNoSignedZeros();
3243+
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
3244+
*this, E, Intrinsic::minnum,
3245+
Intrinsic::experimental_constrained_minnum, &FMF));
3246+
}
32403247

32413248
case Builtin::BIfmaximum_num:
32423249
case Builtin::BIfmaximum_numf:
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %clang_cc1 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK
2+
3+
float fminf (float, float);
4+
double fmin (double, double);
5+
long double fminl (long double, long double);
6+
float fmaxf (float, float);
7+
double fmax (double, double);
8+
long double fmaxl (long double, long double);
9+
10+
// CHECK: call nsz float @llvm.minnum.f32
11+
float fmin1(float a, float b) {
12+
return fminf(a, b);
13+
}
14+
// CHECK: call nsz double @llvm.minnum.f64
15+
float fmin2(double a, double b) {
16+
return fmin(a, b);
17+
}
18+
// CHECK: call nsz x86_fp80 @llvm.minnum.f80
19+
float fmin3(long double a, long double b) {
20+
return fminl(a, b);
21+
}
22+
// CHECK: call nsz float @llvm.maxnum.f32
23+
float fmax1(float a, float b) {
24+
return fmaxf(a, b);
25+
}
26+
// CHECK: call nsz double @llvm.maxnum.f64
27+
float fmax2(double a, double b) {
28+
return fmax(a, b);
29+
}
30+
// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
31+
float fmax3(long double a, long double b) {
32+
return fmaxl(a, b);
33+
}

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2476,12 +2476,14 @@ class IRBuilderBase {
24762476
public:
24772477
CallInst *CreateCall(FunctionType *FTy, Value *Callee,
24782478
ArrayRef<Value *> Args = {}, const Twine &Name = "",
2479-
MDNode *FPMathTag = nullptr) {
2479+
MDNode *FPMathTag = nullptr,
2480+
FastMathFlags *uFMF = nullptr) {
24802481
CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
24812482
if (IsFPConstrained)
24822483
setConstrainedFPCallAttr(CI);
2483-
if (isa<FPMathOperator>(CI))
2484-
setFPAttrs(CI, FPMathTag, FMF);
2484+
if (isa<FPMathOperator>(CI)) {
2485+
setFPAttrs(CI, FPMathTag, uFMF ? (FMF | *uFMF) : FMF);
2486+
}
24852487
return Insert(CI, Name);
24862488
}
24872489

@@ -2497,9 +2499,10 @@ class IRBuilderBase {
24972499
}
24982500

24992501
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = {},
2500-
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2502+
const Twine &Name = "", MDNode *FPMathTag = nullptr,
2503+
FastMathFlags *uFMF = nullptr) {
25012504
return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name,
2502-
FPMathTag);
2505+
FPMathTag, uFMF);
25032506
}
25042507

25052508
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
@@ -2512,7 +2515,8 @@ class IRBuilderBase {
25122515
CallInst *CreateConstrainedFPCall(
25132516
Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "",
25142517
std::optional<RoundingMode> Rounding = std::nullopt,
2515-
std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2518+
std::optional<fp::ExceptionBehavior> Except = std::nullopt,
2519+
FastMathFlags *FMF = nullptr);
25162520

25172521
Value *CreateSelect(Value *C, Value *True, Value *False,
25182522
const Twine &Name = "", Instruction *MDFrom = nullptr);

llvm/lib/IR/IRBuilder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCmp(
10561056
CallInst *IRBuilderBase::CreateConstrainedFPCall(
10571057
Function *Callee, ArrayRef<Value *> Args, const Twine &Name,
10581058
std::optional<RoundingMode> Rounding,
1059-
std::optional<fp::ExceptionBehavior> Except) {
1059+
std::optional<fp::ExceptionBehavior> Except, FastMathFlags *FMF) {
10601060
llvm::SmallVector<Value *, 6> UseArgs;
10611061

10621062
append_range(UseArgs, Args);
@@ -1065,7 +1065,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCall(
10651065
UseArgs.push_back(getConstrainedFPRounding(Rounding));
10661066
UseArgs.push_back(getConstrainedFPExcept(Except));
10671067

1068-
CallInst *C = CreateCall(Callee, UseArgs, Name);
1068+
CallInst *C = CreateCall(Callee, UseArgs, Name, nullptr, FMF);
10691069
setConstrainedFPCallAttr(C);
10701070
return C;
10711071
}

0 commit comments

Comments
 (0)