Skip to content

Commit 4cb7472

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 0fbf91a commit 4cb7472

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
@@ -510,19 +510,20 @@ static Value *emitUnaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
510510

511511
// Emit an intrinsic that has 2 operands of the same type as its result.
512512
// Depending on mode, this may be a constrained floating-point intrinsic.
513-
static Value *emitBinaryMaybeConstrainedFPBuiltin(CodeGenFunction &CGF,
514-
const CallExpr *E, unsigned IntrinsicID,
515-
unsigned ConstrainedIntrinsicID) {
513+
static Value *emitBinaryMaybeConstrainedFPBuiltin(
514+
CodeGenFunction &CGF, const CallExpr *E, unsigned IntrinsicID,
515+
unsigned ConstrainedIntrinsicID, llvm::FastMathFlags *FMF = nullptr) {
516516
llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
517517
llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
518518

519519
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
520520
if (CGF.Builder.getIsFPConstrained()) {
521521
Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID, Src0->getType());
522-
return CGF.Builder.CreateConstrainedFPCall(F, { Src0, Src1 });
522+
return CGF.Builder.CreateConstrainedFPCall(F, {Src0, Src1}, "",
523+
std::nullopt, std::nullopt, FMF);
523524
} else {
524525
Function *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType());
525-
return CGF.Builder.CreateCall(F, { Src0, Src1 });
526+
return CGF.Builder.CreateCall(F, {Src0, Src1}, "", nullptr, FMF);
526527
}
527528
}
528529

@@ -2846,10 +2847,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
28462847
case Builtin::BI__builtin_fmaxf:
28472848
case Builtin::BI__builtin_fmaxf16:
28482849
case Builtin::BI__builtin_fmaxl:
2849-
case Builtin::BI__builtin_fmaxf128:
2850-
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
2851-
Intrinsic::maxnum,
2852-
Intrinsic::experimental_constrained_maxnum));
2850+
case Builtin::BI__builtin_fmaxf128: {
2851+
llvm::FastMathFlags FMF;
2852+
FMF.setNoSignedZeros();
2853+
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
2854+
*this, E, Intrinsic::maxnum,
2855+
Intrinsic::experimental_constrained_maxnum, &FMF));
2856+
}
28532857

28542858
case Builtin::BIfmin:
28552859
case Builtin::BIfminf:
@@ -2858,10 +2862,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
28582862
case Builtin::BI__builtin_fminf:
28592863
case Builtin::BI__builtin_fminf16:
28602864
case Builtin::BI__builtin_fminl:
2861-
case Builtin::BI__builtin_fminf128:
2862-
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
2863-
Intrinsic::minnum,
2864-
Intrinsic::experimental_constrained_minnum));
2865+
case Builtin::BI__builtin_fminf128: {
2866+
llvm::FastMathFlags FMF;
2867+
FMF.setNoSignedZeros();
2868+
return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
2869+
*this, E, Intrinsic::minnum,
2870+
Intrinsic::experimental_constrained_minnum, &FMF));
2871+
}
28652872

28662873
case Builtin::BIfmaximum_num:
28672874
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
@@ -2438,12 +2438,14 @@ class IRBuilderBase {
24382438
public:
24392439
CallInst *CreateCall(FunctionType *FTy, Value *Callee,
24402440
ArrayRef<Value *> Args = {}, const Twine &Name = "",
2441-
MDNode *FPMathTag = nullptr) {
2441+
MDNode *FPMathTag = nullptr,
2442+
FastMathFlags *uFMF = nullptr) {
24422443
CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles);
24432444
if (IsFPConstrained)
24442445
setConstrainedFPCallAttr(CI);
2445-
if (isa<FPMathOperator>(CI))
2446-
setFPAttrs(CI, FPMathTag, FMF);
2446+
if (isa<FPMathOperator>(CI)) {
2447+
setFPAttrs(CI, FPMathTag, uFMF ? (FMF | *uFMF) : FMF);
2448+
}
24472449
return Insert(CI, Name);
24482450
}
24492451

@@ -2459,9 +2461,10 @@ class IRBuilderBase {
24592461
}
24602462

24612463
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = {},
2462-
const Twine &Name = "", MDNode *FPMathTag = nullptr) {
2464+
const Twine &Name = "", MDNode *FPMathTag = nullptr,
2465+
FastMathFlags *uFMF = nullptr) {
24632466
return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name,
2464-
FPMathTag);
2467+
FPMathTag, uFMF);
24652468
}
24662469

24672470
CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
@@ -2474,7 +2477,8 @@ class IRBuilderBase {
24742477
CallInst *CreateConstrainedFPCall(
24752478
Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "",
24762479
std::optional<RoundingMode> Rounding = std::nullopt,
2477-
std::optional<fp::ExceptionBehavior> Except = std::nullopt);
2480+
std::optional<fp::ExceptionBehavior> Except = std::nullopt,
2481+
FastMathFlags *FMF = nullptr);
24782482

24792483
Value *CreateSelect(Value *C, Value *True, Value *False,
24802484
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
@@ -1031,7 +1031,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCmp(
10311031
CallInst *IRBuilderBase::CreateConstrainedFPCall(
10321032
Function *Callee, ArrayRef<Value *> Args, const Twine &Name,
10331033
std::optional<RoundingMode> Rounding,
1034-
std::optional<fp::ExceptionBehavior> Except) {
1034+
std::optional<fp::ExceptionBehavior> Except, FastMathFlags *FMF) {
10351035
llvm::SmallVector<Value *, 6> UseArgs;
10361036

10371037
append_range(UseArgs, Args);
@@ -1040,7 +1040,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCall(
10401040
UseArgs.push_back(getConstrainedFPRounding(Rounding));
10411041
UseArgs.push_back(getConstrainedFPExcept(Except));
10421042

1043-
CallInst *C = CreateCall(Callee, UseArgs, Name);
1043+
CallInst *C = CreateCall(Callee, UseArgs, Name, nullptr, FMF);
10441044
setConstrainedFPCallAttr(C);
10451045
return C;
10461046
}

0 commit comments

Comments
 (0)