Skip to content

Commit 94092d2

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 136f257 commit 94092d2

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

@@ -3203,10 +3204,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
32033204
case Builtin::BI__builtin_fmaxf:
32043205
case Builtin::BI__builtin_fmaxf16:
32053206
case Builtin::BI__builtin_fmaxl:
3206-
case Builtin::BI__builtin_fmaxf128:
3207-
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
3208-
Intrinsic::maxnum,
3209-
Intrinsic::experimental_constrained_maxnum));
3207+
case Builtin::BI__builtin_fmaxf128: {
3208+
llvm::FastMathFlags FMF;
3209+
FMF.setNoSignedZeros();
3210+
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
3211+
*this, E, Intrinsic::maxnum,
3212+
Intrinsic::experimental_constrained_maxnum, &FMF));
3213+
}
32103214

32113215
case Builtin::BIfmin:
32123216
case Builtin::BIfminf:
@@ -3215,10 +3219,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
32153219
case Builtin::BI__builtin_fminf:
32163220
case Builtin::BI__builtin_fminf16:
32173221
case Builtin::BI__builtin_fminl:
3218-
case Builtin::BI__builtin_fminf128:
3219-
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
3220-
Intrinsic::minnum,
3221-
Intrinsic::experimental_constrained_minnum));
3222+
case Builtin::BI__builtin_fminf128: {
3223+
llvm::FastMathFlags FMF;
3224+
FMF.setNoSignedZeros();
3225+
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
3226+
*this, E, Intrinsic::minnum,
3227+
Intrinsic::experimental_constrained_minnum, &FMF));
3228+
}
32223229

32233230
case Builtin::BIfmaximum_num:
32243231
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
@@ -2452,12 +2452,14 @@ class IRBuilderBase {
24522452
public:
24532453
CallInst *CreateCall(FunctionType *FTy, Value *Callee,
24542454
ArrayRef<Value *> Args = {}, const Twine &Name = "",
2455-
MDNode *FPMathTag = nullptr) {
2455+
MDNode *FPMathTag = nullptr,
2456+
FastMathFlags *uFMF = nullptr) {
24562457
CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
24572458
if (IsFPConstrained)
24582459
setConstrainedFPCallAttr(CI);
2459-
if (isa<FPMathOperator>(CI))
2460-
setFPAttrs(CI, FPMathTag, FMF);
2460+
if (isa<FPMathOperator>(CI)) {
2461+
setFPAttrs(CI, FPMathTag, uFMF ? (FMF | *uFMF) : FMF);
2462+
}
24612463
return Insert(CI, Name);
24622464
}
24632465

@@ -2473,9 +2475,10 @@ class IRBuilderBase {
24732475
}
24742476

24752477
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = {},
2476-
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2478+
const Twine &Name = "", MDNode *FPMathTag = nullptr,
2479+
FastMathFlags *uFMF = nullptr) {
24772480
return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name,
2478-
FPMathTag);
2481+
FPMathTag, uFMF);
24792482
}
24802483

24812484
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
@@ -2488,7 +2491,8 @@ class IRBuilderBase {
24882491
CallInst *CreateConstrainedFPCall(
24892492
Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "",
24902493
std::optional<RoundingMode> Rounding = std::nullopt,
2491-
std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2494+
std::optional<fp::ExceptionBehavior> Except = std::nullopt,
2495+
FastMathFlags *FMF = nullptr);
24922496

24932497
Value *CreateSelect(Value *C, Value *True, Value *False,
24942498
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
@@ -1036,7 +1036,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCmp(
10361036
CallInst *IRBuilderBase::CreateConstrainedFPCall(
10371037
Function *Callee, ArrayRef<Value *> Args, const Twine &Name,
10381038
std::optional<RoundingMode> Rounding,
1039-
std::optional<fp::ExceptionBehavior> Except) {
1039+
std::optional<fp::ExceptionBehavior> Except, FastMathFlags *FMF) {
10401040
llvm::SmallVector<Value *, 6> UseArgs;
10411041

10421042
append_range(UseArgs, Args);
@@ -1045,7 +1045,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCall(
10451045
UseArgs.push_back(getConstrainedFPRounding(Rounding));
10461046
UseArgs.push_back(getConstrainedFPExcept(Except));
10471047

1048-
CallInst *C = CreateCall(Callee, UseArgs, Name);
1048+
CallInst *C = CreateCall(Callee, UseArgs, Name, nullptr, FMF);
10491049
setConstrainedFPCallAttr(C);
10501050
return C;
10511051
}

0 commit comments

Comments
 (0)