[clang] [llvm] [PowerPC] Add _Float16 datatype support for Power8+ with -mfloat16 flag (PR #196559)
Tony Varghese via cfe-commits
cfe-commits at lists.llvm.org
Fri May 8 08:47:30 PDT 2026
https://github.com/tonykuttai created https://github.com/llvm/llvm-project/pull/196559
This patch introduces experimental half-precision floating-point (_Float16)
support for PowerPC Power8 and later architectures, enabled via the new
-mfloat16 compiler flag.
Key changes:
- Add -mfloat16 flag to enable half-precision floating-point support
- Register f16 as a legal type using VHFRCRegClass (VSX half-precision registers)
- Implement f16 operations with promotion to f32 for arithmetic operations
- Add hardware conversion support for Power9+ (xscvhpdp/xscvdphp instructions)
- Use libcall conversions for Power8 (__extendhfsf2, __truncsfhf2, etc.)
- Support direct load/store operations for f16 values
- Handle f16 in calling conventions with proper register allocation
- Add comprehensive test coverage for AIX and Linux platforms
The implementation addresses correctness issues from GitHub issues #97975
(intermediate precision) and #97981 (NaN payload corruption) by treating
f16 as a first-class type rather than using lossy conversion functions.
Power9+ uses native hardware instructions for conversions, while Power8
falls back to compiler-rt library functions for type conversions.
>From 3eac451d7fc074275cae21da7e585ea034edf997 Mon Sep 17 00:00:00 2001
From: Tony Varghese <tonypalampalliyil at gmail.com>
Date: Fri, 8 May 2026 20:04:01 +0530
Subject: [PATCH] [PowerPC] Add _Float16 datatype support for Power8+ with
-mfloat16 flag
This patch introduces experimental half-precision floating-point (_Float16)
support for PowerPC Power8 and later architectures, enabled via the new
-mfloat16 compiler flag.
Key changes:
- Add -mfloat16 flag to enable half-precision floating-point support
- Register f16 as a legal type using VHFRCRegClass (VSX half-precision registers)
- Implement f16 operations with promotion to f32 for arithmetic operations
- Add hardware conversion support for Power9+ (xscvhpdp/xscvdphp instructions)
- Use libcall conversions for Power8 (__extendhfsf2, __truncsfhf2, etc.)
- Support direct load/store operations for f16 values
- Handle f16 in calling conventions with proper register allocation
- Add comprehensive test coverage for AIX and Linux platforms
The implementation addresses correctness issues from GitHub issues #97975
(intermediate precision) and #97981 (NaN payload corruption) by treating
f16 as a first-class type rather than using lossy conversion functions.
Power9+ uses native hardware instructions for conversions, while Power8
falls back to compiler-rt library functions for type conversions.
---
clang/include/clang/Options/Options.td | 2 +
clang/lib/Basic/Targets/PPC.cpp | 11 +
clang/lib/Basic/Targets/PPC.h | 5 +
clang/lib/Driver/ToolChains/Arch/PPC.cpp | 5 +
clang/test/CodeGen/PowerPC/half-float16-ppc.c | 154 +
.../PowerPC/GISel/PPCRegisterBankInfo.cpp | 3 +-
llvm/lib/Target/PowerPC/PPC.td | 5 +
llvm/lib/Target/PowerPC/PPCCallingConv.td | 13 +-
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 101 +-
llvm/lib/Target/PowerPC/PPCISelLowering.h | 5 +
llvm/lib/Target/PowerPC/PPCInstrVSX.td | 82 +
llvm/lib/Target/PowerPC/PPCRegisterInfo.td | 7 +
llvm/test/CodeGen/PowerPC/f16-aix-psa.ll | 96 +
llvm/test/CodeGen/PowerPC/half-float16-ppc.ll | 4198 +++++++++++++++++
llvm/test/CodeGen/PowerPC/shrink-wrap.mir | 2 +-
15 files changed, 4673 insertions(+), 16 deletions(-)
create mode 100644 clang/test/CodeGen/PowerPC/half-float16-ppc.c
create mode 100644 llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
create mode 100644 llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 5eeabf4c33b76..3e4f189637e0a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5919,6 +5919,8 @@ def mcrbits : Flag<["-"], "mcrbits">, Group<m_ppc_Features_Group>,
"(the enablement of CR-bit tracking support) is the default for "
"POWER8 and above, as well as for all other CPUs when "
"optimization is applied (-O2 and above).">;
+def mfloat16 : Flag<["-"], "mfloat16">, Group<m_ppc_Features_Group>,
+ HelpText<"Enable half-precision floating point (experimental).">;
def mno_crbits : Flag<["-"], "mno-crbits">, Group<m_ppc_Features_Group>;
def minvariant_function_descriptors :
Flag<["-"], "minvariant-function-descriptors">, Group<m_ppc_Features_Group>;
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index c9a41df806aff..f999372f31a94 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -82,6 +82,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasQuadwordAtomics = true;
} else if (Feature == "+longcall") {
UseLongCalls = true;
+ } else if (Feature == "+float16") {
+ HasFloat16 = true;
}
// TODO: Finish this list and add an assert that we've handled them
// all.
@@ -504,6 +506,7 @@ static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
Found |= FindVSXSubfeature("+crypto", "-mcrypto", "-msoft-float");
Found |= FindVSXSubfeature("+power10-vector", "-mpower10-vector",
"-msoft-float");
+ Found |= FindVSXSubfeature("+float16", "-mfloat16", "-msoft-float");
}
if (Found)
return false;
@@ -555,6 +558,14 @@ bool PPCTargetInfo::initFeatureMap(
return false;
}
+ if (!(ArchDefs & ArchDefinePwr8)) {
+ if (llvm::is_contained(FeaturesVec, "+float16")) {
+ // Reject -mfloat16 on pre-Power8 CPUs.
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat16" << CPU;
+ return false;
+ }
+ }
+
if (!(ArchDefs & ArchDefinePwr10)) {
if (llvm::is_contained(FeaturesVec, "+mma")) {
// MMA operations are not available pre-Power10.
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index a9f49aa3aebe1..df263eac0d6de 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -73,6 +73,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
bool HasPCRelativeMemops = false;
bool HasQuadwordAtomics = false;
bool UseLongCalls = false;
+ bool HasFloat16 = false;
protected:
std::string ABI;
@@ -362,6 +363,10 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
bool hasBitIntType() const override { return true; }
+ // Returns true when _Float16 is available as a native type. Requires the
+ // explicit opt-in (-mfloat16).
+ bool hasFloat16Type() const override { return HasFloat16; }
+
bool isSPRegName(StringRef RegName) const override {
return RegName == "r1" || RegName == "x1";
}
diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index 17051980f34fb..f06645038cfca 100644
--- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -77,6 +77,11 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
D.Diag(diag::err_opt_not_valid_on_target)
<< "-maix-shared-lib-tls-model-opt";
+ // The _Float16 datatype is supported throguh the -mfloat16 flag.
+ if (Args.hasArg(options::OPT_mfloat16)) {
+ Features.push_back("+float16");
+ }
+
// The integrated assembler counts as a "modern AIX assembler" for the
// purposes of the modern-aix-as.
if (Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
diff --git a/clang/test/CodeGen/PowerPC/half-float16-ppc.c b/clang/test/CodeGen/PowerPC/half-float16-ppc.c
new file mode 100644
index 0000000000000..45b336d03f7db
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/half-float16-ppc.c
@@ -0,0 +1,154 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple powerpc-unknown-unknown -O2 -emit-llvm %s -o - \
+// RUN: -target-cpu pwr8 -target-feature +float16 | FileCheck %s
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __INT64_TYPE__ int64_t;
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+// ============================================
+// Arithmetic Operations
+// ============================================
+// CHECK-LABEL: define dso_local noundef half @c_add(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[UNPROMOTION:%.*]] = fadd half [[A]], [[B]]
+// CHECK-NEXT: ret half [[UNPROMOTION]]
+//
+_Float16 c_add(_Float16 a, _Float16 b) { return a + b; }
+
+
+// CHECK-LABEL: define dso_local noundef half @c_sub(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[UNPROMOTION:%.*]] = fsub half [[A]], [[B]]
+// CHECK-NEXT: ret half [[UNPROMOTION]]
+//
+_Float16 c_sub(_Float16 a, _Float16 b) { return a - b; }
+
+// CHECK-LABEL: define dso_local noundef half @c_mul(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[UNPROMOTION:%.*]] = fmul half [[A]], [[B]]
+// CHECK-NEXT: ret half [[UNPROMOTION]]
+//
+_Float16 c_mul(_Float16 a, _Float16 b) { return a * b; }
+
+// CHECK-LABEL: define dso_local noundef half @c_div(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[UNPROMOTION:%.*]] = fdiv half [[A]], [[B]]
+// CHECK-NEXT: ret half [[UNPROMOTION]]
+//
+_Float16 c_div(_Float16 a, _Float16 b) { return a / b; }
+
+// ============================================
+// Unary Operations
+// ============================================
+
+// CHECK-LABEL: define dso_local noundef half @c_neg(
+// CHECK-SAME: half noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[UNPROMOTION:%.*]] = fneg half [[A]]
+// CHECK-NEXT: ret half [[UNPROMOTION]]
+//
+_Float16 c_neg(_Float16 a) { return -a; }
+
+// ============================================
+// Compare Operations
+// ============================================
+
+// CHECK-LABEL: define dso_local range(i32 0, 2) i32 @c_eq(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CMP:%.*]] = fcmp oeq half [[A]], [[B]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// CHECK-NEXT: ret i32 [[CONV]]
+//
+int c_eq(_Float16 a, _Float16 b){ return a == b; }
+
+// CHECK-LABEL: define dso_local range(i32 0, 2) i32 @c_ne(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CMP:%.*]] = fcmp une half [[A]], [[B]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// CHECK-NEXT: ret i32 [[CONV]]
+//
+int c_ne(_Float16 a, _Float16 b){ return a != b; }
+
+// CHECK-LABEL: define dso_local range(i32 0, 2) i32 @c_lt(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CMP:%.*]] = fcmp olt half [[A]], [[B]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// CHECK-NEXT: ret i32 [[CONV]]
+//
+int c_lt(_Float16 a, _Float16 b){ return a < b; }
+
+// CHECK-LABEL: define dso_local range(i32 0, 2) i32 @c_le(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CMP:%.*]] = fcmp ole half [[A]], [[B]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// CHECK-NEXT: ret i32 [[CONV]]
+//
+int c_le(_Float16 a, _Float16 b){ return a <= b; }
+
+// CHECK-LABEL: define dso_local range(i32 0, 2) i32 @c_gt(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CMP:%.*]] = fcmp ogt half [[A]], [[B]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// CHECK-NEXT: ret i32 [[CONV]]
+//
+int c_gt(_Float16 a, _Float16 b){ return a > b; }
+
+// CHECK-LABEL: define dso_local range(i32 0, 2) i32 @c_ge(
+// CHECK-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CMP:%.*]] = fcmp oge half [[A]], [[B]]
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// CHECK-NEXT: ret i32 [[CONV]]
+//
+int c_ge(_Float16 a, _Float16 b){ return a >= b; }
+
+// ============================================
+// Conversion Operations: half <-> float/double
+// ============================================
+
+// CHECK-LABEL: define dso_local noundef float @to_f32(
+// CHECK-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = fpext half [[X]] to float
+// CHECK-NEXT: ret float [[CONV]]
+//
+float to_f32(_Float16 x){ return (float)x; }
+
+// CHECK-LABEL: define dso_local noundef double @to_f64(
+// CHECK-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = fpext half [[X]] to double
+// CHECK-NEXT: ret double [[CONV]]
+//
+double to_f64(_Float16 x){ return (double)x; }
+
+// CHECK-LABEL: define dso_local noundef half @from_f32(
+// CHECK-SAME: float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = fptrunc float [[X]] to half
+// CHECK-NEXT: ret half [[CONV]]
+//
+_Float16 from_f32(float x){ return (_Float16)x; }
+
+// CHECK-LABEL: define dso_local noundef half @from_f64(
+// CHECK-SAME: double noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CONV:%.*]] = fptrunc double [[X]] to half
+// CHECK-NEXT: ret half [[CONV]]
+//
+_Float16 from_f64(double x){ return (_Float16)x; }
diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
index 3370dedbecb16..fb6eccfe043b5 100644
--- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
+++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
@@ -34,7 +34,8 @@ PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
LLT Ty) const {
switch (RC.getID()) {
case PPC::VSFRCRegClassID:
- case PPC::SPILLTOVSRRC_and_VSFRCRegClassID:
+ case PPC::VHFRCRegClassID:
+ case PPC::SPILLTOVSRRC_and_VHFRCRegClassID:
case PPC::SPILLTOVSRRC_and_VFRCRegClassID:
case PPC::SPILLTOVSRRC_and_F4RCRegClassID:
case PPC::F8RCRegClassID:
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index 7b4bae60f7e74..43982c4c5c5fb 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -71,6 +71,10 @@ def FeatureModernAIXAs
"AIX system assembler is modern enough to support new mnes">;
def FeatureHardFloat : SubtargetFeature<"hard-float", "HasHardFloat", "true",
"Enable floating-point instructions">;
+def FeatureFloat16 :
+ SubtargetFeature<"float16",
+ "HasFloat16", "true",
+ "Enable half-precision floating point support (experimental)">;
// Specifies that we are in 64-bit mode or that we should use 64-bit registers
// in 32-bit mode when possible. Requires Feature64Bit to be enabled.
@@ -405,6 +409,7 @@ def HasOnlySwappingMemOps : Predicate<"!Subtarget->hasP9Vector()">;
def NoP10Vector : Predicate<"!Subtarget->hasP10Vector()">;
def HasP10Vector : Predicate<"Subtarget->hasP10Vector()">;
def HasFutureVector : Predicate<"Subtarget->hasFutureVector()">;
+def HasFloat16 : Predicate<"Subtarget->hasFloat16()">;
// Predicates used to differenciate between different ISAs.
def IsISA2_06 : Predicate<"Subtarget->isISA2_06()">;
diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td b/llvm/lib/Target/PowerPC/PPCCallingConv.td
index 5d4fe06ebdddd..961da883748dc 100644
--- a/llvm/lib/Target/PowerPC/PPCCallingConv.td
+++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td
@@ -75,6 +75,9 @@ def RetCC_PPC : CallingConv<[
CCIfType<[i64], CCAssignToReg<[X3, X4, X5, X6]>>,
CCIfType<[i128], CCAssignToReg<[X3, X4, X5, X6]>>,
+ // Return f16 in FPR as 16 bit value.
+ CCIfType<[f16], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>,
+
// Floating point types returned as "direct" go into F1 .. F8; note that
// only the ELFv2 ABI fully utilizes all these registers.
CCIfNotSubtarget<"hasSPE()",
@@ -125,8 +128,8 @@ def CC_PPC64_ELF : CallingConv<[
CCIfType<[i64], CCAssignToReg<[X3, X4, X5, X6, X7, X8, X9, X10]>>,
// Handle fp types and shadow the corresponding registers as necessary.
- CCIfType<[f32, f64], CCIfNotVarArg<CCCustom<"CC_PPC64_ELF_Shadow_GPR_Regs">>>,
- CCIfType<[f32, f64],
+ CCIfType<[f16, f32, f64], CCIfNotVarArg<CCCustom<"CC_PPC64_ELF_Shadow_GPR_Regs">>>,
+ CCIfType<[f16, f32, f64],
CCIfNotVarArg<CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10,
F11, F12, F13]>>>,
@@ -161,7 +164,7 @@ def CC_PPC64_ELF_FIS : CallingConv<[
CCIfType<[i16], CCPromoteToType<i64>>,
CCIfType<[i32], CCPromoteToType<i64>>,
CCIfType<[i64], CCAssignToReg<[X3, X4, X5, X6, X7, X8, X9, X10]>>,
- CCIfType<[f32, f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>
+ CCIfType<[f16, f32, f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>
]>;
// Simple return-value convention for 64-bit ELF PowerPC fast isel.
@@ -178,6 +181,7 @@ def RetCC_PPC64_ELF_FIS : CallingConv<[
CCIfType<[i32], CCPromoteToType<i64>>,
CCIfType<[i64], CCAssignToReg<[X3, X4, X5, X6]>>,
CCIfType<[i128], CCAssignToReg<[X3, X4, X5, X6]>>,
+ CCIfType<[f16], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>,
CCIfType<[f32], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>,
CCIfType<[f64], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>,
CCIfType<[f128],
@@ -218,6 +222,9 @@ def CC_PPC32_SVR4_Common : CallingConv<[
// The first 8 integer arguments are passed in integer registers.
CCIfType<[i32], CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>,
+ // Pass f16 in FPRs.
+ CCIfType<[f16], CCAssignToReg<[F1, F2, F3, F4, F5, F6, F7, F8]>>,
+
// Make sure the i64 words from a long double are either both passed in
// registers or both passed on the stack.
CCIfType<[f64], CCIfSplit<CCCustom<"CC_PPC32_SVR4_Custom_AlignFPArgRegs">>>,
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 407093fd2b849..3a79e46e51bed 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -261,6 +261,68 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setTruncStoreAction(MVT::f32, MVT::f16, Expand);
}
+ // Only active when -mfloat16 is passed and hard float is enabled.
+ // This block intentionally overrides some actions set above
+ // because when f16 is a first-class type we handle load/store
+ // directly rather than through extending loads.
+ if (Subtarget.hasFloat16() && Subtarget.hasHardFloat()) {
+ // Make f16 a legal type.
+ addRegisterClass(MVT::f16, &PPC::VHFRCRegClass);
+
+ // PowerPC has no native f16 arithmetic instructions. All arithmetic,
+ // comparisons, rounding, transcendentals, and min/max must be promoted
+ // to f32 for computation. On P8 this means libcalls (__extendhfsf2 /
+ // __truncsfhf2); on P9 this means xscvhpdp/xsaddsp.../xscvdphp sequences.
+ static const unsigned F16PromoteOps[] = {
+ ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM, ISD::FMINIMUMNUM,
+ ISD::FMAXIMUM, ISD::FMINIMUM, ISD::FADD, ISD::FSUB,
+ ISD::FMUL, ISD::FMA, ISD::FDIV, ISD::FSQRT,
+ ISD::FREM, ISD::FPOW, ISD::FLOG, ISD::FLOG2,
+ ISD::FLOG10, ISD::FEXP, ISD::FEXP2, ISD::FEXP10,
+ ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FRINT,
+ ISD::FNEARBYINT, ISD::FROUND, ISD::FROUNDEVEN, ISD::FCANONICALIZE,
+ ISD::FSIN, ISD::FCOS, ISD::SETCC, ISD::SELECT_CC,
+ ISD::SELECT};
+
+ // Promote all the arithmetic operations defined above to f32.
+ setOperationAction(F16PromoteOps, MVT::f16, Promote);
+
+ setOperationAction(ISD::LOAD, MVT::f16, Legal);
+ setOperationAction(ISD::STORE, MVT::f16, Legal);
+
+ // Legal handling for bit manipulation.
+ setOperationAction(ISD::FABS, MVT::f16, Legal);
+ setOperationAction(ISD::FNEG, MVT::f16, Legal);
+ setOperationAction(ISD::FCOPYSIGN, MVT::f16, Legal);
+
+ // Expand constant FP.
+ setOperationAction(ISD::ConstantFP, MVT::f16, Expand);
+
+ // Expand extending loads and truncating stores.
+ for (MVT VT : {MVT::f32, MVT::f64}) {
+ setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand);
+ setTruncStoreAction(VT, MVT::f16, Expand);
+ }
+
+ if (Subtarget.hasP9Vector()) {
+ // P9+: Hardware support for conversions.
+ setOperationAction(ISD::FP_EXTEND, MVT::f32, Legal);
+ setOperationAction(ISD::FP_EXTEND, MVT::f64, Legal);
+ setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f32, Legal);
+ setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f64, Legal);
+ setOperationAction(ISD::FP_ROUND, MVT::f16, Legal);
+ setOperationAction(ISD::STRICT_FP_ROUND, MVT::f16, Legal);
+ } else {
+ // P8: Conversions via libcalls
+ setOperationAction(ISD::FP_EXTEND, MVT::f32, Expand);
+ setOperationAction(ISD::FP_EXTEND, MVT::f64, Expand);
+ setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f32, Expand);
+ setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f64, Expand);
+ setOperationAction(ISD::FP_ROUND, MVT::f16, Expand);
+ setOperationAction(ISD::STRICT_FP_ROUND, MVT::f16, Expand);
+ }
+ }
+
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
// PowerPC has pre-inc load and store's.
@@ -1675,6 +1737,12 @@ bool PPCTargetLowering::hasSPE() const {
return Subtarget.hasSPE();
}
+/// Tell the ABI lowering infrastructure to use FPRs for _Float16 parameters
+/// and return values rather than GPRs. Active only when -mfloat16 is enabled.
+bool PPCTargetLowering::useFPRegsForHalfType() const {
+ return Subtarget.hasFloat16() && Subtarget.hasHardFloat();
+}
+
bool PPCTargetLowering::preferIncOfAddToSubOfNot(EVT VT) const {
return VT.isScalarInteger();
}
@@ -4630,6 +4698,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
ArgOffset += 8;
break;
+ case MVT::f16:
case MVT::f32:
case MVT::f64:
// These can be scalar arguments or elements of a float array type
@@ -6497,6 +6566,7 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
if (!IsFastCall)
ArgOffset += PtrByteSize;
break;
+ case MVT::f16:
case MVT::f32:
case MVT::f64: {
// These can be scalar arguments or elements of a float array type
@@ -6843,6 +6913,7 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
return false;
}
+ case MVT::f16:
case MVT::f32:
case MVT::f64: {
// Parameter save area (PSA) is reserved even if the float passes in fpr.
@@ -6986,10 +7057,9 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
}
// So far, this function is only used by LowerFormalArguments_AIX()
-static const TargetRegisterClass *getRegClassForSVT(MVT::SimpleValueType SVT,
- bool IsPPC64,
- bool HasP8Vector,
- bool HasVSX) {
+static const TargetRegisterClass *
+getRegClassForSVT(MVT::SimpleValueType SVT, bool IsPPC64, bool HasP8Vector,
+ bool HasVSX, bool HasFloat16) {
assert((IsPPC64 || SVT != MVT::i64) &&
"i64 should have been split for 32-bit codegen.");
@@ -7000,6 +7070,10 @@ static const TargetRegisterClass *getRegClassForSVT(MVT::SimpleValueType SVT,
case MVT::i32:
case MVT::i64:
return IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
+ case MVT::f16:
+ if (HasFloat16 && HasP8Vector)
+ return &PPC::VHFRCRegClass;
+ llvm_unreachable("f16 requires Power8 or later");
case MVT::f32:
return HasP8Vector ? &PPC::VSSRCRegClass : &PPC::F4RCRegClass;
case MVT::f64:
@@ -7144,8 +7218,9 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
continue;
if (SaveParams && VA.isRegLoc() && !Flags.isByVal() && !VA.needsCustom()) {
- const TargetRegisterClass *RegClass = getRegClassForSVT(
- LocVT.SimpleTy, IsPPC64, Subtarget.hasP8Vector(), Subtarget.hasVSX());
+ const TargetRegisterClass *RegClass =
+ getRegClassForSVT(LocVT.SimpleTy, IsPPC64, Subtarget.hasP8Vector(),
+ Subtarget.hasVSX(), Subtarget.hasFloat16());
// On PPC64, debugger assumes extended 8-byte values are stored from GPR.
MVT SaveVT = RegClass == &PPC::G8RCRegClass ? MVT::i64 : LocVT;
const Register VReg = MF.addLiveIn(VA.getLocReg(), RegClass);
@@ -7231,7 +7306,8 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
MVT::SimpleValueType SVT = VA.getLocVT().SimpleTy;
MF.addLiveIn(VA.getLocReg(),
getRegClassForSVT(SVT, IsPPC64, Subtarget.hasP8Vector(),
- Subtarget.hasVSX()));
+ Subtarget.hasVSX(),
+ Subtarget.hasFloat16()));
};
HandleMemLoc();
@@ -7260,6 +7336,9 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
switch (VA.getValVT().SimpleTy) {
default:
report_fatal_error("Unhandled value type for argument.");
+ case MVT::f16:
+ FuncInfo->appendParameterType(PPCFunctionInfo::ShortFloatingPoint);
+ break;
case MVT::f32:
FuncInfo->appendParameterType(PPCFunctionInfo::ShortFloatingPoint);
break;
@@ -7367,10 +7446,10 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
if (VA.isRegLoc() && !VA.needsCustom()) {
MVT::SimpleValueType SVT = ValVT.SimpleTy;
- Register VReg =
- MF.addLiveIn(VA.getLocReg(),
- getRegClassForSVT(SVT, IsPPC64, Subtarget.hasP8Vector(),
- Subtarget.hasVSX()));
+ Register VReg = MF.addLiveIn(
+ VA.getLocReg(),
+ getRegClassForSVT(SVT, IsPPC64, Subtarget.hasP8Vector(),
+ Subtarget.hasVSX(), Subtarget.hasFloat16()));
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, LocVT);
if (ValVT.isScalarInteger() &&
(ValVT.getFixedSizeInBits() < LocVT.getFixedSizeInBits())) {
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 1778da5aba2fd..841aad46cffbd 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -214,6 +214,11 @@ namespace llvm {
bool hasSPE() const;
+ // Override to tell the ABI framework that _Float16 passes through FPRs
+ // when -mfloat16 is active. Without this, the generic lowering would
+ // try to pass f16 values in integer registers.
+ bool useFPRegsForHalfType() const override;
+
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override {
return MVT::i32;
}
diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
index 1f6bccaf127b8..c23234f8b27ec 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
@@ -4063,6 +4063,88 @@ def : Pat<(i32 (fp_to_f16 f32:$A)),
(i32 (MFVSRWZ (XSCVDPHP (COPY_TO_REGCLASS $A, VSFRC))))>;
def : Pat<(i32 (fp_to_f16 f64:$A)), (i32 (MFVSRWZ (XSCVDPHP $A)))>;
+// P9 f16 patterns (HasFloat16, HasP9Vector)
+// P9 has dedicated halfword VSX memory ops and scalar conversion instructions.
+let Predicates = [HasFloat16, HasP9Vector] in {
+ // Load halfword into VSX half container (no conversion on load).
+ def : Pat<(f16 (load ForceXForm:$src)),
+ (COPY_TO_REGCLASS (LXSIHZX ForceXForm:$src), VHFRC)>;
+
+ // Store half container using STXSIHX (stores low 16 bits as halfword).
+ def : Pat<(store f16:$src, ForceXForm:$dst),
+ (STXSIHX (COPY_TO_REGCLASS $src, VHFRC), ForceXForm:$dst)>;
+
+ // FP_ROUND to f16 container.
+ def : Pat<(f16 (fpround f64:$src)),
+ (COPY_TO_REGCLASS (XSCVDPHP $src), VHFRC)>;
+
+ def : Pat<(f16 (fpround f32:$src)),
+ (COPY_TO_REGCLASS
+ (XSCVDPHP (COPY_TO_REGCLASS $src, VSFRC)), // treat as f64 container for the op
+ VHFRC)>;
+
+ // FP_EXTEND from f16 container -> f64.
+ def : Pat<(f64 (fpextend f16:$src)),
+ (XSCVHPDP (COPY_TO_REGCLASS $src, VHFRC))>;
+
+ // FP_EXTEND from f16 container -> f32.
+ def : Pat<(f32 (fpextend f16:$src)),
+ (COPY_TO_REGCLASS
+ (XSCVHPDP (COPY_TO_REGCLASS $src, VHFRC)),
+ VSSRC)>;
+
+ // fabs, fneg, fcopysign: intentionally handled via bit manipulation on ALL
+ // hardware including P9+. The round-trip through f64 via XSCVHPDP/XSCVDPHP
+ // does not preserve NaN payloads (signalling NaN -> quiet NaN, payload bits
+ // corrupted). These operations must be pure bit moves. See llvm/llvm-project#97981.
+}
+
+
+// P8 f16 patterns (HasFloat16, HasP8Vector)
+// P8 has no halfword VSX memory ops. Load/store goes through GPR roundtrip.
+// These patterns also fire on P9 (P9 satisfies HasP8Vector), providing
+// the fabs/fneg/fcopysign patterns for all hardware.
+let Predicates = [HasFloat16, HasP8Vector] in {
+ // Store f16: Move VSX half container -> GPR, then Store Halfword.
+ def : Pat<(store f16:$src, xoaddr:$dst),
+ (STHX (MFVSRWZ (COPY_TO_REGCLASS $src, VHFRC)), xoaddr:$dst)>;
+ def : Pat<(store f16:$src, iaddrX16:$dst),
+ (STH (MFVSRWZ (COPY_TO_REGCLASS $src, VHFRC)), iaddrX16:$dst)>;
+
+ // Load f16: Load Halfword -> GPR, then Move GPR -> VSX half container.
+ def : Pat<(f16 (load xoaddr:$src)),
+ (COPY_TO_REGCLASS (MTVSRWZ (LHZX xoaddr:$src)), VHFRC)>;
+ def : Pat<(f16 (load iaddrX16:$src)),
+ (COPY_TO_REGCLASS (MTVSRWZ (LHZ iaddrX16:$src)), VHFRC)>;
+
+ // fabs: clear sign bit (AND with 0x7FFF in the 16-bit lane).
+ def : Pat<(fabs f16:$src),
+ (COPY_TO_REGCLASS
+ (MTVSRWZ
+ (RLWINM (MFVSRWZ (COPY_TO_REGCLASS $src, VHFRC)),
+ 0, 17, 31)),
+ VHFRC)>;
+
+ // fneg: flip sign bit (XOR with 0x8000).
+ def : Pat<(fneg f16:$src),
+ (COPY_TO_REGCLASS
+ (MTVSRWZ
+ (XORI (MFVSRWZ (COPY_TO_REGCLASS $src, VHFRC)),
+ 32768)),
+ VHFRC)>;
+
+ // fcopysign: (mag & 0x7FFF) | (sign & 0x8000).
+ def : Pat<(fcopysign f16:$mag, f16:$sign),
+ (COPY_TO_REGCLASS
+ (MTVSRWZ
+ (OR
+ (RLWINM (MFVSRWZ (COPY_TO_REGCLASS $mag, VHFRC)),
+ 0, 17, 31),
+ (RLWINM (MFVSRWZ (COPY_TO_REGCLASS $sign, VHFRC)),
+ 0, 16, 16))),
+ VHFRC)>;
+}
+
// Vector sign extensions
def : Pat<(f64 (PPCVexts f64:$A, 1)),
(f64 (COPY_TO_REGCLASS (VEXTSB2Ds $A), VSFRC))>;
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 90c7be4297935..1b2e78a0b658a 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -408,6 +408,13 @@ def SPILLTOVSRRC : PPCRegisterClass<[i64, f64], 64,
// Register class for single precision scalars in VSX registers
def VSSRC : PPCRegisterClass<[f32], 32, (add VSFRC)>;
+// PowerPC has no f16 arithmetic instructions. F16 values must use VSX registers
+// to utilize the VSX conversion instructions. Suppress pressure set generation
+// to preserve VSSRC pressure index.
+let GeneratePressureSet = 0 in {
+ def VHFRC : PPCRegisterClass<[f16], 16, (add VSFRC)>;
+}
+
def CRBITRC : PPCRegisterClassWithSize<[i1], 32,
(add CR2LT, CR2GT, CR2EQ, CR2UN,
CR3LT, CR3GT, CR3EQ, CR3UN,
diff --git a/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll b/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
new file mode 100644
index 0000000000000..c5dc260586913
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
@@ -0,0 +1,96 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr9 \
+; RUN: -mattr=+float16,+vsx,+power9-vector < %s | FileCheck %s --check-prefix=P9-AIX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr9 \
+; RUN: -mattr=+float16,+vsx,+power9-vector < %s | FileCheck %s --check-prefix=P9-AIX-32
+
+; 14th f16 argument goes to stack.
+; The first 13 f16 args exhaust F1-F13. The 14th must come from the PSA.
+; PSA starts at SP+48 on PPC64 AIX. With 8-byte slots, the 14th arg is at
+; SP+48+(13*8)=SP+152. This confirms each preceding slot was 8 bytes wide.
+define half @test_14th_arg(
+; P9-AIX-64-LABEL: test_14th_arg:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: addi 3, 1, 152
+; P9-AIX-64-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_14th_arg:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: addi 3, 1, 76
+; P9-AIX-32-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-32-NEXT: blr
+ half %a0, half %a1, half %a2, half %a3,
+ half %a4, half %a5, half %a6, half %a7,
+ half %a8, half %a9, half %a10, half %a11,
+ half %a12, half %a13) {
+ ret half %a13
+}
+
+; Mixed f16 and i64 arguments.
+; Verifies GPR shadow is consumed for each f16 argument.
+; Expected register layout on PPC64 AIX:
+; %f0 (half) -> F1, GPR shadow consumes X3
+; %i0 (i64) -> X4
+; %f1 (half) -> F2, GPR shadow consumes X5
+; %i1 (i64) -> X6
+; If GPR shadow is missing, %i1 would land in X4 instead of X6.
+; The return value %i1 must come from X6 (mr 3, 6).
+define i64 @test_mixed_args(half %f0, i64 %i0, half %f1, i64 %i1) {
+; P9-AIX-64-LABEL: test_mixed_args:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mr 3, 6
+; P9-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_mixed_args:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mr 4, 8
+; P9-AIX-32-NEXT: mr 3, 7
+; P9-AIX-32-NEXT: blr
+ ret i64 %i1
+}
+
+; Vararg function receiving f16 arguments.
+; Verifies GPR shadow slots are saved to PSA for vararg access.
+; X4-X10 must be saved starting at SP+56 (immediately after %count slot).
+; The first vararg f16 value must be loaded via lxsihzx from SP+56.
+declare void @llvm.va_start(ptr)
+declare void @llvm.va_end(ptr)
+
+define half @test_vararg_f16(i32 %count, ...) {
+; P9-AIX-64-LABEL: test_vararg_f16:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: addi 3, 1, 58
+; P9-AIX-64-NEXT: std 4, 56(1)
+; P9-AIX-64-NEXT: std 5, 64(1)
+; P9-AIX-64-NEXT: std 6, 72(1)
+; P9-AIX-64-NEXT: std 7, 80(1)
+; P9-AIX-64-NEXT: std 8, 88(1)
+; P9-AIX-64-NEXT: std 9, 96(1)
+; P9-AIX-64-NEXT: std 10, 104(1)
+; P9-AIX-64-NEXT: std 3, -8(1)
+; P9-AIX-64-NEXT: addi 3, 1, 56
+; P9-AIX-64-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_vararg_f16:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: addi 3, 1, 30
+; P9-AIX-32-NEXT: stw 4, 28(1)
+; P9-AIX-32-NEXT: stw 5, 32(1)
+; P9-AIX-32-NEXT: stw 6, 36(1)
+; P9-AIX-32-NEXT: stw 7, 40(1)
+; P9-AIX-32-NEXT: stw 8, 44(1)
+; P9-AIX-32-NEXT: stw 9, 48(1)
+; P9-AIX-32-NEXT: stw 10, 52(1)
+; P9-AIX-32-NEXT: stw 3, -4(1)
+; P9-AIX-32-NEXT: addi 3, 1, 28
+; P9-AIX-32-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-32-NEXT: blr
+entry:
+ %va = alloca ptr
+ call void @llvm.va_start(ptr %va)
+ %val = va_arg ptr %va, half
+ call void @llvm.va_end(ptr %va)
+ ret half %val
+}
diff --git a/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
new file mode 100644
index 0000000000000..61ef84e5c9fd0
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
@@ -0,0 +1,4198 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr8 \
+; RUN: -mattr=+float16 < %s | FileCheck %s --check-prefix=P8-AIX-32
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr8 \
+; RUN: -mattr=+float16 < %s | FileCheck %s --check-prefix=P8-AIX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr9 \
+; RUN: -mattr=+float16,+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-AIX-32
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr9 \
+; RUN: -mattr=+float16,+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-AIX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu -mcpu=pwr8 \
+; RUN: -mattr=+float16 < %s | FileCheck %s --check-prefix=P8-LINUX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu -mcpu=pwr9 \
+; RUN: -mattr=+float16,+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-LINUX-64
+
+; ========================================================================================
+; Load/Store Operations
+; ISD::LOAD, ISD::STORE
+; ========================================================================================
+
+define half @load_half(ptr %p) nounwind {
+; P8-AIX-32-LABEL: load_half:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: lhzx 3, 0, 3
+; P8-AIX-32-NEXT: mtfprwz 1, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: load_half:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: lhzx 3, 0, 3
+; P8-AIX-64-NEXT: mtfprwz 1, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: load_half:
+; P9: # %bb.0: # %entry
+; P9-NEXT: lxsihzx 1, 0, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: load_half:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: lhzx 3, 0, 3
+; P8-LINUX-64-NEXT: mtfprwz 1, 3
+; P8-LINUX-64-NEXT: blr
+entry:
+ %v = load half, ptr %p
+ ret half %v
+}
+
+define void @store_half(ptr %p, half %v) nounwind {
+; P8-AIX-32-LABEL: store_half:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mffprwz 4, 1
+; P8-AIX-32-NEXT: sthx 4, 0, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: store_half:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mffprwz 4, 1
+; P8-AIX-64-NEXT: sthx 4, 0, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: store_half:
+; P9: # %bb.0: # %entry
+; P9-NEXT: stxsihx 1, 0, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: store_half:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mffprwz 4, 1
+; P8-LINUX-64-NEXT: sthx 4, 0, 3
+; P8-LINUX-64-NEXT: blr
+entry:
+ store half %v, ptr %p
+ ret void
+}
+
+; ========================================================================================
+; Basic Arithmetic Operations
+; ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FDIV
+; ========================================================================================
+
+define half @op_add(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_add:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsaddsp 1, 1, 30
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_add:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsaddsp 1, 1, 30
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_add:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xsaddsp 0, 1, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_add:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsaddsp 1, 1, 30
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %unpromotion = fadd half %a, %b
+ ret half %unpromotion
+}
+
+define half @op_sub(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_sub:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xssubsp 1, 1, 30
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_sub:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xssubsp 1, 1, 30
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_sub:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xssubsp 0, 1, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_sub:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xssubsp 1, 1, 30
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %unpromotion = fsub half %a, %b
+ ret half %unpromotion
+}
+
+define half @op_mul(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_mul:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsmulsp 1, 1, 30
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_mul:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsmulsp 1, 1, 30
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_mul:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xsmulsp 0, 1, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_mul:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsmulsp 1, 1, 30
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %unpromotion = fmul half %a, %b
+ ret half %unpromotion
+}
+
+define half @op_div(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_div:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsdivsp 1, 1, 30
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_div:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsdivsp 1, 1, 30
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_div:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xsdivsp 0, 1, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_div:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsdivsp 1, 1, 30
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %unpromotion = fdiv half %a, %b
+ ret half %unpromotion
+}
+
+; ========================================================================================
+; Advanced Arithmetic Operations
+; ISD::FMA (promoted to f64), ISD::FSQRT, ISD::FREM
+; ========================================================================================
+
+define half @test_fma(half %a, half %b, half %c) nounwind {
+; P8-AIX-32-LABEL: test_fma:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 29, 56(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 30, 2
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 3
+; P8-AIX-32-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 29, 1
+; P8-AIX-32-NEXT: fmr 1, 30
+; P8-AIX-32-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsmaddadp 1, 29, 30
+; P8-AIX-32-NEXT: bl .__truncdfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 29, 56(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_fma:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -144(1)
+; P8-AIX-64-NEXT: std 0, 160(1)
+; P8-AIX-64-NEXT: stfd 29, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: stfd 30, 128(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 30, 2
+; P8-AIX-64-NEXT: stfd 31, 136(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 3
+; P8-AIX-64-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 29, 1
+; P8-AIX-64-NEXT: fmr 1, 30
+; P8-AIX-64-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsmaddadp 1, 29, 30
+; P8-AIX-64-NEXT: bl .__truncdfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 136(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 128(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 29, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 144
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: test_fma:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xscvhpdp 2, 3
+; P9-NEXT: xsmaddadp 2, 1, 0
+; P9-NEXT: xscvdphp 1, 2
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_fma:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 29, -24(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -64(1)
+; P8-LINUX-64-NEXT: std 0, 80(1)
+; P8-LINUX-64-NEXT: fmr 31, 3
+; P8-LINUX-64-NEXT: fmr 30, 2
+; P8-LINUX-64-NEXT: bl __extendhfdf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 29, 1
+; P8-LINUX-64-NEXT: fmr 1, 30
+; P8-LINUX-64-NEXT: bl __extendhfdf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfdf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsmaddadp 1, 29, 30
+; P8-LINUX-64-NEXT: bl __truncdfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 64
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: lfd 29, -24(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: blr
+entry:
+ %r = call half @llvm.fma.f16(half %a, half %b, half %c)
+ ret half %r
+}
+
+define half @test_sqrt(half %a) {
+; P8-AIX-32-LABEL: test_sqrt:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xssqrtsp 1, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_sqrt:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xssqrtsp 1, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: test_sqrt:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 1
+; P9-NEXT: xssqrtsp 0, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_sqrt:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: .cfi_def_cfa_offset 32
+; P8-LINUX-64-NEXT: .cfi_offset lr, 16
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xssqrtsp 1, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %r = call half @llvm.sqrt.f16(half %a)
+ ret half %r
+}
+
+define half @test_frem(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: test_frem:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 2, 30
+; P8-AIX-32-NEXT: bl .fmodf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_frem:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 2, 30
+; P8-AIX-64-NEXT: bl .fmodf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_frem:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: xscvhpdp 2, 2
+; P9-AIX-32-NEXT: bl .fmodf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_frem:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: xscvhpdp 2, 2
+; P9-AIX-64-NEXT: bl .fmodf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_frem:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 2, 30
+; P8-LINUX-64-NEXT: bl fmodf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_frem:
+; P9-LINUX-64: # %bb.0: # %entry
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: xscvhpdp 2, 2
+; P9-LINUX-64-NEXT: bl fmodf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+entry:
+ %r = frem half %a, %b
+ ret half %r
+}
+
+; ========================================================================================
+; Comparison Operations
+; ISD::SETCC
+; ========================================================================================
+
+define zeroext i1 @op_eq(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_eq:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 30
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: li 3, 0
+; P8-AIX-32-NEXT: li 4, 1
+; P8-AIX-32-NEXT: iseleq 3, 4, 3
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_eq:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 30
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: li 3, 0
+; P8-AIX-64-NEXT: li 4, 1
+; P8-AIX-64-NEXT: iseleq 3, 4, 3
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_eq:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: li 3, 0
+; P9-NEXT: li 4, 1
+; P9-NEXT: fcmpu 0, 1, 0
+; P9-NEXT: iseleq 3, 4, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_eq:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 30
+; P8-LINUX-64-NEXT: li 3, 0
+; P8-LINUX-64-NEXT: li 4, 1
+; P8-LINUX-64-NEXT: iseleq 3, 4, 3
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %cmp = fcmp oeq half %a, %b
+ ret i1 %cmp
+}
+
+define zeroext i1 @op_ne(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_ne:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 30
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: li 3, 1
+; P8-AIX-32-NEXT: iseleq 3, 0, 3
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_ne:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 30
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: li 3, 1
+; P8-AIX-64-NEXT: iseleq 3, 0, 3
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_ne:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: li 3, 1
+; P9-NEXT: fcmpu 0, 1, 0
+; P9-NEXT: iseleq 3, 0, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_ne:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 30
+; P8-LINUX-64-NEXT: li 3, 1
+; P8-LINUX-64-NEXT: iseleq 3, 0, 3
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %cmp = fcmp une half %a, %b
+ ret i1 %cmp
+}
+
+define zeroext i1 @op_lt(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_lt:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 30
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: li 3, 0
+; P8-AIX-32-NEXT: li 4, 1
+; P8-AIX-32-NEXT: isellt 3, 4, 3
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_lt:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 30
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: li 3, 0
+; P8-AIX-64-NEXT: li 4, 1
+; P8-AIX-64-NEXT: isellt 3, 4, 3
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_lt:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: li 3, 0
+; P9-NEXT: li 4, 1
+; P9-NEXT: fcmpu 0, 1, 0
+; P9-NEXT: isellt 3, 4, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_lt:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 30
+; P8-LINUX-64-NEXT: li 3, 0
+; P8-LINUX-64-NEXT: li 4, 1
+; P8-LINUX-64-NEXT: isellt 3, 4, 3
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %cmp = fcmp olt half %a, %b
+ ret i1 %cmp
+}
+
+define zeroext i1 @op_le(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_le:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 30
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: li 3, 1
+; P8-AIX-32-NEXT: cror 20, 3, 1
+; P8-AIX-32-NEXT: isel 3, 0, 3, 20
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_le:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 30
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: li 3, 1
+; P8-AIX-64-NEXT: cror 20, 3, 1
+; P8-AIX-64-NEXT: isel 3, 0, 3, 20
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_le:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: li 3, 1
+; P9-NEXT: fcmpu 0, 1, 0
+; P9-NEXT: cror 20, 3, 1
+; P9-NEXT: isel 3, 0, 3, 20
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_le:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 30
+; P8-LINUX-64-NEXT: li 3, 1
+; P8-LINUX-64-NEXT: cror 20, 3, 1
+; P8-LINUX-64-NEXT: isel 3, 0, 3, 20
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %cmp = fcmp ole half %a, %b
+ ret i1 %cmp
+}
+
+define zeroext i1 @op_gt(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_gt:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 30
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: li 3, 0
+; P8-AIX-32-NEXT: li 4, 1
+; P8-AIX-32-NEXT: iselgt 3, 4, 3
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_gt:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 30
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: li 3, 0
+; P8-AIX-64-NEXT: li 4, 1
+; P8-AIX-64-NEXT: iselgt 3, 4, 3
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_gt:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: li 3, 0
+; P9-NEXT: li 4, 1
+; P9-NEXT: fcmpu 0, 1, 0
+; P9-NEXT: iselgt 3, 4, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_gt:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 30
+; P8-LINUX-64-NEXT: li 3, 0
+; P8-LINUX-64-NEXT: li 4, 1
+; P8-LINUX-64-NEXT: iselgt 3, 4, 3
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %cmp = fcmp ogt half %a, %b
+ ret i1 %cmp
+}
+
+define zeroext i1 @op_ge(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_ge:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 30
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: li 3, 1
+; P8-AIX-32-NEXT: cror 20, 3, 0
+; P8-AIX-32-NEXT: isel 3, 0, 3, 20
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_ge:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 30
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: li 3, 1
+; P8-AIX-64-NEXT: cror 20, 3, 0
+; P8-AIX-64-NEXT: isel 3, 0, 3, 20
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_ge:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: li 3, 1
+; P9-NEXT: fcmpu 0, 1, 0
+; P9-NEXT: cror 20, 3, 0
+; P9-NEXT: isel 3, 0, 3, 20
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_ge:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 30
+; P8-LINUX-64-NEXT: li 3, 1
+; P8-LINUX-64-NEXT: cror 20, 3, 0
+; P8-LINUX-64-NEXT: isel 3, 0, 3, 20
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %cmp = fcmp oge half %a, %b
+ ret i1 %cmp
+}
+
+; ========================================================================================
+; Control Flow Operations
+; ISD::SELECT, ISD::SELECT_CC
+; ========================================================================================
+
+define half @op_select(i1 %cond, half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_select:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mfcr 12
+; P8-AIX-32-NEXT: stw 12, 4(1)
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: andi. 3, 3, 1
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: crmove 8, 1
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 30
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bc 12, 8, L..BB15_2
+; P8-AIX-32-NEXT: # %bb.1: # %entry
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: L..BB15_2: # %entry
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: lwz 12, 4(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: mtocrf 32, 12
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_select:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mfcr 12
+; P8-AIX-64-NEXT: stw 12, 8(1)
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: andi. 3, 3, 1
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: crmove 8, 1
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 30
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bc 12, 8, L..BB15_2
+; P8-AIX-64-NEXT: # %bb.1: # %entry
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: L..BB15_2: # %entry
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: lwz 12, 8(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: mtocrf 32, 12
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: op_select:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: xscvhpdp 2, 2
+; P9-AIX-32-NEXT: xscvhpdp 0, 1
+; P9-AIX-32-NEXT: andi. 3, 3, 1
+; P9-AIX-32-NEXT: bc 12, 1, L..BB15_2
+; P9-AIX-32-NEXT: # %bb.1: # %entry
+; P9-AIX-32-NEXT: fmr 0, 2
+; P9-AIX-32-NEXT: L..BB15_2: # %entry
+; P9-AIX-32-NEXT: xscvdphp 1, 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: op_select:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: xscvhpdp 2, 2
+; P9-AIX-64-NEXT: xscvhpdp 0, 1
+; P9-AIX-64-NEXT: andi. 3, 3, 1
+; P9-AIX-64-NEXT: bc 12, 1, L..BB15_2
+; P9-AIX-64-NEXT: # %bb.1: # %entry
+; P9-AIX-64-NEXT: fmr 0, 2
+; P9-AIX-64-NEXT: L..BB15_2: # %entry
+; P9-AIX-64-NEXT: xscvdphp 1, 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_select:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mfocrf 12, 32
+; P8-LINUX-64-NEXT: stw 12, 8(1)
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: stfd 30, 32(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: andi. 3, 3, 1
+; P8-LINUX-64-NEXT: stfd 31, 40(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: crmove 8, 1
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 30
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bc 12, 8, .LBB15_2
+; P8-LINUX-64-NEXT: # %bb.1: # %entry
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: .LBB15_2: # %entry
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: lfd 31, 40(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, 32(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lwz 12, 8(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: mtocrf 32, 12
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: op_select:
+; P9-LINUX-64: # %bb.0: # %entry
+; P9-LINUX-64-NEXT: xscvhpdp 2, 2
+; P9-LINUX-64-NEXT: xscvhpdp 0, 1
+; P9-LINUX-64-NEXT: andi. 3, 3, 1
+; P9-LINUX-64-NEXT: bc 12, 1, .LBB15_2
+; P9-LINUX-64-NEXT: # %bb.1: # %entry
+; P9-LINUX-64-NEXT: fmr 0, 2
+; P9-LINUX-64-NEXT: .LBB15_2: # %entry
+; P9-LINUX-64-NEXT: xscvdphp 1, 0
+; P9-LINUX-64-NEXT: blr
+entry:
+ %r = select i1 %cond, half %a, half %b
+ ret half %r
+}
+
+define half @op_select_cc(half %a, half %b, half %c, half %d) nounwind {
+; P8-AIX-32-LABEL: op_select_cc:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mfcr 12
+; P8-AIX-32-NEXT: stw 12, 4(1)
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -96(1)
+; P8-AIX-32-NEXT: stw 0, 104(1)
+; P8-AIX-32-NEXT: stfd 29, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 29, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 28, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: stfd 30, 80(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 30, 3
+; P8-AIX-32-NEXT: stfd 31, 88(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 4
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 28, 1
+; P8-AIX-32-NEXT: fmr 1, 29
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 2, 1, 28
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 30
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bc 12, 8, L..BB16_2
+; P8-AIX-32-NEXT: # %bb.1:
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: L..BB16_2:
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 88(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 80(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 29, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 28, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 96
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: lwz 12, 4(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: mtocrf 32, 12
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_select_cc:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mfcr 12
+; P8-AIX-64-NEXT: stw 12, 8(1)
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -144(1)
+; P8-AIX-64-NEXT: std 0, 160(1)
+; P8-AIX-64-NEXT: stfd 29, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 29, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 28, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: stfd 30, 128(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 30, 3
+; P8-AIX-64-NEXT: stfd 31, 136(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 4
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 28, 1
+; P8-AIX-64-NEXT: fmr 1, 29
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 2, 1, 28
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 30
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bc 12, 8, L..BB16_2
+; P8-AIX-64-NEXT: # %bb.1:
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: L..BB16_2:
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 136(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 128(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 29, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 28, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 144
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: lwz 12, 8(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: mtocrf 32, 12
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: op_select_cc:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: xscvhpdp 0, 2
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: fcmpu 0, 1, 0
+; P9-AIX-32-NEXT: xscvhpdp 1, 4
+; P9-AIX-32-NEXT: xscvhpdp 0, 3
+; P9-AIX-32-NEXT: bc 12, 0, L..BB16_2
+; P9-AIX-32-NEXT: # %bb.1:
+; P9-AIX-32-NEXT: fmr 0, 1
+; P9-AIX-32-NEXT: L..BB16_2:
+; P9-AIX-32-NEXT: xscvdphp 1, 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: op_select_cc:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: xscvhpdp 0, 2
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: fcmpu 0, 1, 0
+; P9-AIX-64-NEXT: xscvhpdp 1, 4
+; P9-AIX-64-NEXT: xscvhpdp 0, 3
+; P9-AIX-64-NEXT: bc 12, 0, L..BB16_2
+; P9-AIX-64-NEXT: # %bb.1:
+; P9-AIX-64-NEXT: fmr 0, 1
+; P9-AIX-64-NEXT: L..BB16_2:
+; P9-AIX-64-NEXT: xscvdphp 1, 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_select_cc:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mfocrf 12, 32
+; P8-LINUX-64-NEXT: stw 12, 8(1)
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -64(1)
+; P8-LINUX-64-NEXT: std 0, 80(1)
+; P8-LINUX-64-NEXT: stfd 29, 40(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: fmr 29, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: stfd 28, 32(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 30, 48(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: fmr 30, 3
+; P8-LINUX-64-NEXT: stfd 31, 56(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: fmr 31, 4
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 28, 1
+; P8-LINUX-64-NEXT: fmr 1, 29
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 2, 1, 28
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 30
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bc 12, 8, .LBB16_2
+; P8-LINUX-64-NEXT: # %bb.1:
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: .LBB16_2:
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: lfd 31, 56(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, 48(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 29, 40(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 28, 32(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: addi 1, 1, 64
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lwz 12, 8(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: mtocrf 32, 12
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: op_select_cc:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: xscvhpdp 0, 2
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: fcmpu 0, 1, 0
+; P9-LINUX-64-NEXT: xscvhpdp 1, 4
+; P9-LINUX-64-NEXT: xscvhpdp 0, 3
+; P9-LINUX-64-NEXT: bc 12, 0, .LBB16_2
+; P9-LINUX-64-NEXT: # %bb.1:
+; P9-LINUX-64-NEXT: fmr 0, 1
+; P9-LINUX-64-NEXT: .LBB16_2:
+; P9-LINUX-64-NEXT: xscvdphp 1, 0
+; P9-LINUX-64-NEXT: blr
+ %cmp = fcmp olt half %a, %b
+ %r = select i1 %cmp, half %c, half %d
+ ret half %r
+}
+
+; ========================================================================================
+; Min/Max Operations
+; ISD::FMINNUM/FMAXNUM (non-NaN), ISD::FMINIMUM/FMAXIMUM (IEEE 754-2019, NaN-propagating)
+; ========================================================================================
+
+define half @op_fmin(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_fmin:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsmindp 1, 1, 30
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_fmin:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsmindp 1, 1, 30
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_fmin:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xsmindp 0, 1, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_fmin:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsmindp 1, 1, 30
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.minnum.f16(half %a, half %b)
+ ret half %0
+}
+
+define half @op_fmax(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: op_fmax:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsmaxdp 1, 1, 30
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_fmax:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsmaxdp 1, 1, 30
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_fmax:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xsmaxdp 0, 1, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_fmax:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsmaxdp 1, 1, 30
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.maxnum.f16(half %a, half %b)
+ ret half %0
+}
+
+define half @test_minimum(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: test_minimum:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 30
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 31
+; P8-AIX-32-NEXT: bc 12, 3, L..BB19_2
+; P8-AIX-32-NEXT: # %bb.1: # %entry
+; P8-AIX-32-NEXT: xsmindp 1, 1, 31
+; P8-AIX-32-NEXT: b L..BB19_3
+; P8-AIX-32-NEXT: L..BB19_2:
+; P8-AIX-32-NEXT: lwz 3, L..C0(2) # %const.0
+; P8-AIX-32-NEXT: lfs 1, 0(3)
+; P8-AIX-32-NEXT: L..BB19_3: # %entry
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_minimum:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 30
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 31
+; P8-AIX-64-NEXT: bc 12, 3, L..BB19_2
+; P8-AIX-64-NEXT: # %bb.1: # %entry
+; P8-AIX-64-NEXT: xsmindp 1, 1, 31
+; P8-AIX-64-NEXT: b L..BB19_3
+; P8-AIX-64-NEXT: L..BB19_2:
+; P8-AIX-64-NEXT: ld 3, L..C0(2) # %const.0
+; P8-AIX-64-NEXT: lfs 1, 0(3)
+; P8-AIX-64-NEXT: L..BB19_3: # %entry
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_minimum:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: xscvhpdp 0, 2
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: fcmpu 0, 1, 0
+; P9-AIX-32-NEXT: bc 12, 3, L..BB19_2
+; P9-AIX-32-NEXT: # %bb.1: # %entry
+; P9-AIX-32-NEXT: xsmindp 0, 1, 0
+; P9-AIX-32-NEXT: xscvdphp 1, 0
+; P9-AIX-32-NEXT: blr
+; P9-AIX-32-NEXT: L..BB19_2:
+; P9-AIX-32-NEXT: lwz 3, L..C0(2) # %const.0
+; P9-AIX-32-NEXT: lfs 0, 0(3)
+; P9-AIX-32-NEXT: xscvdphp 1, 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_minimum:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: xscvhpdp 0, 2
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: fcmpu 0, 1, 0
+; P9-AIX-64-NEXT: bc 12, 3, L..BB19_2
+; P9-AIX-64-NEXT: # %bb.1: # %entry
+; P9-AIX-64-NEXT: xsmindp 0, 1, 0
+; P9-AIX-64-NEXT: xscvdphp 1, 0
+; P9-AIX-64-NEXT: blr
+; P9-AIX-64-NEXT: L..BB19_2:
+; P9-AIX-64-NEXT: ld 3, L..C0(2) # %const.0
+; P9-AIX-64-NEXT: lfs 0, 0(3)
+; P9-AIX-64-NEXT: xscvdphp 1, 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_minimum:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 30
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 31
+; P8-LINUX-64-NEXT: bc 12, 3, .LBB19_2
+; P8-LINUX-64-NEXT: # %bb.1: # %entry
+; P8-LINUX-64-NEXT: xsmindp 1, 1, 31
+; P8-LINUX-64-NEXT: b .LBB19_3
+; P8-LINUX-64-NEXT: .LBB19_2:
+; P8-LINUX-64-NEXT: addis 3, 2, .LCPI19_0 at toc@ha
+; P8-LINUX-64-NEXT: lfs 1, .LCPI19_0 at toc@l(3)
+; P8-LINUX-64-NEXT: .LBB19_3: # %entry
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_minimum:
+; P9-LINUX-64: # %bb.0: # %entry
+; P9-LINUX-64-NEXT: xscvhpdp 0, 2
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: fcmpu 0, 1, 0
+; P9-LINUX-64-NEXT: bc 12, 3, .LBB19_2
+; P9-LINUX-64-NEXT: # %bb.1: # %entry
+; P9-LINUX-64-NEXT: xsmindp 0, 1, 0
+; P9-LINUX-64-NEXT: xscvdphp 1, 0
+; P9-LINUX-64-NEXT: blr
+; P9-LINUX-64-NEXT: .LBB19_2:
+; P9-LINUX-64-NEXT: addis 3, 2, .LCPI19_0 at toc@ha
+; P9-LINUX-64-NEXT: lfs 0, .LCPI19_0 at toc@l(3)
+; P9-LINUX-64-NEXT: xscvdphp 1, 0
+; P9-LINUX-64-NEXT: blr
+entry:
+ %r = call half @llvm.minimum.f16(half %a, half %b)
+ ret half %r
+}
+
+define half @test_maximum(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: test_maximum:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 30
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fcmpu 0, 1, 31
+; P8-AIX-32-NEXT: bc 12, 3, L..BB20_2
+; P8-AIX-32-NEXT: # %bb.1: # %entry
+; P8-AIX-32-NEXT: xsmaxdp 1, 1, 31
+; P8-AIX-32-NEXT: b L..BB20_3
+; P8-AIX-32-NEXT: L..BB20_2:
+; P8-AIX-32-NEXT: lwz 3, L..C1(2) # %const.0
+; P8-AIX-32-NEXT: lfs 1, 0(3)
+; P8-AIX-32-NEXT: L..BB20_3: # %entry
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_maximum:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 30
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fcmpu 0, 1, 31
+; P8-AIX-64-NEXT: bc 12, 3, L..BB20_2
+; P8-AIX-64-NEXT: # %bb.1: # %entry
+; P8-AIX-64-NEXT: xsmaxdp 1, 1, 31
+; P8-AIX-64-NEXT: b L..BB20_3
+; P8-AIX-64-NEXT: L..BB20_2:
+; P8-AIX-64-NEXT: ld 3, L..C1(2) # %const.0
+; P8-AIX-64-NEXT: lfs 1, 0(3)
+; P8-AIX-64-NEXT: L..BB20_3: # %entry
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_maximum:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: xscvhpdp 0, 2
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: fcmpu 0, 1, 0
+; P9-AIX-32-NEXT: bc 12, 3, L..BB20_2
+; P9-AIX-32-NEXT: # %bb.1: # %entry
+; P9-AIX-32-NEXT: xsmaxdp 0, 1, 0
+; P9-AIX-32-NEXT: xscvdphp 1, 0
+; P9-AIX-32-NEXT: blr
+; P9-AIX-32-NEXT: L..BB20_2:
+; P9-AIX-32-NEXT: lwz 3, L..C1(2) # %const.0
+; P9-AIX-32-NEXT: lfs 0, 0(3)
+; P9-AIX-32-NEXT: xscvdphp 1, 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_maximum:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: xscvhpdp 0, 2
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: fcmpu 0, 1, 0
+; P9-AIX-64-NEXT: bc 12, 3, L..BB20_2
+; P9-AIX-64-NEXT: # %bb.1: # %entry
+; P9-AIX-64-NEXT: xsmaxdp 0, 1, 0
+; P9-AIX-64-NEXT: xscvdphp 1, 0
+; P9-AIX-64-NEXT: blr
+; P9-AIX-64-NEXT: L..BB20_2:
+; P9-AIX-64-NEXT: ld 3, L..C1(2) # %const.0
+; P9-AIX-64-NEXT: lfs 0, 0(3)
+; P9-AIX-64-NEXT: xscvdphp 1, 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_maximum:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 30
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fcmpu 0, 1, 31
+; P8-LINUX-64-NEXT: bc 12, 3, .LBB20_2
+; P8-LINUX-64-NEXT: # %bb.1: # %entry
+; P8-LINUX-64-NEXT: xsmaxdp 1, 1, 31
+; P8-LINUX-64-NEXT: b .LBB20_3
+; P8-LINUX-64-NEXT: .LBB20_2:
+; P8-LINUX-64-NEXT: addis 3, 2, .LCPI20_0 at toc@ha
+; P8-LINUX-64-NEXT: lfs 1, .LCPI20_0 at toc@l(3)
+; P8-LINUX-64-NEXT: .LBB20_3: # %entry
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_maximum:
+; P9-LINUX-64: # %bb.0: # %entry
+; P9-LINUX-64-NEXT: xscvhpdp 0, 2
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: fcmpu 0, 1, 0
+; P9-LINUX-64-NEXT: bc 12, 3, .LBB20_2
+; P9-LINUX-64-NEXT: # %bb.1: # %entry
+; P9-LINUX-64-NEXT: xsmaxdp 0, 1, 0
+; P9-LINUX-64-NEXT: xscvdphp 1, 0
+; P9-LINUX-64-NEXT: blr
+; P9-LINUX-64-NEXT: .LBB20_2:
+; P9-LINUX-64-NEXT: addis 3, 2, .LCPI20_0 at toc@ha
+; P9-LINUX-64-NEXT: lfs 0, .LCPI20_0 at toc@l(3)
+; P9-LINUX-64-NEXT: xscvdphp 1, 0
+; P9-LINUX-64-NEXT: blr
+entry:
+ %r = call half @llvm.maximum.f16(half %a, half %b)
+ ret half %r
+}
+
+; ========================================================================================
+; Rounding Operations
+; ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FROUND, ISD::FRINT, ISD::FNEARBYINT, ISD::FROUNDEVEN
+; ========================================================================================
+
+define half @op_ceil(half %a) nounwind {
+; P8-AIX-32-LABEL: op_ceil:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsrdpip 1, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_ceil:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsrdpip 1, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_ceil:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 1
+; P9-NEXT: xsrdpip 0, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_ceil:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsrdpip 1, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.ceil.f16(half %a)
+ ret half %0
+}
+
+define half @op_floor(half %a) nounwind {
+; P8-AIX-32-LABEL: op_floor:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsrdpim 1, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_floor:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsrdpim 1, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_floor:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 1
+; P9-NEXT: xsrdpim 0, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_floor:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsrdpim 1, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.floor.f16(half %a)
+ ret half %0
+}
+
+define half @op_trunc(half %a) nounwind {
+; P8-AIX-32-LABEL: op_trunc:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsrdpiz 1, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_trunc:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsrdpiz 1, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_trunc:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 1
+; P9-NEXT: xsrdpiz 0, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_trunc:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsrdpiz 1, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.trunc.f16(half %a)
+ ret half %0
+}
+
+define half @op_round(half %a) nounwind {
+; P8-AIX-32-LABEL: op_round:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsrdpi 1, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_round:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsrdpi 1, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_round:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 1
+; P9-NEXT: xsrdpi 0, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_round:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsrdpi 1, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.round.f16(half %a)
+ ret half %0
+}
+
+define half @op_rint(half %a) nounwind {
+; P8-AIX-32-LABEL: op_rint:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsrdpic 1, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_rint:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsrdpic 1, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_rint:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 1
+; P9-NEXT: xsrdpic 0, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_rint:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsrdpic 1, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.rint.f16(half %a)
+ ret half %0
+}
+
+define half @op_nearbyint(half %a) nounwind {
+; P8-AIX-32-LABEL: op_nearbyint:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .nearbyintf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_nearbyint:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .nearbyintf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: op_nearbyint:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .nearbyintf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: op_nearbyint:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .nearbyintf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_nearbyint:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl nearbyintf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: op_nearbyint:
+; P9-LINUX-64: # %bb.0: # %entry
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl nearbyintf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+entry:
+ %0 = tail call half @llvm.nearbyint.f16(half %a)
+ ret half %0
+}
+
+define half @test_roundeven(half %a) nounwind {
+; P8-AIX-32-LABEL: test_roundeven:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .roundevenf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_roundeven:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .roundevenf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_roundeven:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .roundevenf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_roundeven:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .roundevenf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_roundeven:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl roundevenf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_roundeven:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl roundevenf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.roundeven.f16(half %a)
+ ret half %r
+}
+
+; ========================================================================================
+; Bit Manipulation Operations
+; ISD::FABS, ISD::FNEG, ISD::FCOPYSIGN
+; ========================================================================================
+
+define half @test_fabs(half %a) nounwind {
+; P8-AIX-32-LABEL: test_fabs:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mffprwz 3, 1
+; P8-AIX-32-NEXT: clrlwi 3, 3, 17
+; P8-AIX-32-NEXT: mtfprwz 1, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_fabs:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mffprwz 3, 1
+; P8-AIX-64-NEXT: clrlwi 3, 3, 17
+; P8-AIX-64-NEXT: mtfprwz 1, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: test_fabs:
+; P9: # %bb.0: # %entry
+; P9-NEXT: mffprwz 3, 1
+; P9-NEXT: clrlwi 3, 3, 17
+; P9-NEXT: mtfprwz 1, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_fabs:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mffprwz 3, 1
+; P8-LINUX-64-NEXT: clrlwi 3, 3, 17
+; P8-LINUX-64-NEXT: mtfprwz 1, 3
+; P8-LINUX-64-NEXT: blr
+entry:
+ %r = call half @llvm.fabs.f16(half %a)
+ ret half %r
+}
+
+define half @test_fneg(half %a) nounwind {
+; P8-AIX-32-LABEL: test_fneg:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mffprwz 3, 1
+; P8-AIX-32-NEXT: xori 3, 3, 32768
+; P8-AIX-32-NEXT: mtfprwz 1, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_fneg:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mffprwz 3, 1
+; P8-AIX-64-NEXT: xori 3, 3, 32768
+; P8-AIX-64-NEXT: mtfprwz 1, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: test_fneg:
+; P9: # %bb.0: # %entry
+; P9-NEXT: mffprwz 3, 1
+; P9-NEXT: xori 3, 3, 32768
+; P9-NEXT: mtfprwz 1, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_fneg:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mffprwz 3, 1
+; P8-LINUX-64-NEXT: xori 3, 3, 32768
+; P8-LINUX-64-NEXT: mtfprwz 1, 3
+; P8-LINUX-64-NEXT: blr
+entry:
+ %r = fneg half %a
+ ret half %r
+}
+
+define half @test_fcopysign(half %mag, half %sign) nounwind {
+; P8-AIX-32-LABEL: test_fcopysign:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mffprwz 3, 2
+; P8-AIX-32-NEXT: mffprwz 4, 1
+; P8-AIX-32-NEXT: rlwinm 3, 3, 0, 16, 16
+; P8-AIX-32-NEXT: clrlwi 4, 4, 17
+; P8-AIX-32-NEXT: or 3, 4, 3
+; P8-AIX-32-NEXT: mtfprwz 1, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_fcopysign:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mffprwz 3, 2
+; P8-AIX-64-NEXT: mffprwz 4, 1
+; P8-AIX-64-NEXT: rlwinm 3, 3, 0, 16, 16
+; P8-AIX-64-NEXT: clrlwi 4, 4, 17
+; P8-AIX-64-NEXT: or 3, 4, 3
+; P8-AIX-64-NEXT: mtfprwz 1, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: test_fcopysign:
+; P9: # %bb.0: # %entry
+; P9-NEXT: mffprwz 3, 2
+; P9-NEXT: mffprwz 4, 1
+; P9-NEXT: rlwinm 3, 3, 0, 16, 16
+; P9-NEXT: clrlwi 4, 4, 17
+; P9-NEXT: or 3, 4, 3
+; P9-NEXT: mtfprwz 1, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_fcopysign:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mffprwz 3, 2
+; P8-LINUX-64-NEXT: mffprwz 4, 1
+; P8-LINUX-64-NEXT: rlwinm 3, 3, 0, 16, 16
+; P8-LINUX-64-NEXT: clrlwi 4, 4, 17
+; P8-LINUX-64-NEXT: or 3, 4, 3
+; P8-LINUX-64-NEXT: mtfprwz 1, 3
+; P8-LINUX-64-NEXT: blr
+entry:
+ %r = call half @llvm.copysign.f16(half %mag, half %sign)
+ ret half %r
+}
+
+; ========================================================================================
+; Special Operations
+; ISD::FCANONICALIZE - Canonicalize NaN representation
+; ========================================================================================
+
+define half @test_canonicalize(half %a) nounwind {
+; P8-AIX-32-LABEL: test_canonicalize:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsmaxdp 1, 1, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_canonicalize:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsmaxdp 1, 1, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: test_canonicalize:
+; P9: # %bb.0:
+; P9-NEXT: xscvhpdp 0, 1
+; P9-NEXT: xsmaxdp 0, 0, 0
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_canonicalize:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsmaxdp 1, 1, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+ %r = call half @llvm.canonicalize.f16(half %a)
+ ret half %r
+}
+
+; ========================================================================================
+; Transcendental Functions - Power
+; ISD::FPOW , calls libm powf()
+; ========================================================================================
+
+define half @test_pow(half %a, half %b) nounwind {
+; P8-AIX-32-LABEL: test_pow:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 2, 30
+; P8-AIX-32-NEXT: bl .powf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_pow:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -128(1)
+; P8-AIX-64-NEXT: std 0, 144(1)
+; P8-AIX-64-NEXT: stfd 31, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 30, 112(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 2, 30
+; P8-AIX-64-NEXT: bl .powf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 112(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 128
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_pow:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: xscvhpdp 2, 2
+; P9-AIX-32-NEXT: bl .powf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_pow:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: xscvhpdp 2, 2
+; P9-AIX-64-NEXT: bl .powf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_pow:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -48(1)
+; P8-LINUX-64-NEXT: fmr 31, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 64(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 2, 30
+; P8-LINUX-64-NEXT: bl powf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 48
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_pow:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: xscvhpdp 2, 2
+; P9-LINUX-64-NEXT: bl powf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.pow.f16(half %a, half %b)
+ ret half %r
+}
+
+; ========================================================================================
+; Transcendental Functions - Logarithms
+; ISD::FLOG, ISD::FLOG2, ISD::FLOG10 , calls libm
+; ========================================================================================
+
+define half @test_log(half %a) nounwind {
+; P8-AIX-32-LABEL: test_log:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .logf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_log:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .logf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_log:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .logf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_log:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .logf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_log:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl logf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_log:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl logf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.log.f16(half %a)
+ ret half %r
+}
+
+define half @test_log2(half %a) nounwind {
+; P8-AIX-32-LABEL: test_log2:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .log2f[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_log2:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .log2f[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_log2:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .log2f[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_log2:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .log2f[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_log2:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl log2f
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_log2:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl log2f
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.log2.f16(half %a)
+ ret half %r
+}
+
+define half @test_log10(half %a) nounwind {
+; P8-AIX-32-LABEL: test_log10:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .log10f[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_log10:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .log10f[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_log10:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .log10f[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_log10:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .log10f[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_log10:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl log10f
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_log10:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl log10f
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.log10.f16(half %a)
+ ret half %r
+}
+
+; ========================================================================================
+; Transcendental Functions - Exponentials
+; ISD::FEXP, ISD::FEXP2, ISD::FEXP10 , calls libm
+; ========================================================================================
+
+define half @test_exp(half %a) nounwind {
+; P8-AIX-32-LABEL: test_exp:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .expf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_exp:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .expf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_exp:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .expf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_exp:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .expf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_exp:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl expf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_exp:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl expf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.exp.f16(half %a)
+ ret half %r
+}
+
+define half @test_exp2(half %a) nounwind {
+; P8-AIX-32-LABEL: test_exp2:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .exp2f[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_exp2:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .exp2f[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_exp2:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .exp2f[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_exp2:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .exp2f[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_exp2:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl exp2f
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_exp2:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl exp2f
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.exp2.f16(half %a)
+ ret half %r
+}
+
+define half @test_exp10(half %a) nounwind {
+; P8-AIX-32-LABEL: test_exp10:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .exp10f[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_exp10:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .exp10f[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_exp10:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .exp10f[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_exp10:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .exp10f[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_exp10:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl exp10f
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_exp10:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl exp10f
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.exp10.f16(half %a)
+ ret half %r
+}
+
+; ========================================================================================
+; Transcendental Functions - Trigonometric
+; ISD::FSIN, ISD::FCOS , calls libm
+; ========================================================================================
+
+define half @test_sin(half %a) nounwind {
+; P8-AIX-32-LABEL: test_sin:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .sinf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_sin:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .sinf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_sin:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .sinf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_sin:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .sinf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_sin:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl sinf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_sin:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl sinf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.sin.f16(half %a)
+ ret half %r
+}
+
+define half @test_cos(half %a) nounwind {
+; P8-AIX-32-LABEL: test_cos:
+; P8-AIX-32: # %bb.0:
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .cosf[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_cos:
+; P8-AIX-64: # %bb.0:
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .cosf[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_cos:
+; P9-AIX-32: # %bb.0:
+; P9-AIX-32-NEXT: mflr 0
+; P9-AIX-32-NEXT: stwu 1, -64(1)
+; P9-AIX-32-NEXT: stw 0, 72(1)
+; P9-AIX-32-NEXT: xscvhpdp 1, 1
+; P9-AIX-32-NEXT: bl .cosf[PR]
+; P9-AIX-32-NEXT: nop
+; P9-AIX-32-NEXT: xscvdphp 1, 1
+; P9-AIX-32-NEXT: addi 1, 1, 64
+; P9-AIX-32-NEXT: lwz 0, 8(1)
+; P9-AIX-32-NEXT: mtlr 0
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_cos:
+; P9-AIX-64: # %bb.0:
+; P9-AIX-64-NEXT: mflr 0
+; P9-AIX-64-NEXT: stdu 1, -112(1)
+; P9-AIX-64-NEXT: std 0, 128(1)
+; P9-AIX-64-NEXT: xscvhpdp 1, 1
+; P9-AIX-64-NEXT: bl .cosf[PR]
+; P9-AIX-64-NEXT: nop
+; P9-AIX-64-NEXT: xscvdphp 1, 1
+; P9-AIX-64-NEXT: addi 1, 1, 112
+; P9-AIX-64-NEXT: ld 0, 16(1)
+; P9-AIX-64-NEXT: mtlr 0
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_cos:
+; P8-LINUX-64: # %bb.0:
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl cosf
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_cos:
+; P9-LINUX-64: # %bb.0:
+; P9-LINUX-64-NEXT: mflr 0
+; P9-LINUX-64-NEXT: stdu 1, -32(1)
+; P9-LINUX-64-NEXT: std 0, 48(1)
+; P9-LINUX-64-NEXT: xscvhpdp 1, 1
+; P9-LINUX-64-NEXT: bl cosf
+; P9-LINUX-64-NEXT: nop
+; P9-LINUX-64-NEXT: xscvdphp 1, 1
+; P9-LINUX-64-NEXT: addi 1, 1, 32
+; P9-LINUX-64-NEXT: ld 0, 16(1)
+; P9-LINUX-64-NEXT: mtlr 0
+; P9-LINUX-64-NEXT: blr
+ %r = call half @llvm.cos.f16(half %a)
+ ret half %r
+}
+
+; ========================================================================================
+; Type Conversion Operations
+; ISD::FP_EXTEND (f16->f32/f64), ISD::FP_ROUND (f32/f64->f16)
+; P9+: Hardware (xscvhpdp/xscvdphp), P8: Library calls
+; ========================================================================================
+
+define float @op_f16_to_f32(half %h) nounwind {
+; P8-AIX-32-LABEL: op_f16_to_f32:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_f16_to_f32:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_f16_to_f32:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_f16_to_f32:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %conv = fpext half %h to float
+ ret float %conv
+}
+
+define double @op_f16_to_f64(half %h) nounwind {
+; P8-AIX-32-LABEL: op_f16_to_f64:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_f16_to_f64:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__extendhfdf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_f16_to_f64:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_f16_to_f64:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __extendhfdf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %conv = fpext half %h to double
+ ret double %conv
+}
+
+define half @op_f32_to_f16(float %f) nounwind {
+; P8-AIX-32-LABEL: op_f32_to_f16:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_f32_to_f16:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_f32_to_f16:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvdphp 1, 1
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_f32_to_f16:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %conv = fptrunc float %f to half
+ ret half %conv
+}
+
+define half @op_f64_to_f16(double %d) nounwind {
+; P8-AIX-32-LABEL: op_f64_to_f16:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -64(1)
+; P8-AIX-32-NEXT: stw 0, 72(1)
+; P8-AIX-32-NEXT: bl .__truncdfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: addi 1, 1, 64
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: op_f64_to_f16:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -112(1)
+; P8-AIX-64-NEXT: std 0, 128(1)
+; P8-AIX-64-NEXT: bl .__truncdfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: addi 1, 1, 112
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: op_f64_to_f16:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvdphp 1, 1
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: op_f64_to_f16:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stdu 1, -32(1)
+; P8-LINUX-64-NEXT: std 0, 48(1)
+; P8-LINUX-64-NEXT: bl __truncdfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 32
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: blr
+entry:
+ %conv = fptrunc double %d to half
+ ret half %conv
+}
+
+; ========================================================================================
+; Bitcast Operations
+; Bitcast between f16 and i16 (no conversion, reinterpret bits)
+; Test that bitcast between i16 and half is lossless when -mfloat16 is active.
+; This verifies the fix for the miscompilation described in llvm/llvm-project#97981,
+; where passing/returning half used lossy float conversion functions (__gnu_h2f_ieee,
+; __gnu_f2h_ieee) that silenced signalling NaNs and corrupted NaN payloads.
+; ========================================================================================
+
+define half @to_half(i16 %bits) nounwind {
+; P8-AIX-32-LABEL: to_half:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: sth 3, -2(1)
+; P8-AIX-32-NEXT: lhz 3, -2(1)
+; P8-AIX-32-NEXT: mtfprwz 1, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: to_half:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: sth 3, -2(1)
+; P8-AIX-64-NEXT: lhz 3, -2(1)
+; P8-AIX-64-NEXT: mtfprwz 1, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: to_half:
+; P9: # %bb.0: # %entry
+; P9-NEXT: sth 3, -2(1)
+; P9-NEXT: addi 3, 1, -2
+; P9-NEXT: lxsihzx 1, 0, 3
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: to_half:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: sth 3, -2(1)
+; P8-LINUX-64-NEXT: lhz 3, -2(1)
+; P8-LINUX-64-NEXT: mtfprwz 1, 3
+; P8-LINUX-64-NEXT: blr
+entry:
+ %f = bitcast i16 %bits to half
+ ret half %f
+}
+
+define i16 @from_half(half %f) nounwind {
+; P8-AIX-32-LABEL: from_half:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mffprwz 3, 1
+; P8-AIX-32-NEXT: sth 3, -2(1)
+; P8-AIX-32-NEXT: lhz 3, -2(1)
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: from_half:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mffprwz 3, 1
+; P8-AIX-64-NEXT: sth 3, -2(1)
+; P8-AIX-64-NEXT: lhz 3, -2(1)
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: from_half:
+; P9: # %bb.0: # %entry
+; P9-NEXT: addi 3, 1, -2
+; P9-NEXT: stxsihx 1, 0, 3
+; P9-NEXT: lhz 3, -2(1)
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: from_half:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mffprwz 3, 1
+; P8-LINUX-64-NEXT: sth 3, -2(1)
+; P8-LINUX-64-NEXT: lhz 3, -2(1)
+; P8-LINUX-64-NEXT: blr
+entry:
+ %bits = bitcast half %f to i16
+ ret i16 %bits
+}
+
+; ========================================================================================
+; Edge Cases and Correctness Tests
+; llvm/llvm-project#97975
+; ========================================================================================
+; Test that consecutive half operations round intermediate results back to f16
+; precision between each operation when -mfloat16 is active.
+; This verifies the fix for the miscompilation described in llvm/llvm-project#97975,
+; where backends kept intermediate results at f32 precision across consecutive
+; half operations, causing incorrect results. For example:
+; 65504.0 + 65504.0 + (-65504.0) should produce infinity at f16 precision
+; but produces 65504.0 if the intermediate is kept at f32 precision.
+; ========================================================================================
+
+define half @consecutive_add(half %a, half %b, half %c) nounwind {
+; P8-AIX-32-LABEL: consecutive_add:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: mflr 0
+; P8-AIX-32-NEXT: stwu 1, -80(1)
+; P8-AIX-32-NEXT: stw 0, 88(1)
+; P8-AIX-32-NEXT: stfd 30, 64(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 2
+; P8-AIX-32-NEXT: stfd 29, 56(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: stfd 31, 72(1) # 8-byte Folded Spill
+; P8-AIX-32-NEXT: fmr 31, 3
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 29, 1
+; P8-AIX-32-NEXT: fmr 1, 30
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsaddsp 1, 1, 29
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: fmr 30, 1
+; P8-AIX-32-NEXT: fmr 1, 31
+; P8-AIX-32-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: xsaddsp 1, 30, 1
+; P8-AIX-32-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-32-NEXT: nop
+; P8-AIX-32-NEXT: lfd 31, 72(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 30, 64(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: lfd 29, 56(1) # 8-byte Folded Reload
+; P8-AIX-32-NEXT: addi 1, 1, 80
+; P8-AIX-32-NEXT: lwz 0, 8(1)
+; P8-AIX-32-NEXT: mtlr 0
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: consecutive_add:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: mflr 0
+; P8-AIX-64-NEXT: stdu 1, -144(1)
+; P8-AIX-64-NEXT: std 0, 160(1)
+; P8-AIX-64-NEXT: stfd 30, 128(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 2
+; P8-AIX-64-NEXT: stfd 29, 120(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: stfd 31, 136(1) # 8-byte Folded Spill
+; P8-AIX-64-NEXT: fmr 31, 3
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 29, 1
+; P8-AIX-64-NEXT: fmr 1, 30
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsaddsp 1, 1, 29
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: fmr 30, 1
+; P8-AIX-64-NEXT: fmr 1, 31
+; P8-AIX-64-NEXT: bl .__extendhfsf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: xsaddsp 1, 30, 1
+; P8-AIX-64-NEXT: bl .__truncsfhf2[PR]
+; P8-AIX-64-NEXT: nop
+; P8-AIX-64-NEXT: lfd 31, 136(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 30, 128(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: lfd 29, 120(1) # 8-byte Folded Reload
+; P8-AIX-64-NEXT: addi 1, 1, 144
+; P8-AIX-64-NEXT: ld 0, 16(1)
+; P8-AIX-64-NEXT: mtlr 0
+; P8-AIX-64-NEXT: blr
+;
+; P9-LABEL: consecutive_add:
+; P9: # %bb.0: # %entry
+; P9-NEXT: xscvhpdp 0, 2
+; P9-NEXT: xscvhpdp 1, 1
+; P9-NEXT: xsaddsp 0, 1, 0
+; P9-NEXT: xscvdphp 0, 0
+; P9-NEXT: xscvhpdp 0, 0
+; P9-NEXT: xscvhpdp 1, 3
+; P9-NEXT: xsaddsp 0, 0, 1
+; P9-NEXT: xscvdphp 1, 0
+; P9-NEXT: blr
+;
+; P8-LINUX-64-LABEL: consecutive_add:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: mflr 0
+; P8-LINUX-64-NEXT: stfd 29, -24(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 30, -16(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stfd 31, -8(1) # 8-byte Folded Spill
+; P8-LINUX-64-NEXT: stdu 1, -64(1)
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 2
+; P8-LINUX-64-NEXT: std 0, 80(1)
+; P8-LINUX-64-NEXT: fmr 31, 3
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 29, 1
+; P8-LINUX-64-NEXT: fmr 1, 30
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsaddsp 1, 1, 29
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: fmr 30, 1
+; P8-LINUX-64-NEXT: fmr 1, 31
+; P8-LINUX-64-NEXT: bl __extendhfsf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: xsaddsp 1, 30, 1
+; P8-LINUX-64-NEXT: bl __truncsfhf2
+; P8-LINUX-64-NEXT: nop
+; P8-LINUX-64-NEXT: addi 1, 1, 64
+; P8-LINUX-64-NEXT: ld 0, 16(1)
+; P8-LINUX-64-NEXT: lfd 31, -8(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: lfd 30, -16(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: mtlr 0
+; P8-LINUX-64-NEXT: lfd 29, -24(1) # 8-byte Folded Reload
+; P8-LINUX-64-NEXT: blr
+entry:
+ %d = fadd half %a, %b
+ %e = fadd half %d, %c
+ ret half %e
+}
+
+; ========================================================================================
+; ConstantFP - Expand path, materialized as integer
+; ========================================================================================
+
+; 0xH3C00 = 1.0 in IEEE 754 f16 encoding
+define half @test_constant_fp() nounwind {
+; P8-AIX-32-LABEL: test_constant_fp:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: lwz 3, L..C2(2) # %const.0
+; P8-AIX-32-NEXT: lhzx 3, 0, 3
+; P8-AIX-32-NEXT: mtfprwz 1, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_constant_fp:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: ld 3, L..C2(2) # %const.0
+; P8-AIX-64-NEXT: lhzx 3, 0, 3
+; P8-AIX-64-NEXT: mtfprwz 1, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_constant_fp:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: lwz 3, L..C2(2) # %const.0
+; P9-AIX-32-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_constant_fp:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: ld 3, L..C2(2) # %const.0
+; P9-AIX-64-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_constant_fp:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: addis 3, 2, .LCPI48_0 at toc@ha
+; P8-LINUX-64-NEXT: lhz 3, .LCPI48_0 at toc@l(3)
+; P8-LINUX-64-NEXT: mtfprwz 1, 3
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_constant_fp:
+; P9-LINUX-64: # %bb.0: # %entry
+; P9-LINUX-64-NEXT: addis 3, 2, .LCPI48_0 at toc@ha
+; P9-LINUX-64-NEXT: addi 3, 3, .LCPI48_0 at toc@l
+; P9-LINUX-64-NEXT: lxsihzx 1, 0, 3
+; P9-LINUX-64-NEXT: blr
+entry:
+ ret half 0xH3C00
+}
+
+define half @test_constant_zero() nounwind {
+; P8-AIX-32-LABEL: test_constant_zero:
+; P8-AIX-32: # %bb.0: # %entry
+; P8-AIX-32-NEXT: lwz 3, L..C3(2) # %const.0
+; P8-AIX-32-NEXT: lhzx 3, 0, 3
+; P8-AIX-32-NEXT: mtfprwz 1, 3
+; P8-AIX-32-NEXT: blr
+;
+; P8-AIX-64-LABEL: test_constant_zero:
+; P8-AIX-64: # %bb.0: # %entry
+; P8-AIX-64-NEXT: ld 3, L..C3(2) # %const.0
+; P8-AIX-64-NEXT: lhzx 3, 0, 3
+; P8-AIX-64-NEXT: mtfprwz 1, 3
+; P8-AIX-64-NEXT: blr
+;
+; P9-AIX-32-LABEL: test_constant_zero:
+; P9-AIX-32: # %bb.0: # %entry
+; P9-AIX-32-NEXT: lwz 3, L..C3(2) # %const.0
+; P9-AIX-32-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-32-NEXT: blr
+;
+; P9-AIX-64-LABEL: test_constant_zero:
+; P9-AIX-64: # %bb.0: # %entry
+; P9-AIX-64-NEXT: ld 3, L..C3(2) # %const.0
+; P9-AIX-64-NEXT: lxsihzx 1, 0, 3
+; P9-AIX-64-NEXT: blr
+;
+; P8-LINUX-64-LABEL: test_constant_zero:
+; P8-LINUX-64: # %bb.0: # %entry
+; P8-LINUX-64-NEXT: addis 3, 2, .LCPI49_0 at toc@ha
+; P8-LINUX-64-NEXT: lhz 3, .LCPI49_0 at toc@l(3)
+; P8-LINUX-64-NEXT: mtfprwz 1, 3
+; P8-LINUX-64-NEXT: blr
+;
+; P9-LINUX-64-LABEL: test_constant_zero:
+; P9-LINUX-64: # %bb.0: # %entry
+; P9-LINUX-64-NEXT: addis 3, 2, .LCPI49_0 at toc@ha
+; P9-LINUX-64-NEXT: addi 3, 3, .LCPI49_0 at toc@l
+; P9-LINUX-64-NEXT: lxsihzx 1, 0, 3
+; P9-LINUX-64-NEXT: blr
+entry:
+ ret half 0.0
+}
+
+; ========================================================================================
+; Intrinsic Declarations
+; ========================================================================================
+
+declare half @llvm.canonicalize.f16(half)
+declare half @llvm.ceil.f16(half)
+declare half @llvm.copysign.f16(half, half)
+declare half @llvm.cos.f16(half)
+declare half @llvm.exp.f16(half)
+declare half @llvm.exp10.f16(half)
+declare half @llvm.exp2.f16(half)
+declare half @llvm.fabs.f16(half)
+declare half @llvm.floor.f16(half)
+declare half @llvm.fma.f16(half, half, half)
+declare half @llvm.log.f16(half)
+declare half @llvm.log10.f16(half)
+declare half @llvm.log2.f16(half)
+declare half @llvm.maximum.f16(half, half)
+declare half @llvm.maxnum.f16(half, half)
+declare half @llvm.minimum.f16(half, half)
+declare half @llvm.minnum.f16(half, half)
+declare half @llvm.nearbyint.f16(half)
+declare half @llvm.pow.f16(half, half)
+declare half @llvm.rint.f16(half)
+declare half @llvm.round.f16(half)
+declare half @llvm.roundeven.f16(half)
+declare half @llvm.sin.f16(half)
+declare half @llvm.sqrt.f16(half)
+declare half @llvm.trunc.f16(half)
diff --git a/llvm/test/CodeGen/PowerPC/shrink-wrap.mir b/llvm/test/CodeGen/PowerPC/shrink-wrap.mir
index 4981c81291c9e..3e70b3051b80d 100644
--- a/llvm/test/CodeGen/PowerPC/shrink-wrap.mir
+++ b/llvm/test/CodeGen/PowerPC/shrink-wrap.mir
@@ -88,7 +88,7 @@ body: |
; CHECK-NEXT: successors: %bb.4(0x7c000000), %bb.5(0x04000000)
; CHECK-NEXT: liveins: $r4, $x3
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: INLINEASM &"add $0, $1, $2", attdialect, regdef:GPRC, def renamable $r4, reguse:GPRC, renamable $r3, reguse:GPRC, killed renamable $r4, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15, clobber, implicit-def dead early-clobber $r16, clobber, implicit-def dead early-clobber $r17, clobber, implicit-def dead early-clobber $r18, clobber, implicit-def dead early-clobber $r19, clobber, implicit-def dead early-clobber $r20, clobber, implicit-def dead early-clobber $r21, clobber, implicit-def dead early-clobber $r22, clobber, implicit-def dead early-clobber $r23, clobber, implicit-def dead early-clobber $r24, clobber, implicit-def dead early-clobber $r25, clobber, implicit-def dead early-clobber $r26, clobber, implicit-def dead early-clobber $r27, clobber, implicit-def dead early-clobber $r28, clobber, implicit-def dead early-clobber $r29, clobber, implicit-def dead early-clobber $r30, clobber, implicit-def dead early-clobber $r31
+ ; CHECK-NEXT: INLINEASM &"add $0, $1, $2", attdialect, regdef:VSSRC, def renamable $r4, reguse:VSSRC, renamable $r3, reguse:VSSRC, killed renamable $r4, clobber, implicit-def dead early-clobber $r14, clobber, implicit-def dead early-clobber $r15, clobber, implicit-def dead early-clobber $r16, clobber, implicit-def dead early-clobber $r17, clobber, implicit-def dead early-clobber $r18, clobber, implicit-def dead early-clobber $r19, clobber, implicit-def dead early-clobber $r20, clobber, implicit-def dead early-clobber $r21, clobber, implicit-def dead early-clobber $r22, clobber, implicit-def dead early-clobber $r23, clobber, implicit-def dead early-clobber $r24, clobber, implicit-def dead early-clobber $r25, clobber, implicit-def dead early-clobber $r26, clobber, implicit-def dead early-clobber $r27, clobber, implicit-def dead early-clobber $r28, clobber, implicit-def dead early-clobber $r29, clobber, implicit-def dead early-clobber $r30, clobber, implicit-def dead early-clobber $r31
; CHECK-NEXT: BDNZ8 %bb.4, implicit-def dead $ctr8, implicit $ctr8
; CHECK-NEXT: B %bb.5
; CHECK-NEXT: {{ $}}
More information about the cfe-commits
mailing list