[clang] [llvm] Clang: emit llvm.minnum and llvm.maxnum with nsz always (PR #113133)
YunQiang Su via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 27 02:06:11 PST 2025
https://github.com/wzssyqa updated https://github.com/llvm/llvm-project/pull/113133
>From 34654e8872814090664dd5ac476e801d83fa6cfc Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Mon, 21 Oct 2024 15:18:38 +0800
Subject: [PATCH 1/7] Clang: emit llvm.minnum and llvm.maxnum with nsz always
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.
---
clang/lib/CodeGen/CGBuiltin.cpp | 33 ++++++++++++--------
clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c | 33 ++++++++++++++++++++
llvm/include/llvm/IR/IRBuilder.h | 16 ++++++----
llvm/lib/IR/IRBuilder.cpp | 4 +--
4 files changed, 65 insertions(+), 21 deletions(-)
create mode 100644 clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65fac01d58362..f8a13101d586b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -689,19 +689,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);
}
}
@@ -3203,10 +3204,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:
@@ -3215,10 +3219,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 0000000000000..9798baf0432fe
--- /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 933dbb306d1fc..a310e023e77e6 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -2448,12 +2448,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);
}
@@ -2469,9 +2471,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,
@@ -2484,7 +2487,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 134459265cecb..f6f6c6bd6e6be 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -1036,7 +1036,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);
@@ -1045,7 +1045,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;
}
>From 38c6bd7236188b80809d7fbd731582b83b9b7d24 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 22 Oct 2024 09:56:06 +0800
Subject: [PATCH 2/7] fix testcases
---
clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c | 36 ++++++++++++---
clang/test/Headers/__clang_hip_math.hip | 48 ++++++++++----------
2 files changed, 54 insertions(+), 30 deletions(-)
diff --git a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
index 9798baf0432fe..a708d5cd3ac9e 100644
--- a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
+++ b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
@@ -8,26 +8,50 @@ double fmax (double, double);
long double fmaxl (long double, long double);
// CHECK: call nsz float @llvm.minnum.f32
-float fmin1(float a, float b) {
+float fmin32(float a, float b) {
return fminf(a, b);
}
+// CHECK: call nsz float @llvm.minnum.f32
+float fmin32b(float a, float b) {
+ return __builtin_fminf(a, b);
+}
// CHECK: call nsz double @llvm.minnum.f64
-float fmin2(double a, double b) {
+float fmin64(double a, double b) {
return fmin(a, b);
}
+// CHECK: call nsz double @llvm.minnum.f64
+float fmin64b(double a, double b) {
+ return __builtin_fmin(a, b);
+}
// CHECK: call nsz x86_fp80 @llvm.minnum.f80
-float fmin3(long double a, long double b) {
+float fmin80(long double a, long double b) {
return fminl(a, b);
}
+// CHECK: call nsz x86_fp80 @llvm.minnum.f80
+float fmin80b(long double a, long double b) {
+ return __builtin_fminl(a, b);
+}
// CHECK: call nsz float @llvm.maxnum.f32
-float fmax1(float a, float b) {
+float fmax32(float a, float b) {
return fmaxf(a, b);
}
+// CHECK: call nsz float @llvm.maxnum.f32
+float fmax32b(float a, float b) {
+ return __builtin_fmaxf(a, b);
+}
// CHECK: call nsz double @llvm.maxnum.f64
-float fmax2(double a, double b) {
+float fmax64(double a, double b) {
return fmax(a, b);
}
+// CHECK: call nsz double @llvm.maxnum.f64
+float fmax64b(double a, double b) {
+ return __builtin_fmax(a, b);
+}
// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
-float fmax3(long double a, long double b) {
+float fmax80(long double a, long double b) {
return fmaxl(a, b);
}
+// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
+float fmax80b(long double a, long double b) {
+ return __builtin_fmaxl(a, b);
+}
diff --git a/clang/test/Headers/__clang_hip_math.hip b/clang/test/Headers/__clang_hip_math.hip
index e4254d1e64bec..b37f11e16fbd4 100644
--- a/clang/test/Headers/__clang_hip_math.hip
+++ b/clang/test/Headers/__clang_hip_math.hip
@@ -1248,17 +1248,17 @@ extern "C" __device__ double test_fma_rn(double x, double y, double z) {
// DEFAULT-LABEL: @test_fmaxf(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
// DEFAULT-NEXT: ret float [[TMP0]]
//
// FINITEONLY-LABEL: @test_fmaxf(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
// FINITEONLY-NEXT: ret float [[TMP0]]
//
// APPROX-LABEL: @test_fmaxf(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
// APPROX-NEXT: ret float [[TMP0]]
//
extern "C" __device__ float test_fmaxf(float x, float y) {
@@ -1267,17 +1267,17 @@ extern "C" __device__ float test_fmaxf(float x, float y) {
// DEFAULT-LABEL: @test_fmax(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
// DEFAULT-NEXT: ret double [[TMP0]]
//
// FINITEONLY-LABEL: @test_fmax(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
// FINITEONLY-NEXT: ret double [[TMP0]]
//
// APPROX-LABEL: @test_fmax(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
// APPROX-NEXT: ret double [[TMP0]]
//
extern "C" __device__ double test_fmax(double x, double y) {
@@ -1286,17 +1286,17 @@ extern "C" __device__ double test_fmax(double x, double y) {
// DEFAULT-LABEL: @test_fminf(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
// DEFAULT-NEXT: ret float [[TMP0]]
//
// FINITEONLY-LABEL: @test_fminf(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
// FINITEONLY-NEXT: ret float [[TMP0]]
//
// APPROX-LABEL: @test_fminf(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
// APPROX-NEXT: ret float [[TMP0]]
//
extern "C" __device__ float test_fminf(float x, float y) {
@@ -1305,17 +1305,17 @@ extern "C" __device__ float test_fminf(float x, float y) {
// DEFAULT-LABEL: @test_fmin(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
// DEFAULT-NEXT: ret double [[TMP0]]
//
// FINITEONLY-LABEL: @test_fmin(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
// FINITEONLY-NEXT: ret double [[TMP0]]
//
// APPROX-LABEL: @test_fmin(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
// APPROX-NEXT: ret double [[TMP0]]
//
extern "C" __device__ double test_fmin(double x, double y) {
@@ -5114,17 +5114,17 @@ extern "C" __device__ double test__fma_rn(double x, double y, double z) {
// DEFAULT-LABEL: @test_float_min(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
// DEFAULT-NEXT: ret float [[TMP0]]
//
// FINITEONLY-LABEL: @test_float_min(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
// FINITEONLY-NEXT: ret float [[TMP0]]
//
// APPROX-LABEL: @test_float_min(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]])
// APPROX-NEXT: ret float [[TMP0]]
//
extern "C" __device__ float test_float_min(float x, float y) {
@@ -5133,17 +5133,17 @@ extern "C" __device__ float test_float_min(float x, float y) {
// DEFAULT-LABEL: @test_float_max(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
// DEFAULT-NEXT: ret float [[TMP0]]
//
// FINITEONLY-LABEL: @test_float_max(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
// FINITEONLY-NEXT: ret float [[TMP0]]
//
// APPROX-LABEL: @test_float_max(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef float @llvm.maxnum.f32(float [[X:%.*]], float [[Y:%.*]])
// APPROX-NEXT: ret float [[TMP0]]
//
extern "C" __device__ float test_float_max(float x, float y) {
@@ -5152,17 +5152,17 @@ extern "C" __device__ float test_float_max(float x, float y) {
// DEFAULT-LABEL: @test_double_min(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
// DEFAULT-NEXT: ret double [[TMP0]]
//
// FINITEONLY-LABEL: @test_double_min(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
// FINITEONLY-NEXT: ret double [[TMP0]]
//
// APPROX-LABEL: @test_double_min(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.minnum.f64(double [[X:%.*]], double [[Y:%.*]])
// APPROX-NEXT: ret double [[TMP0]]
//
extern "C" __device__ double test_double_min(double x, double y) {
@@ -5171,17 +5171,17 @@ extern "C" __device__ double test_double_min(double x, double y) {
// DEFAULT-LABEL: @test_double_max(
// DEFAULT-NEXT: entry:
-// DEFAULT-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// DEFAULT-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
// DEFAULT-NEXT: ret double [[TMP0]]
//
// FINITEONLY-LABEL: @test_double_max(
// FINITEONLY-NEXT: entry:
-// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// FINITEONLY-NEXT: [[TMP0:%.*]] = tail call nnan ninf nsz contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
// FINITEONLY-NEXT: ret double [[TMP0]]
//
// APPROX-LABEL: @test_double_max(
// APPROX-NEXT: entry:
-// APPROX-NEXT: [[TMP0:%.*]] = tail call contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
+// APPROX-NEXT: [[TMP0:%.*]] = tail call nsz contract noundef double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
// APPROX-NEXT: ret double [[TMP0]]
//
extern "C" __device__ double test_double_max(double x, double y) {
>From 74a7574e7d42c9120439e79eec9e20c367287578 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 22 Oct 2024 10:21:35 +0800
Subject: [PATCH 3/7] -ffp-exception-behavior=strict
---
clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c | 45 +++++++-------------
1 file changed, 15 insertions(+), 30 deletions(-)
diff --git a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
index a708d5cd3ac9e..f2ae4a49f6303 100644
--- a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
+++ b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -ffp-exception-behavior=strict -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-STRICT
float fminf (float, float);
double fmin (double, double);
@@ -8,50 +9,34 @@ double fmax (double, double);
long double fmaxl (long double, long double);
// CHECK: call nsz float @llvm.minnum.f32
-float fmin32(float a, float b) {
+// CHECK-STRICT: call nsz float @llvm.experimental.constrained.minnum.f32{{.*}} #2
+float fmin1(float a, float b) {
return fminf(a, b);
}
-// CHECK: call nsz float @llvm.minnum.f32
-float fmin32b(float a, float b) {
- return __builtin_fminf(a, b);
-}
// CHECK: call nsz double @llvm.minnum.f64
-float fmin64(double a, double b) {
+// CHECK-STRICT: call nsz double @llvm.experimental.constrained.minnum.f64{{.*}} #2
+float fmin2(double a, double b) {
return fmin(a, b);
}
-// CHECK: call nsz double @llvm.minnum.f64
-float fmin64b(double a, double b) {
- return __builtin_fmin(a, b);
-}
// CHECK: call nsz x86_fp80 @llvm.minnum.f80
-float fmin80(long double a, long double b) {
+// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80{{.*}} #2
+float fmin3(long double a, long double b) {
return fminl(a, b);
}
-// CHECK: call nsz x86_fp80 @llvm.minnum.f80
-float fmin80b(long double a, long double b) {
- return __builtin_fminl(a, b);
-}
// CHECK: call nsz float @llvm.maxnum.f32
-float fmax32(float a, float b) {
+// CHECK-STRICT: call nsz float @llvm.experimental.constrained.maxnum.f32{{.*}} #2
+float fmax1(float a, float b) {
return fmaxf(a, b);
}
-// CHECK: call nsz float @llvm.maxnum.f32
-float fmax32b(float a, float b) {
- return __builtin_fmaxf(a, b);
-}
// CHECK: call nsz double @llvm.maxnum.f64
-float fmax64(double a, double b) {
+// CHECK-STRICT: call nsz double @llvm.experimental.constrained.maxnum.f64{{.*}} #2
+float fmax2(double a, double b) {
return fmax(a, b);
}
-// CHECK: call nsz double @llvm.maxnum.f64
-float fmax64b(double a, double b) {
- return __builtin_fmax(a, b);
-}
// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
-float fmax80(long double a, long double b) {
+// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80{{.*}} #2
+float fmax3(long double a, long double b) {
return fmaxl(a, b);
}
-// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
-float fmax80b(long double a, long double b) {
- return __builtin_fmaxl(a, b);
-}
+
+//CHECK-STRICT: attributes #2 = { strictfp }
>From f2f07bdf9c3aafd0da9e63315d3f9f2ad8e5d06d Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 22 Oct 2024 10:36:46 +0800
Subject: [PATCH 4/7] add missing builtin test
---
clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c | 40 +++++++++++++++++---
1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
index f2ae4a49f6303..afe626d921125 100644
--- a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
+++ b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
@@ -10,33 +10,63 @@ long double fmaxl (long double, long double);
// CHECK: call nsz float @llvm.minnum.f32
// CHECK-STRICT: call nsz float @llvm.experimental.constrained.minnum.f32{{.*}} #2
-float fmin1(float a, float b) {
+float fmin32(float a, float b) {
return fminf(a, b);
}
+// CHECK: call nsz float @llvm.minnum.f32
+// CHECK-STRICT: call nsz float @llvm.experimental.constrained.minnum.f32{{.*}} #2
+float fmin32b(float a, float b) {
+ return __builtin_fminf(a, b);
+}
// CHECK: call nsz double @llvm.minnum.f64
// CHECK-STRICT: call nsz double @llvm.experimental.constrained.minnum.f64{{.*}} #2
-float fmin2(double a, double b) {
+float fmin64(double a, double b) {
return fmin(a, b);
}
+// CHECK: call nsz double @llvm.minnum.f64
+// CHECK-STRICT: call nsz double @llvm.experimental.constrained.minnum.f64{{.*}} #2
+float fmin64b(double a, double b) {
+ return __builtin_fmin(a, b);
+}
// CHECK: call nsz x86_fp80 @llvm.minnum.f80
// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80{{.*}} #2
-float fmin3(long double a, long double b) {
+float fmin80(long double a, long double b) {
return fminl(a, b);
}
+// CHECK: call nsz x86_fp80 @llvm.minnum.f80
+// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80{{.*}} #2
+float fmin80b(long double a, long double b) {
+ return __builtin_fminl(a, b);
+}
// CHECK: call nsz float @llvm.maxnum.f32
// CHECK-STRICT: call nsz float @llvm.experimental.constrained.maxnum.f32{{.*}} #2
-float fmax1(float a, float b) {
+float fmax32(float a, float b) {
return fmaxf(a, b);
}
+// CHECK: call nsz float @llvm.maxnum.f32
+// CHECK-STRICT: call nsz float @llvm.experimental.constrained.maxnum.f32{{.*}} #2
+float fmax32b(float a, float b) {
+ return __builtin_fmaxf(a, b);
+}
// CHECK: call nsz double @llvm.maxnum.f64
// CHECK-STRICT: call nsz double @llvm.experimental.constrained.maxnum.f64{{.*}} #2
-float fmax2(double a, double b) {
+float fmax64(double a, double b) {
return fmax(a, b);
}
+// CHECK: call nsz double @llvm.maxnum.f64
+// CHECK-STRICT: call nsz double @llvm.experimental.constrained.maxnum.f64{{.*}} #2
+float fmax64b(double a, double b) {
+ return __builtin_fmax(a, b);
+}
// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80{{.*}} #2
float fmax3(long double a, long double b) {
return fmaxl(a, b);
}
+// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
+// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80{{.*}} #2
+float fmax80b(long double a, long double b) {
+ return __builtin_fmaxl(a, b);
+}
//CHECK-STRICT: attributes #2 = { strictfp }
>From 055a68180d13365a7657dbc807961248ab5e111d Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Tue, 22 Oct 2024 11:03:09 +0800
Subject: [PATCH 5/7] test auto vectorize
---
clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c | 60 +++++++++++++++++++-
1 file changed, 58 insertions(+), 2 deletions(-)
diff --git a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
index afe626d921125..4729fd6e27896 100644
--- a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
+++ b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK
-// RUN: %clang_cc1 -ffp-exception-behavior=strict -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-STRICT
+// RUN: %clang_cc1 -vectorize-loops -vectorize-slp -O3 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -vectorize-loops -vectorize-slp -O3 -ffp-exception-behavior=strict -DENSTRICT=1 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-STRICT
float fminf (float, float);
double fmin (double, double);
@@ -18,6 +18,20 @@ float fmin32(float a, float b) {
float fmin32b(float a, float b) {
return __builtin_fminf(a, b);
}
+#if !defined(ENSTRICT)
+// CHECK: call nsz <4 x float> @llvm.minnum.v4f32(<4 x float> %0, <4 x float> %1)
+float *pfmin32(float* a, float* b, float* restrict c) {
+ for (int i=0; i<4; i++)
+ c[i] = fminf(a[i], b[i]);
+ return c;
+}
+// CHECK: call nsz <4 x float> @llvm.minnum.v4f32(<4 x float> %0, <4 x float> %1)
+float *pfmin32b(float* a, float* b, float* restrict c) {
+ for (int i=0; i<4; i++)
+ c[i] = __builtin_fminf(a[i], b[i]);
+ return c;
+}
+#endif
// CHECK: call nsz double @llvm.minnum.f64
// CHECK-STRICT: call nsz double @llvm.experimental.constrained.minnum.f64{{.*}} #2
float fmin64(double a, double b) {
@@ -28,6 +42,20 @@ float fmin64(double a, double b) {
float fmin64b(double a, double b) {
return __builtin_fmin(a, b);
}
+#if !defined(ENSTRICT)
+// CHECK: call nsz <2 x double> @llvm.minnum.v2f64(<2 x double> %0, <2 x double> %1)
+double *pfmin64(double* a, double* b, double* restrict c) {
+ for (int i=0; i<2; i++)
+ c[i] = fmin(a[i], b[i]);
+ return c;
+}
+// CHECK: call nsz <2 x double> @llvm.minnum.v2f64(<2 x double> %0, <2 x double> %1)
+double *pfmin64b(double* a, double* b, double* restrict c) {
+ for (int i=0; i<2; i++)
+ c[i] = __builtin_fmin(a[i], b[i]);
+ return c;
+}
+#endif
// CHECK: call nsz x86_fp80 @llvm.minnum.f80
// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80{{.*}} #2
float fmin80(long double a, long double b) {
@@ -48,6 +76,20 @@ float fmax32(float a, float b) {
float fmax32b(float a, float b) {
return __builtin_fmaxf(a, b);
}
+#if !defined(ENSTRICT)
+// CHECK: call nsz <4 x float> @llvm.maxnum.v4f32(<4 x float> %0, <4 x float> %1)
+float *pfmax32(float* a, float* b, float* restrict c) {
+ for (int i=0; i<4; i++)
+ c[i] = fmaxf(a[i], b[i]);
+ return c;
+}
+// CHECK: call nsz <4 x float> @llvm.maxnum.v4f32(<4 x float> %0, <4 x float> %1)
+float *pfmax32b(float* a, float* b, float* restrict c) {
+ for (int i=0; i<4; i++)
+ c[i] = __builtin_fmaxf(a[i], b[i]);
+ return c;
+}
+#endif
// CHECK: call nsz double @llvm.maxnum.f64
// CHECK-STRICT: call nsz double @llvm.experimental.constrained.maxnum.f64{{.*}} #2
float fmax64(double a, double b) {
@@ -63,6 +105,20 @@ float fmax64b(double a, double b) {
float fmax3(long double a, long double b) {
return fmaxl(a, b);
}
+#if !defined(ENSTRICT)
+// CHECK: call nsz <2 x double> @llvm.maxnum.v2f64(<2 x double> %0, <2 x double> %1)
+double *pfmax64(double* a, double* b, double* restrict c) {
+ for (int i=0; i<2; i++)
+ c[i] = fmax(a[i], b[i]);
+ return c;
+}
+// CHECK: call nsz <2 x double> @llvm.maxnum.v2f64(<2 x double> %0, <2 x double> %1)
+double *pfmax64b(double* a, double* b, double* restrict c) {
+ for (int i=0; i<2; i++)
+ c[i] = __builtin_fmax(a[i], b[i]);
+ return c;
+}
+#endif
// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80{{.*}} #2
float fmax80b(long double a, long double b) {
>From 93e987657cbd08d035593e1cdb8796295d68b5a8 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Wed, 23 Oct 2024 11:10:52 +0800
Subject: [PATCH 6/7] fix test cases
---
clang/test/CodeGen/RISCV/math-builtins.c | 24 +++++++++----------
clang/test/CodeGen/builtins.c | 12 +++++-----
.../test/CodeGen/constrained-math-builtins.c | 16 ++++++-------
clang/test/CodeGen/math-builtins-long.c | 16 ++++++-------
clang/test/CodeGenOpenCL/builtins-f16.cl | 4 ++--
.../amdgcn_openmp_device_math_constexpr.cpp | 8 +++----
6 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/clang/test/CodeGen/RISCV/math-builtins.c b/clang/test/CodeGen/RISCV/math-builtins.c
index 9630d62f0f482..e4f456c8eabd7 100644
--- a/clang/test/CodeGen/RISCV/math-builtins.c
+++ b/clang/test/CodeGen/RISCV/math-builtins.c
@@ -134,22 +134,22 @@ long double truncl(long double);
// RV32-NEXT: [[TMP44:%.*]] = call fp128 @llvm.floor.f128(fp128 [[TMP43]])
// RV32-NEXT: [[TMP45:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV32-NEXT: [[TMP46:%.*]] = load float, ptr [[FARG_ADDR]], align 4
-// RV32-NEXT: [[TMP47:%.*]] = call float @llvm.maxnum.f32(float [[TMP45]], float [[TMP46]])
+// RV32-NEXT: [[TMP47:%.*]] = call nsz float @llvm.maxnum.f32(float [[TMP45]], float [[TMP46]])
// RV32-NEXT: [[TMP48:%.*]] = load double, ptr [[DARG_ADDR]], align 8
// RV32-NEXT: [[TMP49:%.*]] = load double, ptr [[DARG_ADDR]], align 8
-// RV32-NEXT: [[TMP50:%.*]] = call double @llvm.maxnum.f64(double [[TMP48]], double [[TMP49]])
+// RV32-NEXT: [[TMP50:%.*]] = call nsz double @llvm.maxnum.f64(double [[TMP48]], double [[TMP49]])
// RV32-NEXT: [[TMP51:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
// RV32-NEXT: [[TMP52:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
-// RV32-NEXT: [[TMP53:%.*]] = call fp128 @llvm.maxnum.f128(fp128 [[TMP51]], fp128 [[TMP52]])
+// RV32-NEXT: [[TMP53:%.*]] = call nsz fp128 @llvm.maxnum.f128(fp128 [[TMP51]], fp128 [[TMP52]])
// RV32-NEXT: [[TMP54:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV32-NEXT: [[TMP55:%.*]] = load float, ptr [[FARG_ADDR]], align 4
-// RV32-NEXT: [[TMP56:%.*]] = call float @llvm.minnum.f32(float [[TMP54]], float [[TMP55]])
+// RV32-NEXT: [[TMP56:%.*]] = call nsz float @llvm.minnum.f32(float [[TMP54]], float [[TMP55]])
// RV32-NEXT: [[TMP57:%.*]] = load double, ptr [[DARG_ADDR]], align 8
// RV32-NEXT: [[TMP58:%.*]] = load double, ptr [[DARG_ADDR]], align 8
-// RV32-NEXT: [[TMP59:%.*]] = call double @llvm.minnum.f64(double [[TMP57]], double [[TMP58]])
+// RV32-NEXT: [[TMP59:%.*]] = call nsz double @llvm.minnum.f64(double [[TMP57]], double [[TMP58]])
// RV32-NEXT: [[TMP60:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
// RV32-NEXT: [[TMP61:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
-// RV32-NEXT: [[TMP62:%.*]] = call fp128 @llvm.minnum.f128(fp128 [[TMP60]], fp128 [[TMP61]])
+// RV32-NEXT: [[TMP62:%.*]] = call nsz fp128 @llvm.minnum.f128(fp128 [[TMP60]], fp128 [[TMP61]])
// RV32-NEXT: [[TMP63:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV32-NEXT: [[TMP64:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV32-NEXT: [[FMOD:%.*]] = frem float [[TMP63]], [[TMP64]]
@@ -310,22 +310,22 @@ long double truncl(long double);
// RV64-NEXT: [[TMP44:%.*]] = call fp128 @llvm.floor.f128(fp128 [[TMP43]])
// RV64-NEXT: [[TMP45:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV64-NEXT: [[TMP46:%.*]] = load float, ptr [[FARG_ADDR]], align 4
-// RV64-NEXT: [[TMP47:%.*]] = call float @llvm.maxnum.f32(float [[TMP45]], float [[TMP46]])
+// RV64-NEXT: [[TMP47:%.*]] = call nsz float @llvm.maxnum.f32(float [[TMP45]], float [[TMP46]])
// RV64-NEXT: [[TMP48:%.*]] = load double, ptr [[DARG_ADDR]], align 8
// RV64-NEXT: [[TMP49:%.*]] = load double, ptr [[DARG_ADDR]], align 8
-// RV64-NEXT: [[TMP50:%.*]] = call double @llvm.maxnum.f64(double [[TMP48]], double [[TMP49]])
+// RV64-NEXT: [[TMP50:%.*]] = call nsz double @llvm.maxnum.f64(double [[TMP48]], double [[TMP49]])
// RV64-NEXT: [[TMP51:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
// RV64-NEXT: [[TMP52:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
-// RV64-NEXT: [[TMP53:%.*]] = call fp128 @llvm.maxnum.f128(fp128 [[TMP51]], fp128 [[TMP52]])
+// RV64-NEXT: [[TMP53:%.*]] = call nsz fp128 @llvm.maxnum.f128(fp128 [[TMP51]], fp128 [[TMP52]])
// RV64-NEXT: [[TMP54:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV64-NEXT: [[TMP55:%.*]] = load float, ptr [[FARG_ADDR]], align 4
-// RV64-NEXT: [[TMP56:%.*]] = call float @llvm.minnum.f32(float [[TMP54]], float [[TMP55]])
+// RV64-NEXT: [[TMP56:%.*]] = call nsz float @llvm.minnum.f32(float [[TMP54]], float [[TMP55]])
// RV64-NEXT: [[TMP57:%.*]] = load double, ptr [[DARG_ADDR]], align 8
// RV64-NEXT: [[TMP58:%.*]] = load double, ptr [[DARG_ADDR]], align 8
-// RV64-NEXT: [[TMP59:%.*]] = call double @llvm.minnum.f64(double [[TMP57]], double [[TMP58]])
+// RV64-NEXT: [[TMP59:%.*]] = call nsz double @llvm.minnum.f64(double [[TMP57]], double [[TMP58]])
// RV64-NEXT: [[TMP60:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
// RV64-NEXT: [[TMP61:%.*]] = load fp128, ptr [[LDARG_ADDR]], align 16
-// RV64-NEXT: [[TMP62:%.*]] = call fp128 @llvm.minnum.f128(fp128 [[TMP60]], fp128 [[TMP61]])
+// RV64-NEXT: [[TMP62:%.*]] = call nsz fp128 @llvm.minnum.f128(fp128 [[TMP60]], fp128 [[TMP61]])
// RV64-NEXT: [[TMP63:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV64-NEXT: [[TMP64:%.*]] = load float, ptr [[FARG_ADDR]], align 4
// RV64-NEXT: [[FMOD:%.*]] = frem float [[TMP63]], [[TMP64]]
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index eda6c67fdad00..72e195e82d424 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -343,22 +343,22 @@ void test_float_builtin_ops(float F, double D, long double LD, int I) {
// CHECK: call x86_fp80 @llvm.canonicalize.f80(x86_fp80
resf = __builtin_fminf(F, F);
- // CHECK: call float @llvm.minnum.f32
+ // CHECK: call nsz float @llvm.minnum.f32
resd = __builtin_fmin(D, D);
- // CHECK: call double @llvm.minnum.f64
+ // CHECK: call nsz double @llvm.minnum.f64
resld = __builtin_fminl(LD, LD);
- // CHECK: call x86_fp80 @llvm.minnum.f80
+ // CHECK: call nsz x86_fp80 @llvm.minnum.f80
resf = __builtin_fmaxf(F, F);
- // CHECK: call float @llvm.maxnum.f32
+ // CHECK: call nsz float @llvm.maxnum.f32
resd = __builtin_fmax(D, D);
- // CHECK: call double @llvm.maxnum.f64
+ // CHECK: call nsz double @llvm.maxnum.f64
resld = __builtin_fmaxl(LD, LD);
- // CHECK: call x86_fp80 @llvm.maxnum.f80
+ // CHECK: call nsz x86_fp80 @llvm.maxnum.f80
resf = __builtin_fminimum_numf(F, F);
// CHECK: call float @llvm.minimumnum.f32
diff --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c
index 68b9e75283c54..ae07cce05b307 100644
--- a/clang/test/CodeGen/constrained-math-builtins.c
+++ b/clang/test/CodeGen/constrained-math-builtins.c
@@ -123,17 +123,17 @@ __builtin_atan2(f,f); __builtin_atan2f(f,f); __builtin_atan2l(f,f);
__builtin_fmax(f,f); __builtin_fmaxf(f,f); __builtin_fmaxl(f,f); __builtin_fmaxf128(f,f);
-// CHECK: call double @llvm.experimental.constrained.maxnum.f64(double %{{.*}}, double %{{.*}}, metadata !"fpexcept.strict")
-// CHECK: call float @llvm.experimental.constrained.maxnum.f32(float %{{.*}}, float %{{.*}}, metadata !"fpexcept.strict")
-// CHECK: call x86_fp80 @llvm.experimental.constrained.maxnum.f80(x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, metadata !"fpexcept.strict")
-// CHECK: call fp128 @llvm.experimental.constrained.maxnum.f128(fp128 %{{.*}}, fp128 %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz double @llvm.experimental.constrained.maxnum.f64(double %{{.*}}, double %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz float @llvm.experimental.constrained.maxnum.f32(float %{{.*}}, float %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80(x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz fp128 @llvm.experimental.constrained.maxnum.f128(fp128 %{{.*}}, fp128 %{{.*}}, metadata !"fpexcept.strict")
__builtin_fmin(f,f); __builtin_fminf(f,f); __builtin_fminl(f,f); __builtin_fminf128(f,f);
-// CHECK: call double @llvm.experimental.constrained.minnum.f64(double %{{.*}}, double %{{.*}}, metadata !"fpexcept.strict")
-// CHECK: call float @llvm.experimental.constrained.minnum.f32(float %{{.*}}, float %{{.*}}, metadata !"fpexcept.strict")
-// CHECK: call x86_fp80 @llvm.experimental.constrained.minnum.f80(x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, metadata !"fpexcept.strict")
-// CHECK: call fp128 @llvm.experimental.constrained.minnum.f128(fp128 %{{.*}}, fp128 %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz double @llvm.experimental.constrained.minnum.f64(double %{{.*}}, double %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz float @llvm.experimental.constrained.minnum.f32(float %{{.*}}, float %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80(x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, metadata !"fpexcept.strict")
+// CHECK: call nsz fp128 @llvm.experimental.constrained.minnum.f128(fp128 %{{.*}}, fp128 %{{.*}}, metadata !"fpexcept.strict")
__builtin_llrint(f); __builtin_llrintf(f); __builtin_llrintl(f); __builtin_llrintf128(f);
diff --git a/clang/test/CodeGen/math-builtins-long.c b/clang/test/CodeGen/math-builtins-long.c
index 183349e0f0173..f1e4988e37871 100644
--- a/clang/test/CodeGen/math-builtins-long.c
+++ b/clang/test/CodeGen/math-builtins-long.c
@@ -148,16 +148,16 @@ void foo(long double f, long double *l, int *i, const char *c) {
// PPCF128: call fp128 @llvm.floor.f128(fp128 %{{.+}})
__builtin_floorl(f);
- // F80: call x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
- // PPC: call ppc_fp128 @llvm.maxnum.ppcf128(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}})
- // X86F128: call fp128 @llvm.maxnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
- // PPCF128: call fp128 @llvm.maxnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
+ // F80: call nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
+ // PPC: call nsz ppc_fp128 @llvm.maxnum.ppcf128(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}})
+ // X86F128: call nsz fp128 @llvm.maxnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
+ // PPCF128: call nsz fp128 @llvm.maxnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
__builtin_fmaxl(f,f);
- // F80: call x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
- // PPC: call ppc_fp128 @llvm.minnum.ppcf128(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}})
- // X86F128: call fp128 @llvm.minnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
- // PPCF128: call fp128 @llvm.minnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
+ // F80: call nsz x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}})
+ // PPC: call nsz ppc_fp128 @llvm.minnum.ppcf128(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}})
+ // X86F128: call nsz fp128 @llvm.minnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
+ // PPCF128: call nsz fp128 @llvm.minnum.f128(fp128 %{{.+}}, fp128 %{{.+}})
__builtin_fminl(f,f);
// F80: call x86_fp80 @llvm.nearbyint.f80(x86_fp80 %{{.+}})
diff --git a/clang/test/CodeGenOpenCL/builtins-f16.cl b/clang/test/CodeGenOpenCL/builtins-f16.cl
index e8b62fe0830cd..f30ed0a1944ff 100644
--- a/clang/test/CodeGenOpenCL/builtins-f16.cl
+++ b/clang/test/CodeGenOpenCL/builtins-f16.cl
@@ -48,10 +48,10 @@ void test_half_builtins(half h0, half h1, half h2, int i0) {
// CHECK: call half @llvm.fma.f16(half %h0, half %h1, half %h2)
res = __builtin_fmaf16(h0, h1 ,h2);
- // CHECK: call half @llvm.maxnum.f16(half %h0, half %h1)
+ // CHECK: call nsz half @llvm.maxnum.f16(half %h0, half %h1)
res = __builtin_fmaxf16(h0, h1);
- // CHECK: call half @llvm.minnum.f16(half %h0, half %h1)
+ // CHECK: call nsz half @llvm.minnum.f16(half %h0, half %h1)
res = __builtin_fminf16(h0, h1);
// CHECK: frem half %h0, %h1
diff --git a/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp b/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp
index 0fdc02edc1508..855333132c4de 100644
--- a/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp
+++ b/clang/test/Headers/amdgcn_openmp_device_math_constexpr.cpp
@@ -208,7 +208,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f);
// CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]])
+// CHECK-NEXT: [[TMP2:%.*]] = call nsz noundef float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]])
// CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL17constexpr_min_f32 to ptr), align 4
// CHECK-NEXT: ret void
//
@@ -226,7 +226,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f);
// CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]])
+// CHECK-NEXT: [[TMP2:%.*]] = call nsz noundef float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]])
// CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL17constexpr_max_f32 to ptr), align 4
// CHECK-NEXT: ret void
//
@@ -260,7 +260,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f);
// CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]])
+// CHECK-NEXT: [[TMP2:%.*]] = call nsz noundef float @llvm.minnum.f32(float [[TMP0]], float [[TMP1]])
// CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL19constexpr_fminf_f32 to ptr), align 4
// CHECK-NEXT: ret void
//
@@ -278,7 +278,7 @@ const float constexpr_fmaxf_f32 = fmaxf(2.0f, -4.0f);
// CHECK-NEXT: store float -4.000000e+00, ptr [[__Y_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[__X_ADDR_ASCAST_I]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__Y_ADDR_ASCAST_I]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = call noundef float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]])
+// CHECK-NEXT: [[TMP2:%.*]] = call nsz noundef float @llvm.maxnum.f32(float [[TMP0]], float [[TMP1]])
// CHECK-NEXT: store float [[TMP2]], ptr addrspacecast (ptr addrspace(1) @_ZL19constexpr_fmaxf_f32 to ptr), align 4
// CHECK-NEXT: ret void
//
>From a3f35676d6bc929d6065e44b65f6aaa01087ca7b Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at debian.org>
Date: Thu, 27 Feb 2025 18:05:43 +0800
Subject: [PATCH 7/7] update testcase
---
clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c | 577 ++++++++++++++++---
1 file changed, 504 insertions(+), 73 deletions(-)
diff --git a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
index 4729fd6e27896..ea07e9bc2d416 100644
--- a/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
+++ b/clang/test/CodeGen/fmaxnum_fminnum_use_nsz.c
@@ -1,5 +1,14 @@
-// RUN: %clang_cc1 -vectorize-loops -vectorize-slp -O3 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK
-// RUN: %clang_cc1 -vectorize-loops -vectorize-slp -O3 -ffp-exception-behavior=strict -DENSTRICT=1 -triple x86_64 %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-STRICT
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -fno-fast-math -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK
+//
+// RUN: %clang_cc1 -fsigned-zeros -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -menable-no-nans -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-NO-NANS
+// RUN: %clang_cc1 -menable-no-infs -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-NO-INFS
+/// FIXME: -ffinite-math-only
+// RUN: %clang_cc1 -ffast-math -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-FAST
+//
+// RUN: %clang_cc1 -O3 -ffp-exception-behavior=strict -DENSTRICT=1 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-STRICT
float fminf (float, float);
double fmin (double, double);
@@ -8,121 +17,543 @@ float fmaxf (float, float);
double fmax (double, double);
long double fmaxl (long double, long double);
-// CHECK: call nsz float @llvm.minnum.f32
-// CHECK-STRICT: call nsz float @llvm.experimental.constrained.minnum.f32{{.*}} #2
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+
+// CHECK-LABEL: define dso_local noundef float @fmin32(
+// CHECK-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmin32(
+// CHECK-NO-NANS-SAME: float noundef nofpclass(nan) [[A:%.*]], float noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-NO-NANS-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmin32(
+// CHECK-NO-INFS-SAME: float noundef nofpclass(inf) [[A:%.*]], float noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-NO-INFS-NEXT: ret float [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmin32(
+// CHECK-FAST-SAME: float noundef nofpclass(nan inf) [[A:%.*]], float noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-FAST-NEXT: ret float [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmin32(
+// CHECK-STRICT-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.experimental.constrained.minnum.f32(float [[A]], float [[B]], metadata !"fpexcept.strict") #[[ATTR2:[0-9]+]]
+// CHECK-STRICT-NEXT: ret float [[TMP0]]
+//
float fmin32(float a, float b) {
return fminf(a, b);
}
-// CHECK: call nsz float @llvm.minnum.f32
-// CHECK-STRICT: call nsz float @llvm.experimental.constrained.minnum.f32{{.*}} #2
+// CHECK-LABEL: define dso_local noundef float @fmin32b(
+// CHECK-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmin32b(
+// CHECK-NO-NANS-SAME: float noundef nofpclass(nan) [[A:%.*]], float noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-NO-NANS-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmin32b(
+// CHECK-NO-INFS-SAME: float noundef nofpclass(inf) [[A:%.*]], float noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-NO-INFS-NEXT: ret float [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmin32b(
+// CHECK-FAST-SAME: float noundef nofpclass(nan inf) [[A:%.*]], float noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.minnum.f32(float [[A]], float [[B]])
+// CHECK-FAST-NEXT: ret float [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmin32b(
+// CHECK-STRICT-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.experimental.constrained.minnum.f32(float [[A]], float [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret float [[TMP0]]
+//
float fmin32b(float a, float b) {
return __builtin_fminf(a, b);
}
#if !defined(ENSTRICT)
-// CHECK: call nsz <4 x float> @llvm.minnum.v4f32(<4 x float> %0, <4 x float> %1)
-float *pfmin32(float* a, float* b, float* restrict c) {
- for (int i=0; i<4; i++)
- c[i] = fminf(a[i], b[i]);
- return c;
-}
-// CHECK: call nsz <4 x float> @llvm.minnum.v4f32(<4 x float> %0, <4 x float> %1)
-float *pfmin32b(float* a, float* b, float* restrict c) {
- for (int i=0; i<4; i++)
- c[i] = __builtin_fminf(a[i], b[i]);
+// CHECK-LABEL: define dso_local noundef <4 x float> @pfmin32(
+// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]], <4 x float> noundef [[C:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ELT_MIN:%.*]] = tail call <4 x float> @llvm.minnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-NEXT: ret <4 x float> [[ELT_MIN]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) <4 x float> @pfmin32(
+// CHECK-NO-NANS-SAME: <4 x float> noundef nofpclass(nan) [[A:%.*]], <4 x float> noundef nofpclass(nan) [[B:%.*]], <4 x float> noundef nofpclass(nan) [[C:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[ELT_MIN:%.*]] = tail call nnan <4 x float> @llvm.minnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-NO-NANS-NEXT: ret <4 x float> [[ELT_MIN]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) <4 x float> @pfmin32(
+// CHECK-NO-INFS-SAME: <4 x float> noundef nofpclass(inf) [[A:%.*]], <4 x float> noundef nofpclass(inf) [[B:%.*]], <4 x float> noundef nofpclass(inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[ELT_MIN:%.*]] = tail call ninf <4 x float> @llvm.minnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-NO-INFS-NEXT: ret <4 x float> [[ELT_MIN]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) <4 x float> @pfmin32(
+// CHECK-FAST-SAME: <4 x float> noundef nofpclass(nan inf) [[A:%.*]], <4 x float> noundef nofpclass(nan inf) [[B:%.*]], <4 x float> noundef nofpclass(nan inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[ELT_MIN:%.*]] = tail call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.minnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-FAST-NEXT: ret <4 x float> [[ELT_MIN]]
+//
+float4 pfmin32(float4 a, float4 b, float4 c) {
+ c = __builtin_elementwise_min(a, b);
return c;
}
#endif
-// CHECK: call nsz double @llvm.minnum.f64
-// CHECK-STRICT: call nsz double @llvm.experimental.constrained.minnum.f64{{.*}} #2
+// CHECK-LABEL: define dso_local noundef float @fmin64(
+// CHECK-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-NEXT: [[CONV:%.*]] = fptrunc double [[TMP0]] to float
+// CHECK-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmin64(
+// CHECK-NO-NANS-SAME: double noundef nofpclass(nan) [[A:%.*]], double noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-NO-NANS-NEXT: [[CONV:%.*]] = fptrunc nnan double [[TMP0]] to float
+// CHECK-NO-NANS-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmin64(
+// CHECK-NO-INFS-SAME: double noundef nofpclass(inf) [[A:%.*]], double noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-NO-INFS-NEXT: [[CONV:%.*]] = fptrunc ninf double [[TMP0]] to float
+// CHECK-NO-INFS-NEXT: ret float [[CONV]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmin64(
+// CHECK-FAST-SAME: double noundef nofpclass(nan inf) [[A:%.*]], double noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-FAST-NEXT: [[CONV:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP0]] to float
+// CHECK-FAST-NEXT: ret float [[CONV]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmin64(
+// CHECK-STRICT-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.experimental.constrained.minnum.f64(double [[A]], double [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: [[CONV:%.*]] = tail call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP0]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret float [[CONV]]
+//
float fmin64(double a, double b) {
return fmin(a, b);
}
-// CHECK: call nsz double @llvm.minnum.f64
-// CHECK-STRICT: call nsz double @llvm.experimental.constrained.minnum.f64{{.*}} #2
+// CHECK-LABEL: define dso_local noundef float @fmin64b(
+// CHECK-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-NEXT: [[CONV:%.*]] = fptrunc double [[TMP0]] to float
+// CHECK-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmin64b(
+// CHECK-NO-NANS-SAME: double noundef nofpclass(nan) [[A:%.*]], double noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-NO-NANS-NEXT: [[CONV:%.*]] = fptrunc nnan double [[TMP0]] to float
+// CHECK-NO-NANS-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmin64b(
+// CHECK-NO-INFS-SAME: double noundef nofpclass(inf) [[A:%.*]], double noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-NO-INFS-NEXT: [[CONV:%.*]] = fptrunc ninf double [[TMP0]] to float
+// CHECK-NO-INFS-NEXT: ret float [[CONV]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmin64b(
+// CHECK-FAST-SAME: double noundef nofpclass(nan inf) [[A:%.*]], double noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn double @llvm.minnum.f64(double [[A]], double [[B]])
+// CHECK-FAST-NEXT: [[CONV:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP0]] to float
+// CHECK-FAST-NEXT: ret float [[CONV]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmin64b(
+// CHECK-STRICT-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.experimental.constrained.minnum.f64(double [[A]], double [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: [[CONV:%.*]] = tail call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP0]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret float [[CONV]]
+//
float fmin64b(double a, double b) {
return __builtin_fmin(a, b);
}
#if !defined(ENSTRICT)
-// CHECK: call nsz <2 x double> @llvm.minnum.v2f64(<2 x double> %0, <2 x double> %1)
-double *pfmin64(double* a, double* b, double* restrict c) {
- for (int i=0; i<2; i++)
- c[i] = fmin(a[i], b[i]);
- return c;
-}
-// CHECK: call nsz <2 x double> @llvm.minnum.v2f64(<2 x double> %0, <2 x double> %1)
-double *pfmin64b(double* a, double* b, double* restrict c) {
- for (int i=0; i<2; i++)
- c[i] = __builtin_fmin(a[i], b[i]);
+// CHECK-LABEL: define dso_local noundef <2 x double> @pfmin64(
+// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]], <2 x double> noundef [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ELT_MIN:%.*]] = tail call <2 x double> @llvm.minnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-NEXT: ret <2 x double> [[ELT_MIN]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) <2 x double> @pfmin64(
+// CHECK-NO-NANS-SAME: <2 x double> noundef nofpclass(nan) [[A:%.*]], <2 x double> noundef nofpclass(nan) [[B:%.*]], <2 x double> noundef nofpclass(nan) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[ELT_MIN:%.*]] = tail call nnan <2 x double> @llvm.minnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-NO-NANS-NEXT: ret <2 x double> [[ELT_MIN]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) <2 x double> @pfmin64(
+// CHECK-NO-INFS-SAME: <2 x double> noundef nofpclass(inf) [[A:%.*]], <2 x double> noundef nofpclass(inf) [[B:%.*]], <2 x double> noundef nofpclass(inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[ELT_MIN:%.*]] = tail call ninf <2 x double> @llvm.minnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-NO-INFS-NEXT: ret <2 x double> [[ELT_MIN]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) <2 x double> @pfmin64(
+// CHECK-FAST-SAME: <2 x double> noundef nofpclass(nan inf) [[A:%.*]], <2 x double> noundef nofpclass(nan inf) [[B:%.*]], <2 x double> noundef nofpclass(nan inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[ELT_MIN:%.*]] = tail call reassoc nnan ninf nsz arcp afn <2 x double> @llvm.minnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-FAST-NEXT: ret <2 x double> [[ELT_MIN]]
+//
+double2 pfmin64(double2 a, double2 b, double2 c) {
+ c = __builtin_elementwise_min(a, b);
return c;
}
#endif
-// CHECK: call nsz x86_fp80 @llvm.minnum.f80
-// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80{{.*}} #2
-float fmin80(long double a, long double b) {
+// CHECK-LABEL: define dso_local noundef x86_fp80 @fmin80(
+// CHECK-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) x86_fp80 @fmin80(
+// CHECK-NO-NANS-SAME: x86_fp80 noundef nofpclass(nan) [[A:%.*]], x86_fp80 noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-NANS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) x86_fp80 @fmin80(
+// CHECK-NO-INFS-SAME: x86_fp80 noundef nofpclass(inf) [[A:%.*]], x86_fp80 noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-INFS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) x86_fp80 @fmin80(
+// CHECK-FAST-SAME: x86_fp80 noundef nofpclass(nan inf) [[A:%.*]], x86_fp80 noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-FAST-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local x86_fp80 @fmin80(
+// CHECK-STRICT-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret x86_fp80 [[TMP0]]
+//
+long double fmin80(long double a, long double b) {
return fminl(a, b);
}
-// CHECK: call nsz x86_fp80 @llvm.minnum.f80
-// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80{{.*}} #2
-float fmin80b(long double a, long double b) {
+// CHECK-LABEL: define dso_local noundef x86_fp80 @fmin80b(
+// CHECK-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) x86_fp80 @fmin80b(
+// CHECK-NO-NANS-SAME: x86_fp80 noundef nofpclass(nan) [[A:%.*]], x86_fp80 noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-NANS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) x86_fp80 @fmin80b(
+// CHECK-NO-INFS-SAME: x86_fp80 noundef nofpclass(inf) [[A:%.*]], x86_fp80 noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-INFS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) x86_fp80 @fmin80b(
+// CHECK-FAST-SAME: x86_fp80 noundef nofpclass(nan inf) [[A:%.*]], x86_fp80 noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-FAST-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local x86_fp80 @fmin80b(
+// CHECK-STRICT-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.experimental.constrained.minnum.f80(x86_fp80 [[A]], x86_fp80 [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret x86_fp80 [[TMP0]]
+//
+long double fmin80b(long double a, long double b) {
return __builtin_fminl(a, b);
}
-// CHECK: call nsz float @llvm.maxnum.f32
-// CHECK-STRICT: call nsz float @llvm.experimental.constrained.maxnum.f32{{.*}} #2
+// CHECK-LABEL: define dso_local noundef float @fmax32(
+// CHECK-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmax32(
+// CHECK-NO-NANS-SAME: float noundef nofpclass(nan) [[A:%.*]], float noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-NO-NANS-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmax32(
+// CHECK-NO-INFS-SAME: float noundef nofpclass(inf) [[A:%.*]], float noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-NO-INFS-NEXT: ret float [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmax32(
+// CHECK-FAST-SAME: float noundef nofpclass(nan inf) [[A:%.*]], float noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-FAST-NEXT: ret float [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmax32(
+// CHECK-STRICT-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.experimental.constrained.maxnum.f32(float [[A]], float [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret float [[TMP0]]
+//
float fmax32(float a, float b) {
return fmaxf(a, b);
}
-// CHECK: call nsz float @llvm.maxnum.f32
-// CHECK-STRICT: call nsz float @llvm.experimental.constrained.maxnum.f32{{.*}} #2
+// CHECK-LABEL: define dso_local noundef float @fmax32b(
+// CHECK-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmax32b(
+// CHECK-NO-NANS-SAME: float noundef nofpclass(nan) [[A:%.*]], float noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-NO-NANS-NEXT: ret float [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmax32b(
+// CHECK-NO-INFS-SAME: float noundef nofpclass(inf) [[A:%.*]], float noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-NO-INFS-NEXT: ret float [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmax32b(
+// CHECK-FAST-SAME: float noundef nofpclass(nan inf) [[A:%.*]], float noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.maxnum.f32(float [[A]], float [[B]])
+// CHECK-FAST-NEXT: ret float [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmax32b(
+// CHECK-STRICT-SAME: float noundef [[A:%.*]], float noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz float @llvm.experimental.constrained.maxnum.f32(float [[A]], float [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret float [[TMP0]]
+//
float fmax32b(float a, float b) {
return __builtin_fmaxf(a, b);
}
#if !defined(ENSTRICT)
-// CHECK: call nsz <4 x float> @llvm.maxnum.v4f32(<4 x float> %0, <4 x float> %1)
-float *pfmax32(float* a, float* b, float* restrict c) {
- for (int i=0; i<4; i++)
- c[i] = fmaxf(a[i], b[i]);
- return c;
-}
-// CHECK: call nsz <4 x float> @llvm.maxnum.v4f32(<4 x float> %0, <4 x float> %1)
-float *pfmax32b(float* a, float* b, float* restrict c) {
- for (int i=0; i<4; i++)
- c[i] = __builtin_fmaxf(a[i], b[i]);
+// CHECK-LABEL: define dso_local noundef <4 x float> @pfmax32(
+// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]], <4 x float> noundef [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ELT_MAX:%.*]] = tail call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-NEXT: ret <4 x float> [[ELT_MAX]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) <4 x float> @pfmax32(
+// CHECK-NO-NANS-SAME: <4 x float> noundef nofpclass(nan) [[A:%.*]], <4 x float> noundef nofpclass(nan) [[B:%.*]], <4 x float> noundef nofpclass(nan) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[ELT_MAX:%.*]] = tail call nnan <4 x float> @llvm.maxnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-NO-NANS-NEXT: ret <4 x float> [[ELT_MAX]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) <4 x float> @pfmax32(
+// CHECK-NO-INFS-SAME: <4 x float> noundef nofpclass(inf) [[A:%.*]], <4 x float> noundef nofpclass(inf) [[B:%.*]], <4 x float> noundef nofpclass(inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[ELT_MAX:%.*]] = tail call ninf <4 x float> @llvm.maxnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-NO-INFS-NEXT: ret <4 x float> [[ELT_MAX]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) <4 x float> @pfmax32(
+// CHECK-FAST-SAME: <4 x float> noundef nofpclass(nan inf) [[A:%.*]], <4 x float> noundef nofpclass(nan inf) [[B:%.*]], <4 x float> noundef nofpclass(nan inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[ELT_MAX:%.*]] = tail call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.maxnum.v4f32(<4 x float> [[A]], <4 x float> [[B]])
+// CHECK-FAST-NEXT: ret <4 x float> [[ELT_MAX]]
+//
+float4 pfmax32(float4 a, float4 b, float4 c) {
+ c = __builtin_elementwise_max(a, b);
return c;
}
#endif
-// CHECK: call nsz double @llvm.maxnum.f64
-// CHECK-STRICT: call nsz double @llvm.experimental.constrained.maxnum.f64{{.*}} #2
+// CHECK-LABEL: define dso_local noundef float @fmax64(
+// CHECK-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-NEXT: [[CONV:%.*]] = fptrunc double [[TMP0]] to float
+// CHECK-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmax64(
+// CHECK-NO-NANS-SAME: double noundef nofpclass(nan) [[A:%.*]], double noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-NO-NANS-NEXT: [[CONV:%.*]] = fptrunc nnan double [[TMP0]] to float
+// CHECK-NO-NANS-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmax64(
+// CHECK-NO-INFS-SAME: double noundef nofpclass(inf) [[A:%.*]], double noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-NO-INFS-NEXT: [[CONV:%.*]] = fptrunc ninf double [[TMP0]] to float
+// CHECK-NO-INFS-NEXT: ret float [[CONV]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmax64(
+// CHECK-FAST-SAME: double noundef nofpclass(nan inf) [[A:%.*]], double noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-FAST-NEXT: [[CONV:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP0]] to float
+// CHECK-FAST-NEXT: ret float [[CONV]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmax64(
+// CHECK-STRICT-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.experimental.constrained.maxnum.f64(double [[A]], double [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: [[CONV:%.*]] = tail call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP0]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret float [[CONV]]
+//
float fmax64(double a, double b) {
return fmax(a, b);
}
-// CHECK: call nsz double @llvm.maxnum.f64
-// CHECK-STRICT: call nsz double @llvm.experimental.constrained.maxnum.f64{{.*}} #2
+// CHECK-LABEL: define dso_local noundef float @fmax64b(
+// CHECK-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-NEXT: [[CONV:%.*]] = fptrunc double [[TMP0]] to float
+// CHECK-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) float @fmax64b(
+// CHECK-NO-NANS-SAME: double noundef nofpclass(nan) [[A:%.*]], double noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-NO-NANS-NEXT: [[CONV:%.*]] = fptrunc nnan double [[TMP0]] to float
+// CHECK-NO-NANS-NEXT: ret float [[CONV]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) float @fmax64b(
+// CHECK-NO-INFS-SAME: double noundef nofpclass(inf) [[A:%.*]], double noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-NO-INFS-NEXT: [[CONV:%.*]] = fptrunc ninf double [[TMP0]] to float
+// CHECK-NO-INFS-NEXT: ret float [[CONV]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) float @fmax64b(
+// CHECK-FAST-SAME: double noundef nofpclass(nan inf) [[A:%.*]], double noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn double @llvm.maxnum.f64(double [[A]], double [[B]])
+// CHECK-FAST-NEXT: [[CONV:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn double [[TMP0]] to float
+// CHECK-FAST-NEXT: ret float [[CONV]]
+//
+// CHECK-STRICT-LABEL: define dso_local float @fmax64b(
+// CHECK-STRICT-SAME: double noundef [[A:%.*]], double noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz double @llvm.experimental.constrained.maxnum.f64(double [[A]], double [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: [[CONV:%.*]] = tail call float @llvm.experimental.constrained.fptrunc.f32.f64(double [[TMP0]], metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret float [[CONV]]
+//
float fmax64b(double a, double b) {
return __builtin_fmax(a, b);
}
-// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
-// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80{{.*}} #2
-float fmax3(long double a, long double b) {
- return fmaxl(a, b);
-}
#if !defined(ENSTRICT)
-// CHECK: call nsz <2 x double> @llvm.maxnum.v2f64(<2 x double> %0, <2 x double> %1)
-double *pfmax64(double* a, double* b, double* restrict c) {
- for (int i=0; i<2; i++)
- c[i] = fmax(a[i], b[i]);
- return c;
-}
-// CHECK: call nsz <2 x double> @llvm.maxnum.v2f64(<2 x double> %0, <2 x double> %1)
-double *pfmax64b(double* a, double* b, double* restrict c) {
- for (int i=0; i<2; i++)
- c[i] = __builtin_fmax(a[i], b[i]);
+// CHECK-LABEL: define dso_local noundef <2 x double> @pfmax64(
+// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]], <2 x double> noundef [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[ELT_MAX:%.*]] = tail call <2 x double> @llvm.maxnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-NEXT: ret <2 x double> [[ELT_MAX]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) <2 x double> @pfmax64(
+// CHECK-NO-NANS-SAME: <2 x double> noundef nofpclass(nan) [[A:%.*]], <2 x double> noundef nofpclass(nan) [[B:%.*]], <2 x double> noundef nofpclass(nan) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[ELT_MAX:%.*]] = tail call nnan <2 x double> @llvm.maxnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-NO-NANS-NEXT: ret <2 x double> [[ELT_MAX]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) <2 x double> @pfmax64(
+// CHECK-NO-INFS-SAME: <2 x double> noundef nofpclass(inf) [[A:%.*]], <2 x double> noundef nofpclass(inf) [[B:%.*]], <2 x double> noundef nofpclass(inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[ELT_MAX:%.*]] = tail call ninf <2 x double> @llvm.maxnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-NO-INFS-NEXT: ret <2 x double> [[ELT_MAX]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) <2 x double> @pfmax64(
+// CHECK-FAST-SAME: <2 x double> noundef nofpclass(nan inf) [[A:%.*]], <2 x double> noundef nofpclass(nan inf) [[B:%.*]], <2 x double> noundef nofpclass(nan inf) [[C:%.*]]) local_unnamed_addr #[[ATTR2]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[ELT_MAX:%.*]] = tail call reassoc nnan ninf nsz arcp afn <2 x double> @llvm.maxnum.v2f64(<2 x double> [[A]], <2 x double> [[B]])
+// CHECK-FAST-NEXT: ret <2 x double> [[ELT_MAX]]
+//
+double2 pfmax64(double2 a, double2 b, double2 c) {
+ c = __builtin_elementwise_max(a, b);
return c;
}
#endif
-// CHECK: call nsz x86_fp80 @llvm.maxnum.f80
-// CHECK-STRICT: call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80{{.*}} #2
-float fmax80b(long double a, long double b) {
+// CHECK-LABEL: define dso_local noundef x86_fp80 @fmax80(
+// CHECK-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) x86_fp80 @fmax80(
+// CHECK-NO-NANS-SAME: x86_fp80 noundef nofpclass(nan) [[A:%.*]], x86_fp80 noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-NANS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) x86_fp80 @fmax80(
+// CHECK-NO-INFS-SAME: x86_fp80 noundef nofpclass(inf) [[A:%.*]], x86_fp80 noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-INFS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) x86_fp80 @fmax80(
+// CHECK-FAST-SAME: x86_fp80 noundef nofpclass(nan inf) [[A:%.*]], x86_fp80 noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-FAST-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local x86_fp80 @fmax80(
+// CHECK-STRICT-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret x86_fp80 [[TMP0]]
+//
+long double fmax80(long double a, long double b) {
+ return fmaxl(a, b);
+}
+// CHECK-LABEL: define dso_local noundef x86_fp80 @fmax80b(
+// CHECK-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-NANS-LABEL: define dso_local nofpclass(nan) x86_fp80 @fmax80b(
+// CHECK-NO-NANS-SAME: x86_fp80 noundef nofpclass(nan) [[A:%.*]], x86_fp80 noundef nofpclass(nan) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-NANS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-NANS-NEXT: [[TMP0:%.*]] = tail call nnan nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-NANS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-NO-INFS-LABEL: define dso_local nofpclass(inf) x86_fp80 @fmax80b(
+// CHECK-NO-INFS-SAME: x86_fp80 noundef nofpclass(inf) [[A:%.*]], x86_fp80 noundef nofpclass(inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NO-INFS-NEXT: [[ENTRY:.*:]]
+// CHECK-NO-INFS-NEXT: [[TMP0:%.*]] = tail call ninf nsz x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-NO-INFS-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-FAST-LABEL: define dso_local nofpclass(nan inf) x86_fp80 @fmax80b(
+// CHECK-FAST-SAME: x86_fp80 noundef nofpclass(nan inf) [[A:%.*]], x86_fp80 noundef nofpclass(nan inf) [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-FAST-NEXT: [[ENTRY:.*:]]
+// CHECK-FAST-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]])
+// CHECK-FAST-NEXT: ret x86_fp80 [[TMP0]]
+//
+// CHECK-STRICT-LABEL: define dso_local x86_fp80 @fmax80b(
+// CHECK-STRICT-SAME: x86_fp80 noundef [[A:%.*]], x86_fp80 noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-STRICT-NEXT: [[ENTRY:.*:]]
+// CHECK-STRICT-NEXT: [[TMP0:%.*]] = tail call nsz x86_fp80 @llvm.experimental.constrained.maxnum.f80(x86_fp80 [[A]], x86_fp80 [[B]], metadata !"fpexcept.strict") #[[ATTR2]]
+// CHECK-STRICT-NEXT: ret x86_fp80 [[TMP0]]
+//
+long double fmax80b(long double a, long double b) {
return __builtin_fmaxl(a, b);
}
-//CHECK-STRICT: attributes #2 = { strictfp }
More information about the llvm-commits
mailing list