[clang] [llvm] [PowerPC] _Float16 scalar datatype support for Power8+ (PR #196559)

Tony Varghese via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 21 06:50:40 PDT 2026


https://github.com/tonykuttai updated https://github.com/llvm/llvm-project/pull/196559

>From d0eab040460c110fabc58ab7059bfae732f5c7f4 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 1/8] [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 07fec9e9aac21..08ac88447d9ea 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6065,6 +6065,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 1ecb474c1ede8..2f135b52122ed 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 22880e5a04a3f..1ba1096012c2c 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;
@@ -364,6 +365,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 d060d8ae2fac8..63a7bcca01ae8 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 ba2a4e6a9695c..2501f206e5a85 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -70,6 +70,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.
@@ -418,6 +422,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 91125abb89504..48e06c5e4ca1c 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.
@@ -1696,6 +1758,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();
 }
@@ -4685,6 +4753,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
@@ -6590,6 +6659,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
@@ -6936,6 +7006,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.
@@ -7079,10 +7150,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.");
 
@@ -7093,6 +7163,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:
@@ -7237,8 +7311,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);
@@ -7324,7 +7399,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();
@@ -7353,6 +7429,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;
@@ -7460,10 +7539,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 a39f7e0d3c35f..3a659c0ff28f6 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 4171ff46baddd..a4042039da24c 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
@@ -4058,6 +4058,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: {{  $}}

>From 38263b81abda8e5379eff9badb797483490c019c Mon Sep 17 00:00:00 2001
From: Tony Varghese <tonypalampalliyil at gmail.com>
Date: Mon, 11 May 2026 15:55:18 +0530
Subject: [PATCH 2/8] [PowerPC] Decouple _Float16 ISel and AIX ABI routing from
 -mfloat16 flag

---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 11 +++++------
 llvm/lib/Target/PowerPC/PPCInstrVSX.td      |  7 ++-----
 2 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 48e06c5e4ca1c..3ba3edb6e386b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -7152,7 +7152,7 @@ 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, bool HasFloat16) {
+                  bool HasVSX) {
   assert((IsPPC64 || SVT != MVT::i64) &&
          "i64 should have been split for 32-bit codegen.");
 
@@ -7164,7 +7164,7 @@ getRegClassForSVT(MVT::SimpleValueType SVT, bool IsPPC64, bool HasP8Vector,
   case MVT::i64:
     return IsPPC64 ? &PPC::G8RCRegClass : &PPC::GPRCRegClass;
   case MVT::f16:
-    if (HasFloat16 && HasP8Vector)
+    if (HasP8Vector)
       return &PPC::VHFRCRegClass;
     llvm_unreachable("f16 requires Power8 or later");
   case MVT::f32:
@@ -7313,7 +7313,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
     if (SaveParams && VA.isRegLoc() && !Flags.isByVal() && !VA.needsCustom()) {
       const TargetRegisterClass *RegClass =
           getRegClassForSVT(LocVT.SimpleTy, IsPPC64, Subtarget.hasP8Vector(),
-                            Subtarget.hasVSX(), Subtarget.hasFloat16());
+                            Subtarget.hasVSX());
       // 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);
@@ -7399,8 +7399,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
         MVT::SimpleValueType SVT = VA.getLocVT().SimpleTy;
         MF.addLiveIn(VA.getLocReg(),
                      getRegClassForSVT(SVT, IsPPC64, Subtarget.hasP8Vector(),
-                                       Subtarget.hasVSX(),
-                                       Subtarget.hasFloat16()));
+                                       Subtarget.hasVSX()));
       };
 
       HandleMemLoc();
@@ -7542,7 +7541,7 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
       Register VReg = MF.addLiveIn(
           VA.getLocReg(),
           getRegClassForSVT(SVT, IsPPC64, Subtarget.hasP8Vector(),
-                            Subtarget.hasVSX(), Subtarget.hasFloat16()));
+                            Subtarget.hasVSX()));
       SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, LocVT);
       if (ValVT.isScalarInteger() &&
           (ValVT.getFixedSizeInBits() < LocVT.getFixedSizeInBits())) {
diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
index a4042039da24c..b7a6247c511a0 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
@@ -4058,9 +4058,8 @@ 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 {
+let Predicates = [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)>;
@@ -4094,12 +4093,10 @@ let Predicates = [HasFloat16, HasP9Vector] in {
   // 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 {
+let Predicates = [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)>;

>From 5536332f68bbeb6f8d84d2182b4282f42582cade Mon Sep 17 00:00:00 2001
From: Tony Varghese <tony.varghese at ibm.com>
Date: Fri, 19 Jun 2026 19:54:47 +0530
Subject: [PATCH 3/8] [PowerPC] Fix ABI routing, f16 ISel legalization and
 FP_ROUND/EXTEND lowering.

---
 clang/test/Driver/ppc-float16-support-check.c |  26 +
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   | 184 +++-
 llvm/lib/Target/PowerPC/PPCISelLowering.h     |   3 -
 llvm/test/CodeGen/PowerPC/f128-conv.ll        |  13 +-
 llvm/test/CodeGen/PowerPC/f16-aix-psa.ll      |   8 +
 llvm/test/CodeGen/PowerPC/half-float16-ppc.ll |  41 +-
 llvm/test/CodeGen/PowerPC/half.ll             | 528 ++++++------
 llvm/test/CodeGen/PowerPC/ldexp.ll            |   7 +-
 llvm/test/CodeGen/PowerPC/llvm.frexp.ll       | 127 ++-
 llvm/test/CodeGen/PowerPC/llvm.modf.ll        |  75 +-
 llvm/test/CodeGen/PowerPC/pr48519.ll          |  70 +-
 llvm/test/CodeGen/PowerPC/pr49092.ll          |   6 +
 llvm/test/CodeGen/PowerPC/vector-llrint.ll    | 815 +++++++++---------
 llvm/test/CodeGen/PowerPC/vector-lrint.ll     | 815 +++++++++---------
 14 files changed, 1460 insertions(+), 1258 deletions(-)
 create mode 100644 clang/test/Driver/ppc-float16-support-check.c

diff --git a/clang/test/Driver/ppc-float16-support-check.c b/clang/test/Driver/ppc-float16-support-check.c
new file mode 100644
index 0000000000000..b7864d169f806
--- /dev/null
+++ b/clang/test/Driver/ppc-float16-support-check.c
@@ -0,0 +1,26 @@
+// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN:   -mcpu=pwr9 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
+// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN:   -mcpu=pwr8 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
+
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN:   -mcpu=pwr7 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN:   -mcpu=pwr6 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
+
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN:   -mcpu=pwr9 -mfloat16 -msoft-float %s 2>&1 | FileCheck %s --check-prefix=SOFTFLOAT
+
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
+// RUN:   -mcpu=pwr9 %s 2>&1 | FileCheck %s --check-prefix=NOFLAG
+
+_Float16 f;
+
+// HASFLOAT16-NOT: option '-mfloat16' cannot be specified with
+// HASFLOAT16-NOT: _Float16 is not supported on this target
+
+// BADCPU: option '-mfloat16' cannot be specified with
+
+// SOFTFLOAT: option '-mfloat16' cannot be specified with '-msoft-float'
+
+// NOFLAG: _Float16 is not supported on this target
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 3ba3edb6e386b..502155292b5e3 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -261,11 +261,12 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
     setTruncStoreAction(MVT::f32, MVT::f16, Expand);
   }
 
-  // Only active when -mfloat16 is passed and hard float is enabled.
+  // Make f16 a legal type whenever the hardware can back it (VSX half-
+  // precision registers on Power8+) 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()) {
+  if (Subtarget.hasP8Vector() && Subtarget.hasHardFloat()) {
     // Make f16 a legal type.
     addRegisterClass(MVT::f16, &PPC::VHFRCRegClass);
 
@@ -282,11 +283,22 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
         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};
+        ISD::SELECT,     ISD::FLDEXP,   ISD::FFREXP,      ISD::FMODF,
+        ISD::FATAN2,     ISD::FPOWI};
 
     // Promote all the arithmetic operations defined above to f32.
     setOperationAction(F16PromoteOps, MVT::f16, Promote);
 
+    // ISD::LRINT/LLRINT/LROUND/LLROUND have a result type that differs from
+    // their f16 operand (an integer, not f16), and SelectionDAGLegalize's
+    // PromoteNode computes the type to
+    // promote to from the *result* type, so a plain Promote action on the
+    // f16 operand is silently mismatched there and trips an assertion.
+    // Lower them manually instead: extend the f16 operand to f32 and
+    // re-emit the same node, which is already legal/handled for f32.
+    setOperationAction({ISD::LRINT, ISD::LLRINT, ISD::LROUND, ISD::LLROUND},
+                       MVT::f16, Custom);
+
     setOperationAction(ISD::LOAD, MVT::f16, Legal);
     setOperationAction(ISD::STORE, MVT::f16, Legal);
 
@@ -304,22 +316,34 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setTruncStoreAction(VT, MVT::f16, Expand);
     }
 
+    // FP_ROUND/STRICT_FP_ROUND to f16 is Custom on both P8 and P9: f32/f64
+    // sources are hardware-legal on P9 and need a libcall on P8, while an
+    // f128 source needs a libcall either way (no direct f128->f16
+    // instruction even on P9). The action table can't express this
+    // per-source distinction since it is keyed only on the f16 result
+    // type, so LowerFP_ROUND resolves it based on the actual operand type.
+    setOperationAction(ISD::FP_ROUND, MVT::f16, Custom);
+    setOperationAction(ISD::STRICT_FP_ROUND, MVT::f16, Custom);
+
     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);
+      // P8: Conversions via libcalls (__extendhfsf2/__extendhfdf2 etc).
+      // FP_EXTEND/STRICT_FP_EXTEND with an f32 result only ever have f16 as
+      // the source on this target, so it is safe to mark them Expand
+      // directly. An f64 result is ambiguous between f16->f64 (needs a
+      // libcall) and the common, always-legal f32->f64 widening, which the
+      // operation-action table cannot distinguish since it is keyed only on
+      // the result type. Use Custom for the f64 case so LowerFP_EXTEND can
+      // split f16->f64 into f16->f32->f64 while leaving f32->f64 untouched.
+      // FP_EXTEND with f16 as the source is the only case PowerPC needs to
+      // handle here (f32 has no other narrower legal source on this
+      // target; f64's other source, f32, is always legal and must be left
+      // alone). Use Custom rather than Expand:
+      // Custom only intercepts the f16-sourced case in LowerFP_EXTEND and
+      // otherwise defers to the existing (already-legal) default.
+      setOperationAction(ISD::FP_EXTEND, MVT::f32, Custom);
+      setOperationAction(ISD::FP_EXTEND, MVT::f64, Custom);
     }
   }
 
@@ -1340,7 +1364,11 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::FSUB, MVT::f128, Legal);
       setOperationAction(ISD::FDIV, MVT::f128, Legal);
       setOperationAction(ISD::FMUL, MVT::f128, Legal);
-      setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal);
+      // Custom rather than Legal: f16 is also a legal source type (see the
+      // f16 setup above), and there is no direct f16->f128 hardware
+      // instruction, so LowerFP_EXTEND needs to route that case through a
+      // libcall while leaving the genuinely-legal f32/f64 sources alone.
+      setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom);
 
       setOperationAction(ISD::FMA, MVT::f128, Legal);
       setCondCodeAction(ISD::SETULT, MVT::f128, Expand);
@@ -1368,6 +1396,9 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::STRICT_FDIV, MVT::f128, Legal);
       setOperationAction(ISD::STRICT_FMA, MVT::f128, Legal);
       setOperationAction(ISD::STRICT_FSQRT, MVT::f128, Legal);
+      // NOTE: STRICT_FP_EXTEND to f128 is left Legal (not Custom like the
+      // non-strict case above) since LowerOperation has no dispatch case
+      // for it; a strict half->fp128 extend is an unhandled known gap.
       setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f128, Legal);
       setOperationAction(ISD::STRICT_FP_ROUND, MVT::f64, Legal);
       setOperationAction(ISD::STRICT_FP_ROUND, MVT::f32, Legal);
@@ -1402,8 +1433,13 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::FMA, MVT::f128, Expand);
       setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand);
 
-      // Expand the fp_extend if the target type is fp128.
-      setOperationAction(ISD::FP_EXTEND, MVT::f128, Expand);
+      // f16 is also a legal source type on this subtarget (see the f16
+      // setup above) and has no usable Expand lowering to f128 (no
+      // libcall handles f16->f128 directly), so this needs Custom rather
+      // than Expand to let LowerFP_EXTEND route it through f32. The
+      // existing f32/f64->f128 behavior is replicated there explicitly
+      // via the same libcalls Expand would have produced.
+      setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom);
       setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f128, Expand);
 
       // Expand the fp_round if the source type is fp128.
@@ -1758,10 +1794,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.
+/// Tell the ABI lowering infrastructure to use FPRs for f16 parameters
+/// and return values rather than GPRs whenever the hardware can hold them
+/// in VSX registers. This must not depend on -mfloat16: that flag only
+/// controls whether _Float16 is a spellable source-level type, not the ABI.
 bool PPCTargetLowering::useFPRegsForHalfType() const {
-  return Subtarget.hasFloat16() && Subtarget.hasHardFloat();
+  return Subtarget.hasP8Vector() && Subtarget.hasHardFloat();
 }
 
 bool PPCTargetLowering::preferIncOfAddToSubOfNot(EVT VT) const {
@@ -12659,8 +12697,40 @@ SDValue PPCTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
 
 SDValue PPCTargetLowering::LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
   bool IsStrict = Op->isStrictFPOpcode();
-  if (Op.getOperand(IsStrict ? 1 : 0).getValueType() == MVT::f128 &&
-      !Subtarget.hasP9Vector())
+  SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
+  SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
+  EVT SrcVT = Src.getValueType();
+  EVT DstVT = Op.getValueType();
+  SDLoc dl(Op);
+
+  if (DstVT == MVT::f16) {
+    // No source type has a direct hardware rounding path to f16 except
+    // f32/f64 on P9; everything else (f128 on either subtarget, f32/f64
+    // on P8) goes through a libcall. FP_ROUND/f16 is registered Custom
+    // for all of these because the action table can't distinguish them
+    // by source type, being keyed only on the f16 result.
+    if (SrcVT == MVT::f32 || SrcVT == MVT::f64) {
+      if (Subtarget.hasP9Vector())
+        return Op;
+    }
+    RTLIB::Libcall LC;
+    if (SrcVT == MVT::f128)
+      LC = RTLIB::FPROUND_F128_F16;
+    else if (SrcVT == MVT::f64)
+      LC = RTLIB::FPROUND_F64_F16;
+    else {
+      assert(SrcVT == MVT::f32 && "Unexpected source type for fp_round");
+      LC = RTLIB::FPROUND_F32_F16;
+    }
+    MakeLibCallOptions CallOptions;
+    std::pair<SDValue, SDValue> Result =
+        makeLibCall(DAG, LC, MVT::f16, Src, CallOptions, dl, Chain);
+    if (!IsStrict)
+      return Result.first;
+    return DAG.getMergeValues({Result.first, Result.second}, dl);
+  }
+
+  if (SrcVT == MVT::f128 && !Subtarget.hasP9Vector())
     return SDValue();
 
   return Op;
@@ -12672,6 +12742,59 @@ SDValue PPCTargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
   assert(Op.getOpcode() == ISD::FP_EXTEND &&
          "Should only be called for ISD::FP_EXTEND");
 
+  // On Power8 there is no hardware instruction extending f16 directly to
+  // f32 or f64; route those through the appropriate libcall. FP_EXTEND is
+  // marked Custom (rather than Expand) for f16-sourced cases so that the
+  // common, unrelated extends sharing the same result type (there is no
+  // other legal source for f32; f32->f64 for f64) are left untouched,
+  // since marking the whole opcode Expand would otherwise also divert
+  // those through the generic stack-conversion expansion.
+  if (Op.getOperand(0).getValueType() == MVT::f16) {
+    SDLoc dl(Op);
+    MakeLibCallOptions CallOptions;
+    SDValue Ext32 = makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32,
+                                Op.getOperand(0), CallOptions, dl)
+                        .first;
+    if (Op.getValueType() == MVT::f32)
+      return Ext32;
+    assert((Op.getValueType() == MVT::f64 || Op.getValueType() == MVT::f128) &&
+           "Unexpected f16 extend result");
+    // f32->f64 is always hardware-legal. f32->f128 is hardware-legal only
+    // with P9 IEEE-f128 support; on the older libcall-based f128
+    // emulation (VSX but no P9), it needs an explicit libcall too, since
+    // there is no instruction pattern to select it directly.
+    if (Op.getValueType() == MVT::f128 && !Subtarget.hasP9Vector())
+      return makeLibCall(DAG, RTLIB::FPEXT_F32_F128, MVT::f128, Ext32,
+                         CallOptions, dl)
+          .first;
+    return DAG.getNode(ISD::FP_EXTEND, dl, Op.getValueType(), Ext32);
+  }
+
+  // Reached only on the libcall-based f128 emulation path (VSX but no P9),
+  // where FP_EXTEND/f128 is Custom solely so the f16-sourced case above can
+  // be intercepted; every other source here previously relied on the
+  // generic Expand action, which doesn't have a usable lowering for f128,
+  // so replicate it explicitly via libcall instead.
+  if (Op.getValueType() == MVT::f128 && !Subtarget.hasP9Vector()) {
+    SDLoc dl(Op);
+    MakeLibCallOptions CallOptions;
+    RTLIB::Libcall LC = Op.getOperand(0).getValueType() == MVT::f64
+                            ? RTLIB::FPEXT_F64_F128
+                            : RTLIB::FPEXT_F32_F128;
+    return makeLibCall(DAG, LC, MVT::f128, Op.getOperand(0), CallOptions, dl)
+        .first;
+  }
+
+  // The common, scalar, always-legal widening cases (f32->f64, and
+  // f32/f64->f128 when P9 IEEE-f128 hardware is present) are already fine
+  // as constructed; hand the unchanged node back rather than falling into
+  // Expand. Deliberately scoped to scalar types only: returning the node
+  // unchanged for vector cases below (e.g. widening a <4 x half> extend)
+  // trips a "potential legalization loop" assertion, since the vector
+  // type legalizer expects Custom to actually transform the node.
+  if (!Op.getValueType().isVector())
+    return Op;
+
   // FIXME: handle extends from half precision float vectors on P9.
   // We only want to custom lower an extend from v2f32 to v2f64.
   if (Op.getValueType() != MVT::v2f64 ||
@@ -13047,6 +13170,19 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::STRICT_FP_ROUND:
   case ISD::FP_ROUND:
     return LowerFP_ROUND(Op, DAG);
+  case ISD::LRINT:
+  case ISD::LLRINT:
+  case ISD::LROUND:
+  case ISD::LLROUND: {
+    // Only reached for an f16 operand (the only case registered Custom);
+    // promote it to f32, which already has working support for these ops.
+    assert(Op.getOperand(0).getValueType() == MVT::f16 &&
+           "Unexpected operand type for custom-lowered LRINT/LLRINT/"
+           "LROUND/LLROUND");
+    SDLoc dl(Op);
+    SDValue Ext32 = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, Op.getOperand(0));
+    return DAG.getNode(Op.getOpcode(), dl, Op.getValueType(), Ext32);
+  }
   case ISD::ROTL:               return LowerROTL(Op, DAG);
 
   // For counter-based loop handling.
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 3a659c0ff28f6..b8e89c9890a2c 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -214,9 +214,6 @@ 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 {
diff --git a/llvm/test/CodeGen/PowerPC/f128-conv.ll b/llvm/test/CodeGen/PowerPC/f128-conv.ll
index 080843217e8c9..ff46373f59927 100644
--- a/llvm/test/CodeGen/PowerPC/f128-conv.ll
+++ b/llvm/test/CodeGen/PowerPC/f128-conv.ll
@@ -1373,17 +1373,22 @@ entry:
 define fp128 @ext(half %a) nounwind {
 ; CHECK-LABEL: ext:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    clrlwi r3, r3, 16
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp v2, f0
+; CHECK-NEXT:    mflr r0
+; CHECK-NEXT:    stdu r1, -32(r1)
+; CHECK-NEXT:    std r0, 48(r1)
+; CHECK-NEXT:    bl __extendhfsf2
+; CHECK-NEXT:    nop
+; CHECK-NEXT:    xscpsgndp v2, f1, f1
 ; CHECK-NEXT:    xscvdpqp v2, v2
+; CHECK-NEXT:    addi r1, r1, 32
+; CHECK-NEXT:    ld r0, 16(r1)
+; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr
 ;
 ; CHECK-P8-LABEL: ext:
 ; CHECK-P8:       # %bb.0: # %entry
 ; CHECK-P8-NEXT:    mflr r0
 ; CHECK-P8-NEXT:    stdu r1, -32(r1)
-; CHECK-P8-NEXT:    clrldi r3, r3, 48
 ; CHECK-P8-NEXT:    std r0, 48(r1)
 ; CHECK-P8-NEXT:    bl __extendhfsf2
 ; CHECK-P8-NEXT:    nop
diff --git a/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll b/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
index c5dc260586913..755371365d2e0 100644
--- a/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
+++ b/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
@@ -4,6 +4,14 @@
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr9 \
 ; RUN:   -mattr=+float16,+vsx,+power9-vector < %s | FileCheck %s --check-prefix=P9-AIX-32
 
+; The following RUN lines omit -mattr=+float16: ABI routing through the
+; PSA must depend only on hardware capability, not this target feature, so
+; output must be byte-identical to the corresponding runs above.
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr9 \
+; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefix=P9-AIX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr9 \
+; RUN:   -mattr=+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
diff --git a/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
index 61ef84e5c9fd0..7fb79d50f5a32 100644
--- a/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
+++ b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
@@ -12,6 +12,23 @@
 ; 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
 
+; The following RUN lines omit -mattr=+float16 entirely. f16 legalization and
+; ABI routing (FPR vs GPR) must depend only on hardware capability
+; (HasP8Vector/HasHardFloat), not on this target feature, so the codegen
+; below must be byte-identical to the corresponding runs above.
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr8 \
+; RUN:   < %s | FileCheck %s --check-prefix=P8-AIX-32
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr8 \
+; RUN:   < %s | FileCheck %s --check-prefix=P8-AIX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr9 \
+; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-AIX-32
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr9 \
+; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-AIX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu -mcpu=pwr8 \
+; RUN:   < %s | FileCheck %s --check-prefix=P8-LINUX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu -mcpu=pwr9 \
+; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-LINUX-64
+
 ; ========================================================================================
 ; Load/Store Operations
 ; ISD::LOAD, ISD::STORE
@@ -446,15 +463,15 @@ define half @test_fma(half %a, half %b, half %c) nounwind {
 ; 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:    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 .__extendhfdf2[PR]
+; 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 .__extendhfdf2[PR]
+; P8-AIX-32-NEXT:    bl .__extendhfsf2[PR]
 ; P8-AIX-32-NEXT:    nop
 ; P8-AIX-32-NEXT:    xsmaddadp 1, 29, 30
 ; P8-AIX-32-NEXT:    bl .__truncdfhf2[PR]
@@ -477,15 +494,15 @@ define half @test_fma(half %a, half %b, half %c) nounwind {
 ; 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:    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 .__extendhfdf2[PR]
+; 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 .__extendhfdf2[PR]
+; P8-AIX-64-NEXT:    bl .__extendhfsf2[PR]
 ; P8-AIX-64-NEXT:    nop
 ; P8-AIX-64-NEXT:    xsmaddadp 1, 29, 30
 ; P8-AIX-64-NEXT:    bl .__truncdfhf2[PR]
@@ -517,15 +534,15 @@ define half @test_fma(half %a, half %b, half %c) nounwind {
 ; 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:    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 __extendhfdf2
+; 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 __extendhfdf2
+; P8-LINUX-64-NEXT:    bl __extendhfsf2
 ; P8-LINUX-64-NEXT:    nop
 ; P8-LINUX-64-NEXT:    xsmaddadp 1, 29, 30
 ; P8-LINUX-64-NEXT:    bl __truncdfhf2
@@ -3725,7 +3742,7 @@ define double @op_f16_to_f64(half %h) nounwind {
 ; 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:    bl .__extendhfsf2[PR]
 ; P8-AIX-32-NEXT:    nop
 ; P8-AIX-32-NEXT:    addi 1, 1, 64
 ; P8-AIX-32-NEXT:    lwz 0, 8(1)
@@ -3737,7 +3754,7 @@ define double @op_f16_to_f64(half %h) nounwind {
 ; 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:    bl .__extendhfsf2[PR]
 ; P8-AIX-64-NEXT:    nop
 ; P8-AIX-64-NEXT:    addi 1, 1, 112
 ; P8-AIX-64-NEXT:    ld 0, 16(1)
@@ -3754,7 +3771,7 @@ define double @op_f16_to_f64(half %h) nounwind {
 ; 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:    bl __extendhfsf2
 ; P8-LINUX-64-NEXT:    nop
 ; P8-LINUX-64-NEXT:    addi 1, 1, 32
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
diff --git a/llvm/test/CodeGen/PowerPC/half.ll b/llvm/test/CodeGen/PowerPC/half.ll
index 651da88ca99fd..e0284c7597618 100644
--- a/llvm/test/CodeGen/PowerPC/half.ll
+++ b/llvm/test/CodeGen/PowerPC/half.ll
@@ -24,10 +24,16 @@ define void @store(half %x, ptr %p) nounwind {
 ; PPC32-NEXT:    sth r3, 0(r4)
 ; PPC32-NEXT:    blr
 ;
-; CHECK-LABEL: store:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    sth r3, 0(r4)
-; CHECK-NEXT:    blr
+; P8-LABEL: store:
+; P8:       # %bb.0:
+; P8-NEXT:    mffprwz r3, f1
+; P8-NEXT:    sthx r3, 0, r4
+; P8-NEXT:    blr
+;
+; P9-LABEL: store:
+; P9:       # %bb.0:
+; P9-NEXT:    stxsihx f1, 0, r4
+; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: store:
 ; SOFT:       # %bb.0:
@@ -48,10 +54,16 @@ define half @return(ptr %p) nounwind {
 ; PPC32-NEXT:    lhz r3, 0(r3)
 ; PPC32-NEXT:    blr
 ;
-; CHECK-LABEL: return:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lhz r3, 0(r3)
-; CHECK-NEXT:    blr
+; P8-LABEL: return:
+; P8:       # %bb.0:
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f1, r3
+; P8-NEXT:    blr
+;
+; P9-LABEL: return:
+; P9:       # %bb.0:
+; P9-NEXT:    lxsihzx f1, 0, r3
+; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: return:
 ; SOFT:       # %bb.0:
@@ -73,11 +85,19 @@ define void @test_load_store(ptr %in, ptr %out) nounwind {
 ; PPC32-NEXT:    sth r3, 0(r4)
 ; PPC32-NEXT:    blr
 ;
-; CHECK-LABEL: test_load_store:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lhz r3, 0(r3)
-; CHECK-NEXT:    sth r3, 0(r4)
-; CHECK-NEXT:    blr
+; P8-LABEL: test_load_store:
+; P8:       # %bb.0:
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f0, r3
+; P8-NEXT:    mffprwz r3, f0
+; P8-NEXT:    sthx r3, 0, r4
+; P8-NEXT:    blr
+;
+; P9-LABEL: test_load_store:
+; P9:       # %bb.0:
+; P9-NEXT:    lxsihzx f0, 0, r3
+; P9-NEXT:    stxsihx f0, 0, r4
+; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_load_store:
 ; SOFT:       # %bb.0:
@@ -151,9 +171,19 @@ define half @from_bits(i16 %x) nounwind {
 ; PPC32:       # %bb.0:
 ; PPC32-NEXT:    blr
 ;
-; CHECK-LABEL: from_bits:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    blr
+; P8-LABEL: from_bits:
+; P8:       # %bb.0:
+; P8-NEXT:    sth r3, -2(r1)
+; P8-NEXT:    lhz r3, -2(r1)
+; P8-NEXT:    mtfprwz f1, r3
+; P8-NEXT:    blr
+;
+; P9-LABEL: from_bits:
+; P9:       # %bb.0:
+; P9-NEXT:    sth r3, -2(r1)
+; P9-NEXT:    addi r3, r1, -2
+; P9-NEXT:    lxsihzx f1, 0, r3
+; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: from_bits:
 ; SOFT:       # %bb.0:
@@ -171,9 +201,19 @@ define i16 @to_bits(half %x) nounwind {
 ; PPC32:       # %bb.0:
 ; PPC32-NEXT:    blr
 ;
-; CHECK-LABEL: to_bits:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    blr
+; P8-LABEL: to_bits:
+; P8:       # %bb.0:
+; P8-NEXT:    mffprwz r3, f1
+; P8-NEXT:    sth r3, -2(r1)
+; P8-NEXT:    lhz r3, -2(r1)
+; P8-NEXT:    blr
+;
+; P9-LABEL: to_bits:
+; P9:       # %bb.0:
+; P9-NEXT:    addi r3, r1, -2
+; P9-NEXT:    stxsihx f1, 0, r3
+; P9-NEXT:    lhz r3, -2(r1)
+; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: to_bits:
 ; SOFT:       # %bb.0:
@@ -204,7 +244,8 @@ define float @test_extend32(ptr %addr) nounwind {
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    stdu r1, -32(r1)
 ; P8-NEXT:    std r0, 48(r1)
-; P8-NEXT:    lhz r3, 0(r3)
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f1, r3
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    addi r1, r1, 32
@@ -265,7 +306,8 @@ define double @test_extend64(ptr %addr) nounwind {
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    stdu r1, -32(r1)
 ; P8-NEXT:    std r0, 48(r1)
-; P8-NEXT:    lhz r3, 0(r3)
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f1, r3
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    addi r1, r1, 32
@@ -335,7 +377,8 @@ define void @test_trunc32(float %in, ptr %addr) nounwind {
 ; P8-NEXT:    mr r30, r4
 ; P8-NEXT:    bl __truncsfhf2
 ; P8-NEXT:    nop
-; P8-NEXT:    sth r3, 0(r30)
+; P8-NEXT:    mffprwz r3, f1
+; P8-NEXT:    sthx r3, 0, r30
 ; P8-NEXT:    addi r1, r1, 48
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
@@ -409,7 +452,8 @@ define void @test_trunc64(double %in, ptr %addr) nounwind {
 ; P8-NEXT:    mr r30, r4
 ; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
-; P8-NEXT:    sth r3, 0(r30)
+; P8-NEXT:    mffprwz r3, f1
+; P8-NEXT:    sthx r3, 0, r30
 ; P8-NEXT:    addi r1, r1, 48
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
@@ -473,24 +517,15 @@ define i64 @test_fptosi_i64(ptr %p) nounwind {
 ;
 ; P8-LABEL: test_fptosi_i64:
 ; P8:       # %bb.0:
-; P8-NEXT:    mflr r0
-; P8-NEXT:    stdu r1, -32(r1)
-; P8-NEXT:    std r0, 48(r1)
-; P8-NEXT:    lhz r3, 0(r3)
-; P8-NEXT:    bl __extendhfsf2
-; P8-NEXT:    nop
-; P8-NEXT:    xscvdpsxds f0, f1
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f0, r3
+; P8-NEXT:    xscvdpsxds f0, f0
 ; P8-NEXT:    mffprd r3, f0
-; P8-NEXT:    addi r1, r1, 32
-; P8-NEXT:    ld r0, 16(r1)
-; P8-NEXT:    mtlr r0
 ; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_fptosi_i64:
 ; P9:       # %bb.0:
-; P9-NEXT:    lhz r3, 0(r3)
-; P9-NEXT:    mtfprwz f0, r3
-; P9-NEXT:    xscvhpdp f0, f0
+; P9-NEXT:    lxsihzx f0, 0, r3
 ; P9-NEXT:    xscvdpsxds f0, f0
 ; P9-NEXT:    mffprd r3, f0
 ; P9-NEXT:    blr
@@ -551,13 +586,12 @@ define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stdu r1, -48(r1)
-; P8-NEXT:    mtfprd f0, r3
 ; P8-NEXT:    std r0, 64(r1)
 ; P8-NEXT:    mr r30, r4
-; P8-NEXT:    xscvsxdsp f1, f0
-; P8-NEXT:    bl __truncsfhf2
+; P8-NEXT:    bl __floatdihf
 ; P8-NEXT:    nop
-; P8-NEXT:    sth r3, 0(r30)
+; P8-NEXT:    mffprwz r3, f1
+; P8-NEXT:    sthx r3, 0, r30
 ; P8-NEXT:    addi r1, r1, 48
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
@@ -566,11 +600,18 @@ define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
 ;
 ; P9-LABEL: test_sitofp_i64:
 ; P9:       # %bb.0:
-; P9-NEXT:    mtfprd f0, r3
-; P9-NEXT:    xscvsxdsp f0, f0
-; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    mffprwz r3, f0
-; P9-NEXT:    sth r3, 0(r4)
+; P9-NEXT:    mflr r0
+; P9-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
+; P9-NEXT:    stdu r1, -48(r1)
+; P9-NEXT:    std r0, 64(r1)
+; P9-NEXT:    mr r30, r4
+; P9-NEXT:    bl __floatdihf
+; P9-NEXT:    nop
+; P9-NEXT:    stxsihx f1, 0, r30
+; P9-NEXT:    addi r1, r1, 48
+; P9-NEXT:    ld r0, 16(r1)
+; P9-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
+; P9-NEXT:    mtlr r0
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_sitofp_i64:
@@ -641,24 +682,15 @@ define i64 @test_fptoui_i64(ptr %p) nounwind {
 ;
 ; P8-LABEL: test_fptoui_i64:
 ; P8:       # %bb.0:
-; P8-NEXT:    mflr r0
-; P8-NEXT:    stdu r1, -32(r1)
-; P8-NEXT:    std r0, 48(r1)
-; P8-NEXT:    lhz r3, 0(r3)
-; P8-NEXT:    bl __extendhfsf2
-; P8-NEXT:    nop
-; P8-NEXT:    xscvdpuxds f0, f1
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f0, r3
+; P8-NEXT:    xscvdpuxds f0, f0
 ; P8-NEXT:    mffprd r3, f0
-; P8-NEXT:    addi r1, r1, 32
-; P8-NEXT:    ld r0, 16(r1)
-; P8-NEXT:    mtlr r0
 ; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_fptoui_i64:
 ; P9:       # %bb.0:
-; P9-NEXT:    lhz r3, 0(r3)
-; P9-NEXT:    mtfprwz f0, r3
-; P9-NEXT:    xscvhpdp f0, f0
+; P9-NEXT:    lxsihzx f0, 0, r3
 ; P9-NEXT:    xscvdpuxds f0, f0
 ; P9-NEXT:    mffprd r3, f0
 ; P9-NEXT:    blr
@@ -734,13 +766,12 @@ define void @test_uitofp_i64(i64 %a, ptr %p) nounwind {
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stdu r1, -48(r1)
-; P8-NEXT:    mtfprd f0, r3
 ; P8-NEXT:    std r0, 64(r1)
 ; P8-NEXT:    mr r30, r4
-; P8-NEXT:    xscvuxdsp f1, f0
-; P8-NEXT:    bl __truncsfhf2
+; P8-NEXT:    bl __floatundihf
 ; P8-NEXT:    nop
-; P8-NEXT:    sth r3, 0(r30)
+; P8-NEXT:    mffprwz r3, f1
+; P8-NEXT:    sthx r3, 0, r30
 ; P8-NEXT:    addi r1, r1, 48
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
@@ -749,11 +780,18 @@ define void @test_uitofp_i64(i64 %a, ptr %p) nounwind {
 ;
 ; P9-LABEL: test_uitofp_i64:
 ; P9:       # %bb.0:
-; P9-NEXT:    mtfprd f0, r3
-; P9-NEXT:    xscvuxdsp f0, f0
-; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    mffprwz r3, f0
-; P9-NEXT:    sth r3, 0(r4)
+; P9-NEXT:    mflr r0
+; P9-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
+; P9-NEXT:    stdu r1, -48(r1)
+; P9-NEXT:    std r0, 64(r1)
+; P9-NEXT:    mr r30, r4
+; P9-NEXT:    bl __floatundihf
+; P9-NEXT:    nop
+; P9-NEXT:    stxsihx f1, 0, r30
+; P9-NEXT:    addi r1, r1, 48
+; P9-NEXT:    ld r0, 16(r1)
+; P9-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
+; P9-NEXT:    mtlr r0
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_uitofp_i64:
@@ -873,89 +911,71 @@ define <4 x float> @test_extend32_vec4(ptr %p) nounwind {
 ; P8-LABEL: test_extend32_vec4:
 ; P8:       # %bb.0:
 ; P8-NEXT:    mflr r0
-; P8-NEXT:    stdu r1, -144(r1)
-; P8-NEXT:    li r4, 80
-; P8-NEXT:    std r0, 160(r1)
-; P8-NEXT:    std r29, 120(r1) # 8-byte Folded Spill
-; P8-NEXT:    std r30, 128(r1) # 8-byte Folded Spill
+; P8-NEXT:    stdu r1, -112(r1)
+; P8-NEXT:    li r4, 48
+; P8-NEXT:    std r0, 128(r1)
+; P8-NEXT:    stfd f31, 104(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f30, 96(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f29, 88(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stxvd2x vs62, r1, r4 # 16-byte Folded Spill
-; P8-NEXT:    li r4, 96
+; P8-NEXT:    li r4, 64
 ; P8-NEXT:    stxvd2x vs63, r1, r4 # 16-byte Folded Spill
-; P8-NEXT:    lwz r4, 4(r3)
-; P8-NEXT:    stw r4, 64(r1)
-; P8-NEXT:    lwz r3, 0(r3)
-; P8-NEXT:    stw r3, 48(r1)
-; P8-NEXT:    addi r3, r1, 64
-; P8-NEXT:    lxvd2x vs62, 0, r3
-; P8-NEXT:    addi r3, r1, 48
-; P8-NEXT:    lxvd2x vs0, 0, r3
-; P8-NEXT:    mffprd r30, f0
-; P8-NEXT:    clrldi r3, r30, 48
-; P8-NEXT:    clrlwi r3, r3, 16
+; P8-NEXT:    lhz r4, 4(r3)
+; P8-NEXT:    mtfprwz f31, r4
+; P8-NEXT:    lhz r4, 6(r3)
+; P8-NEXT:    mtfprwz f30, r4
+; P8-NEXT:    lhz r4, 2(r3)
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f1, r4
+; P8-NEXT:    mtfprwz f29, r3
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    mfvsrd r29, vs62
 ; P8-NEXT:    xxlor vs63, f1, f1
-; P8-NEXT:    clrldi r3, r29, 48
-; P8-NEXT:    clrlwi r3, r3, 16
+; P8-NEXT:    fmr f1, f30
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    rldicl r3, r30, 48, 48
 ; P8-NEXT:    xxmrghd vs0, vs1, vs63
-; P8-NEXT:    clrlwi r3, r3, 16
+; P8-NEXT:    fmr f1, f31
 ; P8-NEXT:    xvcvdpsp vs62, vs0
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    rldicl r3, r29, 48, 48
 ; P8-NEXT:    xxlor vs63, f1, f1
-; P8-NEXT:    clrlwi r3, r3, 16
+; P8-NEXT:    fmr f1, f29
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    xxmrghd vs0, vs1, vs63
-; P8-NEXT:    li r3, 96
-; P8-NEXT:    ld r30, 128(r1) # 8-byte Folded Reload
-; P8-NEXT:    ld r29, 120(r1) # 8-byte Folded Reload
+; P8-NEXT:    xxmrghd vs0, vs63, vs1
+; P8-NEXT:    li r3, 64
+; P8-NEXT:    lfd f31, 104(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f30, 96(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f29, 88(r1) # 8-byte Folded Reload
 ; P8-NEXT:    xvcvdpsp vs34, vs0
 ; P8-NEXT:    lxvd2x vs63, r1, r3 # 16-byte Folded Reload
-; P8-NEXT:    li r3, 80
-; P8-NEXT:    vmrgew v2, v2, v30
+; P8-NEXT:    li r3, 48
+; P8-NEXT:    vmrgew v2, v30, v2
 ; P8-NEXT:    lxvd2x vs62, r1, r3 # 16-byte Folded Reload
-; P8-NEXT:    addi r1, r1, 144
+; P8-NEXT:    addi r1, r1, 112
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    mtlr r0
 ; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_extend32_vec4:
 ; P9:       # %bb.0:
-; P9-NEXT:    lwz r4, 4(r3)
-; P9-NEXT:    stw r4, -16(r1)
-; P9-NEXT:    lwz r3, 0(r3)
-; P9-NEXT:    lxv vs34, -16(r1)
-; P9-NEXT:    stw r3, -32(r1)
-; P9-NEXT:    li r3, 0
-; P9-NEXT:    lxv vs35, -32(r1)
-; P9-NEXT:    vextuhrx r4, r3, v3
-; P9-NEXT:    vextuhrx r3, r3, v2
-; P9-NEXT:    clrlwi r4, r4, 16
-; P9-NEXT:    clrlwi r3, r3, 16
-; P9-NEXT:    mtfprwz f0, r4
-; P9-NEXT:    mtfprwz f1, r3
-; P9-NEXT:    li r3, 2
-; P9-NEXT:    xscvhpdp f0, f0
+; P9-NEXT:    li r4, 4
+; P9-NEXT:    lxsihzx f3, 0, r3
+; P9-NEXT:    lxsihzx f0, r3, r4
+; P9-NEXT:    li r4, 6
+; P9-NEXT:    lxsihzx f1, r3, r4
+; P9-NEXT:    li r4, 2
+; P9-NEXT:    lxsihzx f2, r3, r4
+; P9-NEXT:    xscvhpdp f2, f2
 ; P9-NEXT:    xscvhpdp f1, f1
-; P9-NEXT:    vextuhrx r4, r3, v3
-; P9-NEXT:    vextuhrx r3, r3, v2
-; P9-NEXT:    clrlwi r4, r4, 16
-; P9-NEXT:    clrlwi r3, r3, 16
-; P9-NEXT:    xxmrghd vs0, vs1, vs0
-; P9-NEXT:    mtfprwz f1, r3
-; P9-NEXT:    xvcvdpsp vs36, vs0
-; P9-NEXT:    mtfprwz f0, r4
 ; P9-NEXT:    xscvhpdp f0, f0
-; P9-NEXT:    xscvhpdp f1, f1
-; P9-NEXT:    xxmrghd vs0, vs1, vs0
-; P9-NEXT:    xvcvdpsp vs34, vs0
-; P9-NEXT:    vmrgew v2, v2, v4
+; P9-NEXT:    xxmrghd vs1, vs1, vs2
+; P9-NEXT:    xvcvdpsp vs34, vs1
+; P9-NEXT:    xscvhpdp f1, f3
+; P9-NEXT:    xxmrghd vs0, vs0, vs1
+; P9-NEXT:    xvcvdpsp vs35, vs0
+; P9-NEXT:    vmrgew v2, v2, v3
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_extend32_vec4:
@@ -1078,38 +1098,42 @@ define <4 x double> @test_extend64_vec4(ptr %p) nounwind {
 ; P8:       # %bb.0:
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    stdu r1, -112(r1)
-; P8-NEXT:    std r0, 128(r1)
 ; P8-NEXT:    li r4, 48
-; P8-NEXT:    std r28, 80(r1) # 8-byte Folded Spill
-; P8-NEXT:    lhz r28, 2(r3)
-; P8-NEXT:    std r29, 88(r1) # 8-byte Folded Spill
-; P8-NEXT:    std r30, 96(r1) # 8-byte Folded Spill
-; P8-NEXT:    lhz r30, 6(r3)
-; P8-NEXT:    lhz r29, 4(r3)
-; P8-NEXT:    lhz r3, 0(r3)
+; P8-NEXT:    std r0, 128(r1)
+; P8-NEXT:    stfd f31, 104(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f30, 96(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f29, 88(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stxvd2x vs62, r1, r4 # 16-byte Folded Spill
 ; P8-NEXT:    li r4, 64
 ; P8-NEXT:    stxvd2x vs63, r1, r4 # 16-byte Folded Spill
+; P8-NEXT:    lhz r4, 2(r3)
+; P8-NEXT:    mtfprwz f31, r4
+; P8-NEXT:    lhz r4, 6(r3)
+; P8-NEXT:    mtfprwz f30, r4
+; P8-NEXT:    lhz r4, 4(r3)
+; P8-NEXT:    lhzx r3, 0, r3
+; P8-NEXT:    mtfprwz f1, r4
+; P8-NEXT:    mtfprwz f29, r3
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    mr r3, r28
 ; P8-NEXT:    xxlor vs63, f1, f1
+; P8-NEXT:    fmr f1, f30
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    mr r3, r29
 ; P8-NEXT:    xxmrghd vs63, vs1, vs63
+; P8-NEXT:    fmr f1, f31
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    mr r3, r30
 ; P8-NEXT:    xxlor vs62, f1, f1
+; P8-NEXT:    fmr f1, f29
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    li r3, 64
-; P8-NEXT:    vmr v2, v31
-; P8-NEXT:    xxmrghd vs35, vs1, vs62
-; P8-NEXT:    ld r30, 96(r1) # 8-byte Folded Reload
-; P8-NEXT:    ld r29, 88(r1) # 8-byte Folded Reload
-; P8-NEXT:    ld r28, 80(r1) # 8-byte Folded Reload
+; P8-NEXT:    vmr v3, v31
+; P8-NEXT:    xxmrghd vs34, vs62, vs1
+; P8-NEXT:    lfd f31, 104(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f30, 96(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f29, 88(r1) # 8-byte Folded Reload
 ; P8-NEXT:    lxvd2x vs63, r1, r3 # 16-byte Folded Reload
 ; P8-NEXT:    li r3, 48
 ; P8-NEXT:    lxvd2x vs62, r1, r3 # 16-byte Folded Reload
@@ -1120,20 +1144,19 @@ define <4 x double> @test_extend64_vec4(ptr %p) nounwind {
 ;
 ; P9-LABEL: test_extend64_vec4:
 ; P9:       # %bb.0:
-; P9-NEXT:    lhz r4, 6(r3)
-; P9-NEXT:    lhz r5, 4(r3)
-; P9-NEXT:    lhz r6, 2(r3)
-; P9-NEXT:    lhz r3, 0(r3)
-; P9-NEXT:    mtfprwz f0, r3
-; P9-NEXT:    mtfprwz f1, r6
-; P9-NEXT:    xscvhpdp f0, f0
+; P9-NEXT:    li r4, 2
+; P9-NEXT:    lxsihzx f3, 0, r3
+; P9-NEXT:    lxsihzx f0, r3, r4
+; P9-NEXT:    li r4, 6
+; P9-NEXT:    lxsihzx f1, r3, r4
+; P9-NEXT:    li r4, 4
+; P9-NEXT:    lxsihzx f2, r3, r4
+; P9-NEXT:    xscvhpdp f2, f2
 ; P9-NEXT:    xscvhpdp f1, f1
-; P9-NEXT:    xxmrghd vs34, vs1, vs0
-; P9-NEXT:    mtfprwz f0, r5
-; P9-NEXT:    mtfprwz f1, r4
 ; P9-NEXT:    xscvhpdp f0, f0
-; P9-NEXT:    xscvhpdp f1, f1
-; P9-NEXT:    xxmrghd vs35, vs1, vs0
+; P9-NEXT:    xxmrghd vs35, vs1, vs2
+; P9-NEXT:    xscvhpdp f1, f3
+; P9-NEXT:    xxmrghd vs34, vs0, vs1
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_extend64_vec4:
@@ -1279,40 +1302,44 @@ define void @test_trunc32_vec4(<4 x float> %a, ptr %p) nounwind {
 ; P8-NEXT:    xxsldwi vs0, vs34, vs34, 3
 ; P8-NEXT:    li r3, 48
 ; P8-NEXT:    std r0, 128(r1)
-; P8-NEXT:    std r27, 72(r1) # 8-byte Folded Spill
-; P8-NEXT:    std r28, 80(r1) # 8-byte Folded Spill
-; P8-NEXT:    std r29, 88(r1) # 8-byte Folded Spill
+; P8-NEXT:    std r30, 72(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f29, 88(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f30, 96(r1) # 8-byte Folded Spill
+; P8-NEXT:    mr r30, r5
 ; P8-NEXT:    xscvspdpn f1, vs0
-; P8-NEXT:    std r30, 96(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f31, 104(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stxvd2x vs63, r1, r3 # 16-byte Folded Spill
-; P8-NEXT:    mr r30, r5
 ; P8-NEXT:    vmr v31, v2
 ; P8-NEXT:    bl __truncsfhf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    xxswapd vs0, vs63
-; P8-NEXT:    mr r29, r3
+; P8-NEXT:    fmr f31, f1
 ; P8-NEXT:    xscvspdpn f1, vs0
 ; P8-NEXT:    bl __truncsfhf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    xxsldwi vs0, vs63, vs63, 1
-; P8-NEXT:    mr r28, r3
+; P8-NEXT:    fmr f30, f1
 ; P8-NEXT:    xscvspdpn f1, vs0
 ; P8-NEXT:    bl __truncsfhf2
 ; P8-NEXT:    nop
+; P8-NEXT:    fmr f29, f1
 ; P8-NEXT:    xscvspdpn f1, vs63
-; P8-NEXT:    mr r27, r3
 ; P8-NEXT:    bl __truncsfhf2
 ; P8-NEXT:    nop
+; P8-NEXT:    mffprwz r3, f29
+; P8-NEXT:    lfd f29, 88(r1) # 8-byte Folded Reload
+; P8-NEXT:    sth r3, 4(r30)
+; P8-NEXT:    mffprwz r3, f1
 ; P8-NEXT:    sth r3, 6(r30)
+; P8-NEXT:    mffprwz r3, f30
+; P8-NEXT:    lfd f30, 96(r1) # 8-byte Folded Reload
+; P8-NEXT:    sth r3, 2(r30)
+; P8-NEXT:    mffprwz r3, f31
+; P8-NEXT:    lfd f31, 104(r1) # 8-byte Folded Reload
+; P8-NEXT:    sthx r3, 0, r30
 ; P8-NEXT:    li r3, 48
-; P8-NEXT:    sth r27, 4(r30)
-; P8-NEXT:    ld r27, 72(r1) # 8-byte Folded Reload
-; P8-NEXT:    sth r28, 2(r30)
-; P8-NEXT:    sth r29, 0(r30)
-; P8-NEXT:    ld r30, 96(r1) # 8-byte Folded Reload
-; P8-NEXT:    ld r29, 88(r1) # 8-byte Folded Reload
+; P8-NEXT:    ld r30, 72(r1) # 8-byte Folded Reload
 ; P8-NEXT:    lxvd2x vs63, r1, r3 # 16-byte Folded Reload
-; P8-NEXT:    ld r28, 80(r1) # 8-byte Folded Reload
 ; P8-NEXT:    addi r1, r1, 112
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    mtlr r0
@@ -1321,24 +1348,23 @@ define void @test_trunc32_vec4(<4 x float> %a, ptr %p) nounwind {
 ; P9-LABEL: test_trunc32_vec4:
 ; P9:       # %bb.0:
 ; P9-NEXT:    xxsldwi vs0, vs34, vs34, 3
-; P9-NEXT:    xxsldwi vs1, vs34, vs34, 1
+; P9-NEXT:    xxswapd vs1, vs34
+; P9-NEXT:    xscvspdpn f3, vs34
+; P9-NEXT:    li r3, 6
 ; P9-NEXT:    xscvspdpn f0, vs0
+; P9-NEXT:    xxsldwi vs2, vs34, vs34, 1
 ; P9-NEXT:    xscvspdpn f1, vs1
+; P9-NEXT:    xscvspdpn f2, vs2
 ; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    mffprwz r3, f0
-; P9-NEXT:    xxswapd vs0, vs34
-; P9-NEXT:    xscvspdpn f0, vs0
-; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    xscvdphp f1, f1
-; P9-NEXT:    mffprwz r4, f1
-; P9-NEXT:    xscvspdpn f1, vs34
 ; P9-NEXT:    xscvdphp f1, f1
-; P9-NEXT:    sth r4, 4(r5)
-; P9-NEXT:    mffprwz r4, f0
-; P9-NEXT:    sth r3, 0(r5)
-; P9-NEXT:    sth r4, 2(r5)
-; P9-NEXT:    mffprwz r6, f1
-; P9-NEXT:    sth r6, 6(r5)
+; P9-NEXT:    xscvdphp f2, f2
+; P9-NEXT:    xscvdphp f3, f3
+; P9-NEXT:    stxsihx f3, r5, r3
+; P9-NEXT:    li r3, 4
+; P9-NEXT:    stxsihx f0, 0, r5
+; P9-NEXT:    stxsihx f2, r5, r3
+; P9-NEXT:    li r3, 2
+; P9-NEXT:    stxsihx f1, r5, r3
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_trunc32_vec4:
@@ -1477,11 +1503,11 @@ define void @test_trunc64_vec4(<4 x double> %a, ptr %p) nounwind {
 ; P8-NEXT:    li r3, 48
 ; P8-NEXT:    std r0, 144(r1)
 ; P8-NEXT:    xxswapd vs1, vs34
-; P8-NEXT:    std r27, 88(r1) # 8-byte Folded Spill
-; P8-NEXT:    std r28, 96(r1) # 8-byte Folded Spill
-; P8-NEXT:    std r29, 104(r1) # 8-byte Folded Spill
-; P8-NEXT:    std r30, 112(r1) # 8-byte Folded Spill
+; P8-NEXT:    std r30, 88(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f29, 104(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f30, 112(r1) # 8-byte Folded Spill
 ; P8-NEXT:    mr r30, r7
+; P8-NEXT:    stfd f31, 120(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stxvd2x vs62, r1, r3 # 16-byte Folded Spill
 ; P8-NEXT:    li r3, 64
 ; P8-NEXT:    vmr v30, v2
@@ -1489,29 +1515,33 @@ define void @test_trunc64_vec4(<4 x double> %a, ptr %p) nounwind {
 ; P8-NEXT:    vmr v31, v3
 ; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
+; P8-NEXT:    fmr f31, f1
 ; P8-NEXT:    xxswapd vs1, vs63
-; P8-NEXT:    mr r29, r3
 ; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
+; P8-NEXT:    fmr f30, f1
 ; P8-NEXT:    xxlor f1, vs62, vs62
-; P8-NEXT:    mr r28, r3
 ; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
+; P8-NEXT:    fmr f29, f1
 ; P8-NEXT:    xxlor f1, vs63, vs63
-; P8-NEXT:    mr r27, r3
 ; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
+; P8-NEXT:    mffprwz r3, f29
+; P8-NEXT:    lfd f29, 104(r1) # 8-byte Folded Reload
+; P8-NEXT:    sth r3, 2(r30)
+; P8-NEXT:    mffprwz r3, f1
 ; P8-NEXT:    sth r3, 6(r30)
+; P8-NEXT:    mffprwz r3, f30
+; P8-NEXT:    lfd f30, 112(r1) # 8-byte Folded Reload
+; P8-NEXT:    sth r3, 4(r30)
+; P8-NEXT:    mffprwz r3, f31
+; P8-NEXT:    lfd f31, 120(r1) # 8-byte Folded Reload
+; P8-NEXT:    sthx r3, 0, r30
 ; P8-NEXT:    li r3, 64
-; P8-NEXT:    sth r27, 2(r30)
-; P8-NEXT:    ld r27, 88(r1) # 8-byte Folded Reload
-; P8-NEXT:    sth r28, 4(r30)
-; P8-NEXT:    sth r29, 0(r30)
-; P8-NEXT:    ld r30, 112(r1) # 8-byte Folded Reload
-; P8-NEXT:    ld r29, 104(r1) # 8-byte Folded Reload
+; P8-NEXT:    ld r30, 88(r1) # 8-byte Folded Reload
 ; P8-NEXT:    lxvd2x vs63, r1, r3 # 16-byte Folded Reload
 ; P8-NEXT:    li r3, 48
-; P8-NEXT:    ld r28, 96(r1) # 8-byte Folded Reload
 ; P8-NEXT:    lxvd2x vs62, r1, r3 # 16-byte Folded Reload
 ; P8-NEXT:    addi r1, r1, 128
 ; P8-NEXT:    ld r0, 16(r1)
@@ -1521,19 +1551,18 @@ define void @test_trunc64_vec4(<4 x double> %a, ptr %p) nounwind {
 ; P9-LABEL: test_trunc64_vec4:
 ; P9:       # %bb.0:
 ; P9-NEXT:    xxswapd vs0, vs34
+; P9-NEXT:    xxswapd vs1, vs35
+; P9-NEXT:    li r3, 6
 ; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    mffprwz r3, f0
-; P9-NEXT:    xxswapd vs0, vs35
-; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    xscvdphp f1, vs34
-; P9-NEXT:    mffprwz r4, f1
-; P9-NEXT:    xscvdphp f1, vs35
-; P9-NEXT:    sth r3, 0(r7)
-; P9-NEXT:    sth r4, 2(r7)
-; P9-NEXT:    mffprwz r4, f0
-; P9-NEXT:    sth r4, 4(r7)
-; P9-NEXT:    mffprwz r5, f1
-; P9-NEXT:    sth r5, 6(r7)
+; P9-NEXT:    xscvdphp f1, f1
+; P9-NEXT:    xscvdphp f2, vs34
+; P9-NEXT:    xscvdphp f3, vs35
+; P9-NEXT:    stxsihx f3, r7, r3
+; P9-NEXT:    li r3, 2
+; P9-NEXT:    stxsihx f0, 0, r7
+; P9-NEXT:    stxsihx f2, r7, r3
+; P9-NEXT:    li r3, 4
+; P9-NEXT:    stxsihx f1, r7, r3
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_trunc64_vec4:
@@ -1665,52 +1694,56 @@ define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
 ; P8-LABEL: test_sitofp_fadd_i32:
 ; P8:       # %bb.0:
 ; P8-NEXT:    mflr r0
-; P8-NEXT:    std r30, -24(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stdu r1, -64(r1)
-; P8-NEXT:    mtfprwa f0, r3
 ; P8-NEXT:    std r0, 80(r1)
-; P8-NEXT:    lhz r30, 0(r4)
-; P8-NEXT:    xscvsxdsp f1, f0
-; P8-NEXT:    bl __truncsfhf2
+; P8-NEXT:    xoris r3, r3, 32768
+; P8-NEXT:    lhzx r4, 0, r4
+; P8-NEXT:    stw r3, 40(r1)
+; P8-NEXT:    addis r3, r2, .LCPI19_0 at toc@ha
+; P8-NEXT:    mtfprwz f31, r4
+; P8-NEXT:    lis r4, 17200
+; P8-NEXT:    lfs f1, .LCPI19_0 at toc@l(r3)
+; P8-NEXT:    stw r4, 44(r1)
+; P8-NEXT:    lfd f0, 40(r1)
+; P8-NEXT:    xssubdp f1, f0, f1
+; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
-; P8-NEXT:    clrldi r3, r3, 48
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    mr r3, r30
-; P8-NEXT:    fmr f31, f1
+; P8-NEXT:    fmr f30, f1
+; P8-NEXT:    fmr f1, f31
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    xsaddsp f1, f1, f31
+; P8-NEXT:    xsaddsp f1, f1, f30
 ; P8-NEXT:    bl __truncsfhf2
 ; P8-NEXT:    nop
-; P8-NEXT:    clrldi r3, r3, 48
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    addi r1, r1, 64
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
-; P8-NEXT:    ld r30, -24(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
 ; P8-NEXT:    mtlr r0
 ; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_sitofp_fadd_i32:
 ; P9:       # %bb.0:
-; P9-NEXT:    mtfprwa f0, r3
-; P9-NEXT:    lhz r4, 0(r4)
-; P9-NEXT:    xscvsxdsp f0, f0
-; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    mffprwz r3, f0
-; P9-NEXT:    mtfprwz f0, r4
-; P9-NEXT:    clrlwi r3, r3, 16
-; P9-NEXT:    xscvhpdp f0, f0
-; P9-NEXT:    mtfprwz f1, r3
+; P9-NEXT:    xoris r3, r3, 32768
+; P9-NEXT:    lxsihzx f0, 0, r4
+; P9-NEXT:    lis r4, 17200
+; P9-NEXT:    stw r3, -8(r1)
+; P9-NEXT:    addis r3, r2, .LCPI19_0 at toc@ha
+; P9-NEXT:    stw r4, -4(r1)
+; P9-NEXT:    lfd f1, -8(r1)
+; P9-NEXT:    lfs f2, .LCPI19_0 at toc@l(r3)
+; P9-NEXT:    xssubdp f1, f1, f2
+; P9-NEXT:    xscvdphp f1, f1
 ; P9-NEXT:    xscvhpdp f1, f1
+; P9-NEXT:    xscvhpdp f0, f0
 ; P9-NEXT:    xsaddsp f0, f0, f1
 ; P9-NEXT:    xscvdphp f0, f0
-; P9-NEXT:    mffprwz r3, f0
-; P9-NEXT:    clrlwi r3, r3, 16
-; P9-NEXT:    mtfprwz f0, r3
 ; P9-NEXT:    xscvhpdp f1, f0
 ; P9-NEXT:    blr
 ;
@@ -1817,14 +1850,17 @@ define half @PR40273(half) nounwind {
 ; P8:       # %bb.0:
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    stdu r1, -32(r1)
-; P8-NEXT:    clrldi r3, r3, 48
 ; P8-NEXT:    std r0, 48(r1)
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    xxlxor f0, f0, f0
-; P8-NEXT:    li r3, 15360
+; P8-NEXT:    li r3, 2
+; P8-NEXT:    addis r4, r2, .LCPI20_0 at toc@ha
 ; P8-NEXT:    fcmpu cr0, f1, f0
+; P8-NEXT:    addi r4, r4, .LCPI20_0 at toc@l
 ; P8-NEXT:    iseleq r3, 0, r3
+; P8-NEXT:    lhzx r3, r4, r3
+; P8-NEXT:    mtfprwz f1, r3
 ; P8-NEXT:    addi r1, r1, 32
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    mtlr r0
@@ -1832,13 +1868,14 @@ define half @PR40273(half) nounwind {
 ;
 ; P9-LABEL: PR40273:
 ; P9:       # %bb.0:
-; P9-NEXT:    clrlwi r3, r3, 16
-; P9-NEXT:    xxlxor f1, f1, f1
-; P9-NEXT:    mtfprwz f0, r3
-; P9-NEXT:    li r3, 15360
-; P9-NEXT:    xscvhpdp f0, f0
-; P9-NEXT:    fcmpu cr0, f0, f1
+; P9-NEXT:    xscvhpdp f1, f1
+; P9-NEXT:    xxlxor f0, f0, f0
+; P9-NEXT:    li r3, 2
+; P9-NEXT:    addis r4, r2, .LCPI20_0 at toc@ha
+; P9-NEXT:    addi r4, r4, .LCPI20_0 at toc@l
+; P9-NEXT:    fcmpu cr0, f1, f0
 ; P9-NEXT:    iseleq r3, 0, r3
+; P9-NEXT:    lxsihzx f1, r4, r3
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: PR40273:
@@ -1895,7 +1932,9 @@ define half @fabs(half %x) nounwind {
 ;
 ; CHECK-LABEL: fabs:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    clrldi r3, r3, 49
+; CHECK-NEXT:    mffprwz r3, f1
+; CHECK-NEXT:    clrlwi r3, r3, 17
+; CHECK-NEXT:    mtfprwz f1, r3
 ; CHECK-NEXT:    blr
 ;
 ; SOFT-LABEL: fabs:
@@ -1919,9 +1958,12 @@ define half @fcopysign(half %x, half %y) nounwind {
 ;
 ; CHECK-LABEL: fcopysign:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    rotldi r4, r4, 49
-; CHECK-NEXT:    clrldi r3, r3, 49
-; CHECK-NEXT:    rldimi r3, r4, 15, 32
+; CHECK-NEXT:    mffprwz r3, f2
+; CHECK-NEXT:    mffprwz r4, f1
+; CHECK-NEXT:    rlwinm r3, r3, 0, 16, 16
+; CHECK-NEXT:    clrlwi r4, r4, 17
+; CHECK-NEXT:    or r3, r4, r3
+; CHECK-NEXT:    mtfprwz f1, r3
 ; CHECK-NEXT:    blr
 ;
 ; SOFT-LABEL: fcopysign:
diff --git a/llvm/test/CodeGen/PowerPC/ldexp.ll b/llvm/test/CodeGen/PowerPC/ldexp.ll
index 3c8439683cba5..dd6825c38e9de 100644
--- a/llvm/test/CodeGen/PowerPC/ldexp.ll
+++ b/llvm/test/CodeGen/PowerPC/ldexp.ll
@@ -143,15 +143,12 @@ define half @ldexp_f16(half %arg0, i32 %arg1) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -32(r1)
-; CHECK-NEXT:    clrlwi r3, r3, 16
 ; CHECK-NEXT:    std r0, 48(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    extsw r4, r4
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl ldexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    mffprwz r3, f0
+; CHECK-NEXT:    xscvdphp f1, f1
 ; CHECK-NEXT:    addi r1, r1, 32
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
diff --git a/llvm/test/CodeGen/PowerPC/llvm.frexp.ll b/llvm/test/CodeGen/PowerPC/llvm.frexp.ll
index b0f9fd47a1e54..703e353be3424 100644
--- a/llvm/test/CodeGen/PowerPC/llvm.frexp.ll
+++ b/llvm/test/CodeGen/PowerPC/llvm.frexp.ll
@@ -7,16 +7,13 @@ define { half, i32 } @test_frexp_f16_i32(half %a) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -48(r1)
-; CHECK-NEXT:    clrlwi r3, r3, 16
 ; CHECK-NEXT:    std r0, 64(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    lwz r4, 44(r1)
-; CHECK-NEXT:    mffprwz r3, f0
+; CHECK-NEXT:    xscvdphp f1, f1
+; CHECK-NEXT:    lwz r3, 44(r1)
 ; CHECK-NEXT:    addi r1, r1, 48
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
@@ -30,15 +27,12 @@ define half @test_frexp_f16_i32_only_use_fract(half %a) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -48(r1)
-; CHECK-NEXT:    clrlwi r3, r3, 16
 ; CHECK-NEXT:    std r0, 64(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    mffprwz r3, f0
+; CHECK-NEXT:    xscvdphp f1, f1
 ; CHECK-NEXT:    addi r1, r1, 48
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
@@ -53,11 +47,9 @@ define i32 @test_frexp_f16_i32_only_use_exp(half %a) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -48(r1)
-; CHECK-NEXT:    clrlwi r3, r3, 16
 ; CHECK-NEXT:    std r0, 64(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    lwz r3, 44(r1)
@@ -74,42 +66,35 @@ define { <2 x half>, <2 x i32> } @test_frexp_v2f16_v2i32(<2 x half> %a) nounwind
 ; CHECK-LABEL: test_frexp_v2f16_v2i32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
-; CHECK-NEXT:    std r29, -24(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    std r29, -40(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    std r30, -32(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
 ; CHECK-NEXT:    stdu r1, -80(r1)
-; CHECK-NEXT:    clrlwi r29, r3, 16
-; CHECK-NEXT:    clrlwi r3, r4, 16
-; CHECK-NEXT:    addi r30, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
 ; CHECK-NEXT:    std r0, 96(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
+; CHECK-NEXT:    addi r30, r1, 36
+; CHECK-NEXT:    fmr f31, f2
 ; CHECK-NEXT:    mr r4, r30
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    mtfprwz f0, r29
-; CHECK-NEXT:    addi r29, r1, 40
-; CHECK-NEXT:    sth r3, 50(r1)
-; CHECK-NEXT:    xscvhpdp f1, f0
+; CHECK-NEXT:    xscvdphp f30, f1
+; CHECK-NEXT:    xscvhpdp f1, f31
+; CHECK-NEXT:    addi r29, r1, 32
 ; CHECK-NEXT:    mr r4, r29
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    li r4, 2
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    sth r3, 48(r1)
-; CHECK-NEXT:    li r3, 0
-; CHECK-NEXT:    lxv v3, 48(r1)
-; CHECK-NEXT:    lfiwzx f0, 0, r29
-; CHECK-NEXT:    lfiwzx f1, 0, r30
+; CHECK-NEXT:    xscvdphp f2, f1
+; CHECK-NEXT:    lfiwzx f0, 0, r30
+; CHECK-NEXT:    lfiwzx f1, 0, r29
 ; CHECK-NEXT:    xxmrghw v2, vs1, vs0
-; CHECK-NEXT:    vextuhrx r3, r3, v3
-; CHECK-NEXT:    vextuhrx r4, r4, v3
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    addi r1, r1, 80
 ; CHECK-NEXT:    ld r0, 16(r1)
-; CHECK-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, -24(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, -32(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r29, -40(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr
   %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
@@ -120,35 +105,26 @@ define <2 x half> @test_frexp_v2f16_v2i32_only_use_fract(<2 x half> %a) nounwind
 ; CHECK-LABEL: test_frexp_v2f16_v2i32_only_use_fract:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
-; CHECK-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    stdu r1, -80(r1)
-; CHECK-NEXT:    clrlwi r30, r3, 16
-; CHECK-NEXT:    clrlwi r3, r4, 16
+; CHECK-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stdu r1, -64(r1)
+; CHECK-NEXT:    std r0, 80(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    std r0, 96(r1)
-; CHECK-NEXT:    xscvhpdp f1, f0
+; CHECK-NEXT:    fmr f31, f2
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
+; CHECK-NEXT:    xscvdphp f30, f1
+; CHECK-NEXT:    xscvhpdp f1, f31
 ; CHECK-NEXT:    addi r4, r1, 40
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    mtfprwz f0, r30
-; CHECK-NEXT:    sth r3, 50(r1)
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    li r4, 2
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    sth r3, 48(r1)
-; CHECK-NEXT:    li r3, 0
-; CHECK-NEXT:    lxv v2, 48(r1)
-; CHECK-NEXT:    vextuhrx r3, r3, v2
-; CHECK-NEXT:    vextuhrx r4, r4, v2
-; CHECK-NEXT:    addi r1, r1, 80
+; CHECK-NEXT:    xscvdphp f2, f1
+; CHECK-NEXT:    fmr f1, f30
+; CHECK-NEXT:    addi r1, r1, 64
 ; CHECK-NEXT:    ld r0, 16(r1)
-; CHECK-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr
   %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
@@ -160,31 +136,30 @@ define <2 x i32> @test_frexp_v2f16_v2i32_only_use_exp(<2 x half> %a) nounwind {
 ; CHECK-LABEL: test_frexp_v2f16_v2i32_only_use_exp:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
-; CHECK-NEXT:    std r29, -24(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    stdu r1, -64(r1)
-; CHECK-NEXT:    clrlwi r3, r3, 16
-; CHECK-NEXT:    std r0, 80(r1)
-; CHECK-NEXT:    addi r30, r1, 32
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    clrlwi r29, r4, 16
+; CHECK-NEXT:    std r29, -32(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    std r30, -24(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stdu r1, -80(r1)
+; CHECK-NEXT:    std r0, 96(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
+; CHECK-NEXT:    addi r30, r1, 44
+; CHECK-NEXT:    fmr f31, f2
 ; CHECK-NEXT:    mr r4, r30
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtfprwz f0, r29
-; CHECK-NEXT:    addi r29, r1, 36
-; CHECK-NEXT:    xscvhpdp f1, f0
+; CHECK-NEXT:    xscvhpdp f1, f31
+; CHECK-NEXT:    addi r29, r1, 40
 ; CHECK-NEXT:    mr r4, r29
 ; CHECK-NEXT:    bl frexpf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    lfiwzx f0, 0, r30
 ; CHECK-NEXT:    lfiwzx f1, 0, r29
 ; CHECK-NEXT:    xxmrghw v2, vs1, vs0
-; CHECK-NEXT:    addi r1, r1, 64
+; CHECK-NEXT:    addi r1, r1, 80
 ; CHECK-NEXT:    ld r0, 16(r1)
-; CHECK-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, -24(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, -24(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r29, -32(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr
   %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
diff --git a/llvm/test/CodeGen/PowerPC/llvm.modf.ll b/llvm/test/CodeGen/PowerPC/llvm.modf.ll
index fa9082278826c..e2d73405cba33 100644
--- a/llvm/test/CodeGen/PowerPC/llvm.modf.ll
+++ b/llvm/test/CodeGen/PowerPC/llvm.modf.ll
@@ -10,17 +10,13 @@ define { half, half } @test_modf_f16(half %a) {
 ; CHECK-NEXT:    std r0, 64(r1)
 ; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    .cfi_offset lr, 16
-; CHECK-NEXT:    clrlwi r3, r3, 16
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl modff
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    mffprwz r3, f0
+; CHECK-NEXT:    xscvdphp f1, f1
 ; CHECK-NEXT:    lfs f0, 44(r1)
-; CHECK-NEXT:    xscvdphp f0, f0
-; CHECK-NEXT:    mffprwz r4, f0
+; CHECK-NEXT:    xscvdphp f2, f0
 ; CHECK-NEXT:    addi r1, r1, 48
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
@@ -37,14 +33,11 @@ define half @test_modf_f16_only_use_fractional_part(half %a) {
 ; CHECK-NEXT:    std r0, 64(r1)
 ; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    .cfi_offset lr, 16
-; CHECK-NEXT:    clrlwi r3, r3, 16
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl modff
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    mffprwz r3, f0
+; CHECK-NEXT:    xscvdphp f1, f1
 ; CHECK-NEXT:    addi r1, r1, 48
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
@@ -62,15 +55,12 @@ define half @test_modf_f16_only_use_integral_part(half %a) {
 ; CHECK-NEXT:    std r0, 64(r1)
 ; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    .cfi_offset lr, 16
-; CHECK-NEXT:    clrlwi r3, r3, 16
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl modff
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    lfs f0, 44(r1)
-; CHECK-NEXT:    xscvdphp f0, f0
-; CHECK-NEXT:    mffprwz r3, f0
+; CHECK-NEXT:    xscvdphp f1, f0
 ; CHECK-NEXT:    addi r1, r1, 48
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
@@ -84,53 +74,34 @@ define { <2 x half>, <2 x half> } @test_modf_v2f16(<2 x half> %a) {
 ; CHECK-LABEL: test_modf_v2f16:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
-; CHECK-NEXT:    .cfi_def_cfa_offset 96
+; CHECK-NEXT:    .cfi_def_cfa_offset 64
 ; CHECK-NEXT:    .cfi_offset lr, 16
-; CHECK-NEXT:    .cfi_offset r30, -24
+; CHECK-NEXT:    .cfi_offset f30, -16
 ; CHECK-NEXT:    .cfi_offset f31, -8
-; CHECK-NEXT:    std r30, -24(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
 ; CHECK-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    stdu r1, -96(r1)
-; CHECK-NEXT:    clrlwi r30, r3, 16
-; CHECK-NEXT:    clrlwi r3, r4, 16
+; CHECK-NEXT:    stdu r1, -64(r1)
+; CHECK-NEXT:    std r0, 80(r1)
+; CHECK-NEXT:    xscvhpdp f1, f1
 ; CHECK-NEXT:    addi r4, r1, 44
-; CHECK-NEXT:    mtfprwz f0, r3
-; CHECK-NEXT:    std r0, 112(r1)
-; CHECK-NEXT:    xscvhpdp f1, f0
+; CHECK-NEXT:    fmr f31, f2
 ; CHECK-NEXT:    bl modff
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    lfs f0, 44(r1)
+; CHECK-NEXT:    xscvdphp f30, f1
+; CHECK-NEXT:    xscvhpdp f1, f31
 ; CHECK-NEXT:    addi r4, r1, 40
-; CHECK-NEXT:    xscvdphp f0, f0
-; CHECK-NEXT:    fmr f31, f1
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    mtfprwz f0, r30
-; CHECK-NEXT:    sth r3, 50(r1)
-; CHECK-NEXT:    xscvhpdp f1, f0
 ; CHECK-NEXT:    bl modff
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    xscvdphp f2, f1
+; CHECK-NEXT:    lfs f0, 44(r1)
+; CHECK-NEXT:    xscvdphp f3, f0
 ; CHECK-NEXT:    lfs f0, 40(r1)
-; CHECK-NEXT:    li r5, 0
-; CHECK-NEXT:    li r6, 2
-; CHECK-NEXT:    xscvdphp f0, f0
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    sth r3, 48(r1)
-; CHECK-NEXT:    xscvdphp f0, f31
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    sth r3, 66(r1)
-; CHECK-NEXT:    xscvdphp f0, f1
-; CHECK-NEXT:    lxv v2, 48(r1)
-; CHECK-NEXT:    mffprwz r3, f0
-; CHECK-NEXT:    sth r3, 64(r1)
-; CHECK-NEXT:    lxv v3, 64(r1)
-; CHECK-NEXT:    vextuhrx r3, r5, v3
-; CHECK-NEXT:    vextuhrx r4, r6, v3
-; CHECK-NEXT:    vextuhrx r5, r5, v2
-; CHECK-NEXT:    vextuhrx r6, r6, v2
-; CHECK-NEXT:    addi r1, r1, 96
+; CHECK-NEXT:    fmr f1, f30
+; CHECK-NEXT:    xscvdphp f4, f0
+; CHECK-NEXT:    addi r1, r1, 64
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r30, -24(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr
   %result = call { <2 x half>, <2 x half> } @llvm.modf.v2f16(<2 x half> %a)
diff --git a/llvm/test/CodeGen/PowerPC/pr48519.ll b/llvm/test/CodeGen/PowerPC/pr48519.ll
index 61a8ebe49e6dd..7a29a90cc3c3e 100644
--- a/llvm/test/CodeGen/PowerPC/pr48519.ll
+++ b/llvm/test/CodeGen/PowerPC/pr48519.ll
@@ -12,40 +12,43 @@ define void @julia__typed_vcat_20() #0 {
 ; CHECK-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
 ; CHECK-NEXT:    stdu r1, -48(r1)
 ; CHECK-NEXT:    li r30, 0
-; CHECK-NEXT:    li r4, 1
+; CHECK-NEXT:    li r3, 1
 ; CHECK-NEXT:    std r0, 64(r1)
-; CHECK-NEXT:    .p2align 4
+; CHECK-NEXT:    .p2align 5
 ; CHECK-NEXT:  .LBB0_1: # %bb3
 ; CHECK-NEXT:    #
-; CHECK-NEXT:    addi r3, r4, -1
-; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    xscvsxdsp f1, f0
-; CHECK-NEXT:    bl __truncsfhf2
+; CHECK-NEXT:    addi r3, r3, -1
+; CHECK-NEXT:    bl __floatdihf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    addi r30, r30, -1
-; CHECK-NEXT:    li r4, 0
+; CHECK-NEXT:    li r3, 0
 ; CHECK-NEXT:    cmpldi r30, 0
 ; CHECK-NEXT:    bc 12, gt, .LBB0_1
 ; CHECK-NEXT:  # %bb.2: # %bb11
+; CHECK-NEXT:    mffprwz r3, f1
 ; CHECK-NEXT:    sth r3, 128(0)
 ;
 ; CHECK-P9-LABEL: julia__typed_vcat_20:
 ; CHECK-P9:       # %bb.0: # %bb
-; CHECK-P9-NEXT:    li r3, 0
-; CHECK-P9-NEXT:    mtctr r3
+; CHECK-P9-NEXT:    mflr r0
+; CHECK-P9-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
+; CHECK-P9-NEXT:    stdu r1, -48(r1)
+; CHECK-P9-NEXT:    li r30, 0
 ; CHECK-P9-NEXT:    li r3, 1
+; CHECK-P9-NEXT:    std r0, 64(r1)
 ; CHECK-P9-NEXT:    .p2align 5
 ; CHECK-P9-NEXT:  .LBB0_1: # %bb3
 ; CHECK-P9-NEXT:    #
 ; CHECK-P9-NEXT:    addi r3, r3, -1
-; CHECK-P9-NEXT:    mtfprd f0, r3
+; CHECK-P9-NEXT:    bl __floatdihf
+; CHECK-P9-NEXT:    nop
+; CHECK-P9-NEXT:    addi r30, r30, -1
 ; CHECK-P9-NEXT:    li r3, 0
-; CHECK-P9-NEXT:    xscvsxdsp f0, f0
-; CHECK-P9-NEXT:    xscvdphp f0, f0
-; CHECK-P9-NEXT:    bdnz .LBB0_1
+; CHECK-P9-NEXT:    cmpldi r30, 0
+; CHECK-P9-NEXT:    bc 12, gt, .LBB0_1
 ; CHECK-P9-NEXT:  # %bb.2: # %bb11
-; CHECK-P9-NEXT:    mffprwz r3, f0
-; CHECK-P9-NEXT:    sth r3, 128(0)
+; CHECK-P9-NEXT:    li r3, 128
+; CHECK-P9-NEXT:    stxsihx f1, 0, r3
 bb:
   %i = load i64, ptr addrspace(11) null, align 8
   %i1 = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %i, i64 0)
@@ -77,7 +80,7 @@ define void @julia__hypot_17() #0 {
 ; CHECK-NEXT:    stdu r1, -48(r1)
 ; CHECK-NEXT:    li r30, 3
 ; CHECK-NEXT:    std r0, 64(r1)
-; CHECK-NEXT:    .p2align 5
+; CHECK-NEXT:    .p2align 4
 ; CHECK-NEXT:  .LBB1_1: # %bb1
 ; CHECK-NEXT:    #
 ; CHECK-NEXT:    addi r30, r30, -1
@@ -86,6 +89,7 @@ define void @julia__hypot_17() #0 {
 ; CHECK-NEXT:  # %bb.2: # %bb3
 ; CHECK-NEXT:    #
 ; CHECK-NEXT:    lhz r3, 0(0)
+; CHECK-NEXT:    mtfprwz f1, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    fcmpu cr0, f1, f1
@@ -154,7 +158,9 @@ define void @func_48786() #0 {
 ; CHECK-NEXT:    bc 4, 4*cr5+lt, .LBB2_5
 ; CHECK-NEXT:  # %bb.4: # %bb8
 ; CHECK-NEXT:    #
-; CHECK-NEXT:    lhz r3, 0(r3)
+; CHECK-NEXT:    lhzx r3, 0, r3
+; CHECK-NEXT:    mtfprwz f0, r3
+; CHECK-NEXT:    mffprwz r3, f0
 ; CHECK-NEXT:    sth r3, 0(0)
 ; CHECK-NEXT:    b .LBB2_1
 ; CHECK-NEXT:  .LBB2_5: # %bb15
@@ -164,6 +170,7 @@ define void @func_48786() #0 {
 ; CHECK-P9-NEXT:    ld r3, 0(r3)
 ; CHECK-P9-NEXT:    cmpdi r3, 0
 ; CHECK-P9-NEXT:    mtctr r3
+; CHECK-P9-NEXT:    li r3, 0
 ; CHECK-P9-NEXT:    crnot 4*cr5+lt, eq
 ; CHECK-P9-NEXT:    b .LBB2_2
 ; CHECK-P9-NEXT:    .p2align 5
@@ -178,8 +185,8 @@ define void @func_48786() #0 {
 ; CHECK-P9-NEXT:    bc 4, 4*cr5+lt, .LBB2_5
 ; CHECK-P9-NEXT:  # %bb.4: # %bb8
 ; CHECK-P9-NEXT:    #
-; CHECK-P9-NEXT:    lhz r3, 0(r3)
-; CHECK-P9-NEXT:    sth r3, 0(0)
+; CHECK-P9-NEXT:    lxsihzx f0, 0, r3
+; CHECK-P9-NEXT:    stxsihx f0, 0, r3
 ; CHECK-P9-NEXT:    b .LBB2_1
 ; CHECK-P9-NEXT:  .LBB2_5: # %bb15
 bb:
@@ -227,29 +234,30 @@ bb15:                                             ; preds = %bb5
 define void @func_48785(half %arg) #0 {
 ; CHECK-LABEL: func_48785:
 ; CHECK:       # %bb.0: # %bb
-; CHECK-NEXT:    li r4, 1
-; CHECK-NEXT:    rldic r4, r4, 62, 1
-; CHECK-NEXT:    mtctr r4
-; CHECK-NEXT:    li r4, 0
+; CHECK-NEXT:    li r3, 1
+; CHECK-NEXT:    mffprwz r4, f1
+; CHECK-NEXT:    rldic r3, r3, 62, 1
+; CHECK-NEXT:    mtctr r3
+; CHECK-NEXT:    li r3, 0
 ; CHECK-NEXT:    .p2align 4
 ; CHECK-NEXT:  .LBB3_1: # %bb1
 ; CHECK-NEXT:    #
-; CHECK-NEXT:    sth r3, 0(r4)
-; CHECK-NEXT:    addi r4, r4, 24
+; CHECK-NEXT:    sthx r4, 0, r3
+; CHECK-NEXT:    addi r3, r3, 24
 ; CHECK-NEXT:    bdnz .LBB3_1
 ; CHECK-NEXT:  # %bb.2: # %bb5
 ;
 ; CHECK-P9-LABEL: func_48785:
 ; CHECK-P9:       # %bb.0: # %bb
-; CHECK-P9-NEXT:    li r4, 1
-; CHECK-P9-NEXT:    rldic r4, r4, 62, 1
-; CHECK-P9-NEXT:    mtctr r4
-; CHECK-P9-NEXT:    li r4, 0
+; CHECK-P9-NEXT:    li r3, 1
+; CHECK-P9-NEXT:    rldic r3, r3, 62, 1
+; CHECK-P9-NEXT:    mtctr r3
+; CHECK-P9-NEXT:    li r3, 0
 ; CHECK-P9-NEXT:    .p2align 4
 ; CHECK-P9-NEXT:  .LBB3_1: # %bb1
 ; CHECK-P9-NEXT:    #
-; CHECK-P9-NEXT:    sth r3, 0(r4)
-; CHECK-P9-NEXT:    addi r4, r4, 24
+; CHECK-P9-NEXT:    stxsihx f1, 0, r3
+; CHECK-P9-NEXT:    addi r3, r3, 24
 ; CHECK-P9-NEXT:    bdnz .LBB3_1
 ; CHECK-P9-NEXT:  # %bb.2: # %bb5
 bb:
diff --git a/llvm/test/CodeGen/PowerPC/pr49092.ll b/llvm/test/CodeGen/PowerPC/pr49092.ll
index 3c028e9005ee6..9d04142a5ec14 100644
--- a/llvm/test/CodeGen/PowerPC/pr49092.ll
+++ b/llvm/test/CodeGen/PowerPC/pr49092.ll
@@ -10,12 +10,18 @@ define dso_local half @test2(i64 %a, i64 %b) local_unnamed_addr #0 {
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    addi r3, r3, 11
+; CHECK-NEXT:    sth r3, -2(r1)
+; CHECK-NEXT:    lhz r3, -2(r1)
+; CHECK-NEXT:    mtfprwz f1, r3
 ; CHECK-NEXT:    blr
 ;
 ; CHECK-P9-LABEL: test2:
 ; CHECK-P9:       # %bb.0: # %entry
 ; CHECK-P9-NEXT:    add r3, r4, r3
 ; CHECK-P9-NEXT:    addi r3, r3, 11
+; CHECK-P9-NEXT:    sth r3, -2(r1)
+; CHECK-P9-NEXT:    addi r3, r1, -2
+; CHECK-P9-NEXT:    lxsihzx f1, 0, r3
 ; CHECK-P9-NEXT:    blr
 entry:
   %add = add i64 %b, %a
diff --git a/llvm/test/CodeGen/PowerPC/vector-llrint.ll b/llvm/test/CodeGen/PowerPC/vector-llrint.ll
index 2a7df5fbf2719..6bc7f56d33d00 100644
--- a/llvm/test/CodeGen/PowerPC/vector-llrint.ll
+++ b/llvm/test/CodeGen/PowerPC/vector-llrint.ll
@@ -30,7 +30,6 @@ define <1 x i64> @llrint_v1i64_v1f16(<1 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -32(r1)
-; CHECK-NEXT:    clrldi r3, r3, 48
 ; CHECK-NEXT:    std r0, 48(r1)
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
@@ -77,28 +76,27 @@ define <2 x i64> @llrint_v1i64_v2f16(<2 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -96(r1)
-; CHECK-NEXT:    li r5, 48
-; CHECK-NEXT:    clrldi r3, r3, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 112(r1)
-; CHECK-NEXT:    std r29, 72(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r30, 80(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r4
-; CHECK-NEXT:    stxvd2x v31, r1, r5 # 16-byte Folded Spill
+; CHECK-NEXT:    std r30, 72(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f31, 88(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f31, f2
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 48
-; CHECK-NEXT:    ld r30, 80(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, 72(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, 88(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 72(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    xxmrghd v2, vs0, v31
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    addi r1, r1, 96
@@ -162,51 +160,50 @@ define <4 x i64> @llrint_v4i64_v4f16(<4 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -128(r1)
-; CHECK-NEXT:    li r7, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 144(r1)
-; CHECK-NEXT:    clrldi r3, r3, 48
-; CHECK-NEXT:    std r27, 88(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 96(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r29, 104(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r29, r5
-; CHECK-NEXT:    mr r28, r4
-; CHECK-NEXT:    stxvd2x v30, r1, r7 # 16-byte Folded Spill
-; CHECK-NEXT:    li r7, 64
-; CHECK-NEXT:    std r30, 112(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r6
-; CHECK-NEXT:    stxvd2x v31, r1, r7 # 16-byte Folded Spill
+; CHECK-NEXT:    std r30, 88(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 104(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, 112(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f30, f3
+; CHECK-NEXT:    fmr f29, f2
+; CHECK-NEXT:    stfd f31, 120(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v30, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    fmr f31, f4
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    clrldi r3, r28, 48
+; CHECK-NEXT:    fmr f1, f29
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r27
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r29, 48
 ; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r29
+; CHECK-NEXT:    mtvsrd v30, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 64
 ; CHECK-NEXT:    vmr v2, v31
-; CHECK-NEXT:    ld r30, 112(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, 104(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 96(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r27, 88(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, 120(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, 112(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 104(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 88(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    xxmrghd v3, vs0, v30
@@ -312,99 +309,98 @@ define <8 x i64> @llrint_v8i64_v8f16(<8 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -192(r1)
-; CHECK-NEXT:    li r11, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 208(r1)
-; CHECK-NEXT:    clrldi r3, r3, 48
-; CHECK-NEXT:    std r23, 120(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r24, 128(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r25, 136(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r25, r5
-; CHECK-NEXT:    mr r24, r4
-; CHECK-NEXT:    stxvd2x v28, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 64
-; CHECK-NEXT:    std r26, 144(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r26, r6
-; CHECK-NEXT:    std r27, 152(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 160(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r28, r8
-; CHECK-NEXT:    mr r27, r7
-; CHECK-NEXT:    stxvd2x v29, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 80
-; CHECK-NEXT:    std r29, 168(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r29, r9
-; CHECK-NEXT:    std r30, 176(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r10
-; CHECK-NEXT:    stxvd2x v30, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 96
-; CHECK-NEXT:    stxvd2x v31, r1, r11 # 16-byte Folded Spill
+; CHECK-NEXT:    std r30, 120(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f25, 136(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f26, 144(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f26, f3
+; CHECK-NEXT:    fmr f25, f2
+; CHECK-NEXT:    stfd f27, 152(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v28, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    fmr f27, f4
+; CHECK-NEXT:    stfd f28, 160(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 168(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f29, f6
+; CHECK-NEXT:    fmr f28, f5
+; CHECK-NEXT:    stfd f30, 176(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v29, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    fmr f30, f7
+; CHECK-NEXT:    stfd f31, 184(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f31, f8
+; CHECK-NEXT:    stxvd2x v30, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r23, r3
-; CHECK-NEXT:    clrldi r3, r24, 48
+; CHECK-NEXT:    fmr f1, f25
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r23
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f26
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r25, 48
 ; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r25, r3
-; CHECK-NEXT:    clrldi r3, r26, 48
+; CHECK-NEXT:    fmr f1, f27
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r25
+; CHECK-NEXT:    mtvsrd v30, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f28
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r27, 48
 ; CHECK-NEXT:    xxmrghd v30, vs0, v30
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    clrldi r3, r28, 48
+; CHECK-NEXT:    fmr f1, f29
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v29, r27
+; CHECK-NEXT:    mtvsrd v29, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r29, 48
 ; CHECK-NEXT:    xxmrghd v29, vs0, v29
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v28, r29
+; CHECK-NEXT:    mtvsrd v28, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 96
 ; CHECK-NEXT:    vmr v2, v31
-; CHECK-NEXT:    ld r30, 176(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, 184(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    vmr v3, v30
 ; CHECK-NEXT:    vmr v4, v29
-; CHECK-NEXT:    ld r29, 168(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 160(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, 176(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 168(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 80
-; CHECK-NEXT:    ld r27, 152(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r26, 144(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r25, 136(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r24, 128(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r23, 120(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f28, 160(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f27, 152(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f26, 144(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f25, 136(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 120(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v30, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 64
 ; CHECK-NEXT:    lxvd2x v29, r1, r3 # 16-byte Folded Reload
@@ -592,196 +588,198 @@ define <16 x i64> @llrint_v16i64_v16f16(<16 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -320(r1)
-; CHECK-NEXT:    li r11, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 336(r1)
-; CHECK-NEXT:    std r23, 248(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r23, r3
-; CHECK-NEXT:    lhz r3, 416(r1)
-; CHECK-NEXT:    std r16, 192(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r17, 200(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r17, 432(r1)
-; CHECK-NEXT:    stxvd2x v24, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 64
-; CHECK-NEXT:    std r18, 208(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r18, 440(r1)
-; CHECK-NEXT:    std r19, 216(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r19, 448(r1)
-; CHECK-NEXT:    lhz r16, 424(r1)
-; CHECK-NEXT:    stxvd2x v25, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 80
-; CHECK-NEXT:    std r20, 224(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r20, 456(r1)
-; CHECK-NEXT:    stxvd2x v26, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 96
-; CHECK-NEXT:    std r21, 232(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r22, 240(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r22, 472(r1)
-; CHECK-NEXT:    lhz r21, 464(r1)
-; CHECK-NEXT:    stxvd2x v27, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 112
-; CHECK-NEXT:    std r15, 184(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r24, 256(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r25, 264(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r25, r5
-; CHECK-NEXT:    mr r24, r4
-; CHECK-NEXT:    stxvd2x v28, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 128
-; CHECK-NEXT:    std r26, 272(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r27, 280(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 288(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r29, 296(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r29, r9
-; CHECK-NEXT:    mr r28, r8
-; CHECK-NEXT:    mr r27, r7
-; CHECK-NEXT:    mr r26, r6
-; CHECK-NEXT:    stxvd2x v29, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 144
-; CHECK-NEXT:    std r30, 304(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r10
-; CHECK-NEXT:    stxvd2x v30, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 160
-; CHECK-NEXT:    stxvd2x v31, r1, r11 # 16-byte Folded Spill
+; CHECK-NEXT:    stfd f31, 312(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, 304(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    std r30, 184(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f17, 200(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f17, f2
+; CHECK-NEXT:    stfd f18, 208(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f18, f3
+; CHECK-NEXT:    stxvd2x v24, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    stfd f19, 216(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f19, f4
+; CHECK-NEXT:    stfd f20, 224(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f20, f5
+; CHECK-NEXT:    stfd f21, 232(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f21, f6
+; CHECK-NEXT:    stxvd2x v25, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    stfd f22, 240(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f22, f7
+; CHECK-NEXT:    stfd f23, 248(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f23, f8
+; CHECK-NEXT:    stfd f24, 256(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f24, f9
+; CHECK-NEXT:    stxvd2x v26, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    stfd f25, 264(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f25, f10
+; CHECK-NEXT:    stfd f26, 272(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f26, f11
+; CHECK-NEXT:    stfd f27, 280(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f27, f12
+; CHECK-NEXT:    stxvd2x v27, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 112
+; CHECK-NEXT:    stfd f28, 288(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 296(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f29, f13
+; CHECK-NEXT:    stxvd2x v28, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 128
+; CHECK-NEXT:    stxvd2x v29, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 144
+; CHECK-NEXT:    stxvd2x v30, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 160
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    lhz r3, 472(r1)
+; CHECK-NEXT:    mtfprwz f31, r3
+; CHECK-NEXT:    lhz r3, 464(r1)
+; CHECK-NEXT:    mtfprwz f30, r3
+; CHECK-NEXT:    lhz r3, 456(r1)
+; CHECK-NEXT:    mtfprwz f28, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r15, r3
-; CHECK-NEXT:    mr r3, r16
+; CHECK-NEXT:    fmr f1, f17
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r15
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f18
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r17
 ; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r17, r3
-; CHECK-NEXT:    mr r3, r18
+; CHECK-NEXT:    fmr f1, f19
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r17
+; CHECK-NEXT:    mtvsrd v30, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f20
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r19
 ; CHECK-NEXT:    xxmrghd v30, vs0, v30
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r19, r3
-; CHECK-NEXT:    mr r3, r20
+; CHECK-NEXT:    fmr f1, f21
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v29, r19
+; CHECK-NEXT:    mtvsrd v29, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f22
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r21
 ; CHECK-NEXT:    xxmrghd v29, vs0, v29
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r21, r3
-; CHECK-NEXT:    mr r3, r22
+; CHECK-NEXT:    fmr f1, f23
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v28, r21
+; CHECK-NEXT:    mtvsrd v28, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f24
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r23, 48
 ; CHECK-NEXT:    xxmrghd v28, vs0, v28
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r23, r3
-; CHECK-NEXT:    clrldi r3, r24, 48
+; CHECK-NEXT:    fmr f1, f25
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v27, r23
+; CHECK-NEXT:    mtvsrd v27, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f26
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r25, 48
 ; CHECK-NEXT:    xxmrghd v27, vs0, v27
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r25, r3
-; CHECK-NEXT:    clrldi r3, r26, 48
+; CHECK-NEXT:    fmr f1, f27
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v26, r25
+; CHECK-NEXT:    mtvsrd v26, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f29
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r27, 48
 ; CHECK-NEXT:    xxmrghd v26, vs0, v26
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    clrldi r3, r28, 48
+; CHECK-NEXT:    fmr f1, f28
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v25, r27
+; CHECK-NEXT:    mtvsrd v25, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r29, 48
 ; CHECK-NEXT:    xxmrghd v25, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v24, r29
+; CHECK-NEXT:    mtvsrd v24, r30
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 160
-; CHECK-NEXT:    vmr v6, v31
-; CHECK-NEXT:    ld r30, 304(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    vmr v7, v30
-; CHECK-NEXT:    vmr v8, v29
-; CHECK-NEXT:    ld r29, 296(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 288(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    vmr v2, v31
+; CHECK-NEXT:    lfd f31, 312(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    vmr v3, v30
+; CHECK-NEXT:    vmr v4, v29
+; CHECK-NEXT:    lfd f30, 304(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 296(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 144
-; CHECK-NEXT:    vmr v9, v28
-; CHECK-NEXT:    vmr v2, v27
-; CHECK-NEXT:    vmr v3, v26
-; CHECK-NEXT:    vmr v4, v25
-; CHECK-NEXT:    ld r27, 280(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r26, 272(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    vmr v5, v28
+; CHECK-NEXT:    vmr v6, v27
+; CHECK-NEXT:    vmr v7, v26
+; CHECK-NEXT:    vmr v8, v25
+; CHECK-NEXT:    lfd f28, 288(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f27, 280(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v30, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 128
-; CHECK-NEXT:    ld r25, 264(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r24, 256(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v5, vs0, v24
-; CHECK-NEXT:    ld r23, 248(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r22, 240(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r21, 232(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f26, 272(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f25, 264(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    xxmrghd v9, vs0, v24
+; CHECK-NEXT:    lfd f24, 256(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f23, 248(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f22, 240(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v29, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 112
-; CHECK-NEXT:    ld r20, 224(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r19, 216(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r18, 208(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r17, 200(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r16, 192(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r15, 184(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f21, 232(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 184(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f20, 224(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f19, 216(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f18, 208(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f17, 200(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v28, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 96
 ; CHECK-NEXT:    lxvd2x v27, r1, r3 # 16-byte Folded Reload
@@ -1151,427 +1149,436 @@ define <32 x i64> @llrint_v32i64_v32f16(<32 x half> %x) nounwind {
 ; CHECK-LABEL: llrint_v32i64_v32f16:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
-; CHECK-NEXT:    stdu r1, -576(r1)
-; CHECK-NEXT:    std r0, 592(r1)
-; CHECK-NEXT:    std r30, 560(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stdu r1, -496(r1)
+; CHECK-NEXT:    std r0, 512(r1)
+; CHECK-NEXT:    std r30, 336(r1) # 8-byte Folded Spill
 ; CHECK-NEXT:    mr r30, r3
-; CHECK-NEXT:    lhz r3, 864(r1)
-; CHECK-NEXT:    li r11, 240
-; CHECK-NEXT:    std r14, 432(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r19, 472(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r14, 744(r1)
-; CHECK-NEXT:    stxvd2x v20, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 256
-; CHECK-NEXT:    std r22, 496(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r22, 680(r1)
-; CHECK-NEXT:    std r3, 216(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 856(r1)
-; CHECK-NEXT:    lhz r19, 672(r1)
-; CHECK-NEXT:    stxvd2x v21, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 272
-; CHECK-NEXT:    std r23, 504(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r23, 688(r1)
-; CHECK-NEXT:    stxvd2x v22, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 184(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 848(r1)
-; CHECK-NEXT:    li r11, 288
-; CHECK-NEXT:    std r25, 520(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r25, 696(r1)
-; CHECK-NEXT:    stxvd2x v23, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 304
-; CHECK-NEXT:    std r26, 528(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r27, 536(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 544(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r28, 720(r1)
-; CHECK-NEXT:    lhz r27, 712(r1)
-; CHECK-NEXT:    lhz r26, 704(r1)
-; CHECK-NEXT:    stxvd2x v24, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 176(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 840(r1)
-; CHECK-NEXT:    li r11, 320
-; CHECK-NEXT:    std r29, 552(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r29, 728(r1)
-; CHECK-NEXT:    stxvd2x v25, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 152(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 832(r1)
-; CHECK-NEXT:    li r11, 336
-; CHECK-NEXT:    std r31, 568(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r31, 736(r1)
-; CHECK-NEXT:    stxvd2x v26, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 352
-; CHECK-NEXT:    std r15, 440(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r16, 448(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r17, 456(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r17, r6
-; CHECK-NEXT:    mr r16, r5
-; CHECK-NEXT:    stxvd2x v27, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 144(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 824(r1)
-; CHECK-NEXT:    li r11, 368
-; CHECK-NEXT:    std r18, 464(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r20, 480(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r20, r8
-; CHECK-NEXT:    mr r18, r7
-; CHECK-NEXT:    stxvd2x v28, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 120(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 816(r1)
-; CHECK-NEXT:    li r11, 384
-; CHECK-NEXT:    std r21, 488(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r24, 512(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r24, r10
-; CHECK-NEXT:    mr r21, r9
-; CHECK-NEXT:    stxvd2x v29, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 400
-; CHECK-NEXT:    std r3, 112(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 808(r1)
-; CHECK-NEXT:    stxvd2x v30, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 416
-; CHECK-NEXT:    std r3, 104(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 800(r1)
-; CHECK-NEXT:    stxvd2x v31, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 96(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 792(r1)
-; CHECK-NEXT:    std r3, 88(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f21, 408(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f20, 400(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    li r4, 128
 ; CHECK-NEXT:    lhz r3, 784(r1)
-; CHECK-NEXT:    std r3, 80(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f19, 392(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f18, 384(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    mtfprwz f21, r3
+; CHECK-NEXT:    stxvd2x v20, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 144
+; CHECK-NEXT:    stfd f17, 376(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v21, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 160
+; CHECK-NEXT:    stfd f16, 368(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f15, 360(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f14, 352(r1) # 8-byte Folded Spill
 ; CHECK-NEXT:    lhz r3, 776(r1)
-; CHECK-NEXT:    std r3, 72(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v22, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 176
+; CHECK-NEXT:    std r29, 328(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f22, 416(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f23, 424(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f23, f4
+; CHECK-NEXT:    fmr f22, f3
+; CHECK-NEXT:    mtfprwz f20, r3
+; CHECK-NEXT:    stxvd2x v23, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 192
+; CHECK-NEXT:    stxvd2x v24, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 208
+; CHECK-NEXT:    stfd f24, 432(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f25, 440(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f26, 448(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f27, 456(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f27, f8
+; CHECK-NEXT:    fmr f26, f7
+; CHECK-NEXT:    fmr f25, f6
+; CHECK-NEXT:    fmr f24, f5
 ; CHECK-NEXT:    lhz r3, 768(r1)
-; CHECK-NEXT:    std r3, 64(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v25, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 224
+; CHECK-NEXT:    stfd f28, 464(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 472(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, 480(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f30, f11
+; CHECK-NEXT:    fmr f29, f10
+; CHECK-NEXT:    fmr f28, f9
+; CHECK-NEXT:    xxlor v25, f2, f2
+; CHECK-NEXT:    stfd f31, 488(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v26, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 240
+; CHECK-NEXT:    xxlor v26, f13, f13
+; CHECK-NEXT:    mtfprwz f19, r3
+; CHECK-NEXT:    stxvd2x v27, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 256
 ; CHECK-NEXT:    lhz r3, 760(r1)
-; CHECK-NEXT:    std r3, 56(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v28, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 272
+; CHECK-NEXT:    mtfprwz f18, r3
+; CHECK-NEXT:    stxvd2x v29, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 288
 ; CHECK-NEXT:    lhz r3, 752(r1)
-; CHECK-NEXT:    std r3, 48(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    clrldi r3, r4, 48
+; CHECK-NEXT:    stxvd2x v30, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 304
+; CHECK-NEXT:    stxvd2x v31, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 120
+; CHECK-NEXT:    mtfprwz f17, r3
+; CHECK-NEXT:    stxsdx f12, r1, r4 # 8-byte Folded Spill
+; CHECK-NEXT:    lhz r3, 744(r1)
+; CHECK-NEXT:    mtfprwz f16, r3
+; CHECK-NEXT:    lhz r3, 736(r1)
+; CHECK-NEXT:    mtfprwz f15, r3
+; CHECK-NEXT:    lhz r3, 728(r1)
+; CHECK-NEXT:    mtfprwz f14, r3
+; CHECK-NEXT:    lhz r3, 720(r1)
+; CHECK-NEXT:    mtvsrwz v31, r3
+; CHECK-NEXT:    lhz r3, 712(r1)
+; CHECK-NEXT:    mtvsrwz v30, r3
+; CHECK-NEXT:    lhz r3, 704(r1)
+; CHECK-NEXT:    mtvsrwz v29, r3
+; CHECK-NEXT:    lhz r3, 696(r1)
+; CHECK-NEXT:    mtvsrwz v28, r3
+; CHECK-NEXT:    lhz r3, 688(r1)
+; CHECK-NEXT:    mtvsrwz v27, r3
+; CHECK-NEXT:    lhz r3, 680(r1)
+; CHECK-NEXT:    mtvsrwz v24, r3
+; CHECK-NEXT:    lhz r3, 672(r1)
+; CHECK-NEXT:    mtvsrwz v23, r3
+; CHECK-NEXT:    lhz r3, 664(r1)
+; CHECK-NEXT:    mtvsrwz v22, r3
+; CHECK-NEXT:    lhz r3, 656(r1)
+; CHECK-NEXT:    mtvsrwz v21, r3
+; CHECK-NEXT:    lhz r3, 648(r1)
+; CHECK-NEXT:    mtvsrwz v20, r3
+; CHECK-NEXT:    lhz r3, 640(r1)
+; CHECK-NEXT:    mtfprwz f31, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r15, r3
-; CHECK-NEXT:    clrldi r3, r16, 48
+; CHECK-NEXT:    xxlor f1, v25, v25
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r15
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 224
-; CHECK-NEXT:    xxmrghd vs0, vs0, v31
+; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    xxlor f1, v26, v26
+; CHECK-NEXT:    xxmrghd vs0, vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    clrldi r3, r17, 48
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r17, r3
-; CHECK-NEXT:    clrldi r3, r18, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r17
+; CHECK-NEXT:    mtvsrd v26, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 192
-; CHECK-NEXT:    xxmrghd vs0, vs0, v31
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    xxlor f1, v20, v20
+; CHECK-NEXT:    xxmrghd vs0, vs0, v26
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    clrldi r3, r20, 48
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r20, r3
-; CHECK-NEXT:    clrldi r3, r21, 48
+; CHECK-NEXT:    xxlor f1, v21, v21
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r20
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 160
-; CHECK-NEXT:    xxmrghd vs0, vs0, v31
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    xxlor f1, v22, v22
+; CHECK-NEXT:    xxmrghd vs0, vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    mr r3, r19
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r21, r3
-; CHECK-NEXT:    clrldi r3, r24, 48
+; CHECK-NEXT:    xxlor f1, v23, v23
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r21
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 128
-; CHECK-NEXT:    xxmrghd vs0, v31, vs0
+; CHECK-NEXT:    li r3, 48
+; CHECK-NEXT:    xxlor f1, v24, v24
+; CHECK-NEXT:    xxmrghd vs0, vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    mr r3, r22
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r24, r3
-; CHECK-NEXT:    mr r3, r23
+; CHECK-NEXT:    xxlor f1, v27, v27
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r24
+; CHECK-NEXT:    mtvsrd v27, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r25
-; CHECK-NEXT:    xxmrghd v27, vs0, v31
+; CHECK-NEXT:    xxlor f1, v28, v28
+; CHECK-NEXT:    xxmrghd v27, vs0, v27
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r25, r3
-; CHECK-NEXT:    mr r3, r26
+; CHECK-NEXT:    xxlor f1, v29, v29
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r25
+; CHECK-NEXT:    mtvsrd v29, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r27
-; CHECK-NEXT:    xxmrghd v26, vs0, v31
+; CHECK-NEXT:    xxlor f1, v30, v30
+; CHECK-NEXT:    xxmrghd v29, vs0, v29
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    mr r3, r28
+; CHECK-NEXT:    xxlor f1, v31, v31
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r27
+; CHECK-NEXT:    mtvsrd v31, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f14
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r29
-; CHECK-NEXT:    xxmrghd v25, vs0, v31
+; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f15
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    mr r3, r31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v30, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f16
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r14
-; CHECK-NEXT:    xxmrghd v24, vs0, v31
+; CHECK-NEXT:    xxmrghd v30, vs0, v30
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f17
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 48(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v28, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f18
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 56(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v23, vs0, v31
+; CHECK-NEXT:    xxmrghd v28, vs0, v28
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f19
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 64(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f20
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 72(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v22, vs0, v31
+; CHECK-NEXT:    xxmrghd v24, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f21
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 80(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f22
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 88(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v21, vs0, v31
+; CHECK-NEXT:    xxmrghd v22, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f23
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 96(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f24
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 104(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v20, vs0, v31
+; CHECK-NEXT:    xxmrghd v20, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f25
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 112(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f26
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 120(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v31, vs0, v31
+; CHECK-NEXT:    xxmrghd v25, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f27
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 144(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r29
+; CHECK-NEXT:    mtvsrd v26, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f28
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 152(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v30, vs0, v30
+; CHECK-NEXT:    xxmrghd v26, vs0, v26
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f29
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 176(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v29, r29
+; CHECK-NEXT:    mtvsrd v21, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 184(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v29, vs0, v29
+; CHECK-NEXT:    xxmrghd v21, vs0, v21
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 216(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    li r3, 120
+; CHECK-NEXT:    lxsdx f1, r1, r3 # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v28, r29
+; CHECK-NEXT:    mtvsrd v23, r29
 ; CHECK-NEXT:    bl llrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 240
-; CHECK-NEXT:    xxswapd vs1, v29
-; CHECK-NEXT:    li r4, 128
-; CHECK-NEXT:    xxswapd vs2, v30
-; CHECK-NEXT:    xxswapd vs3, v25
-; CHECK-NEXT:    xxmrghd v2, vs0, v28
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    xxswapd vs1, v21
+; CHECK-NEXT:    li r4, 48
+; CHECK-NEXT:    xxswapd vs2, v26
+; CHECK-NEXT:    xxswapd vs3, v31
+; CHECK-NEXT:    xxmrghd v2, vs0, v23
 ; CHECK-NEXT:    xxswapd vs0, v2
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 224
+; CHECK-NEXT:    li r3, 64
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 208
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    stxvd2x vs2, r30, r3
-; CHECK-NEXT:    li r3, 192
-; CHECK-NEXT:    xxswapd vs0, v31
+; CHECK-NEXT:    li r3, 32
+; CHECK-NEXT:    xxswapd vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 176
+; CHECK-NEXT:    li r3, 16
 ; CHECK-NEXT:    xxswapd vs1, v20
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 160
-; CHECK-NEXT:    xxswapd vs2, v23
-; CHECK-NEXT:    xxswapd vs0, v21
+; CHECK-NEXT:    li r3, 240
+; CHECK-NEXT:    xxswapd vs2, v28
+; CHECK-NEXT:    xxswapd vs0, v22
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 144
-; CHECK-NEXT:    xxswapd vs1, v22
+; CHECK-NEXT:    li r3, 224
+; CHECK-NEXT:    xxswapd vs1, v24
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 128
+; CHECK-NEXT:    li r3, 208
 ; CHECK-NEXT:    stxvd2x vs2, r30, r3
-; CHECK-NEXT:    li r3, 112
-; CHECK-NEXT:    xxswapd vs0, v24
+; CHECK-NEXT:    li r3, 192
+; CHECK-NEXT:    xxswapd vs0, v30
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    li r3, 176
 ; CHECK-NEXT:    stxvd2x vs3, r30, r3
-; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    li r3, 160
 ; CHECK-NEXT:    lxvd2x vs2, r1, r4 # 16-byte Folded Reload
-; CHECK-NEXT:    li r4, 160
-; CHECK-NEXT:    xxswapd vs1, v26
+; CHECK-NEXT:    li r4, 64
+; CHECK-NEXT:    xxswapd vs1, v29
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    li r3, 144
 ; CHECK-NEXT:    lxvd2x vs1, r1, r4 # 16-byte Folded Reload
-; CHECK-NEXT:    li r4, 192
+; CHECK-NEXT:    li r4, 80
 ; CHECK-NEXT:    lxvd2x vs3, r1, r4 # 16-byte Folded Reload
-; CHECK-NEXT:    li r4, 224
+; CHECK-NEXT:    li r4, 96
 ; CHECK-NEXT:    lxvd2x vs4, r1, r4 # 16-byte Folded Reload
 ; CHECK-NEXT:    xxswapd vs0, v27
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 48
+; CHECK-NEXT:    li r3, 128
 ; CHECK-NEXT:    xxswapd vs2, vs2
 ; CHECK-NEXT:    stxvd2x vs2, r30, r3
-; CHECK-NEXT:    li r3, 32
+; CHECK-NEXT:    li r3, 112
 ; CHECK-NEXT:    xxswapd vs1, vs1
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 16
+; CHECK-NEXT:    li r3, 96
 ; CHECK-NEXT:    xxswapd vs3, vs3
 ; CHECK-NEXT:    stxvd2x vs3, r30, r3
-; CHECK-NEXT:    li r3, 416
+; CHECK-NEXT:    li r3, 304
 ; CHECK-NEXT:    xxswapd vs4, vs4
 ; CHECK-NEXT:    stxvd2x vs4, 0, r30
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 400
-; CHECK-NEXT:    ld r31, 568(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r30, 560(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, 552(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 544(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r27, 536(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r26, 528(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r25, 520(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r24, 512(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r23, 504(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r22, 496(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r21, 488(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r20, 480(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r19, 472(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r18, 464(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r17, 456(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r16, 448(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    li r3, 288
+; CHECK-NEXT:    lfd f31, 488(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, 480(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 472(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f28, 464(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f27, 456(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f26, 448(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f25, 440(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f24, 432(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f23, 424(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f22, 416(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f21, 408(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f20, 400(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f19, 392(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f18, 384(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f17, 376(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f16, 368(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v30, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 384
-; CHECK-NEXT:    ld r15, 440(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r14, 432(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    li r3, 272
+; CHECK-NEXT:    lfd f15, 360(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f14, 352(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 336(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r29, 328(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v29, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 368
+; CHECK-NEXT:    li r3, 256
 ; CHECK-NEXT:    lxvd2x v28, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 352
+; CHECK-NEXT:    li r3, 240
 ; CHECK-NEXT:    lxvd2x v27, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 336
+; CHECK-NEXT:    li r3, 224
 ; CHECK-NEXT:    lxvd2x v26, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 320
+; CHECK-NEXT:    li r3, 208
 ; CHECK-NEXT:    lxvd2x v25, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 304
+; CHECK-NEXT:    li r3, 192
 ; CHECK-NEXT:    lxvd2x v24, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 288
+; CHECK-NEXT:    li r3, 176
 ; CHECK-NEXT:    lxvd2x v23, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 272
+; CHECK-NEXT:    li r3, 160
 ; CHECK-NEXT:    lxvd2x v22, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 256
+; CHECK-NEXT:    li r3, 144
 ; CHECK-NEXT:    lxvd2x v21, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 240
+; CHECK-NEXT:    li r3, 128
 ; CHECK-NEXT:    lxvd2x v20, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    addi r1, r1, 576
+; CHECK-NEXT:    addi r1, r1, 496
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/vector-lrint.ll b/llvm/test/CodeGen/PowerPC/vector-lrint.ll
index 254d61d3c21fc..0065e84da6a06 100644
--- a/llvm/test/CodeGen/PowerPC/vector-lrint.ll
+++ b/llvm/test/CodeGen/PowerPC/vector-lrint.ll
@@ -40,7 +40,6 @@ define <1 x i64> @lrint_v1f16(<1 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -32(r1)
-; CHECK-NEXT:    clrldi r3, r3, 48
 ; CHECK-NEXT:    std r0, 48(r1)
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
@@ -87,28 +86,27 @@ define <2 x i64> @lrint_v2f16(<2 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -96(r1)
-; CHECK-NEXT:    li r5, 48
-; CHECK-NEXT:    clrldi r3, r3, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 112(r1)
-; CHECK-NEXT:    std r29, 72(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r30, 80(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r4
-; CHECK-NEXT:    stxvd2x v31, r1, r5 # 16-byte Folded Spill
+; CHECK-NEXT:    std r30, 72(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f31, 88(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f31, f2
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 48
-; CHECK-NEXT:    ld r30, 80(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, 72(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, 88(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 72(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    xxmrghd v2, vs0, v31
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    addi r1, r1, 96
@@ -172,51 +170,50 @@ define <4 x i64> @lrint_v4f16(<4 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -128(r1)
-; CHECK-NEXT:    li r7, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 144(r1)
-; CHECK-NEXT:    clrldi r3, r3, 48
-; CHECK-NEXT:    std r27, 88(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 96(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r29, 104(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r29, r5
-; CHECK-NEXT:    mr r28, r4
-; CHECK-NEXT:    stxvd2x v30, r1, r7 # 16-byte Folded Spill
-; CHECK-NEXT:    li r7, 64
-; CHECK-NEXT:    std r30, 112(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r6
-; CHECK-NEXT:    stxvd2x v31, r1, r7 # 16-byte Folded Spill
+; CHECK-NEXT:    std r30, 88(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 104(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, 112(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f30, f3
+; CHECK-NEXT:    fmr f29, f2
+; CHECK-NEXT:    stfd f31, 120(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v30, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    fmr f31, f4
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    clrldi r3, r28, 48
+; CHECK-NEXT:    fmr f1, f29
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r27
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r29, 48
 ; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r29
+; CHECK-NEXT:    mtvsrd v30, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 64
 ; CHECK-NEXT:    vmr v2, v31
-; CHECK-NEXT:    ld r30, 112(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, 104(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 96(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r27, 88(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, 120(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, 112(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 104(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 88(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    xxmrghd v3, vs0, v30
@@ -322,99 +319,98 @@ define <8 x i64> @lrint_v8f16(<8 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -192(r1)
-; CHECK-NEXT:    li r11, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 208(r1)
-; CHECK-NEXT:    clrldi r3, r3, 48
-; CHECK-NEXT:    std r23, 120(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r24, 128(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r25, 136(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r25, r5
-; CHECK-NEXT:    mr r24, r4
-; CHECK-NEXT:    stxvd2x v28, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 64
-; CHECK-NEXT:    std r26, 144(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r26, r6
-; CHECK-NEXT:    std r27, 152(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 160(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r28, r8
-; CHECK-NEXT:    mr r27, r7
-; CHECK-NEXT:    stxvd2x v29, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 80
-; CHECK-NEXT:    std r29, 168(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r29, r9
-; CHECK-NEXT:    std r30, 176(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r10
-; CHECK-NEXT:    stxvd2x v30, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 96
-; CHECK-NEXT:    stxvd2x v31, r1, r11 # 16-byte Folded Spill
+; CHECK-NEXT:    std r30, 120(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f25, 136(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f26, 144(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f26, f3
+; CHECK-NEXT:    fmr f25, f2
+; CHECK-NEXT:    stfd f27, 152(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v28, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    fmr f27, f4
+; CHECK-NEXT:    stfd f28, 160(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 168(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f29, f6
+; CHECK-NEXT:    fmr f28, f5
+; CHECK-NEXT:    stfd f30, 176(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v29, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    fmr f30, f7
+; CHECK-NEXT:    stfd f31, 184(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f31, f8
+; CHECK-NEXT:    stxvd2x v30, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r23, r3
-; CHECK-NEXT:    clrldi r3, r24, 48
+; CHECK-NEXT:    fmr f1, f25
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r23
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f26
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r25, 48
 ; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r25, r3
-; CHECK-NEXT:    clrldi r3, r26, 48
+; CHECK-NEXT:    fmr f1, f27
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r25
+; CHECK-NEXT:    mtvsrd v30, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f28
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r27, 48
 ; CHECK-NEXT:    xxmrghd v30, vs0, v30
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    clrldi r3, r28, 48
+; CHECK-NEXT:    fmr f1, f29
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v29, r27
+; CHECK-NEXT:    mtvsrd v29, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r29, 48
 ; CHECK-NEXT:    xxmrghd v29, vs0, v29
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v28, r29
+; CHECK-NEXT:    mtvsrd v28, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 96
 ; CHECK-NEXT:    vmr v2, v31
-; CHECK-NEXT:    ld r30, 176(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f31, 184(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    vmr v3, v30
 ; CHECK-NEXT:    vmr v4, v29
-; CHECK-NEXT:    ld r29, 168(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 160(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, 176(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 168(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 80
-; CHECK-NEXT:    ld r27, 152(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r26, 144(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r25, 136(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r24, 128(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r23, 120(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f28, 160(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f27, 152(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f26, 144(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f25, 136(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 120(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v30, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 64
 ; CHECK-NEXT:    lxvd2x v29, r1, r3 # 16-byte Folded Reload
@@ -602,196 +598,198 @@ define <16 x i64> @lrint_v16i64_v16f16(<16 x half> %x) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
 ; CHECK-NEXT:    stdu r1, -320(r1)
-; CHECK-NEXT:    li r11, 48
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    std r0, 336(r1)
-; CHECK-NEXT:    std r23, 248(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r23, r3
-; CHECK-NEXT:    lhz r3, 416(r1)
-; CHECK-NEXT:    std r16, 192(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r17, 200(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r17, 432(r1)
-; CHECK-NEXT:    stxvd2x v24, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 64
-; CHECK-NEXT:    std r18, 208(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r18, 440(r1)
-; CHECK-NEXT:    std r19, 216(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r19, 448(r1)
-; CHECK-NEXT:    lhz r16, 424(r1)
-; CHECK-NEXT:    stxvd2x v25, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 80
-; CHECK-NEXT:    std r20, 224(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r20, 456(r1)
-; CHECK-NEXT:    stxvd2x v26, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 96
-; CHECK-NEXT:    std r21, 232(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r22, 240(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r22, 472(r1)
-; CHECK-NEXT:    lhz r21, 464(r1)
-; CHECK-NEXT:    stxvd2x v27, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 112
-; CHECK-NEXT:    std r15, 184(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r24, 256(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r25, 264(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r25, r5
-; CHECK-NEXT:    mr r24, r4
-; CHECK-NEXT:    stxvd2x v28, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 128
-; CHECK-NEXT:    std r26, 272(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r27, 280(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 288(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r29, 296(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r29, r9
-; CHECK-NEXT:    mr r28, r8
-; CHECK-NEXT:    mr r27, r7
-; CHECK-NEXT:    mr r26, r6
-; CHECK-NEXT:    stxvd2x v29, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 144
-; CHECK-NEXT:    std r30, 304(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r30, r10
-; CHECK-NEXT:    stxvd2x v30, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 160
-; CHECK-NEXT:    stxvd2x v31, r1, r11 # 16-byte Folded Spill
+; CHECK-NEXT:    stfd f31, 312(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, 304(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    std r30, 184(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f17, 200(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f17, f2
+; CHECK-NEXT:    stfd f18, 208(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f18, f3
+; CHECK-NEXT:    stxvd2x v24, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    stfd f19, 216(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f19, f4
+; CHECK-NEXT:    stfd f20, 224(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f20, f5
+; CHECK-NEXT:    stfd f21, 232(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f21, f6
+; CHECK-NEXT:    stxvd2x v25, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    stfd f22, 240(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f22, f7
+; CHECK-NEXT:    stfd f23, 248(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f23, f8
+; CHECK-NEXT:    stfd f24, 256(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f24, f9
+; CHECK-NEXT:    stxvd2x v26, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    stfd f25, 264(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f25, f10
+; CHECK-NEXT:    stfd f26, 272(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f26, f11
+; CHECK-NEXT:    stfd f27, 280(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f27, f12
+; CHECK-NEXT:    stxvd2x v27, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 112
+; CHECK-NEXT:    stfd f28, 288(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 296(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f29, f13
+; CHECK-NEXT:    stxvd2x v28, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 128
+; CHECK-NEXT:    stxvd2x v29, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 144
+; CHECK-NEXT:    stxvd2x v30, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    li r3, 160
+; CHECK-NEXT:    stxvd2x v31, r1, r3 # 16-byte Folded Spill
+; CHECK-NEXT:    lhz r3, 472(r1)
+; CHECK-NEXT:    mtfprwz f31, r3
+; CHECK-NEXT:    lhz r3, 464(r1)
+; CHECK-NEXT:    mtfprwz f30, r3
+; CHECK-NEXT:    lhz r3, 456(r1)
+; CHECK-NEXT:    mtfprwz f28, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r15, r3
-; CHECK-NEXT:    mr r3, r16
+; CHECK-NEXT:    fmr f1, f17
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r15
+; CHECK-NEXT:    mtvsrd v31, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f18
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r17
 ; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r17, r3
-; CHECK-NEXT:    mr r3, r18
+; CHECK-NEXT:    fmr f1, f19
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r17
+; CHECK-NEXT:    mtvsrd v30, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f20
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r19
 ; CHECK-NEXT:    xxmrghd v30, vs0, v30
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r19, r3
-; CHECK-NEXT:    mr r3, r20
+; CHECK-NEXT:    fmr f1, f21
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v29, r19
+; CHECK-NEXT:    mtvsrd v29, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f22
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r21
 ; CHECK-NEXT:    xxmrghd v29, vs0, v29
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r21, r3
-; CHECK-NEXT:    mr r3, r22
+; CHECK-NEXT:    fmr f1, f23
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v28, r21
+; CHECK-NEXT:    mtvsrd v28, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f24
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r23, 48
 ; CHECK-NEXT:    xxmrghd v28, vs0, v28
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r23, r3
-; CHECK-NEXT:    clrldi r3, r24, 48
+; CHECK-NEXT:    fmr f1, f25
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v27, r23
+; CHECK-NEXT:    mtvsrd v27, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f26
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r25, 48
 ; CHECK-NEXT:    xxmrghd v27, vs0, v27
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r25, r3
-; CHECK-NEXT:    clrldi r3, r26, 48
+; CHECK-NEXT:    fmr f1, f27
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v26, r25
+; CHECK-NEXT:    mtvsrd v26, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f29
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r27, 48
 ; CHECK-NEXT:    xxmrghd v26, vs0, v26
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    clrldi r3, r28, 48
+; CHECK-NEXT:    fmr f1, f28
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v25, r27
+; CHECK-NEXT:    mtvsrd v25, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    clrldi r3, r29, 48
 ; CHECK-NEXT:    xxmrghd v25, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    clrldi r3, r30, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r30, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v24, r29
+; CHECK-NEXT:    mtvsrd v24, r30
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
 ; CHECK-NEXT:    li r3, 160
-; CHECK-NEXT:    vmr v6, v31
-; CHECK-NEXT:    ld r30, 304(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    vmr v7, v30
-; CHECK-NEXT:    vmr v8, v29
-; CHECK-NEXT:    ld r29, 296(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 288(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    vmr v2, v31
+; CHECK-NEXT:    lfd f31, 312(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    vmr v3, v30
+; CHECK-NEXT:    vmr v4, v29
+; CHECK-NEXT:    lfd f30, 304(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 296(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 144
-; CHECK-NEXT:    vmr v9, v28
-; CHECK-NEXT:    vmr v2, v27
-; CHECK-NEXT:    vmr v3, v26
-; CHECK-NEXT:    vmr v4, v25
-; CHECK-NEXT:    ld r27, 280(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r26, 272(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    vmr v5, v28
+; CHECK-NEXT:    vmr v6, v27
+; CHECK-NEXT:    vmr v7, v26
+; CHECK-NEXT:    vmr v8, v25
+; CHECK-NEXT:    lfd f28, 288(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f27, 280(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v30, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 128
-; CHECK-NEXT:    ld r25, 264(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r24, 256(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v5, vs0, v24
-; CHECK-NEXT:    ld r23, 248(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r22, 240(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r21, 232(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f26, 272(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f25, 264(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    xxmrghd v9, vs0, v24
+; CHECK-NEXT:    lfd f24, 256(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f23, 248(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f22, 240(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v29, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 112
-; CHECK-NEXT:    ld r20, 224(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r19, 216(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r18, 208(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r17, 200(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r16, 192(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r15, 184(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f21, 232(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 184(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f20, 224(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f19, 216(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f18, 208(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f17, 200(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v28, r1, r3 # 16-byte Folded Reload
 ; CHECK-NEXT:    li r3, 96
 ; CHECK-NEXT:    lxvd2x v27, r1, r3 # 16-byte Folded Reload
@@ -1161,427 +1159,436 @@ define <32 x i64> @lrint_v32i64_v32f16(<32 x half> %x) nounwind {
 ; CHECK-LABEL: lrint_v32i64_v32f16:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    mflr r0
-; CHECK-NEXT:    stdu r1, -576(r1)
-; CHECK-NEXT:    std r0, 592(r1)
-; CHECK-NEXT:    std r30, 560(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stdu r1, -496(r1)
+; CHECK-NEXT:    std r0, 512(r1)
+; CHECK-NEXT:    std r30, 336(r1) # 8-byte Folded Spill
 ; CHECK-NEXT:    mr r30, r3
-; CHECK-NEXT:    lhz r3, 864(r1)
-; CHECK-NEXT:    li r11, 240
-; CHECK-NEXT:    std r14, 432(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r19, 472(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r14, 744(r1)
-; CHECK-NEXT:    stxvd2x v20, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 256
-; CHECK-NEXT:    std r22, 496(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r22, 680(r1)
-; CHECK-NEXT:    std r3, 216(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 856(r1)
-; CHECK-NEXT:    lhz r19, 672(r1)
-; CHECK-NEXT:    stxvd2x v21, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 272
-; CHECK-NEXT:    std r23, 504(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r23, 688(r1)
-; CHECK-NEXT:    stxvd2x v22, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 184(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 848(r1)
-; CHECK-NEXT:    li r11, 288
-; CHECK-NEXT:    std r25, 520(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r25, 696(r1)
-; CHECK-NEXT:    stxvd2x v23, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 304
-; CHECK-NEXT:    std r26, 528(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r27, 536(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r28, 544(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r28, 720(r1)
-; CHECK-NEXT:    lhz r27, 712(r1)
-; CHECK-NEXT:    lhz r26, 704(r1)
-; CHECK-NEXT:    stxvd2x v24, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 176(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 840(r1)
-; CHECK-NEXT:    li r11, 320
-; CHECK-NEXT:    std r29, 552(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r29, 728(r1)
-; CHECK-NEXT:    stxvd2x v25, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 152(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 832(r1)
-; CHECK-NEXT:    li r11, 336
-; CHECK-NEXT:    std r31, 568(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r31, 736(r1)
-; CHECK-NEXT:    stxvd2x v26, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 352
-; CHECK-NEXT:    std r15, 440(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r16, 448(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r17, 456(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r17, r6
-; CHECK-NEXT:    mr r16, r5
-; CHECK-NEXT:    stxvd2x v27, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 144(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 824(r1)
-; CHECK-NEXT:    li r11, 368
-; CHECK-NEXT:    std r18, 464(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r20, 480(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r20, r8
-; CHECK-NEXT:    mr r18, r7
-; CHECK-NEXT:    stxvd2x v28, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 120(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 816(r1)
-; CHECK-NEXT:    li r11, 384
-; CHECK-NEXT:    std r21, 488(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    std r24, 512(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    mr r24, r10
-; CHECK-NEXT:    mr r21, r9
-; CHECK-NEXT:    stxvd2x v29, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 400
-; CHECK-NEXT:    std r3, 112(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 808(r1)
-; CHECK-NEXT:    stxvd2x v30, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    li r11, 416
-; CHECK-NEXT:    std r3, 104(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 800(r1)
-; CHECK-NEXT:    stxvd2x v31, r1, r11 # 16-byte Folded Spill
-; CHECK-NEXT:    std r3, 96(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    lhz r3, 792(r1)
-; CHECK-NEXT:    std r3, 88(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f21, 408(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f20, 400(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    li r4, 128
 ; CHECK-NEXT:    lhz r3, 784(r1)
-; CHECK-NEXT:    std r3, 80(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f19, 392(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f18, 384(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    mtfprwz f21, r3
+; CHECK-NEXT:    stxvd2x v20, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 144
+; CHECK-NEXT:    stfd f17, 376(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v21, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 160
+; CHECK-NEXT:    stfd f16, 368(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f15, 360(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f14, 352(r1) # 8-byte Folded Spill
 ; CHECK-NEXT:    lhz r3, 776(r1)
-; CHECK-NEXT:    std r3, 72(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v22, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 176
+; CHECK-NEXT:    std r29, 328(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f22, 416(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f23, 424(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f23, f4
+; CHECK-NEXT:    fmr f22, f3
+; CHECK-NEXT:    mtfprwz f20, r3
+; CHECK-NEXT:    stxvd2x v23, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 192
+; CHECK-NEXT:    stxvd2x v24, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 208
+; CHECK-NEXT:    stfd f24, 432(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f25, 440(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f26, 448(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f27, 456(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f27, f8
+; CHECK-NEXT:    fmr f26, f7
+; CHECK-NEXT:    fmr f25, f6
+; CHECK-NEXT:    fmr f24, f5
 ; CHECK-NEXT:    lhz r3, 768(r1)
-; CHECK-NEXT:    std r3, 64(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v25, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 224
+; CHECK-NEXT:    stfd f28, 464(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f29, 472(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stfd f30, 480(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    fmr f30, f11
+; CHECK-NEXT:    fmr f29, f10
+; CHECK-NEXT:    fmr f28, f9
+; CHECK-NEXT:    xxlor v25, f2, f2
+; CHECK-NEXT:    stfd f31, 488(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v26, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 240
+; CHECK-NEXT:    xxlor v26, f13, f13
+; CHECK-NEXT:    mtfprwz f19, r3
+; CHECK-NEXT:    stxvd2x v27, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 256
 ; CHECK-NEXT:    lhz r3, 760(r1)
-; CHECK-NEXT:    std r3, 56(r1) # 8-byte Folded Spill
+; CHECK-NEXT:    stxvd2x v28, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 272
+; CHECK-NEXT:    mtfprwz f18, r3
+; CHECK-NEXT:    stxvd2x v29, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 288
 ; CHECK-NEXT:    lhz r3, 752(r1)
-; CHECK-NEXT:    std r3, 48(r1) # 8-byte Folded Spill
-; CHECK-NEXT:    clrldi r3, r4, 48
+; CHECK-NEXT:    stxvd2x v30, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 304
+; CHECK-NEXT:    stxvd2x v31, r1, r4 # 16-byte Folded Spill
+; CHECK-NEXT:    li r4, 120
+; CHECK-NEXT:    mtfprwz f17, r3
+; CHECK-NEXT:    stxsdx f12, r1, r4 # 8-byte Folded Spill
+; CHECK-NEXT:    lhz r3, 744(r1)
+; CHECK-NEXT:    mtfprwz f16, r3
+; CHECK-NEXT:    lhz r3, 736(r1)
+; CHECK-NEXT:    mtfprwz f15, r3
+; CHECK-NEXT:    lhz r3, 728(r1)
+; CHECK-NEXT:    mtfprwz f14, r3
+; CHECK-NEXT:    lhz r3, 720(r1)
+; CHECK-NEXT:    mtvsrwz v31, r3
+; CHECK-NEXT:    lhz r3, 712(r1)
+; CHECK-NEXT:    mtvsrwz v30, r3
+; CHECK-NEXT:    lhz r3, 704(r1)
+; CHECK-NEXT:    mtvsrwz v29, r3
+; CHECK-NEXT:    lhz r3, 696(r1)
+; CHECK-NEXT:    mtvsrwz v28, r3
+; CHECK-NEXT:    lhz r3, 688(r1)
+; CHECK-NEXT:    mtvsrwz v27, r3
+; CHECK-NEXT:    lhz r3, 680(r1)
+; CHECK-NEXT:    mtvsrwz v24, r3
+; CHECK-NEXT:    lhz r3, 672(r1)
+; CHECK-NEXT:    mtvsrwz v23, r3
+; CHECK-NEXT:    lhz r3, 664(r1)
+; CHECK-NEXT:    mtvsrwz v22, r3
+; CHECK-NEXT:    lhz r3, 656(r1)
+; CHECK-NEXT:    mtvsrwz v21, r3
+; CHECK-NEXT:    lhz r3, 648(r1)
+; CHECK-NEXT:    mtvsrwz v20, r3
+; CHECK-NEXT:    lhz r3, 640(r1)
+; CHECK-NEXT:    mtfprwz f31, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r15, r3
-; CHECK-NEXT:    clrldi r3, r16, 48
+; CHECK-NEXT:    xxlor f1, v25, v25
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r15
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 224
-; CHECK-NEXT:    xxmrghd vs0, vs0, v31
+; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    xxlor f1, v26, v26
+; CHECK-NEXT:    xxmrghd vs0, vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    clrldi r3, r17, 48
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r17, r3
-; CHECK-NEXT:    clrldi r3, r18, 48
+; CHECK-NEXT:    fmr f1, f31
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r17
+; CHECK-NEXT:    mtvsrd v26, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 192
-; CHECK-NEXT:    xxmrghd vs0, vs0, v31
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    xxlor f1, v20, v20
+; CHECK-NEXT:    xxmrghd vs0, vs0, v26
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    clrldi r3, r20, 48
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r20, r3
-; CHECK-NEXT:    clrldi r3, r21, 48
+; CHECK-NEXT:    xxlor f1, v21, v21
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r20
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 160
-; CHECK-NEXT:    xxmrghd vs0, vs0, v31
+; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    xxlor f1, v22, v22
+; CHECK-NEXT:    xxmrghd vs0, vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    mr r3, r19
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r21, r3
-; CHECK-NEXT:    clrldi r3, r24, 48
+; CHECK-NEXT:    xxlor f1, v23, v23
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r21
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 128
-; CHECK-NEXT:    xxmrghd vs0, v31, vs0
+; CHECK-NEXT:    li r3, 48
+; CHECK-NEXT:    xxlor f1, v24, v24
+; CHECK-NEXT:    xxmrghd vs0, vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r1, r3 # 16-byte Folded Spill
-; CHECK-NEXT:    mr r3, r22
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r24, r3
-; CHECK-NEXT:    mr r3, r23
+; CHECK-NEXT:    xxlor f1, v27, v27
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r24
+; CHECK-NEXT:    mtvsrd v27, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r25
-; CHECK-NEXT:    xxmrghd v27, vs0, v31
+; CHECK-NEXT:    xxlor f1, v28, v28
+; CHECK-NEXT:    xxmrghd v27, vs0, v27
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r25, r3
-; CHECK-NEXT:    mr r3, r26
+; CHECK-NEXT:    xxlor f1, v29, v29
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r25
+; CHECK-NEXT:    mtvsrd v29, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r27
-; CHECK-NEXT:    xxmrghd v26, vs0, v31
+; CHECK-NEXT:    xxlor f1, v30, v30
+; CHECK-NEXT:    xxmrghd v29, vs0, v29
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mr r27, r3
-; CHECK-NEXT:    mr r3, r28
+; CHECK-NEXT:    xxlor f1, v31, v31
+; CHECK-NEXT:    mr r29, r3
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r27
+; CHECK-NEXT:    mtvsrd v31, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f14
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r29
-; CHECK-NEXT:    xxmrghd v25, vs0, v31
+; CHECK-NEXT:    xxmrghd v31, vs0, v31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f15
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    mr r3, r31
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v30, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f16
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    mr r3, r14
-; CHECK-NEXT:    xxmrghd v24, vs0, v31
+; CHECK-NEXT:    xxmrghd v30, vs0, v30
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f17
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 48(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v28, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f18
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 56(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v23, vs0, v31
+; CHECK-NEXT:    xxmrghd v28, vs0, v28
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f19
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 64(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f20
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 72(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v22, vs0, v31
+; CHECK-NEXT:    xxmrghd v24, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f21
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 80(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f22
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 88(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v21, vs0, v31
+; CHECK-NEXT:    xxmrghd v22, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f23
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 96(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f24
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 104(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v20, vs0, v31
+; CHECK-NEXT:    xxmrghd v20, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f25
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 112(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v31, r29
+; CHECK-NEXT:    mtvsrd v25, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f26
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 120(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v31, vs0, v31
+; CHECK-NEXT:    xxmrghd v25, vs0, v25
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f27
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 144(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v30, r29
+; CHECK-NEXT:    mtvsrd v26, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f28
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 152(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v30, vs0, v30
+; CHECK-NEXT:    xxmrghd v26, vs0, v26
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f29
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 176(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v29, r29
+; CHECK-NEXT:    mtvsrd v21, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
+; CHECK-NEXT:    fmr f1, f30
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    ld r3, 184(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    xxmrghd v29, vs0, v29
+; CHECK-NEXT:    xxmrghd v21, vs0, v21
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mr r29, r3
-; CHECK-NEXT:    ld r3, 216(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    li r3, 120
+; CHECK-NEXT:    lxsdx f1, r1, r3 # 8-byte Folded Reload
 ; CHECK-NEXT:    bl __extendhfsf2
 ; CHECK-NEXT:    nop
-; CHECK-NEXT:    mtvsrd v28, r29
+; CHECK-NEXT:    mtvsrd v23, r29
 ; CHECK-NEXT:    bl lrintf
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    mtfprd f0, r3
-; CHECK-NEXT:    li r3, 240
-; CHECK-NEXT:    xxswapd vs1, v29
-; CHECK-NEXT:    li r4, 128
-; CHECK-NEXT:    xxswapd vs2, v30
-; CHECK-NEXT:    xxswapd vs3, v25
-; CHECK-NEXT:    xxmrghd v2, vs0, v28
+; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    xxswapd vs1, v21
+; CHECK-NEXT:    li r4, 48
+; CHECK-NEXT:    xxswapd vs2, v26
+; CHECK-NEXT:    xxswapd vs3, v31
+; CHECK-NEXT:    xxmrghd v2, vs0, v23
 ; CHECK-NEXT:    xxswapd vs0, v2
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 224
+; CHECK-NEXT:    li r3, 64
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 208
+; CHECK-NEXT:    li r3, 48
 ; CHECK-NEXT:    stxvd2x vs2, r30, r3
-; CHECK-NEXT:    li r3, 192
-; CHECK-NEXT:    xxswapd vs0, v31
+; CHECK-NEXT:    li r3, 32
+; CHECK-NEXT:    xxswapd vs0, v25
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 176
+; CHECK-NEXT:    li r3, 16
 ; CHECK-NEXT:    xxswapd vs1, v20
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 160
-; CHECK-NEXT:    xxswapd vs2, v23
-; CHECK-NEXT:    xxswapd vs0, v21
+; CHECK-NEXT:    li r3, 240
+; CHECK-NEXT:    xxswapd vs2, v28
+; CHECK-NEXT:    xxswapd vs0, v22
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 144
-; CHECK-NEXT:    xxswapd vs1, v22
+; CHECK-NEXT:    li r3, 224
+; CHECK-NEXT:    xxswapd vs1, v24
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 128
+; CHECK-NEXT:    li r3, 208
 ; CHECK-NEXT:    stxvd2x vs2, r30, r3
-; CHECK-NEXT:    li r3, 112
-; CHECK-NEXT:    xxswapd vs0, v24
+; CHECK-NEXT:    li r3, 192
+; CHECK-NEXT:    xxswapd vs0, v30
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 96
+; CHECK-NEXT:    li r3, 176
 ; CHECK-NEXT:    stxvd2x vs3, r30, r3
-; CHECK-NEXT:    li r3, 80
+; CHECK-NEXT:    li r3, 160
 ; CHECK-NEXT:    lxvd2x vs2, r1, r4 # 16-byte Folded Reload
-; CHECK-NEXT:    li r4, 160
-; CHECK-NEXT:    xxswapd vs1, v26
+; CHECK-NEXT:    li r4, 64
+; CHECK-NEXT:    xxswapd vs1, v29
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 64
+; CHECK-NEXT:    li r3, 144
 ; CHECK-NEXT:    lxvd2x vs1, r1, r4 # 16-byte Folded Reload
-; CHECK-NEXT:    li r4, 192
+; CHECK-NEXT:    li r4, 80
 ; CHECK-NEXT:    lxvd2x vs3, r1, r4 # 16-byte Folded Reload
-; CHECK-NEXT:    li r4, 224
+; CHECK-NEXT:    li r4, 96
 ; CHECK-NEXT:    lxvd2x vs4, r1, r4 # 16-byte Folded Reload
 ; CHECK-NEXT:    xxswapd vs0, v27
 ; CHECK-NEXT:    stxvd2x vs0, r30, r3
-; CHECK-NEXT:    li r3, 48
+; CHECK-NEXT:    li r3, 128
 ; CHECK-NEXT:    xxswapd vs2, vs2
 ; CHECK-NEXT:    stxvd2x vs2, r30, r3
-; CHECK-NEXT:    li r3, 32
+; CHECK-NEXT:    li r3, 112
 ; CHECK-NEXT:    xxswapd vs1, vs1
 ; CHECK-NEXT:    stxvd2x vs1, r30, r3
-; CHECK-NEXT:    li r3, 16
+; CHECK-NEXT:    li r3, 96
 ; CHECK-NEXT:    xxswapd vs3, vs3
 ; CHECK-NEXT:    stxvd2x vs3, r30, r3
-; CHECK-NEXT:    li r3, 416
+; CHECK-NEXT:    li r3, 304
 ; CHECK-NEXT:    xxswapd vs4, vs4
 ; CHECK-NEXT:    stxvd2x vs4, 0, r30
 ; CHECK-NEXT:    lxvd2x v31, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 400
-; CHECK-NEXT:    ld r31, 568(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r30, 560(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r29, 552(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r28, 544(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r27, 536(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r26, 528(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r25, 520(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r24, 512(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r23, 504(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r22, 496(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r21, 488(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r20, 480(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r19, 472(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r18, 464(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r17, 456(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r16, 448(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    li r3, 288
+; CHECK-NEXT:    lfd f31, 488(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f30, 480(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f29, 472(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f28, 464(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f27, 456(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f26, 448(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f25, 440(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f24, 432(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f23, 424(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f22, 416(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f21, 408(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f20, 400(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f19, 392(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f18, 384(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f17, 376(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f16, 368(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v30, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 384
-; CHECK-NEXT:    ld r15, 440(r1) # 8-byte Folded Reload
-; CHECK-NEXT:    ld r14, 432(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    li r3, 272
+; CHECK-NEXT:    lfd f15, 360(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    lfd f14, 352(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r30, 336(r1) # 8-byte Folded Reload
+; CHECK-NEXT:    ld r29, 328(r1) # 8-byte Folded Reload
 ; CHECK-NEXT:    lxvd2x v29, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 368
+; CHECK-NEXT:    li r3, 256
 ; CHECK-NEXT:    lxvd2x v28, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 352
+; CHECK-NEXT:    li r3, 240
 ; CHECK-NEXT:    lxvd2x v27, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 336
+; CHECK-NEXT:    li r3, 224
 ; CHECK-NEXT:    lxvd2x v26, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 320
+; CHECK-NEXT:    li r3, 208
 ; CHECK-NEXT:    lxvd2x v25, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 304
+; CHECK-NEXT:    li r3, 192
 ; CHECK-NEXT:    lxvd2x v24, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 288
+; CHECK-NEXT:    li r3, 176
 ; CHECK-NEXT:    lxvd2x v23, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 272
+; CHECK-NEXT:    li r3, 160
 ; CHECK-NEXT:    lxvd2x v22, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 256
+; CHECK-NEXT:    li r3, 144
 ; CHECK-NEXT:    lxvd2x v21, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    li r3, 240
+; CHECK-NEXT:    li r3, 128
 ; CHECK-NEXT:    lxvd2x v20, r1, r3 # 16-byte Folded Reload
-; CHECK-NEXT:    addi r1, r1, 576
+; CHECK-NEXT:    addi r1, r1, 496
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr

>From 34f90bdf07087b92a90d90f8202e1f885fa00331 Mon Sep 17 00:00:00 2001
From: Tony Varghese <tony.varghese at ibm.com>
Date: Fri, 26 Jun 2026 21:49:29 +0530
Subject: [PATCH 4/8] [PowerPC] Fix f16 BR_CC promotion and update stale AIX
 TOC test checks.

- Add ISD::BR_CC to F16PromoteOps so half-precision branch conditions
  are promoted to f32 before reaching SelectCC in PPCISelDAGToDAG.
  Without this, fcmp+br on f16 operands crashed with an assertion in
  SelectCC which only handles f32/f64/f128 comparisons.

- Regenerate half-float16-ppc.ll: AIX TOC addressing for constant pool
  entries changed upstream from a single GP-relative ld (ld 3,L..C0(2))
  to an explicit hi/lo addis+ld pair; update the P8-AIX-64 CHECK lines.

- Regenerate soft-promote-half-br-cc.ll: with f16 arguments now arriving
  in FPRs (f1,f2) rather than GPRs (r3,r4) post ABI fix, update all
  CHECK patterns to reflect the FPR-based calling convention.
---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  6 +++-
 llvm/test/CodeGen/PowerPC/half-float16-ppc.ll | 24 ++++++++-----
 .../PowerPC/soft-promote-half-br-cc.ll        | 36 +++++++------------
 3 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 502155292b5e3..e37a7c2269cc2 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -284,7 +284,11 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
         ISD::FNEARBYINT, ISD::FROUND,   ISD::FROUNDEVEN,  ISD::FCANONICALIZE,
         ISD::FSIN,       ISD::FCOS,     ISD::SETCC,       ISD::SELECT_CC,
         ISD::SELECT,     ISD::FLDEXP,   ISD::FFREXP,      ISD::FMODF,
-        ISD::FATAN2,     ISD::FPOWI};
+        ISD::FATAN2,     ISD::FPOWI,
+        // BR_CC has f16 operands (the comparison inputs) but a chain result.
+        // Without explicit Promote, the f16 comparison reaches SelectCC in
+        // PPCISelDAGToDAG which only knows f32/f64/f128 and asserts.
+        ISD::BR_CC};
 
     // Promote all the arithmetic operations defined above to f32.
     setOperationAction(F16PromoteOps, MVT::f16, Promote);
diff --git a/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
index 7fb79d50f5a32..cbd67c6ed151b 100644
--- a/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
+++ b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
@@ -1877,7 +1877,8 @@ define half @test_minimum(half %a, half %b) nounwind {
 ; 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:    addis 3, L..C0 at u(2)
+; P8-AIX-64-NEXT:    ld 3, L..C0 at l(3)
 ; P8-AIX-64-NEXT:    lfs 1, 0(3)
 ; P8-AIX-64-NEXT:  L..BB19_3: # %entry
 ; P8-AIX-64-NEXT:    bl .__truncsfhf2[PR]
@@ -1916,7 +1917,8 @@ define half @test_minimum(half %a, half %b) nounwind {
 ; 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:    addis 3, L..C0 at u(2)
+; P9-AIX-64-NEXT:    ld 3, L..C0 at l(3)
 ; P9-AIX-64-NEXT:    lfs 0, 0(3)
 ; P9-AIX-64-NEXT:    xscvdphp 1, 0
 ; P9-AIX-64-NEXT:    blr
@@ -2029,7 +2031,8 @@ define half @test_maximum(half %a, half %b) nounwind {
 ; 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:    addis 3, L..C1 at u(2)
+; P8-AIX-64-NEXT:    ld 3, L..C1 at l(3)
 ; P8-AIX-64-NEXT:    lfs 1, 0(3)
 ; P8-AIX-64-NEXT:  L..BB20_3: # %entry
 ; P8-AIX-64-NEXT:    bl .__truncsfhf2[PR]
@@ -2068,7 +2071,8 @@ define half @test_maximum(half %a, half %b) nounwind {
 ; 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:    addis 3, L..C1 at u(2)
+; P9-AIX-64-NEXT:    ld 3, L..C1 at l(3)
 ; P9-AIX-64-NEXT:    lfs 0, 0(3)
 ; P9-AIX-64-NEXT:    xscvdphp 1, 0
 ; P9-AIX-64-NEXT:    blr
@@ -4106,7 +4110,8 @@ define half @test_constant_fp() nounwind {
 ;
 ; 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:    addis 3, L..C2 at u(2)
+; P8-AIX-64-NEXT:    ld 3, L..C2 at l(3)
 ; P8-AIX-64-NEXT:    lhzx 3, 0, 3
 ; P8-AIX-64-NEXT:    mtfprwz 1, 3
 ; P8-AIX-64-NEXT:    blr
@@ -4119,7 +4124,8 @@ define half @test_constant_fp() nounwind {
 ;
 ; 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:    addis 3, L..C2 at u(2)
+; P9-AIX-64-NEXT:    ld 3, L..C2 at l(3)
 ; P9-AIX-64-NEXT:    lxsihzx 1, 0, 3
 ; P9-AIX-64-NEXT:    blr
 ;
@@ -4150,7 +4156,8 @@ define half @test_constant_zero() nounwind {
 ;
 ; 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:    addis 3, L..C3 at u(2)
+; P8-AIX-64-NEXT:    ld 3, L..C3 at l(3)
 ; P8-AIX-64-NEXT:    lhzx 3, 0, 3
 ; P8-AIX-64-NEXT:    mtfprwz 1, 3
 ; P8-AIX-64-NEXT:    blr
@@ -4163,7 +4170,8 @@ define half @test_constant_zero() nounwind {
 ;
 ; 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:    addis 3, L..C3 at u(2)
+; P9-AIX-64-NEXT:    ld 3, L..C3 at l(3)
 ; P9-AIX-64-NEXT:    lxsihzx 1, 0, 3
 ; P9-AIX-64-NEXT:    blr
 ;
diff --git a/llvm/test/CodeGen/PowerPC/soft-promote-half-br-cc.ll b/llvm/test/CodeGen/PowerPC/soft-promote-half-br-cc.ll
index 2726e287f5df7..a390c4e00c152 100644
--- a/llvm/test/CodeGen/PowerPC/soft-promote-half-br-cc.ll
+++ b/llvm/test/CodeGen/PowerPC/soft-promote-half-br-cc.ll
@@ -8,11 +8,7 @@
 define i32 @test_br_cc_olt(half %a, half %b) nounwind {
 ; CHECK-P9-LABEL: test_br_cc_olt:
 ; CHECK-P9:       # %bb.0:
-; CHECK-P9-NEXT:    clrlwi 3, 3, 16
-; CHECK-P9-NEXT:    clrlwi 4, 4, 16
-; CHECK-P9-NEXT:    mtfprwz 0, 4
-; CHECK-P9-NEXT:    mtfprwz 1, 3
-; CHECK-P9-NEXT:    xscvhpdp 0, 0
+; CHECK-P9-NEXT:    xscvhpdp 0, 2
 ; CHECK-P9-NEXT:    xscvhpdp 1, 1
 ; CHECK-P9-NEXT:    fcmpu 0, 1, 0
 ; CHECK-P9-NEXT:    bge 0, .LBB0_2
@@ -26,19 +22,19 @@ define i32 @test_br_cc_olt(half %a, half %b) nounwind {
 ; CHECK-P8-LABEL: test_br_cc_olt:
 ; CHECK-P8:       # %bb.0:
 ; CHECK-P8-NEXT:    mflr 0
-; CHECK-P8-NEXT:    std 30, -24(1) # 8-byte Folded Spill
+; CHECK-P8-NEXT:    stfd 30, -16(1) # 8-byte Folded Spill
 ; CHECK-P8-NEXT:    stfd 31, -8(1) # 8-byte Folded Spill
-; CHECK-P8-NEXT:    stdu 1, -64(1)
-; CHECK-P8-NEXT:    mr 30, 3
-; CHECK-P8-NEXT:    clrldi 3, 4, 48
-; CHECK-P8-NEXT:    std 0, 80(1)
+; CHECK-P8-NEXT:    stdu 1, -48(1)
+; CHECK-P8-NEXT:    fmr 31, 1
+; CHECK-P8-NEXT:    fmr 1, 2
+; CHECK-P8-NEXT:    std 0, 64(1)
 ; CHECK-P8-NEXT:    bl __extendhfsf2
 ; CHECK-P8-NEXT:    nop
-; CHECK-P8-NEXT:    clrldi 3, 30, 48
-; CHECK-P8-NEXT:    fmr 31, 1
+; CHECK-P8-NEXT:    fmr 30, 1
+; CHECK-P8-NEXT:    fmr 1, 31
 ; CHECK-P8-NEXT:    bl __extendhfsf2
 ; CHECK-P8-NEXT:    nop
-; CHECK-P8-NEXT:    fcmpu 0, 1, 31
+; CHECK-P8-NEXT:    fcmpu 0, 1, 30
 ; CHECK-P8-NEXT:    bge 0, .LBB0_2
 ; CHECK-P8-NEXT:  # %bb.1: # %if.then
 ; CHECK-P8-NEXT:    li 3, 1
@@ -46,10 +42,10 @@ define i32 @test_br_cc_olt(half %a, half %b) nounwind {
 ; CHECK-P8-NEXT:  .LBB0_2: # %if.else
 ; CHECK-P8-NEXT:    li 3, 0
 ; CHECK-P8-NEXT:  .LBB0_3: # %if.then
-; CHECK-P8-NEXT:    addi 1, 1, 64
+; CHECK-P8-NEXT:    addi 1, 1, 48
 ; CHECK-P8-NEXT:    ld 0, 16(1)
 ; CHECK-P8-NEXT:    lfd 31, -8(1) # 8-byte Folded Reload
-; CHECK-P8-NEXT:    ld 30, -24(1) # 8-byte Folded Reload
+; CHECK-P8-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; CHECK-P8-NEXT:    mtlr 0
 ; CHECK-P8-NEXT:    blr
   %cmp = fcmp olt half %a, %b
@@ -64,10 +60,8 @@ if.else:
 define i32 @test_br_cc_constant(half %a) nounwind {
 ; CHECK-P9-LABEL: test_br_cc_constant:
 ; CHECK-P9:       # %bb.0:
-; CHECK-P9-NEXT:    clrlwi 3, 3, 16
+; CHECK-P9-NEXT:    xscvhpdp 0, 1
 ; CHECK-P9-NEXT:    xxlxor 1, 1, 1
-; CHECK-P9-NEXT:    mtfprwz 0, 3
-; CHECK-P9-NEXT:    xscvhpdp 0, 0
 ; CHECK-P9-NEXT:    fcmpu 0, 0, 1
 ; CHECK-P9-NEXT:    ble 0, .LBB1_2
 ; CHECK-P9-NEXT:  # %bb.1: # %if.then
@@ -81,7 +75,6 @@ define i32 @test_br_cc_constant(half %a) nounwind {
 ; CHECK-P8:       # %bb.0:
 ; CHECK-P8-NEXT:    mflr 0
 ; CHECK-P8-NEXT:    stdu 1, -32(1)
-; CHECK-P8-NEXT:    clrldi 3, 3, 48
 ; CHECK-P8-NEXT:    std 0, 48(1)
 ; CHECK-P8-NEXT:    bl __extendhfsf2
 ; CHECK-P8-NEXT:    nop
@@ -110,10 +103,8 @@ if.else:
 define fastcc i16 @test_vector_reduce_br(half %arg) nounwind {
 ; CHECK-P9-LABEL: test_vector_reduce_br:
 ; CHECK-P9:       # %bb.0:
-; CHECK-P9-NEXT:    clrlwi 3, 3, 16
+; CHECK-P9-NEXT:    xscvhpdp 0, 1
 ; CHECK-P9-NEXT:    xxlxor 1, 1, 1
-; CHECK-P9-NEXT:    mtfprwz 0, 3
-; CHECK-P9-NEXT:    xscvhpdp 0, 0
 ; CHECK-P9-NEXT:    fcmpu 0, 0, 1
 ; CHECK-P9-NEXT:    bc 12, 0, .LBB2_3
 ; CHECK-P9-NEXT:  # %bb.1:
@@ -130,7 +121,6 @@ define fastcc i16 @test_vector_reduce_br(half %arg) nounwind {
 ; CHECK-P8:       # %bb.0:
 ; CHECK-P8-NEXT:    mflr 0
 ; CHECK-P8-NEXT:    stdu 1, -32(1)
-; CHECK-P8-NEXT:    clrldi 3, 3, 48
 ; CHECK-P8-NEXT:    std 0, 48(1)
 ; CHECK-P8-NEXT:    bl __extendhfsf2
 ; CHECK-P8-NEXT:    nop

>From 638eb376ef0bc5913d716d6779eeef9d90668ba6 Mon Sep 17 00:00:00 2001
From: Tony Varghese <tony.varghese at ibm.com>
Date: Tue, 21 Jul 2026 19:14:58 +0530
Subject: [PATCH 5/8] [PowerPC] Remove the float16 target feature; make
 -mfloat16 front-end-only

Delete FeatureFloat16 and the HasFloat16 predicate from PPC.td and stop
emitting +float16 from the driver. -mfloat16 is now marshalled to
LangOpts.PPCFloat16 and forwarded to cc1 directly; its validation (Power8+
requirement, -msoft-float conflict) moves from the driver feature handling
into PPCTargetInfo::adjust().

The flag is purely a source-level admission gate for the _Float16 type.
It produces no LLVM target feature and has no effect on the
target-features attribute, so ABI and code generation depend only on
hardware capability (hasP8Vector() && hasHardFloat()): two translation
units compiled with and without -mfloat16 have identical calling
conventions.
---
 clang/include/clang/Basic/LangOptions.def     |  1 +
 clang/include/clang/Options/Options.td        |  6 ++-
 clang/lib/Basic/Targets/PPC.cpp               | 21 ++++----
 clang/lib/Driver/ToolChains/Arch/PPC.cpp      |  5 --
 clang/lib/Driver/ToolChains/Clang.cpp         |  1 +
 clang/test/Driver/ppc-float16-support-check.c | 49 ++++++++++++-------
 llvm/lib/Target/PowerPC/PPC.td                |  5 --
 llvm/test/CodeGen/PowerPC/shrink-wrap.mir     |  2 +-
 8 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 0bccf316f2daf..2b96c9f004c48 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -179,6 +179,7 @@ VALUE_LANGOPT(AlignDouble            , 1, 0, NotCompatible, "Controls if doubles
 VALUE_LANGOPT(DoubleSize            , 32, 0, NotCompatible, "width of double")
 VALUE_LANGOPT(LongDoubleSize        , 32, 0, NotCompatible, "width of long double")
 LANGOPT(PPCIEEELongDouble            , 1, 0, NotCompatible, "use IEEE 754 quadruple-precision for long double")
+LANGOPT(PPCFloat16                   , 1, 0, NotCompatible, "PowerPC _Float16 source-type support (-mfloat16)")
 LANGOPT(EnableAIXExtendedAltivecABI  , 1, 0, NotCompatible, "__EXTABI__  predefined macro")
 LANGOPT(EnableAIXQuadwordAtomicsABI  , 1, 0, NotCompatible, "Use 16-byte atomic lock free semantics")
 VALUE_LANGOPT(PICLevel               , 2, 0, Compatible, "__PIC__ level")
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 08ac88447d9ea..d96466b1085ef 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6065,8 +6065,10 @@ 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 mfloat16 : Flag<["-"], "mfloat16">,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Enable half-precision floating point (experimental).">,
+  MarshallingInfoFlag<LangOpts<"PPCFloat16">>;
 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 2f135b52122ed..f0aad29de482b 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -82,8 +82,6 @@ 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.
@@ -506,7 +504,6 @@ 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;
@@ -558,14 +555,6 @@ 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.
@@ -845,6 +834,16 @@ void PPCTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
                            const TargetInfo *Aux) {
   if (HasAltivec)
     Opts.AltiVec = 1;
+  if (Opts.PPCFloat16) {
+    if (FloatABI == SoftFloat)
+      Diags.Report(diag::err_opt_not_valid_with_opt)
+          << "-mfloat16" << "-msoft-float";
+    else if (!(ArchDefs & ArchDefinePwr8))
+      Diags.Report(diag::err_opt_not_valid_with_opt)
+          << "-mfloat16" << getTargetOpts().CPU;
+    else
+      HasFloat16 = true;
+  }
   TargetInfo::adjust(Diags, Opts, Aux);
   if (LongDoubleFormat != &llvm::APFloat::IEEEdouble())
     LongDoubleFormat = Opts.PPCIEEELongDouble
diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index 63a7bcca01ae8..d060d8ae2fac8 100644
--- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -77,11 +77,6 @@ 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/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index fb24d0b877ca6..5f290cdf79faf 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7294,6 +7294,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_ftime_report_json);
   Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
   Args.AddLastArg(CmdArgs, options::OPT_malign_double);
+  Args.AddLastArg(CmdArgs, options::OPT_mfloat16);
   Args.AddLastArg(CmdArgs, options::OPT_fno_temp_file);
 
   if (const char *Name = C.getTimeTraceFile(&JA)) {
diff --git a/clang/test/Driver/ppc-float16-support-check.c b/clang/test/Driver/ppc-float16-support-check.c
index b7864d169f806..30058a185fb4c 100644
--- a/clang/test/Driver/ppc-float16-support-check.c
+++ b/clang/test/Driver/ppc-float16-support-check.c
@@ -1,26 +1,39 @@
-// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
-// RUN:   -mcpu=pwr9 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
-// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
-// RUN:   -mcpu=pwr8 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
-
-// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
-// RUN:   -mcpu=pwr7 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
-// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
-// RUN:   -mcpu=pwr6 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
-
-// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
-// RUN:   -mcpu=pwr9 -mfloat16 -msoft-float %s 2>&1 | FileCheck %s --check-prefix=SOFTFLOAT
-
-// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \
-// RUN:   -mcpu=pwr9 %s 2>&1 | FileCheck %s --check-prefix=NOFLAG
-
-_Float16 f;
-
+// Test the -mfloat16 front-end source-admission gate for _Float16 on PowerPC.
+//
+// The gate is target-independent: _Float16 is admitted with -mfloat16 on Power8+
+// with hard-float, rejected on pre-Power8 CPUs or with -msoft-float, and is absent
+// without the flag. -mfloat16 is front-end-only: it is forwarded to -cc1 and is
+// never translated into a target feature.
+
+// Power8/Power9 + -mfloat16: _Float16 is admitted (no diagnostic).
+// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only -mcpu=pwr9 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
+// RUN: %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only -mcpu=pwr8 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
+// RUN: %clang -target powerpc64-unknown-linux-gnu   -fsyntax-only -mcpu=pwr8 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
+// RUN: %clang -target powerpc64-ibm-aix      -fsyntax-only -mcpu=pwr8 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=HASFLOAT16 --allow-empty
 // HASFLOAT16-NOT: option '-mfloat16' cannot be specified with
 // HASFLOAT16-NOT: _Float16 is not supported on this target
 
+// Pre-Power8 + -mfloat16: rejected.
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only -mcpu=pwr7 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only -mcpu=pwr6 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
+// RUN: not %clang -target powerpc64-unknown-linux-gnu   -fsyntax-only -mcpu=pwr7 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
+// RUN: not %clang -target powerpc64-ibm-aix      -fsyntax-only -mcpu=pwr7 -mfloat16 %s 2>&1 | FileCheck %s --check-prefix=BADCPU
 // BADCPU: option '-mfloat16' cannot be specified with
 
+// -mfloat16 with -msoft-float: rejected.
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only -mcpu=pwr9 -mfloat16 -msoft-float %s 2>&1 | FileCheck %s --check-prefix=SOFTFLOAT
+// RUN: not %clang -target powerpc64-unknown-linux-gnu   -fsyntax-only -mcpu=pwr9 -mfloat16 -msoft-float %s 2>&1 | FileCheck %s --check-prefix=SOFTFLOAT
 // SOFTFLOAT: option '-mfloat16' cannot be specified with '-msoft-float'
 
+// Without -mfloat16: the _Float16 token is not admitted.
+// RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only -mcpu=pwr9 %s 2>&1 | FileCheck %s --check-prefix=NOFLAG
+// RUN: not %clang -target powerpc64-ibm-aix      -fsyntax-only -mcpu=pwr9 %s 2>&1 | FileCheck %s --check-prefix=NOFLAG
 // NOFLAG: _Float16 is not supported on this target
+
+// Front-end-only: -mfloat16 is forwarded to -cc1 as "-mfloat16" and is NOT turned
+// into a "+float16" target feature.
+// RUN: %clang -target powerpc64le-unknown-linux-gnu -mcpu=pwr9 -mfloat16 -### -c %s 2>&1 | FileCheck %s --check-prefix=FORWARD
+// RUN: %clang -target powerpc64-ibm-aix      -mcpu=pwr9 -mfloat16 -### -c %s 2>&1 | FileCheck %s --check-prefix=FORWARD
+// FORWARD: "-mfloat16"
+
+_Float16 f;
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index 2501f206e5a85..ba2a4e6a9695c 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -70,10 +70,6 @@ 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.
@@ -422,7 +418,6 @@ 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/test/CodeGen/PowerPC/shrink-wrap.mir b/llvm/test/CodeGen/PowerPC/shrink-wrap.mir
index 3e70b3051b80d..4981c81291c9e 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: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:   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:   BDNZ8 %bb.4, implicit-def dead $ctr8, implicit $ctr8
   ; CHECK-NEXT:   B %bb.5
   ; CHECK-NEXT: {{  $}}

>From 8ac25faeb3fd31f46c938671a9f6af5de3bde81a Mon Sep 17 00:00:00 2001
From: Tony Varghese <tony.varghese at ibm.com>
Date: Tue, 21 Jul 2026 19:15:29 +0530
Subject: [PATCH 6/8] [PowerPC] Fix f16 int conversions, varargs and calling
 convention

Fix a set of defects in the f16 support found by runtime testing on
Power10 hardware (Linux ELFv2 and AIX) and by review:

- FP_TO_SINT/FP_TO_UINT with an f16 operand are keyed by the legalizer on
  their (legal) integer result type, so the operand was never promoted and
  mis-selected as a double-precision convert, producing silently wrong
  results. Add a DAG combine that extends the operand to f32 first.
- SINT_TO_FP/UINT_TO_FP with an f16 result fell back to a nonexistent
  __floatdihf/__floatundihf libcall for i64 sources. Round through f64
  (fcfid/xscvsxddp then xscvdphp) with a matching combine.
- A variadic f16 argument on ELFv2 hit a BITCAST width assertion in
  LowerCall_64SVR4 when producing the GPR copy of an unnamed FP argument.
  Handle f16 with BITCAST to i16 then ANY_EXTEND, mirroring the f32 path.
- The CC_PPC64_ELF shadow-GPR helper did not count f16, so a scalar f16
  argument failed to reserve its GPR doubleword in the CCState analysis
  used for tail-call and stack-size decisions.
- Map VHFRC to the 8-byte VSX spill slot: the 16-bit value lives in the
  low bits of the 64-bit VSX register, so a full-doubleword store/reload
  is value-preserving and works on both P8 and P9.

Extend half-float16-ppc.ll with int-conversion and variadic coverage, add
f16-elfv2-arg-overflow.ll and P8 coverage to the AIX PSA test, and
regenerate half.ll and pr48519.ll, whose CHECK lines codified the broken
conversion lowering.
---
 clang/test/CodeGen/PowerPC/half-float16-ppc.c |  369 ++-
 llvm/lib/Target/PowerPC/PPCCallingConv.cpp    |    4 +-
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  139 +-
 llvm/lib/Target/PowerPC/PPCInstrInfo.cpp      |    7 +-
 llvm/lib/Target/PowerPC/PPCInstrVSX.td        |   20 +-
 llvm/lib/Target/PowerPC/PPCRegisterInfo.td    |    6 +-
 llvm/test/CodeGen/PowerPC/f16-aix-psa.ll      |   74 +-
 .../CodeGen/PowerPC/f16-elfv2-arg-overflow.ll |  105 +
 llvm/test/CodeGen/PowerPC/half-float16-ppc.ll | 1998 +++++++++++------
 llvm/test/CodeGen/PowerPC/half.ll             |  137 +-
 llvm/test/CodeGen/PowerPC/pr48519.ll          |   24 +-
 11 files changed, 1953 insertions(+), 930 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/f16-elfv2-arg-overflow.ll

diff --git a/clang/test/CodeGen/PowerPC/half-float16-ppc.c b/clang/test/CodeGen/PowerPC/half-float16-ppc.c
index 45b336d03f7db..3cac06e0149ee 100644
--- a/clang/test/CodeGen/PowerPC/half-float16-ppc.c
+++ b/clang/test/CodeGen/PowerPC/half-float16-ppc.c
@@ -1,6 +1,15 @@
 // 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
+// _Float16 IR generation on Power8+ across the ELFv2 (LE/BE) and AIX ABIs and on
+// 32-bit. The instruction stream is identical for all; only the function
+// signatures differ (dso_local on Linux, signext on 64-bit).
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -O2 -emit-llvm %s -o - \
+// RUN:   -target-cpu pwr8 -mfloat16 | FileCheck %s --check-prefixes=CHECK,LINUX64
+// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -O2 -emit-llvm %s -o - \
+// RUN:   -target-cpu pwr8 -mfloat16 | FileCheck %s --check-prefixes=CHECK,LINUX64
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix -O2 -emit-llvm %s -o - \
+// RUN:   -target-cpu pwr8 -mfloat16 | FileCheck %s --check-prefixes=CHECK,AIX64
+// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -O2 -emit-llvm %s -o - \
+// RUN:   -target-cpu pwr8 -mfloat16 | FileCheck %s --check-prefixes=CHECK,PPC32
 
 typedef __INT8_TYPE__    int8_t;
 typedef __INT16_TYPE__   int16_t;
@@ -14,36 +23,84 @@ 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]]
+// LINUX64-LABEL: define dso_local noundef half @c_add(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[UNPROMOTION:%.*]] = fadd half [[A]], [[B]]
+// LINUX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// AIX64-LABEL: define noundef half @c_add(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[UNPROMOTION:%.*]] = fadd half [[A]], [[B]]
+// AIX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// PPC32-LABEL: define dso_local noundef half @c_add(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[UNPROMOTION:%.*]] = fadd half [[A]], [[B]]
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local noundef half @c_sub(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[UNPROMOTION:%.*]] = fsub half [[A]], [[B]]
+// LINUX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// AIX64-LABEL: define noundef half @c_sub(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[UNPROMOTION:%.*]] = fsub half [[A]], [[B]]
+// AIX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// PPC32-LABEL: define dso_local noundef half @c_sub(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[UNPROMOTION:%.*]] = fsub half [[A]], [[B]]
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local noundef half @c_mul(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[UNPROMOTION:%.*]] = fmul half [[A]], [[B]]
+// LINUX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// AIX64-LABEL: define noundef half @c_mul(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[UNPROMOTION:%.*]] = fmul half [[A]], [[B]]
+// AIX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// PPC32-LABEL: define dso_local noundef half @c_mul(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[UNPROMOTION:%.*]] = fmul half [[A]], [[B]]
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local noundef half @c_div(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[UNPROMOTION:%.*]] = fdiv half [[A]], [[B]]
+// LINUX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// AIX64-LABEL: define noundef half @c_div(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[UNPROMOTION:%.*]] = fdiv half [[A]], [[B]]
+// AIX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// PPC32-LABEL: define dso_local noundef half @c_div(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[UNPROMOTION:%.*]] = fdiv half [[A]], [[B]]
+// PPC32-NEXT:    ret half [[UNPROMOTION]]
 //
 _Float16 c_div(_Float16 a, _Float16 b) { return a / b; }
 
@@ -51,11 +108,23 @@ _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]]
+// LINUX64-LABEL: define dso_local noundef half @c_neg(
+// LINUX64-SAME: half noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[UNPROMOTION:%.*]] = fneg half [[A]]
+// LINUX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// AIX64-LABEL: define noundef half @c_neg(
+// AIX64-SAME: half noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[UNPROMOTION:%.*]] = fneg half [[A]]
+// AIX64-NEXT:    ret half [[UNPROMOTION]]
+//
+// PPC32-LABEL: define dso_local noundef half @c_neg(
+// PPC32-SAME: half noundef [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[UNPROMOTION:%.*]] = fneg half [[A]]
+// PPC32-NEXT:    ret half [[UNPROMOTION]]
 //
 _Float16 c_neg(_Float16 a) { return -a; }
 
@@ -63,57 +132,141 @@ _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]]
+// LINUX64-LABEL: define dso_local signext range(i32 0, 2) i32 @c_eq(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CMP:%.*]] = fcmp oeq half [[A]], [[B]]
+// LINUX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// LINUX64-NEXT:    ret i32 [[CONV]]
+//
+// AIX64-LABEL: define signext range(i32 0, 2) i32 @c_eq(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CMP:%.*]] = fcmp oeq half [[A]], [[B]]
+// AIX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// AIX64-NEXT:    ret i32 [[CONV]]
+//
+// PPC32-LABEL: define dso_local range(i32 0, 2) i32 @c_eq(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CMP:%.*]] = fcmp oeq half [[A]], [[B]]
+// PPC32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local signext range(i32 0, 2) i32 @c_ne(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CMP:%.*]] = fcmp une half [[A]], [[B]]
+// LINUX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// LINUX64-NEXT:    ret i32 [[CONV]]
+//
+// AIX64-LABEL: define signext range(i32 0, 2) i32 @c_ne(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CMP:%.*]] = fcmp une half [[A]], [[B]]
+// AIX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// AIX64-NEXT:    ret i32 [[CONV]]
+//
+// PPC32-LABEL: define dso_local range(i32 0, 2) i32 @c_ne(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CMP:%.*]] = fcmp une half [[A]], [[B]]
+// PPC32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local signext range(i32 0, 2) i32 @c_lt(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CMP:%.*]] = fcmp olt half [[A]], [[B]]
+// LINUX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// LINUX64-NEXT:    ret i32 [[CONV]]
+//
+// AIX64-LABEL: define signext range(i32 0, 2) i32 @c_lt(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CMP:%.*]] = fcmp olt half [[A]], [[B]]
+// AIX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// AIX64-NEXT:    ret i32 [[CONV]]
+//
+// PPC32-LABEL: define dso_local range(i32 0, 2) i32 @c_lt(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CMP:%.*]] = fcmp olt half [[A]], [[B]]
+// PPC32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local signext range(i32 0, 2) i32 @c_le(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CMP:%.*]] = fcmp ole half [[A]], [[B]]
+// LINUX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// LINUX64-NEXT:    ret i32 [[CONV]]
+//
+// AIX64-LABEL: define signext range(i32 0, 2) i32 @c_le(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CMP:%.*]] = fcmp ole half [[A]], [[B]]
+// AIX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// AIX64-NEXT:    ret i32 [[CONV]]
+//
+// PPC32-LABEL: define dso_local range(i32 0, 2) i32 @c_le(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CMP:%.*]] = fcmp ole half [[A]], [[B]]
+// PPC32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local signext range(i32 0, 2) i32 @c_gt(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CMP:%.*]] = fcmp ogt half [[A]], [[B]]
+// LINUX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// LINUX64-NEXT:    ret i32 [[CONV]]
+//
+// AIX64-LABEL: define signext range(i32 0, 2) i32 @c_gt(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CMP:%.*]] = fcmp ogt half [[A]], [[B]]
+// AIX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// AIX64-NEXT:    ret i32 [[CONV]]
+//
+// PPC32-LABEL: define dso_local range(i32 0, 2) i32 @c_gt(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CMP:%.*]] = fcmp ogt half [[A]], [[B]]
+// PPC32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local signext range(i32 0, 2) i32 @c_ge(
+// LINUX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CMP:%.*]] = fcmp oge half [[A]], [[B]]
+// LINUX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// LINUX64-NEXT:    ret i32 [[CONV]]
+//
+// AIX64-LABEL: define signext range(i32 0, 2) i32 @c_ge(
+// AIX64-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CMP:%.*]] = fcmp oge half [[A]], [[B]]
+// AIX64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// AIX64-NEXT:    ret i32 [[CONV]]
+//
+// PPC32-LABEL: define dso_local range(i32 0, 2) i32 @c_ge(
+// PPC32-SAME: half noundef [[A:%.*]], half noundef [[B:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CMP:%.*]] = fcmp oge half [[A]], [[B]]
+// PPC32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+// PPC32-NEXT:    ret i32 [[CONV]]
 //
 int c_ge(_Float16 a, _Float16 b){ return a >= b; }
 
@@ -121,34 +274,84 @@ 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]]
+// LINUX64-LABEL: define dso_local noundef float @to_f32(
+// LINUX64-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CONV:%.*]] = fpext half [[X]] to float
+// LINUX64-NEXT:    ret float [[CONV]]
+//
+// AIX64-LABEL: define noundef float @to_f32(
+// AIX64-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CONV:%.*]] = fpext half [[X]] to float
+// AIX64-NEXT:    ret float [[CONV]]
+//
+// PPC32-LABEL: define dso_local noundef float @to_f32(
+// PPC32-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CONV:%.*]] = fpext half [[X]] to float
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local noundef double @to_f64(
+// LINUX64-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CONV:%.*]] = fpext half [[X]] to double
+// LINUX64-NEXT:    ret double [[CONV]]
+//
+// AIX64-LABEL: define noundef double @to_f64(
+// AIX64-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CONV:%.*]] = fpext half [[X]] to double
+// AIX64-NEXT:    ret double [[CONV]]
+//
+// PPC32-LABEL: define dso_local noundef double @to_f64(
+// PPC32-SAME: half noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CONV:%.*]] = fpext half [[X]] to double
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local noundef half @from_f32(
+// LINUX64-SAME: float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CONV:%.*]] = fptrunc float [[X]] to half
+// LINUX64-NEXT:    ret half [[CONV]]
+//
+// AIX64-LABEL: define noundef half @from_f32(
+// AIX64-SAME: float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CONV:%.*]] = fptrunc float [[X]] to half
+// AIX64-NEXT:    ret half [[CONV]]
+//
+// PPC32-LABEL: define dso_local noundef half @from_f32(
+// PPC32-SAME: float noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CONV:%.*]] = fptrunc float [[X]] to half
+// PPC32-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]]
+// LINUX64-LABEL: define dso_local noundef half @from_f64(
+// LINUX64-SAME: double noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// LINUX64-NEXT:  [[ENTRY:.*:]]
+// LINUX64-NEXT:    [[CONV:%.*]] = fptrunc double [[X]] to half
+// LINUX64-NEXT:    ret half [[CONV]]
+//
+// AIX64-LABEL: define noundef half @from_f64(
+// AIX64-SAME: double noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX64-NEXT:  [[ENTRY:.*:]]
+// AIX64-NEXT:    [[CONV:%.*]] = fptrunc double [[X]] to half
+// AIX64-NEXT:    ret half [[CONV]]
+//
+// PPC32-LABEL: define dso_local noundef half @from_f64(
+// PPC32-SAME: double noundef [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// PPC32-NEXT:  [[ENTRY:.*:]]
+// PPC32-NEXT:    [[CONV:%.*]] = fptrunc double [[X]] to half
+// PPC32-NEXT:    ret half [[CONV]]
 //
 _Float16 from_f64(double x){ return (_Float16)x; }
+//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+// CHECK: {{.*}}
diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.cpp b/llvm/lib/Target/PowerPC/PPCCallingConv.cpp
index 3f14cabe78ceb..104bf7fdcfc96 100644
--- a/llvm/lib/Target/PowerPC/PPCCallingConv.cpp
+++ b/llvm/lib/Target/PowerPC/PPCCallingConv.cpp
@@ -38,9 +38,9 @@ inline bool CC_PPC64_ELF_Shadow_GPR_Regs(unsigned &ValNo, MVT &ValVT,
     return false;
 
   // As described in 2.2.4.1 under the "float" section, shadow a single GPR
-  // for single/double precision. ppcf128 gets broken up into two doubles
+  // for half/single/double precision. ppcf128 gets broken up into two doubles
   // and will also shadow GPRs within this section.
-  if (LocVT == MVT::f32 || LocVT == MVT::f64)
+  if (LocVT == MVT::f16 || LocVT == MVT::f32 || LocVT == MVT::f64)
     State.AllocateReg(ELF64ArgGPRs);
   else if (LocVT.is128BitVector() || (LocVT == MVT::f128)) {
     // For vector and __float128 (which is represents the "vector" section
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index e37a7c2269cc2..b18e218e81e0a 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -266,7 +266,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
   // 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.hasP8Vector() && Subtarget.hasHardFloat()) {
+  if (useFPRegsForHalfType()) {
     // Make f16 a legal type.
     addRegisterClass(MVT::f16, &PPC::VHFRCRegClass);
 
@@ -284,11 +284,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
         ISD::FNEARBYINT, ISD::FROUND,   ISD::FROUNDEVEN,  ISD::FCANONICALIZE,
         ISD::FSIN,       ISD::FCOS,     ISD::SETCC,       ISD::SELECT_CC,
         ISD::SELECT,     ISD::FLDEXP,   ISD::FFREXP,      ISD::FMODF,
-        ISD::FATAN2,     ISD::FPOWI,
-        // BR_CC has f16 operands (the comparison inputs) but a chain result.
-        // Without explicit Promote, the f16 comparison reaches SelectCC in
-        // PPCISelDAGToDAG which only knows f32/f64/f128 and asserts.
-        ISD::BR_CC};
+        ISD::FATAN2,     ISD::FPOWI,    ISD::BR_CC};
 
     // Promote all the arithmetic operations defined above to f32.
     setOperationAction(F16PromoteOps, MVT::f16, Promote);
@@ -303,6 +299,24 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
     setOperationAction({ISD::LRINT, ISD::LLRINT, ISD::LROUND, ISD::LLROUND},
                        MVT::f16, Custom);
 
+    // ISD::FP_TO_SINT/FP_TO_UINT (and their strict forms) are keyed by the
+    // SelectionDAG legalizer on their integer result type, which is legal, so
+    // a Promote/Custom action on the f16 operand is never consulted. Left
+    // alone, the f16 operand reaches ISel and is mis-selected as a
+    // double-precision convert (f16 and f64 share the VSX registers), producing
+    // a bare xscvdpsxws with no preceding xscvhpdp. Promote the operand to f32
+    // with a DAG combine instead; FP_TO_*INT(f32) and FP_EXTEND(f16->f32) are
+    // both already handled correctly on P8 and P9.
+    //
+    // The reverse, INT_TO_FP with an f16 result, has no direct lowering for
+    // wide integers (i64 falls back to a missing __floatdihf libcall). Round
+    // through f64 (fcfid[u] then xscvdphp) with the same combine. SINT_TO_FP
+    // and UINT_TO_FP are already registered for combine above; add their strict
+    // forms here.
+    setTargetDAGCombine({ISD::FP_TO_SINT, ISD::FP_TO_UINT,
+                         ISD::STRICT_FP_TO_SINT, ISD::STRICT_FP_TO_UINT,
+                         ISD::STRICT_SINT_TO_FP, ISD::STRICT_UINT_TO_FP});
+
     setOperationAction(ISD::LOAD, MVT::f16, Legal);
     setOperationAction(ISD::STORE, MVT::f16, Legal);
 
@@ -1800,8 +1814,7 @@ bool PPCTargetLowering::hasSPE() const {
 
 /// Tell the ABI lowering infrastructure to use FPRs for f16 parameters
 /// and return values rather than GPRs whenever the hardware can hold them
-/// in VSX registers. This must not depend on -mfloat16: that flag only
-/// controls whether _Float16 is a spellable source-level type, not the ABI.
+/// in VSX registers.
 bool PPCTargetLowering::useFPRegsForHalfType() const {
   return Subtarget.hasP8Vector() && Subtarget.hasHardFloat();
 }
@@ -4803,8 +4816,9 @@ SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
       // float aggregates.
       if (FPR_idx != Num_FPR_Regs) {
         unsigned VReg;
-
-        if (ObjectVT == MVT::f32)
+        if (ObjectVT == MVT::f16)
+          VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::VHFRCRegClass);
+        else if (ObjectVT == MVT::f32)
           VReg = MF.addLiveIn(FPR[FPR_idx],
                               Subtarget.hasP8Vector()
                                   ? &PPC::VSSRCRegClass
@@ -4832,6 +4846,16 @@ SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
             ArgVal = DAG.getNode(ISD::SRL, dl, MVT::i64, ArgVal,
                                  DAG.getConstant(32, dl, MVT::i32));
           ArgVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, ArgVal);
+        } else if (ObjectVT == MVT::f16) {
+          //  The 16 meaningfull bits sit at the byte (ArgOffset % 8) of the 8
+          //  bytes loaded into the ArgVal. Shift it down to the low 16 bits and
+          //  then narrow to i16.
+          unsigned BitInDW = ((ArgOffset % PtrByteSize) * 8);
+          unsigned Shift = (isLittleEndian ? BitInDW : 48 - BitInDW);
+          if (Shift)
+            ArgVal = DAG.getNode(ISD::SRL, dl, MVT::i64, ArgVal,
+                                 DAG.getConstant(Shift, dl, MVT::i32));
+          ArgVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i16, ArgVal);
         }
 
         ArgVal = DAG.getNode(ISD::BITCAST, dl, ObjectVT, ArgVal);
@@ -6732,8 +6756,15 @@ SDValue PPCTargetLowering::LowerCall_64SVR4(
         // out of FPRs before running out of GPRs.
         SDValue ArgVal;
 
-        // Double values are always passed in a single GPR.
-        if (Arg.getValueType() != MVT::f32) {
+        // Half values are only 16 bits: bitcast to i16 and extend into the
+        // GPR (a direct BITCAST to i64 would be a width mismatch). This is
+        // reached for an f16 passed to a vararg callee, which is also placed
+        // in an FPR above.
+        if (Arg.getValueType() == MVT::f16) {
+          ArgVal = DAG.getNode(ISD::BITCAST, dl, MVT::i16, Arg);
+          ArgVal = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i64, ArgVal);
+        } else if (Arg.getValueType() != MVT::f32) {
+          // Double values are always passed in a single GPR.
           ArgVal = DAG.getNode(ISD::BITCAST, dl, MVT::i64, Arg);
 
         // Non-array float values are extended and passed in a GPR.
@@ -7192,9 +7223,10 @@ 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) {
   assert((IsPPC64 || SVT != MVT::i64) &&
          "i64 should have been split for 32-bit codegen.");
 
@@ -7353,9 +7385,8 @@ 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());
       // 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);
@@ -7580,10 +7611,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()));
       SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, LocVT);
       if (ValVT.isScalarInteger() &&
           (ValVT.getFixedSizeInBits() < LocVT.getFixedSizeInBits())) {
@@ -18055,12 +18086,69 @@ static SDValue combineXorSelectCC(SDNode *N, SelectionDAG &DAG) {
       0);
 }
 
+// PowerPC has no f16 FP_TO_SINT/FP_TO_UINT. Promote the f16 operand to f32 so
+// the conversion runs on a type the hardware supports. The FP_EXTEND(f16->f32)
+// is lowered to xscvhpdp on P9 (or __extendhfsf2 on P8); without this the f16
+// value is wrongly treated as an f64 by ISel. Returns SDValue() for non-f16
+// operands so other conversions are untouched.
+static SDValue combineF16FPToInt(SDNode *N, SelectionDAG &DAG) {
+  bool IsStrict = N->isStrictFPOpcode();
+  SDValue Src = N->getOperand(IsStrict ? 1 : 0);
+  if (Src.getValueType() != MVT::f16)
+    return SDValue();
+
+  SDLoc dl(N);
+  EVT DstVT = N->getValueType(0);
+  if (IsStrict) {
+    SDValue Chain = N->getOperand(0);
+    SDValue Ext =
+        DAG.getNode(ISD::STRICT_FP_EXTEND, dl,
+                    DAG.getVTList(MVT::f32, MVT::Other), {Chain, Src});
+    return DAG.getNode(N->getOpcode(), dl, DAG.getVTList(DstVT, MVT::Other),
+                       {Ext.getValue(1), Ext.getValue(0)});
+  }
+  SDValue Ext = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f32, Src);
+  return DAG.getNode(N->getOpcode(), dl, DstVT, Ext);
+}
+
+// PowerPC has no direct integer -> f16 conversion for every integer width: i64
+// in particular falls back to a __floatdihf/__floatundihf libcall that the
+// runtime may not provide. Convert to f64 first (fcfid[u], legal) and round to
+// f16 (xscvdphp), reusing the already-correct FP_ROUND(f64->f16) lowering.
+// Returns SDValue() for non-f16 results so wider conversions are untouched.
+static SDValue combineF16IntToFP(SDNode *N, SelectionDAG &DAG) {
+  if (N->getValueType(0) != MVT::f16)
+    return SDValue();
+
+  bool IsStrict = N->isStrictFPOpcode();
+  SDLoc dl(N);
+  SDValue Src = N->getOperand(IsStrict ? 1 : 0);
+  if (IsStrict) {
+    SDValue Chain = N->getOperand(0);
+    SDValue Wide = DAG.getNode(
+        N->getOpcode(), dl, DAG.getVTList(MVT::f64, MVT::Other), {Chain, Src});
+    return DAG.getNode(
+        ISD::STRICT_FP_ROUND, dl, DAG.getVTList(MVT::f16, MVT::Other),
+        {Wide.getValue(1), Wide.getValue(0), DAG.getIntPtrConstant(0, dl)});
+  }
+  SDValue Wide = DAG.getNode(N->getOpcode(), dl, MVT::f64, Src);
+  return DAG.getNode(ISD::FP_ROUND, dl, MVT::f16, Wide,
+                     DAG.getIntPtrConstant(0, dl, /*isTarget=*/true));
+}
+
 SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
                                              DAGCombinerInfo &DCI) const {
   SelectionDAG &DAG = DCI.DAG;
   SDLoc dl(N);
   switch (N->getOpcode()) {
   default: break;
+  case ISD::FP_TO_SINT:
+  case ISD::FP_TO_UINT:
+  case ISD::STRICT_FP_TO_SINT:
+  case ISD::STRICT_FP_TO_UINT:
+    if (SDValue V = combineF16FPToInt(N, DAG))
+      return V;
+    break;
   case ISD::ADD:
     return combineADD(N, DCI);
   case ISD::AND: {
@@ -18141,7 +18229,14 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
     return DAGCombineTruncBoolExt(N, DCI);
   case ISD::SINT_TO_FP:
   case ISD::UINT_TO_FP:
+    if (SDValue V = combineF16IntToFP(N, DAG))
+      return V;
     return combineFPToIntToFP(N, DCI);
+  case ISD::STRICT_SINT_TO_FP:
+  case ISD::STRICT_UINT_TO_FP:
+    if (SDValue V = combineF16IntToFP(N, DAG))
+      return V;
+    break;
   case ISD::VECTOR_SHUFFLE:
     if (ISD::isNormalLoad(N->getOperand(0).getNode())) {
       LSBaseSDNode* LSBase = cast<LSBaseSDNode>(N->getOperand(0));
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index f415a9776da94..f4c17ef81778a 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -1935,7 +1935,12 @@ unsigned PPCInstrInfo::getSpillIndex(const TargetRegisterClass *RC) const {
     OpcodeIndex = SOK_VRVectorSpill;
   } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) {
     OpcodeIndex = SOK_VSXVectorSpill;
-  } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) {
+  } else if (PPC::VSFRCRegClass.hasSubClassEq(RC) ||
+             PPC::VHFRCRegClass.hasSubClassEq(RC)) {
+    // VHFRC (f16) shares the 64-bit VSX scalar registers with VSFRC. Spill the
+    // full doubleword: the 16-bit value occupies the low bits, so a full-width
+    // store/reload is value-preserving and works on both P8 and P9 (no
+    // halfword VSX store exists on P8).
     OpcodeIndex = SOK_VectorFloat8Spill;
   } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) {
     OpcodeIndex = SOK_VectorFloat4Spill;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
index b7a6247c511a0..5bae3ce988642 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
@@ -4087,16 +4087,12 @@ let Predicates = [HasP9Vector] in {
               (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 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 = [HasP8Vector] in {
+// P8 has no halfword VSX memory ops, so f16 load/store goes through a GPR
+// roundtrip. Restricted to !P9 because P9 selects the dedicated LXSIHZX/STXSIHX
+// patterns above; without NoP9Vector these would redundantly also match on P9.
+let Predicates = [HasP8Vector, NoP9Vector] 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)>;
@@ -4108,7 +4104,15 @@ let Predicates = [HasP8Vector] in {
             (COPY_TO_REGCLASS (MTVSRWZ (LHZX xoaddr:$src)), VHFRC)>;
   def : Pat<(f16 (load iaddrX16:$src)),
             (COPY_TO_REGCLASS (MTVSRWZ (LHZ  iaddrX16:$src)), VHFRC)>;
+}
 
+// fabs, fneg, and fcopysign for f16 are intentionally pure bit manipulations on
+// ALL hardware including P9+, NOT conversion round-trips. A round-trip through
+// f64 via XSCVHPDP/XSCVDPHP does not preserve NaN payloads (signalling NaN ->
+// quiet NaN, payload bits corrupted); these operations must be value-preserving
+// bit moves. Hence [HasP8Vector] (fires on P8 and P9 alike), not NoP9Vector.
+// See llvm/llvm-project#97981.
+let Predicates = [HasP8Vector] in {
   // fabs: clear sign bit (AND with 0x7FFF in the 16-bit lane).
   def : Pat<(fabs f16:$src),
             (COPY_TO_REGCLASS
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 1b2e78a0b658a..50b489582be27 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -412,7 +412,11 @@ def VSSRC : PPCRegisterClass<[f32], 32, (add VSFRC)>;
 // 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)>;
+  // f16 occupies the low bits of a 64-bit VSX scalar register (shared with
+  // VSFRC). There is no 2-byte VSX store on Power8 (STXSIHX is Power9-only), so
+  // VHFRC spills the full doubleword via the 8-byte VSX spill. Force an 8-byte
+  // spill size so the stack slot matches the STXSDX/DFSTOREf64 store width.
+  def VHFRC : PPCRegisterClassWithSize<[f16], 16, (add VSFRC), 64>;
 }
 
 def CRBITRC : PPCRegisterClassWithSize<[i1], 32,
diff --git a/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll b/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
index 755371365d2e0..c30fa6464ddea 100644
--- a/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
+++ b/llvm/test/CodeGen/PowerPC/f16-aix-psa.ll
@@ -1,12 +1,15 @@
 ; 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
-
-; The following RUN lines omit -mattr=+float16: ABI routing through the
-; PSA must depend only on hardware capability, not this target feature, so
-; output must be byte-identical to the corresponding runs above.
+;
+; _Float16 parameter save area (PSA) layout on AIX. Verifies that f16 arguments
+; which overflow the floating-point registers (F1-F13) are passed through the PSA
+; with 8-byte slots, and that each f16 register argument consumes its shadow GPR
+; doubleword. The PSA layout (offsets, 8-byte slots, GPR shadow) is identical on
+; Power8 and Power9; only the leaf halfword access differs (P8: lhz/sth + GPR moves;
+; P9: lxsihzx/stxsihx), so both are checked below.
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr8 \
+; RUN:   < %s | FileCheck %s --check-prefix=P8-AIX-64
+; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr8 \
+; RUN:   < %s | FileCheck %s --check-prefix=P8-AIX-32
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr9 \
 ; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefix=P9-AIX-64
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr9 \
@@ -17,6 +20,18 @@
 ; 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(
+; P8-AIX-64-LABEL: test_14th_arg:
+; P8-AIX-64:       # %bb.0:
+; P8-AIX-64-NEXT:    lhz 3, 152(1)
+; P8-AIX-64-NEXT:    mtfprwz 1, 3
+; P8-AIX-64-NEXT:    blr
+;
+; P8-AIX-32-LABEL: test_14th_arg:
+; P8-AIX-32:       # %bb.0:
+; P8-AIX-32-NEXT:    lhz 3, 76(1)
+; P8-AIX-32-NEXT:    mtfprwz 1, 3
+; P8-AIX-32-NEXT:    blr
+;
 ; P9-AIX-64-LABEL: test_14th_arg:
 ; P9-AIX-64:       # %bb.0:
 ; P9-AIX-64-NEXT:    addi 3, 1, 152
@@ -45,6 +60,17 @@ define half @test_14th_arg(
 ; 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) {
+; P8-AIX-64-LABEL: test_mixed_args:
+; P8-AIX-64:       # %bb.0:
+; P8-AIX-64-NEXT:    mr 3, 6
+; P8-AIX-64-NEXT:    blr
+;
+; P8-AIX-32-LABEL: test_mixed_args:
+; P8-AIX-32:       # %bb.0:
+; P8-AIX-32-NEXT:    mr 4, 8
+; P8-AIX-32-NEXT:    mr 3, 7
+; P8-AIX-32-NEXT:    blr
+;
 ; P9-AIX-64-LABEL: test_mixed_args:
 ; P9-AIX-64:       # %bb.0:
 ; P9-AIX-64-NEXT:    mr 3, 6
@@ -61,11 +87,41 @@ define i64 @test_mixed_args(half %f0, i64 %i0, half %f1, 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.
+; The first vararg f16 value is then loaded from SP+56 (lxsihzx on P9, lhz on P8).
 declare void @llvm.va_start(ptr)
 declare void @llvm.va_end(ptr)
 
 define half @test_vararg_f16(i32 %count, ...) {
+; P8-AIX-64-LABEL: test_vararg_f16:
+; P8-AIX-64:       # %bb.0: # %entry
+; P8-AIX-64-NEXT:    addi 3, 1, 58
+; P8-AIX-64-NEXT:    std 4, 56(1)
+; P8-AIX-64-NEXT:    std 5, 64(1)
+; P8-AIX-64-NEXT:    std 6, 72(1)
+; P8-AIX-64-NEXT:    std 7, 80(1)
+; P8-AIX-64-NEXT:    std 8, 88(1)
+; P8-AIX-64-NEXT:    std 9, 96(1)
+; P8-AIX-64-NEXT:    std 10, 104(1)
+; P8-AIX-64-NEXT:    std 3, -8(1)
+; P8-AIX-64-NEXT:    lhz 3, 56(1)
+; P8-AIX-64-NEXT:    mtfprwz 1, 3
+; P8-AIX-64-NEXT:    blr
+;
+; P8-AIX-32-LABEL: test_vararg_f16:
+; P8-AIX-32:       # %bb.0: # %entry
+; P8-AIX-32-NEXT:    addi 3, 1, 30
+; P8-AIX-32-NEXT:    stw 4, 28(1)
+; P8-AIX-32-NEXT:    stw 5, 32(1)
+; P8-AIX-32-NEXT:    stw 6, 36(1)
+; P8-AIX-32-NEXT:    stw 7, 40(1)
+; P8-AIX-32-NEXT:    stw 8, 44(1)
+; P8-AIX-32-NEXT:    stw 9, 48(1)
+; P8-AIX-32-NEXT:    stw 10, 52(1)
+; P8-AIX-32-NEXT:    stw 3, -4(1)
+; P8-AIX-32-NEXT:    lhz 3, 28(1)
+; P8-AIX-32-NEXT:    mtfprwz 1, 3
+; P8-AIX-32-NEXT:    blr
+;
 ; P9-AIX-64-LABEL: test_vararg_f16:
 ; P9-AIX-64:       # %bb.0: # %entry
 ; P9-AIX-64-NEXT:    addi 3, 1, 58
diff --git a/llvm/test/CodeGen/PowerPC/f16-elfv2-arg-overflow.ll b/llvm/test/CodeGen/PowerPC/f16-elfv2-arg-overflow.ll
new file mode 100644
index 0000000000000..f014af2584db8
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/f16-elfv2-arg-overflow.ll
@@ -0,0 +1,105 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s --check-prefix=CHECK-LE
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
+; RUN:   -mcpu=pwr9 < %s | FileCheck %s --check-prefix=CHECK-BE
+
+; Regression test for f16 formal-argument lowering in
+; LowerFormalArguments_64SVR4 (64-bit ELF, both little- and big-endian).
+;
+; A [N x half] homogeneous float array exhausts the 13 floating-point argument
+; registers (f1..f13); element 13 and beyond overflow into a GPR. Reading the
+; 16-bit value out of the 64-bit GPR requires shifting it down to the low 16
+; bits (by an endian-dependent amount) and narrowing to i16 before the
+; bitcast to f16. Before the fix this asserted:
+;   "Cannot BITCAST between types of different sizes!"  (i64 -> f16)
+;
+; The shift amount tracks the element's byte offset b = ArgOffset % 8:
+;   little-endian: shift = b * 8        big-endian: shift = 48 - b * 8
+; and the source GPR advances at each doubleword boundary.
+
+; element 13 -> byte offset 2 -> LE shift 16 / BE shift 32, from GPR r6
+define half @overflow_b2([20 x half] %a) {
+; CHECK-LE-LABEL: overflow_b2:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    srwi 3, 6, 16
+; CHECK-LE-NEXT:    sth 3, -2(1)
+; CHECK-LE-NEXT:    addi 3, 1, -2
+; CHECK-LE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: overflow_b2:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    rldicl 3, 6, 32, 32
+; CHECK-BE-NEXT:    sth 3, -2(1)
+; CHECK-BE-NEXT:    addi 3, 1, -2
+; CHECK-BE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-BE-NEXT:    blr
+entry:
+  %e = extractvalue [20 x half] %a, 13
+  ret half %e
+}
+
+; element 14 -> byte offset 4 -> LE shift 32 / BE shift 16, from GPR r6
+define half @overflow_b4([20 x half] %a) {
+; CHECK-LE-LABEL: overflow_b4:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    rldicl 3, 6, 32, 32
+; CHECK-LE-NEXT:    sth 3, -2(1)
+; CHECK-LE-NEXT:    addi 3, 1, -2
+; CHECK-LE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: overflow_b4:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    srwi 3, 6, 16
+; CHECK-BE-NEXT:    sth 3, -2(1)
+; CHECK-BE-NEXT:    addi 3, 1, -2
+; CHECK-BE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-BE-NEXT:    blr
+entry:
+  %e = extractvalue [20 x half] %a, 14
+  ret half %e
+}
+
+; element 15 -> byte offset 6 -> LE shift 48 / BE shift 0, from GPR r6
+define half @overflow_b6([20 x half] %a) {
+; CHECK-LE-LABEL: overflow_b6:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    rldicl 3, 6, 16, 48
+; CHECK-LE-NEXT:    sth 3, -2(1)
+; CHECK-LE-NEXT:    addi 3, 1, -2
+; CHECK-LE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: overflow_b6:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    addi 3, 1, -2
+; CHECK-BE-NEXT:    sth 6, -2(1)
+; CHECK-BE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-BE-NEXT:    blr
+entry:
+  %e = extractvalue [20 x half] %a, 15
+  ret half %e
+}
+
+; element 16 -> byte offset 0 -> no shift, source GPR advances to r7
+define half @overflow_b0_nextreg([20 x half] %a) {
+; CHECK-LE-LABEL: overflow_b0_nextreg:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    addi 3, 1, -2
+; CHECK-LE-NEXT:    sth 7, -2(1)
+; CHECK-LE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: overflow_b0_nextreg:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    rldicl 3, 7, 16, 48
+; CHECK-BE-NEXT:    sth 3, -2(1)
+; CHECK-BE-NEXT:    addi 3, 1, -2
+; CHECK-BE-NEXT:    lxsihzx 1, 0, 3
+; CHECK-BE-NEXT:    blr
+entry:
+  %e = extractvalue [20 x half] %a, 16
+  ret half %e
+}
diff --git a/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
index cbd67c6ed151b..031f0cbba74cf 100644
--- a/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
+++ b/llvm/test/CodeGen/PowerPC/half-float16-ppc.ll
@@ -1,31 +1,17 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; Comprehensive f16 ISel coverage for Power8 (GPR-roundtrip + libcall path) and
+; Power9 (hardware xscvhpdp/xscvdphp + lxsihzx/stxsihx) across AIX and Linux, 32-
+; and 64-bit. P8 runs share the common P8 prefix, P9 runs share P9.
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr8 \
-; RUN:   -mattr=+float16 < %s | FileCheck %s --check-prefix=P8-AIX-32
+; RUN:   < %s | FileCheck %s --check-prefixes=P8,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:   < %s | FileCheck %s --check-prefixes=P8,P8-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
-
-; The following RUN lines omit -mattr=+float16 entirely. f16 legalization and
-; ABI routing (FPR vs GPR) must depend only on hardware capability
-; (HasP8Vector/HasHardFloat), not on this target feature, so the codegen
-; below must be byte-identical to the corresponding runs above.
-; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr8 \
-; RUN:   < %s | FileCheck %s --check-prefix=P8-AIX-32
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr8 \
-; RUN:   < %s | FileCheck %s --check-prefix=P8-AIX-64
+; RUN:   < %s | FileCheck %s --check-prefixes=P8,P8-LINUX-64
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix -mcpu=pwr9 \
 ; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-AIX-32
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix -mcpu=pwr9 \
 ; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-AIX-64
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu -mcpu=pwr8 \
-; RUN:   < %s | FileCheck %s --check-prefix=P8-LINUX-64
 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu -mcpu=pwr9 \
 ; RUN:   -mattr=+vsx,+power9-vector < %s | FileCheck %s --check-prefixes=P9,P9-LINUX-64
 
@@ -35,56 +21,32 @@
 ; ========================================================================================
 
 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
+; P8-LABEL: load_half:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    lhzx 3, 0, 3
+; P8-NEXT:    mtfprwz 1, 3
+; P8-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
+; P8-LABEL: store_half:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mffprwz 4, 1
+; P8-NEXT:    sthx 4, 0, 3
+; P8-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
@@ -146,14 +108,6 @@ define half @op_add(half %a, half %b) nounwind {
 ; 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
@@ -178,6 +132,14 @@ define half @op_add(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %unpromotion = fadd half %a, %b
   ret half %unpromotion
@@ -234,14 +196,6 @@ define half @op_sub(half %a, half %b) nounwind {
 ; 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
@@ -266,6 +220,14 @@ define half @op_sub(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %unpromotion = fsub half %a, %b
   ret half %unpromotion
@@ -322,14 +284,6 @@ define half @op_mul(half %a, half %b) nounwind {
 ; 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
@@ -354,6 +308,14 @@ define half @op_mul(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %unpromotion = fmul half %a, %b
   ret half %unpromotion
@@ -410,14 +372,6 @@ define half @op_div(half %a, half %b) nounwind {
 ; 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
@@ -442,6 +396,14 @@ define half @op_div(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %unpromotion = fdiv half %a, %b
   ret half %unpromotion
@@ -515,15 +477,6 @@ define half @test_fma(half %a, half %b, half %c) nounwind {
 ; 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
@@ -554,6 +507,15 @@ define half @test_fma(half %a, half %b, half %c) nounwind {
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-64-NEXT:    lfd 29, -24(1) # 8-byte Folded Reload
 ; P8-LINUX-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
 entry:
     %r = call half @llvm.fma.f16(half %a, half %b, half %c)
     ret half %r
@@ -590,13 +552,6 @@ define half @test_sqrt(half %a) {
 ; 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
@@ -613,6 +568,13 @@ define half @test_sqrt(half %a) {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
     %r = call half @llvm.sqrt.f16(half %a)
     ret half %r
@@ -673,6 +635,33 @@ define half @test_frem(half %a, half %b) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_frem:
 ; P9-AIX-32:       # %bb.0: # %entry
 ; P9-AIX-32-NEXT:    mflr 0
@@ -703,33 +692,6 @@ define half @test_frem(half %a, half %b) nounwind {
 ; 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
@@ -807,16 +769,6 @@ define zeroext i1 @op_eq(half %a, half %b) nounwind {
 ; 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
@@ -842,6 +794,16 @@ define zeroext i1 @op_eq(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %cmp = fcmp oeq half %a, %b
   ret i1 %cmp
@@ -898,15 +860,6 @@ define zeroext i1 @op_ne(half %a, half %b) nounwind {
 ; 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
@@ -931,6 +884,15 @@ define zeroext i1 @op_ne(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %cmp = fcmp une half %a, %b
   ret i1 %cmp
@@ -989,16 +951,6 @@ define zeroext i1 @op_lt(half %a, half %b) nounwind {
 ; 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
@@ -1024,6 +976,16 @@ define zeroext i1 @op_lt(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %cmp = fcmp olt half %a, %b
   ret i1 %cmp
@@ -1082,16 +1044,6 @@ define zeroext i1 @op_le(half %a, half %b) nounwind {
 ; 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
@@ -1117,6 +1069,16 @@ define zeroext i1 @op_le(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %cmp = fcmp ole half %a, %b
   ret i1 %cmp
@@ -1175,16 +1137,6 @@ define zeroext i1 @op_gt(half %a, half %b) nounwind {
 ; 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
@@ -1210,6 +1162,16 @@ define zeroext i1 @op_gt(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %cmp = fcmp ogt half %a, %b
   ret i1 %cmp
@@ -1268,16 +1230,6 @@ define zeroext i1 @op_ge(half %a, half %b) nounwind {
 ; 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
@@ -1303,6 +1255,16 @@ define zeroext i1 @op_ge(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %cmp = fcmp oge half %a, %b
   ret i1 %cmp
@@ -1382,30 +1344,6 @@ define half @op_select(i1 %cond, half %a, half %b) nounwind {
 ; 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
@@ -1440,6 +1378,30 @@ define half @op_select(i1 %cond, half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    mtocrf 32, 12
 ; P8-LINUX-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
+;
 ; P9-LINUX-64-LABEL: op_select:
 ; P9-LINUX-64:       # %bb.0: # %entry
 ; P9-LINUX-64-NEXT:    xscvhpdp 2, 2
@@ -1549,34 +1511,6 @@ define half @op_select_cc(half %a, half %b, half %c, half %d) nounwind {
 ; 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
@@ -1623,6 +1557,34 @@ define half @op_select_cc(half %a, half %b, half %c, half %d) nounwind {
 ; P8-LINUX-64-NEXT:    mtocrf 32, 12
 ; P8-LINUX-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
+;
 ; P9-LINUX-64-LABEL: op_select_cc:
 ; P9-LINUX-64:       # %bb.0:
 ; P9-LINUX-64-NEXT:    xscvhpdp 0, 2
@@ -1697,14 +1659,6 @@ define half @op_fmin(half %a, half %b) nounwind {
 ; 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
@@ -1729,6 +1683,14 @@ define half @op_fmin(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %0 = tail call half @llvm.minnum.f16(half %a, half %b)
   ret half %0
@@ -1785,14 +1747,6 @@ define half @op_fmax(half %a, half %b) nounwind {
 ; 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
@@ -1817,6 +1771,14 @@ define half @op_fmax(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    lfd 30, -16(1) # 8-byte Folded Reload
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %0 = tail call half @llvm.maxnum.f16(half %a, half %b)
   ret half %0
@@ -1890,39 +1852,6 @@ define half @test_minimum(half %a, half %b) nounwind {
 ; 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:    addis 3, L..C0 at u(2)
-; P9-AIX-64-NEXT:    ld 3, L..C0 at l(3)
-; 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
@@ -1956,6 +1885,39 @@ define half @test_minimum(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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:    addis 3, L..C0 at u(2)
+; P9-AIX-64-NEXT:    ld 3, L..C0 at l(3)
+; P9-AIX-64-NEXT:    lfs 0, 0(3)
+; P9-AIX-64-NEXT:    xscvdphp 1, 0
+; P9-AIX-64-NEXT:    blr
+;
 ; P9-LINUX-64-LABEL: test_minimum:
 ; P9-LINUX-64:       # %bb.0: # %entry
 ; P9-LINUX-64-NEXT:    xscvhpdp 0, 2
@@ -2044,39 +2006,6 @@ define half @test_maximum(half %a, half %b) nounwind {
 ; 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:    addis 3, L..C1 at u(2)
-; P9-AIX-64-NEXT:    ld 3, L..C1 at l(3)
-; 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
@@ -2110,6 +2039,39 @@ define half @test_maximum(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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:    addis 3, L..C1 at u(2)
+; P9-AIX-64-NEXT:    ld 3, L..C1 at l(3)
+; P9-AIX-64-NEXT:    lfs 0, 0(3)
+; P9-AIX-64-NEXT:    xscvdphp 1, 0
+; P9-AIX-64-NEXT:    blr
+;
 ; P9-LINUX-64-LABEL: test_maximum:
 ; P9-LINUX-64:       # %bb.0: # %entry
 ; P9-LINUX-64-NEXT:    xscvhpdp 0, 2
@@ -2166,13 +2128,6 @@ define half @op_ceil(half %a) nounwind {
 ; 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
@@ -2187,6 +2142,13 @@ define half @op_ceil(half %a) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %0 = tail call half @llvm.ceil.f16(half %a)
   ret half %0
@@ -2223,13 +2185,6 @@ define half @op_floor(half %a) nounwind {
 ; 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
@@ -2244,6 +2199,13 @@ define half @op_floor(half %a) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %0 = tail call half @llvm.floor.f16(half %a)
   ret half %0
@@ -2280,13 +2242,6 @@ define half @op_trunc(half %a) nounwind {
 ; 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
@@ -2301,6 +2256,13 @@ define half @op_trunc(half %a) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %0 = tail call half @llvm.trunc.f16(half %a)
   ret half %0
@@ -2337,13 +2299,6 @@ define half @op_round(half %a) nounwind {
 ; 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
@@ -2358,6 +2313,13 @@ define half @op_round(half %a) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %0 = tail call half @llvm.round.f16(half %a)
   ret half %0
@@ -2394,13 +2356,6 @@ define half @op_rint(half %a) nounwind {
 ; 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
@@ -2415,6 +2370,13 @@ define half @op_rint(half %a) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
 entry:
   %0 = tail call half @llvm.rint.f16(half %a)
   ret half %0
@@ -2453,6 +2415,22 @@ define half @op_nearbyint(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: op_nearbyint:
 ; P9-AIX-32:       # %bb.0: # %entry
 ; P9-AIX-32-NEXT:    mflr 0
@@ -2481,22 +2459,6 @@ define half @op_nearbyint(half %a) nounwind {
 ; 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
@@ -2548,6 +2510,22 @@ define half @test_roundeven(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_roundeven:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -2576,22 +2554,6 @@ define half @test_roundeven(half %a) nounwind {
 ; 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
@@ -2615,19 +2577,12 @@ define half @test_roundeven(half %a) nounwind {
 ; ========================================================================================
 
 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
+; P8-LABEL: test_fabs:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mffprwz 3, 1
+; P8-NEXT:    clrlwi 3, 3, 17
+; P8-NEXT:    mtfprwz 1, 3
+; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_fabs:
 ; P9:       # %bb.0: # %entry
@@ -2635,32 +2590,18 @@ define half @test_fabs(half %a) nounwind {
 ; 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
+; P8-LABEL: test_fneg:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mffprwz 3, 1
+; P8-NEXT:    xori 3, 3, 32768
+; P8-NEXT:    mtfprwz 1, 3
+; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_fneg:
 ; P9:       # %bb.0: # %entry
@@ -2668,38 +2609,21 @@ define half @test_fneg(half %a) nounwind {
 ; 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
+; P8-LABEL: test_fcopysign:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mffprwz 3, 2
+; P8-NEXT:    mffprwz 4, 1
+; P8-NEXT:    rlwinm 3, 3, 0, 16, 16
+; P8-NEXT:    clrlwi 4, 4, 17
+; P8-NEXT:    or 3, 4, 3
+; P8-NEXT:    mtfprwz 1, 3
+; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_fcopysign:
 ; P9:       # %bb.0: # %entry
@@ -2710,16 +2634,6 @@ define half @test_fcopysign(half %mag, half %sign) nounwind {
 ; 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
@@ -2761,13 +2675,6 @@ define half @test_canonicalize(half %a) nounwind {
 ; 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
@@ -2782,6 +2689,13 @@ define half @test_canonicalize(half %a) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
     %r = call half @llvm.canonicalize.f16(half %a)
     ret half %r
 }
@@ -2846,36 +2760,6 @@ define half @test_pow(half %a, half %b) nounwind {
 ; 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
@@ -2903,6 +2787,36 @@ define half @test_pow(half %a, half %b) nounwind {
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-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
+;
 ; P9-LINUX-64-LABEL: test_pow:
 ; P9-LINUX-64:       # %bb.0:
 ; P9-LINUX-64-NEXT:    mflr 0
@@ -2959,6 +2873,22 @@ define half @test_log(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_log:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -2987,22 +2917,6 @@ define half @test_log(half %a) nounwind {
 ; 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
@@ -3053,6 +2967,22 @@ define half @test_log2(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_log2:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -3081,22 +3011,6 @@ define half @test_log2(half %a) nounwind {
 ; 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
@@ -3147,6 +3061,22 @@ define half @test_log10(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_log10:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -3175,22 +3105,6 @@ define half @test_log10(half %a) nounwind {
 ; 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
@@ -3246,6 +3160,22 @@ define half @test_exp(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_exp:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -3274,22 +3204,6 @@ define half @test_exp(half %a) nounwind {
 ; 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
@@ -3340,6 +3254,22 @@ define half @test_exp2(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_exp2:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -3368,22 +3298,6 @@ define half @test_exp2(half %a) nounwind {
 ; 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
@@ -3434,6 +3348,22 @@ define half @test_exp10(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_exp10:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -3462,22 +3392,6 @@ define half @test_exp10(half %a) nounwind {
 ; 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
@@ -3533,6 +3447,22 @@ define half @test_sin(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_sin:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -3561,22 +3491,6 @@ define half @test_sin(half %a) nounwind {
 ; 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
@@ -3627,6 +3541,22 @@ define half @test_cos(half %a) nounwind {
 ; P8-AIX-64-NEXT:    mtlr 0
 ; P8-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-AIX-32-LABEL: test_cos:
 ; P9-AIX-32:       # %bb.0:
 ; P9-AIX-32-NEXT:    mflr 0
@@ -3655,22 +3585,6 @@ define half @test_cos(half %a) nounwind {
 ; 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
@@ -3691,7 +3605,7 @@ define half @test_cos(half %a) nounwind {
 ; ========================================================================================
 ; Type Conversion Operations
 ; ISD::FP_EXTEND (f16->f32/f64), ISD::FP_ROUND (f32/f64->f16)
-; P9+: Hardware (xscvhpdp/xscvdphp), P8: Library calls
+; P9+ uses hardware (xscvhpdp/xscvdphp); P8 uses library calls.
 ; ========================================================================================
 
 define float @op_f16_to_f32(half %h) nounwind {
@@ -3719,11 +3633,6 @@ define float @op_f16_to_f32(half %h) nounwind {
 ; 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
@@ -3735,6 +3644,11 @@ define float @op_f16_to_f32(half %h) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-64-NEXT:    blr
+;
+; P9-LABEL: op_f16_to_f32:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp 1, 1
+; P9-NEXT:    blr
 entry:
   %conv = fpext half %h to float
   ret float %conv
@@ -3765,11 +3679,6 @@ define double @op_f16_to_f64(half %h) nounwind {
 ; 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
@@ -3781,6 +3690,11 @@ define double @op_f16_to_f64(half %h) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-64-NEXT:    blr
+;
+; P9-LABEL: op_f16_to_f64:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp 1, 1
+; P9-NEXT:    blr
 entry:
   %conv = fpext half %h to double
   ret double %conv
@@ -3811,11 +3725,6 @@ define half @op_f32_to_f16(float %f) nounwind {
 ; 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
@@ -3827,6 +3736,11 @@ define half @op_f32_to_f16(float %f) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-64-NEXT:    blr
+;
+; P9-LABEL: op_f32_to_f16:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvdphp 1, 1
+; P9-NEXT:    blr
 entry:
   %conv = fptrunc float %f to half
   ret half %conv
@@ -3857,11 +3771,6 @@ define half @op_f64_to_f16(double %d) nounwind {
 ; 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
@@ -3873,6 +3782,11 @@ define half @op_f64_to_f16(double %d) nounwind {
 ; P8-LINUX-64-NEXT:    ld 0, 16(1)
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-64-NEXT:    blr
+;
+; P9-LABEL: op_f64_to_f16:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvdphp 1, 1
+; P9-NEXT:    blr
 entry:
   %conv = fptrunc double %d to half
   ret half %conv
@@ -3881,26 +3795,19 @@ entry:
 ; ========================================================================================
 ; Bitcast Operations
 ; Bitcast between f16 and i16 (no conversion, reinterpret bits)
-; Test that bitcast between i16 and half is lossless when -mfloat16 is active.
+; Test that bitcast between i16 and half is lossless.
 ; 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
+; P8-LABEL: to_half:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    sth 3, -2(1)
+; P8-NEXT:    lhz 3, -2(1)
+; P8-NEXT:    mtfprwz 1, 3
+; P8-NEXT:    blr
 ;
 ; P9-LABEL: to_half:
 ; P9:       # %bb.0: # %entry
@@ -3908,32 +3815,18 @@ define half @to_half(i16 %bits) nounwind {
 ; 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
+; P8-LABEL: from_half:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mffprwz 3, 1
+; P8-NEXT:    sth 3, -2(1)
+; P8-NEXT:    lhz 3, -2(1)
+; P8-NEXT:    blr
 ;
 ; P9-LABEL: from_half:
 ; P9:       # %bb.0: # %entry
@@ -3941,13 +3834,6 @@ define i16 @from_half(half %f) nounwind {
 ; 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
@@ -3958,7 +3844,7 @@ entry:
 ; llvm/llvm-project#97975
 ; ========================================================================================
 ; Test that consecutive half operations round intermediate results back to f16
-; precision between each operation when -mfloat16 is active.
+; precision between each operation.
 ; 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:
@@ -4041,18 +3927,6 @@ define half @consecutive_add(half %a, half %b, half %c) nounwind {
 ; 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
@@ -4089,6 +3963,18 @@ define half @consecutive_add(half %a, half %b, half %c) nounwind {
 ; P8-LINUX-64-NEXT:    mtlr 0
 ; P8-LINUX-64-NEXT:    lfd 29, -24(1) # 8-byte Folded Reload
 ; P8-LINUX-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
 entry:
     %d = fadd half %a, %b
     %e = fadd half %d, %c
@@ -4116,6 +4002,13 @@ define half @test_constant_fp() nounwind {
 ; P8-AIX-64-NEXT:    mtfprwz 1, 3
 ; P8-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-AIX-32-LABEL: test_constant_fp:
 ; P9-AIX-32:       # %bb.0: # %entry
 ; P9-AIX-32-NEXT:    lwz 3, L..C2(2) # %const.0
@@ -4129,13 +4022,6 @@ define half @test_constant_fp() nounwind {
 ; 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
@@ -4162,6 +4048,13 @@ define half @test_constant_zero() nounwind {
 ; P8-AIX-64-NEXT:    mtfprwz 1, 3
 ; P8-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-AIX-32-LABEL: test_constant_zero:
 ; P9-AIX-32:       # %bb.0: # %entry
 ; P9-AIX-32-NEXT:    lwz 3, L..C3(2) # %const.0
@@ -4175,13 +4068,6 @@ define half @test_constant_zero() nounwind {
 ; 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
@@ -4192,6 +4078,694 @@ entry:
   ret half 0.0
 }
 
+; f16 <-> integer conversions. The FP_TO_SINT/FP_TO_UINT paths must extend the
+; f16 operand to f32 (xscvhpdp on P9, __extendhfsf2 on P8) before converting;
+; otherwise the f16 value is wrongly treated as an f64 (a bare xscvdpsx*s with
+; no preceding xscvhpdp), silently producing the wrong result.
+define i32 @fptosi_i32(half %a) nounwind {
+; P8-AIX-32-LABEL: fptosi_i32:
+; 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:    xscvdpsxws 0, 1
+; P8-AIX-32-NEXT:    addi 3, 1, 60
+; P8-AIX-32-NEXT:    stfiwx 0, 0, 3
+; P8-AIX-32-NEXT:    lwz 3, 60(1)
+; 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: fptosi_i32:
+; 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:    xscvdpsxws 0, 1
+; P8-AIX-64-NEXT:    mffprwz 3, 0
+; 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
+;
+; P8-LINUX-64-LABEL: fptosi_i32:
+; 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:    xscvdpsxws 0, 1
+; P8-LINUX-64-NEXT:    mffprwz 3, 0
+; 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-AIX-32-LABEL: fptosi_i32:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    xscvhpdp 0, 1
+; P9-AIX-32-NEXT:    addi 3, 1, -4
+; P9-AIX-32-NEXT:    xscvdpsxws 0, 0
+; P9-AIX-32-NEXT:    stfiwx 0, 0, 3
+; P9-AIX-32-NEXT:    lwz 3, -4(1)
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: fptosi_i32:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    xscvhpdp 0, 1
+; P9-AIX-64-NEXT:    xscvdpsxws 0, 0
+; P9-AIX-64-NEXT:    mffprwz 3, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: fptosi_i32:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    xscvhpdp 0, 1
+; P9-LINUX-64-NEXT:    xscvdpsxws 0, 0
+; P9-LINUX-64-NEXT:    mffprwz 3, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = fptosi half %a to i32
+  ret i32 %r
+}
+
+define i32 @fptoui_i32(half %a) nounwind {
+; P8-AIX-32-LABEL: fptoui_i32:
+; 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:    xscvdpuxws 0, 1
+; P8-AIX-32-NEXT:    addi 3, 1, 60
+; P8-AIX-32-NEXT:    stfiwx 0, 0, 3
+; P8-AIX-32-NEXT:    lwz 3, 60(1)
+; 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: fptoui_i32:
+; 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:    xscvdpuxws 0, 1
+; P8-AIX-64-NEXT:    mffprwz 3, 0
+; 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
+;
+; P8-LINUX-64-LABEL: fptoui_i32:
+; 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:    xscvdpuxws 0, 1
+; P8-LINUX-64-NEXT:    mffprwz 3, 0
+; 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-AIX-32-LABEL: fptoui_i32:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    xscvhpdp 0, 1
+; P9-AIX-32-NEXT:    addi 3, 1, -4
+; P9-AIX-32-NEXT:    xscvdpuxws 0, 0
+; P9-AIX-32-NEXT:    stfiwx 0, 0, 3
+; P9-AIX-32-NEXT:    lwz 3, -4(1)
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: fptoui_i32:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    xscvhpdp 0, 1
+; P9-AIX-64-NEXT:    xscvdpuxws 0, 0
+; P9-AIX-64-NEXT:    mffprwz 3, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: fptoui_i32:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    xscvhpdp 0, 1
+; P9-LINUX-64-NEXT:    xscvdpuxws 0, 0
+; P9-LINUX-64-NEXT:    mffprwz 3, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = fptoui half %a to i32
+  ret i32 %r
+}
+
+define i64 @fptosi_i64(half %a) nounwind {
+; P8-AIX-32-LABEL: fptosi_i64:
+; 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:    xscvdpsxds 0, 1
+; P8-AIX-32-NEXT:    stfd 0, 56(1)
+; P8-AIX-32-NEXT:    lwz 3, 56(1)
+; P8-AIX-32-NEXT:    lwz 4, 60(1)
+; 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: fptosi_i64:
+; 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:    xscvdpsxds 0, 1
+; P8-AIX-64-NEXT:    mffprd 3, 0
+; 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
+;
+; P8-LINUX-64-LABEL: fptosi_i64:
+; 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:    xscvdpsxds 0, 1
+; P8-LINUX-64-NEXT:    mffprd 3, 0
+; 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-AIX-32-LABEL: fptosi_i64:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    xscvhpdp 0, 1
+; P9-AIX-32-NEXT:    xscvdpsxds 0, 0
+; P9-AIX-32-NEXT:    stfd 0, -8(1)
+; P9-AIX-32-NEXT:    lwz 3, -8(1)
+; P9-AIX-32-NEXT:    lwz 4, -4(1)
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: fptosi_i64:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    xscvhpdp 0, 1
+; P9-AIX-64-NEXT:    xscvdpsxds 0, 0
+; P9-AIX-64-NEXT:    mffprd 3, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: fptosi_i64:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    xscvhpdp 0, 1
+; P9-LINUX-64-NEXT:    xscvdpsxds 0, 0
+; P9-LINUX-64-NEXT:    mffprd 3, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = fptosi half %a to i64
+  ret i64 %r
+}
+
+define i64 @fptoui_i64(half %a) nounwind {
+; P8-AIX-32-LABEL: fptoui_i64:
+; 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:    xscvdpuxds 0, 1
+; P8-AIX-32-NEXT:    stfd 0, 56(1)
+; P8-AIX-32-NEXT:    lwz 3, 56(1)
+; P8-AIX-32-NEXT:    lwz 4, 60(1)
+; 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: fptoui_i64:
+; 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:    xscvdpuxds 0, 1
+; P8-AIX-64-NEXT:    mffprd 3, 0
+; 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
+;
+; P8-LINUX-64-LABEL: fptoui_i64:
+; 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:    xscvdpuxds 0, 1
+; P8-LINUX-64-NEXT:    mffprd 3, 0
+; 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-AIX-32-LABEL: fptoui_i64:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    xscvhpdp 0, 1
+; P9-AIX-32-NEXT:    xscvdpuxds 0, 0
+; P9-AIX-32-NEXT:    stfd 0, -8(1)
+; P9-AIX-32-NEXT:    lwz 3, -8(1)
+; P9-AIX-32-NEXT:    lwz 4, -4(1)
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: fptoui_i64:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    xscvhpdp 0, 1
+; P9-AIX-64-NEXT:    xscvdpuxds 0, 0
+; P9-AIX-64-NEXT:    mffprd 3, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: fptoui_i64:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    xscvhpdp 0, 1
+; P9-LINUX-64-NEXT:    xscvdpuxds 0, 0
+; P9-LINUX-64-NEXT:    mffprd 3, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = fptoui half %a to i64
+  ret i64 %r
+}
+
+define half @sitofp_i32(i32 %a) nounwind {
+; P8-AIX-32-LABEL: sitofp_i32:
+; 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:    stw 3, 60(1)
+; P8-AIX-32-NEXT:    addi 3, 1, 60
+; P8-AIX-32-NEXT:    lfiwax 0, 0, 3
+; P8-AIX-32-NEXT:    xscvsxddp 1, 0
+; 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: sitofp_i32:
+; P8-AIX-64:       # %bb.0: # %entry
+; P8-AIX-64-NEXT:    mflr 0
+; P8-AIX-64-NEXT:    stdu 1, -112(1)
+; P8-AIX-64-NEXT:    mtfprwa 0, 3
+; P8-AIX-64-NEXT:    std 0, 128(1)
+; P8-AIX-64-NEXT:    xscvsxddp 1, 0
+; 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
+;
+; P8-LINUX-64-LABEL: sitofp_i32:
+; P8-LINUX-64:       # %bb.0: # %entry
+; P8-LINUX-64-NEXT:    mflr 0
+; P8-LINUX-64-NEXT:    stdu 1, -32(1)
+; P8-LINUX-64-NEXT:    mtfprwa 0, 3
+; P8-LINUX-64-NEXT:    std 0, 48(1)
+; P8-LINUX-64-NEXT:    xscvsxddp 1, 0
+; 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
+;
+; P9-AIX-32-LABEL: sitofp_i32:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    stw 3, -4(1)
+; P9-AIX-32-NEXT:    addi 3, 1, -4
+; P9-AIX-32-NEXT:    lfiwax 0, 0, 3
+; P9-AIX-32-NEXT:    xscvsxddp 0, 0
+; P9-AIX-32-NEXT:    xscvdphp 1, 0
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: sitofp_i32:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    mtfprwa 0, 3
+; P9-AIX-64-NEXT:    xscvsxddp 0, 0
+; P9-AIX-64-NEXT:    xscvdphp 1, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: sitofp_i32:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    mtfprwa 0, 3
+; P9-LINUX-64-NEXT:    xscvsxddp 0, 0
+; P9-LINUX-64-NEXT:    xscvdphp 1, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = sitofp i32 %a to half
+  ret half %r
+}
+
+define half @uitofp_i32(i32 %a) nounwind {
+; P8-AIX-32-LABEL: uitofp_i32:
+; 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:    stw 3, 60(1)
+; P8-AIX-32-NEXT:    addi 3, 1, 60
+; P8-AIX-32-NEXT:    lfiwzx 0, 0, 3
+; P8-AIX-32-NEXT:    xscvuxddp 1, 0
+; 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: uitofp_i32:
+; P8-AIX-64:       # %bb.0: # %entry
+; P8-AIX-64-NEXT:    mflr 0
+; P8-AIX-64-NEXT:    stdu 1, -112(1)
+; P8-AIX-64-NEXT:    mtfprwz 0, 3
+; P8-AIX-64-NEXT:    std 0, 128(1)
+; P8-AIX-64-NEXT:    xscvuxddp 1, 0
+; 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
+;
+; P8-LINUX-64-LABEL: uitofp_i32:
+; P8-LINUX-64:       # %bb.0: # %entry
+; P8-LINUX-64-NEXT:    mflr 0
+; P8-LINUX-64-NEXT:    stdu 1, -32(1)
+; P8-LINUX-64-NEXT:    mtfprwz 0, 3
+; P8-LINUX-64-NEXT:    std 0, 48(1)
+; P8-LINUX-64-NEXT:    xscvuxddp 1, 0
+; 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
+;
+; P9-AIX-32-LABEL: uitofp_i32:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    stw 3, -4(1)
+; P9-AIX-32-NEXT:    addi 3, 1, -4
+; P9-AIX-32-NEXT:    lfiwzx 0, 0, 3
+; P9-AIX-32-NEXT:    xscvuxddp 0, 0
+; P9-AIX-32-NEXT:    xscvdphp 1, 0
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: uitofp_i32:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    mtfprwz 0, 3
+; P9-AIX-64-NEXT:    xscvuxddp 0, 0
+; P9-AIX-64-NEXT:    xscvdphp 1, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: uitofp_i32:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    mtfprwz 0, 3
+; P9-LINUX-64-NEXT:    xscvuxddp 0, 0
+; P9-LINUX-64-NEXT:    xscvdphp 1, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = uitofp i32 %a to half
+  ret half %r
+}
+
+; i64 -> f16 must round through f64 (xscvsxddp/xscvudddp + xscvdphp on P9), not
+; fall back to a __floatdihf/__floatundihf libcall that the runtime lacks.
+define half @sitofp_i64(i64 %a) nounwind {
+; P8-AIX-32-LABEL: sitofp_i64:
+; 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:    stw 4, 60(1)
+; P8-AIX-32-NEXT:    stw 3, 56(1)
+; P8-AIX-32-NEXT:    lfd 0, 56(1)
+; P8-AIX-32-NEXT:    xscvsxddp 1, 0
+; 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: sitofp_i64:
+; P8-AIX-64:       # %bb.0: # %entry
+; P8-AIX-64-NEXT:    mflr 0
+; P8-AIX-64-NEXT:    stdu 1, -112(1)
+; P8-AIX-64-NEXT:    mtfprd 0, 3
+; P8-AIX-64-NEXT:    std 0, 128(1)
+; P8-AIX-64-NEXT:    xscvsxddp 1, 0
+; 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
+;
+; P8-LINUX-64-LABEL: sitofp_i64:
+; P8-LINUX-64:       # %bb.0: # %entry
+; P8-LINUX-64-NEXT:    mflr 0
+; P8-LINUX-64-NEXT:    stdu 1, -32(1)
+; P8-LINUX-64-NEXT:    mtfprd 0, 3
+; P8-LINUX-64-NEXT:    std 0, 48(1)
+; P8-LINUX-64-NEXT:    xscvsxddp 1, 0
+; 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
+;
+; P9-AIX-32-LABEL: sitofp_i64:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    stw 4, -4(1)
+; P9-AIX-32-NEXT:    stw 3, -8(1)
+; P9-AIX-32-NEXT:    lfd 0, -8(1)
+; P9-AIX-32-NEXT:    xscvsxddp 0, 0
+; P9-AIX-32-NEXT:    xscvdphp 1, 0
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: sitofp_i64:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    mtfprd 0, 3
+; P9-AIX-64-NEXT:    xscvsxddp 0, 0
+; P9-AIX-64-NEXT:    xscvdphp 1, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: sitofp_i64:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    mtfprd 0, 3
+; P9-LINUX-64-NEXT:    xscvsxddp 0, 0
+; P9-LINUX-64-NEXT:    xscvdphp 1, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = sitofp i64 %a to half
+  ret half %r
+}
+
+define half @uitofp_i64(i64 %a) nounwind {
+; P8-AIX-32-LABEL: uitofp_i64:
+; 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:    stw 4, 60(1)
+; P8-AIX-32-NEXT:    stw 3, 56(1)
+; P8-AIX-32-NEXT:    lfd 0, 56(1)
+; P8-AIX-32-NEXT:    xscvuxddp 1, 0
+; 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: uitofp_i64:
+; P8-AIX-64:       # %bb.0: # %entry
+; P8-AIX-64-NEXT:    mflr 0
+; P8-AIX-64-NEXT:    stdu 1, -112(1)
+; P8-AIX-64-NEXT:    mtfprd 0, 3
+; P8-AIX-64-NEXT:    std 0, 128(1)
+; P8-AIX-64-NEXT:    xscvuxddp 1, 0
+; 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
+;
+; P8-LINUX-64-LABEL: uitofp_i64:
+; P8-LINUX-64:       # %bb.0: # %entry
+; P8-LINUX-64-NEXT:    mflr 0
+; P8-LINUX-64-NEXT:    stdu 1, -32(1)
+; P8-LINUX-64-NEXT:    mtfprd 0, 3
+; P8-LINUX-64-NEXT:    std 0, 48(1)
+; P8-LINUX-64-NEXT:    xscvuxddp 1, 0
+; 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
+;
+; P9-AIX-32-LABEL: uitofp_i64:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    stw 4, -4(1)
+; P9-AIX-32-NEXT:    stw 3, -8(1)
+; P9-AIX-32-NEXT:    lfd 0, -8(1)
+; P9-AIX-32-NEXT:    xscvuxddp 0, 0
+; P9-AIX-32-NEXT:    xscvdphp 1, 0
+; P9-AIX-32-NEXT:    blr
+;
+; P9-AIX-64-LABEL: uitofp_i64:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    mtfprd 0, 3
+; P9-AIX-64-NEXT:    xscvuxddp 0, 0
+; P9-AIX-64-NEXT:    xscvdphp 1, 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: uitofp_i64:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    mtfprd 0, 3
+; P9-LINUX-64-NEXT:    xscvuxddp 0, 0
+; P9-LINUX-64-NEXT:    xscvdphp 1, 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  %r = uitofp i64 %a to half
+  ret half %r
+}
+
+; A half passed to a variadic callee. On ELFv2 the unnamed arg is placed in both
+; an FPR and a GPR; the GPR copy must bitcast the 16-bit half to i16 and extend
+; (a direct bitcast to i64 asserts "Cannot BITCAST between types of different
+; sizes!"). Must compile without crashing.
+declare void @vararg_sink(i32, ...)
+define void @call_vararg_f16(half %x) nounwind {
+; P8-AIX-32-LABEL: call_vararg_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:    mffprwz 3, 1
+; P8-AIX-32-NEXT:    stw 0, 72(1)
+; P8-AIX-32-NEXT:    sth 3, 62(1)
+; P8-AIX-32-NEXT:    li 3, 1
+; P8-AIX-32-NEXT:    lhz 4, 62(1)
+; P8-AIX-32-NEXT:    bl .vararg_sink[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: call_vararg_f16:
+; P8-AIX-64:       # %bb.0: # %entry
+; P8-AIX-64-NEXT:    mflr 0
+; P8-AIX-64-NEXT:    stdu 1, -128(1)
+; P8-AIX-64-NEXT:    mffprwz 3, 1
+; P8-AIX-64-NEXT:    std 0, 144(1)
+; P8-AIX-64-NEXT:    sth 3, 126(1)
+; P8-AIX-64-NEXT:    li 3, 1
+; P8-AIX-64-NEXT:    lhz 4, 126(1)
+; P8-AIX-64-NEXT:    bl .vararg_sink[PR]
+; P8-AIX-64-NEXT:    nop
+; 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
+;
+; P8-LINUX-64-LABEL: call_vararg_f16:
+; P8-LINUX-64:       # %bb.0: # %entry
+; P8-LINUX-64-NEXT:    mflr 0
+; P8-LINUX-64-NEXT:    stdu 1, -112(1)
+; P8-LINUX-64-NEXT:    mffprwz 3, 1
+; P8-LINUX-64-NEXT:    std 0, 128(1)
+; P8-LINUX-64-NEXT:    sth 3, 110(1)
+; P8-LINUX-64-NEXT:    li 3, 1
+; P8-LINUX-64-NEXT:    lhz 4, 110(1)
+; P8-LINUX-64-NEXT:    bl vararg_sink
+; P8-LINUX-64-NEXT:    nop
+; P8-LINUX-64-NEXT:    addi 1, 1, 112
+; P8-LINUX-64-NEXT:    ld 0, 16(1)
+; P8-LINUX-64-NEXT:    mtlr 0
+; P8-LINUX-64-NEXT:    blr
+;
+; P9-AIX-32-LABEL: call_vararg_f16:
+; P9-AIX-32:       # %bb.0: # %entry
+; P9-AIX-32-NEXT:    mflr 0
+; P9-AIX-32-NEXT:    stwu 1, -64(1)
+; P9-AIX-32-NEXT:    addi 3, 1, 62
+; P9-AIX-32-NEXT:    stw 0, 72(1)
+; P9-AIX-32-NEXT:    stxsihx 1, 0, 3
+; P9-AIX-32-NEXT:    li 3, 1
+; P9-AIX-32-NEXT:    lhz 4, 62(1)
+; P9-AIX-32-NEXT:    bl .vararg_sink[PR]
+; P9-AIX-32-NEXT:    nop
+; 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: call_vararg_f16:
+; P9-AIX-64:       # %bb.0: # %entry
+; P9-AIX-64-NEXT:    mflr 0
+; P9-AIX-64-NEXT:    stdu 1, -128(1)
+; P9-AIX-64-NEXT:    addi 3, 1, 126
+; P9-AIX-64-NEXT:    std 0, 144(1)
+; P9-AIX-64-NEXT:    stxsihx 1, 0, 3
+; P9-AIX-64-NEXT:    li 3, 1
+; P9-AIX-64-NEXT:    lhz 4, 126(1)
+; P9-AIX-64-NEXT:    bl .vararg_sink[PR]
+; P9-AIX-64-NEXT:    nop
+; P9-AIX-64-NEXT:    addi 1, 1, 128
+; P9-AIX-64-NEXT:    ld 0, 16(1)
+; P9-AIX-64-NEXT:    mtlr 0
+; P9-AIX-64-NEXT:    blr
+;
+; P9-LINUX-64-LABEL: call_vararg_f16:
+; P9-LINUX-64:       # %bb.0: # %entry
+; P9-LINUX-64-NEXT:    mflr 0
+; P9-LINUX-64-NEXT:    stdu 1, -112(1)
+; P9-LINUX-64-NEXT:    addi 3, 1, 110
+; P9-LINUX-64-NEXT:    std 0, 128(1)
+; P9-LINUX-64-NEXT:    stxsihx 1, 0, 3
+; P9-LINUX-64-NEXT:    li 3, 1
+; P9-LINUX-64-NEXT:    lhz 4, 110(1)
+; P9-LINUX-64-NEXT:    bl vararg_sink
+; P9-LINUX-64-NEXT:    nop
+; P9-LINUX-64-NEXT:    addi 1, 1, 112
+; P9-LINUX-64-NEXT:    ld 0, 16(1)
+; P9-LINUX-64-NEXT:    mtlr 0
+; P9-LINUX-64-NEXT:    blr
+entry:
+  call void (i32, ...) @vararg_sink(i32 1, half %x)
+  ret void
+}
+
 ; ========================================================================================
 ; Intrinsic Declarations
 ; ========================================================================================
diff --git a/llvm/test/CodeGen/PowerPC/half.ll b/llvm/test/CodeGen/PowerPC/half.ll
index e0284c7597618..bfc6072e4d39e 100644
--- a/llvm/test/CodeGen/PowerPC/half.ll
+++ b/llvm/test/CodeGen/PowerPC/half.ll
@@ -517,15 +517,24 @@ define i64 @test_fptosi_i64(ptr %p) nounwind {
 ;
 ; P8-LABEL: test_fptosi_i64:
 ; P8:       # %bb.0:
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
 ; P8-NEXT:    lhzx r3, 0, r3
-; P8-NEXT:    mtfprwz f0, r3
-; P8-NEXT:    xscvdpsxds f0, f0
+; P8-NEXT:    mtfprwz f1, r3
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    xscvdpsxds f0, f1
 ; P8-NEXT:    mffprd r3, f0
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
 ; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_fptosi_i64:
 ; P9:       # %bb.0:
 ; P9-NEXT:    lxsihzx f0, 0, r3
+; P9-NEXT:    xscvhpdp f0, f0
 ; P9-NEXT:    xscvdpsxds f0, f0
 ; P9-NEXT:    mffprd r3, f0
 ; P9-NEXT:    blr
@@ -572,8 +581,8 @@ define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
 ; PPC32-NEXT:    stw r0, 20(r1)
 ; PPC32-NEXT:    stw r30, 8(r1) # 4-byte Folded Spill
 ; PPC32-NEXT:    mr r30, r5
-; PPC32-NEXT:    bl __floatdisf
-; PPC32-NEXT:    bl __truncsfhf2
+; PPC32-NEXT:    bl __floatdidf
+; PPC32-NEXT:    bl __truncdfhf2
 ; PPC32-NEXT:    sth r3, 0(r30)
 ; PPC32-NEXT:    lwz r30, 8(r1) # 4-byte Folded Reload
 ; PPC32-NEXT:    lwz r0, 20(r1)
@@ -586,9 +595,11 @@ define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stdu r1, -48(r1)
+; P8-NEXT:    mtfprd f0, r3
 ; P8-NEXT:    std r0, 64(r1)
 ; P8-NEXT:    mr r30, r4
-; P8-NEXT:    bl __floatdihf
+; P8-NEXT:    xscvsxddp f1, f0
+; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    mffprwz r3, f1
 ; P8-NEXT:    sthx r3, 0, r30
@@ -600,18 +611,10 @@ define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
 ;
 ; P9-LABEL: test_sitofp_i64:
 ; P9:       # %bb.0:
-; P9-NEXT:    mflr r0
-; P9-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
-; P9-NEXT:    stdu r1, -48(r1)
-; P9-NEXT:    std r0, 64(r1)
-; P9-NEXT:    mr r30, r4
-; P9-NEXT:    bl __floatdihf
-; P9-NEXT:    nop
-; P9-NEXT:    stxsihx f1, 0, r30
-; P9-NEXT:    addi r1, r1, 48
-; P9-NEXT:    ld r0, 16(r1)
-; P9-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
-; P9-NEXT:    mtlr r0
+; P9-NEXT:    mtfprd f0, r3
+; P9-NEXT:    xscvsxddp f0, f0
+; P9-NEXT:    xscvdphp f0, f0
+; P9-NEXT:    stxsihx f0, 0, r4
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_sitofp_i64:
@@ -621,10 +624,9 @@ define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
 ; SOFT-NEXT:    stdu r1, -48(r1)
 ; SOFT-NEXT:    std r0, 64(r1)
 ; SOFT-NEXT:    mr r30, r4
-; SOFT-NEXT:    bl __floatdisf
+; SOFT-NEXT:    bl __floatdidf
 ; SOFT-NEXT:    nop
-; SOFT-NEXT:    clrldi r3, r3, 32
-; SOFT-NEXT:    bl __truncsfhf2
+; SOFT-NEXT:    bl __truncdfhf2
 ; SOFT-NEXT:    nop
 ; SOFT-NEXT:    sth r3, 0(r30)
 ; SOFT-NEXT:    addi r1, r1, 48
@@ -637,24 +639,13 @@ define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
 ; BE:       # %bb.0:
 ; BE-NEXT:    mflr r0
 ; BE-NEXT:    stdu r1, -144(r1)
-; BE-NEXT:    sradi r5, r3, 53
 ; BE-NEXT:    std r0, 160(r1)
-; BE-NEXT:    addi r5, r5, 1
-; BE-NEXT:    cmpldi r5, 1
-; BE-NEXT:    std r30, 128(r1) # 8-byte Folded Spill
-; BE-NEXT:    mr r30, r4
-; BE-NEXT:    ble cr0, .LBB12_2
-; BE-NEXT:  # %bb.1:
-; BE-NEXT:    clrldi r4, r3, 53
-; BE-NEXT:    addi r4, r4, 2047
-; BE-NEXT:    or r3, r4, r3
-; BE-NEXT:    rldicr r3, r3, 0, 52
-; BE-NEXT:  .LBB12_2:
 ; BE-NEXT:    std r3, 120(r1)
 ; BE-NEXT:    lfd f0, 120(r1)
-; BE-NEXT:    fcfid f0, f0
-; BE-NEXT:    frsp f1, f0
-; BE-NEXT:    bl __truncsfhf2
+; BE-NEXT:    fcfid f1, f0
+; BE-NEXT:    std r30, 128(r1) # 8-byte Folded Spill
+; BE-NEXT:    mr r30, r4
+; BE-NEXT:    bl __truncdfhf2
 ; BE-NEXT:    nop
 ; BE-NEXT:    sth r3, 0(r30)
 ; BE-NEXT:    ld r30, 128(r1) # 8-byte Folded Reload
@@ -682,15 +673,24 @@ define i64 @test_fptoui_i64(ptr %p) nounwind {
 ;
 ; P8-LABEL: test_fptoui_i64:
 ; P8:       # %bb.0:
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
 ; P8-NEXT:    lhzx r3, 0, r3
-; P8-NEXT:    mtfprwz f0, r3
-; P8-NEXT:    xscvdpuxds f0, f0
+; P8-NEXT:    mtfprwz f1, r3
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    xscvdpuxds f0, f1
 ; P8-NEXT:    mffprd r3, f0
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
 ; P8-NEXT:    blr
 ;
 ; P9-LABEL: test_fptoui_i64:
 ; P9:       # %bb.0:
 ; P9-NEXT:    lxsihzx f0, 0, r3
+; P9-NEXT:    xscvhpdp f0, f0
 ; P9-NEXT:    xscvdpuxds f0, f0
 ; P9-NEXT:    mffprd r3, f0
 ; P9-NEXT:    blr
@@ -766,9 +766,11 @@ define void @test_uitofp_i64(i64 %a, ptr %p) nounwind {
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stdu r1, -48(r1)
+; P8-NEXT:    mtfprd f0, r3
 ; P8-NEXT:    std r0, 64(r1)
 ; P8-NEXT:    mr r30, r4
-; P8-NEXT:    bl __floatundihf
+; P8-NEXT:    xscvuxddp f1, f0
+; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    mffprwz r3, f1
 ; P8-NEXT:    sthx r3, 0, r30
@@ -780,18 +782,10 @@ define void @test_uitofp_i64(i64 %a, ptr %p) nounwind {
 ;
 ; P9-LABEL: test_uitofp_i64:
 ; P9:       # %bb.0:
-; P9-NEXT:    mflr r0
-; P9-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
-; P9-NEXT:    stdu r1, -48(r1)
-; P9-NEXT:    std r0, 64(r1)
-; P9-NEXT:    mr r30, r4
-; P9-NEXT:    bl __floatundihf
-; P9-NEXT:    nop
-; P9-NEXT:    stxsihx f1, 0, r30
-; P9-NEXT:    addi r1, r1, 48
-; P9-NEXT:    ld r0, 16(r1)
-; P9-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
-; P9-NEXT:    mtlr r0
+; P9-NEXT:    mtfprd f0, r3
+; P9-NEXT:    xscvuxddp f0, f0
+; P9-NEXT:    xscvdphp f0, f0
+; P9-NEXT:    stxsihx f0, 0, r4
 ; P9-NEXT:    blr
 ;
 ; SOFT-LABEL: test_uitofp_i64:
@@ -1672,9 +1666,8 @@ define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
 ; PPC32-NEXT:    lfd f0, 8(r1)
 ; PPC32-NEXT:    lfs f1, .LCPI19_0 at l(r3)
 ; PPC32-NEXT:    stfd f31, 24(r1) # 8-byte Folded Spill
-; PPC32-NEXT:    fsub f0, f0, f1
-; PPC32-NEXT:    frsp f1, f0
-; PPC32-NEXT:    bl __truncsfhf2
+; PPC32-NEXT:    fsub f1, f0, f1
+; PPC32-NEXT:    bl __truncdfhf2
 ; PPC32-NEXT:    clrlwi r3, r3, 16
 ; PPC32-NEXT:    bl __extendhfsf2
 ; PPC32-NEXT:    mr r3, r30
@@ -1696,18 +1689,12 @@ define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
 ; P8-NEXT:    mflr r0
 ; P8-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
 ; P8-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
-; P8-NEXT:    stdu r1, -64(r1)
-; P8-NEXT:    std r0, 80(r1)
-; P8-NEXT:    xoris r3, r3, 32768
+; P8-NEXT:    stdu r1, -48(r1)
+; P8-NEXT:    mtfprwa f0, r3
+; P8-NEXT:    std r0, 64(r1)
 ; P8-NEXT:    lhzx r4, 0, r4
-; P8-NEXT:    stw r3, 40(r1)
-; P8-NEXT:    addis r3, r2, .LCPI19_0 at toc@ha
 ; P8-NEXT:    mtfprwz f31, r4
-; P8-NEXT:    lis r4, 17200
-; P8-NEXT:    lfs f1, .LCPI19_0 at toc@l(r3)
-; P8-NEXT:    stw r4, 44(r1)
-; P8-NEXT:    lfd f0, 40(r1)
-; P8-NEXT:    xssubdp f1, f0, f1
+; P8-NEXT:    xscvsxddp f1, f0
 ; P8-NEXT:    bl __truncdfhf2
 ; P8-NEXT:    nop
 ; P8-NEXT:    bl __extendhfsf2
@@ -1721,7 +1708,7 @@ define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
 ; P8-NEXT:    nop
 ; P8-NEXT:    bl __extendhfsf2
 ; P8-NEXT:    nop
-; P8-NEXT:    addi r1, r1, 64
+; P8-NEXT:    addi r1, r1, 48
 ; P8-NEXT:    ld r0, 16(r1)
 ; P8-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
 ; P8-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
@@ -1730,18 +1717,12 @@ define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
 ;
 ; P9-LABEL: test_sitofp_fadd_i32:
 ; P9:       # %bb.0:
-; P9-NEXT:    xoris r3, r3, 32768
+; P9-NEXT:    mtfprwa f1, r3
 ; P9-NEXT:    lxsihzx f0, 0, r4
-; P9-NEXT:    lis r4, 17200
-; P9-NEXT:    stw r3, -8(r1)
-; P9-NEXT:    addis r3, r2, .LCPI19_0 at toc@ha
-; P9-NEXT:    stw r4, -4(r1)
-; P9-NEXT:    lfd f1, -8(r1)
-; P9-NEXT:    lfs f2, .LCPI19_0 at toc@l(r3)
-; P9-NEXT:    xssubdp f1, f1, f2
+; P9-NEXT:    xscvsxddp f1, f1
 ; P9-NEXT:    xscvdphp f1, f1
-; P9-NEXT:    xscvhpdp f1, f1
 ; P9-NEXT:    xscvhpdp f0, f0
+; P9-NEXT:    xscvhpdp f1, f1
 ; P9-NEXT:    xsaddsp f0, f0, f1
 ; P9-NEXT:    xscvdphp f0, f0
 ; P9-NEXT:    xscvhpdp f1, f0
@@ -1756,10 +1737,9 @@ define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
 ; SOFT-NEXT:    extsw r3, r3
 ; SOFT-NEXT:    std r0, 80(r1)
 ; SOFT-NEXT:    mr r30, r4
-; SOFT-NEXT:    bl __floatsisf
+; SOFT-NEXT:    bl __floatsidf
 ; SOFT-NEXT:    nop
-; SOFT-NEXT:    clrldi r3, r3, 32
-; SOFT-NEXT:    bl __truncsfhf2
+; SOFT-NEXT:    bl __truncdfhf2
 ; SOFT-NEXT:    nop
 ; SOFT-NEXT:    mr r29, r3
 ; SOFT-NEXT:    lhz r3, 0(r30)
@@ -1795,10 +1775,9 @@ define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
 ; BE-NEXT:    lhz r30, 0(r4)
 ; BE-NEXT:    std r3, 112(r1)
 ; BE-NEXT:    lfd f0, 112(r1)
-; BE-NEXT:    fcfid f0, f0
+; BE-NEXT:    fcfid f1, f0
 ; BE-NEXT:    stfd f31, 136(r1) # 8-byte Folded Spill
-; BE-NEXT:    frsp f1, f0
-; BE-NEXT:    bl __truncsfhf2
+; BE-NEXT:    bl __truncdfhf2
 ; BE-NEXT:    nop
 ; BE-NEXT:    clrldi r3, r3, 48
 ; BE-NEXT:    bl __extendhfsf2
diff --git a/llvm/test/CodeGen/PowerPC/pr48519.ll b/llvm/test/CodeGen/PowerPC/pr48519.ll
index 7a29a90cc3c3e..895a22ff3ee3b 100644
--- a/llvm/test/CodeGen/PowerPC/pr48519.ll
+++ b/llvm/test/CodeGen/PowerPC/pr48519.ll
@@ -14,11 +14,13 @@ define void @julia__typed_vcat_20() #0 {
 ; CHECK-NEXT:    li r30, 0
 ; CHECK-NEXT:    li r3, 1
 ; CHECK-NEXT:    std r0, 64(r1)
-; CHECK-NEXT:    .p2align 5
+; CHECK-NEXT:    .p2align 4
 ; CHECK-NEXT:  .LBB0_1: # %bb3
 ; CHECK-NEXT:    #
 ; CHECK-NEXT:    addi r3, r3, -1
-; CHECK-NEXT:    bl __floatdihf
+; CHECK-NEXT:    mtfprd f0, r3
+; CHECK-NEXT:    xscvsxddp f1, f0
+; CHECK-NEXT:    bl __truncdfhf2
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    addi r30, r30, -1
 ; CHECK-NEXT:    li r3, 0
@@ -30,25 +32,21 @@ define void @julia__typed_vcat_20() #0 {
 ;
 ; CHECK-P9-LABEL: julia__typed_vcat_20:
 ; CHECK-P9:       # %bb.0: # %bb
-; CHECK-P9-NEXT:    mflr r0
-; CHECK-P9-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
-; CHECK-P9-NEXT:    stdu r1, -48(r1)
-; CHECK-P9-NEXT:    li r30, 0
+; CHECK-P9-NEXT:    li r3, 0
+; CHECK-P9-NEXT:    mtctr r3
 ; CHECK-P9-NEXT:    li r3, 1
-; CHECK-P9-NEXT:    std r0, 64(r1)
 ; CHECK-P9-NEXT:    .p2align 5
 ; CHECK-P9-NEXT:  .LBB0_1: # %bb3
 ; CHECK-P9-NEXT:    #
 ; CHECK-P9-NEXT:    addi r3, r3, -1
-; CHECK-P9-NEXT:    bl __floatdihf
-; CHECK-P9-NEXT:    nop
-; CHECK-P9-NEXT:    addi r30, r30, -1
+; CHECK-P9-NEXT:    mtfprd f0, r3
 ; CHECK-P9-NEXT:    li r3, 0
-; CHECK-P9-NEXT:    cmpldi r30, 0
-; CHECK-P9-NEXT:    bc 12, gt, .LBB0_1
+; CHECK-P9-NEXT:    xscvsxddp f0, f0
+; CHECK-P9-NEXT:    xscvdphp f0, f0
+; CHECK-P9-NEXT:    bdnz .LBB0_1
 ; CHECK-P9-NEXT:  # %bb.2: # %bb11
 ; CHECK-P9-NEXT:    li r3, 128
-; CHECK-P9-NEXT:    stxsihx f1, 0, r3
+; CHECK-P9-NEXT:    stxsihx f0, 0, r3
 bb:
   %i = load i64, ptr addrspace(11) null, align 8
   %i1 = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %i, i64 0)

>From 39a774af64c8df9a9ad482af4ba82c97e620c133 Mon Sep 17 00:00:00 2001
From: Tony Varghese <tony.varghese at ibm.com>
Date: Tue, 21 Jul 2026 19:15:40 +0530
Subject: [PATCH 7/8] [PowerPC] Add _Complex _Float16 and homogeneous-aggregate
 ABI tests

Pin down two calling-convention decisions requested in review:

- _Complex _Float16 is passed and returned as two scalar half components
  (real, imaginary), each in an FPR, consistent with the scalar rule and
  the psABI treatment of complex types.
- A struct of _Float16 members is not a homogeneous floating-point
  aggregate: it is passed as an integer aggregate (GPRs on ELFv2, byval
  on AIX), contrasted with a float aggregate that does use FPRs. The HFA
  question for _Float16 is deliberately left to the psABI.
---
 .../CodeGen/PowerPC/ppc-complex-float16.c     | 66 +++++++++++++
 .../ppc-float16-homogeneous-aggregate.c       | 93 +++++++++++++++++++
 2 files changed, 159 insertions(+)
 create mode 100644 clang/test/CodeGen/PowerPC/ppc-complex-float16.c
 create mode 100644 clang/test/CodeGen/PowerPC/ppc-float16-homogeneous-aggregate.c

diff --git a/clang/test/CodeGen/PowerPC/ppc-complex-float16.c b/clang/test/CodeGen/PowerPC/ppc-complex-float16.c
new file mode 100644
index 0000000000000..81d78095d66fb
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/ppc-complex-float16.c
@@ -0,0 +1,66 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+//
+// _Complex _Float16 calling convention on PowerPC. A complex value is passed and
+// returned as two scalar _Float16 components (real, imaginary) -- each in its own
+// FPR on Power8+ -- as if two separate _Float16 scalars were passed. This follows
+// the OpenPOWER ELFv2 psABI rule that a complex type is treated as two scalar
+// values of its base type, and falls straight out of the scalar _Float16 ABI.
+//
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr9 -mfloat16 \
+// RUN:   -O2 -emit-llvm %s -o - | FileCheck %s --check-prefixes=ELFV2
+// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -target-cpu pwr9 -mfloat16 \
+// RUN:   -O2 -emit-llvm %s -o - | FileCheck %s --check-prefixes=ELFV2
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix -target-cpu pwr9 -mfloat16 \
+// RUN:   -O2 -emit-llvm %s -o - | FileCheck %s --check-prefixes=AIX
+
+// A _Complex _Float16 argument arrives as two half components (real, imag); the
+// result is returned as { half, half }.
+// ELFV2-LABEL: define dso_local { half, half } @cpass(
+// ELFV2-SAME: half noundef [[X_COERCE0:%.*]], half noundef [[X_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// ELFV2-NEXT:  [[ENTRY:.*:]]
+// ELFV2-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue { half, half } poison, half [[X_COERCE0]], 0
+// ELFV2-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue { half, half } [[DOTFCA_0_INSERT]], half [[X_COERCE1]], 1
+// ELFV2-NEXT:    ret { half, half } [[DOTFCA_1_INSERT]]
+//
+// AIX-LABEL: define { half, half } @cpass(
+// AIX-SAME: half noundef [[X_COERCE0:%.*]], half noundef [[X_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// AIX-NEXT:  [[ENTRY:.*:]]
+// AIX-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue { half, half } poison, half [[X_COERCE0]], 0
+// AIX-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue { half, half } [[DOTFCA_0_INSERT]], half [[X_COERCE1]], 1
+// AIX-NEXT:    ret { half, half } [[DOTFCA_1_INSERT]]
+//
+_Complex _Float16 cpass(_Complex _Float16 x) { return x; }
+
+// The real component is simply the first of the two half arguments.
+// ELFV2-LABEL: define dso_local noundef half @creal16(
+// ELFV2-SAME: half noundef returned [[X_COERCE0:%.*]], half noundef [[X_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// ELFV2-NEXT:  [[ENTRY:.*:]]
+// ELFV2-NEXT:    ret half [[X_COERCE0]]
+//
+// AIX-LABEL: define noundef half @creal16(
+// AIX-SAME: half noundef returned [[X_COERCE0:%.*]], half noundef [[X_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX-NEXT:  [[ENTRY:.*:]]
+// AIX-NEXT:    ret half [[X_COERCE0]]
+//
+_Float16 creal16(_Complex _Float16 x) { return __real__ x; }
+
+// Complex arithmetic composes with the scalar f16 promote-to-f32 path.
+// ELFV2-LABEL: define dso_local { half, half } @cadd(
+// ELFV2-SAME: half noundef [[A_COERCE0:%.*]], half noundef [[A_COERCE1:%.*]], half noundef [[B_COERCE0:%.*]], half noundef [[B_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// ELFV2-NEXT:  [[ENTRY:.*:]]
+// ELFV2-NEXT:    [[UNPROMOTION:%.*]] = fadd half [[A_COERCE0]], [[B_COERCE0]]
+// ELFV2-NEXT:    [[UNPROMOTION4:%.*]] = fadd half [[A_COERCE1]], [[B_COERCE1]]
+// ELFV2-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue { half, half } poison, half [[UNPROMOTION]], 0
+// ELFV2-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue { half, half } [[DOTFCA_0_INSERT]], half [[UNPROMOTION4]], 1
+// ELFV2-NEXT:    ret { half, half } [[DOTFCA_1_INSERT]]
+//
+// AIX-LABEL: define { half, half } @cadd(
+// AIX-SAME: half noundef [[A_COERCE0:%.*]], half noundef [[A_COERCE1:%.*]], half noundef [[B_COERCE0:%.*]], half noundef [[B_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX-NEXT:  [[ENTRY:.*:]]
+// AIX-NEXT:    [[UNPROMOTION:%.*]] = fadd half [[A_COERCE0]], [[B_COERCE0]]
+// AIX-NEXT:    [[UNPROMOTION4:%.*]] = fadd half [[A_COERCE1]], [[B_COERCE1]]
+// AIX-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue { half, half } poison, half [[UNPROMOTION]], 0
+// AIX-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue { half, half } [[DOTFCA_0_INSERT]], half [[UNPROMOTION4]], 1
+// AIX-NEXT:    ret { half, half } [[DOTFCA_1_INSERT]]
+//
+_Complex _Float16 cadd(_Complex _Float16 a, _Complex _Float16 b) { return a + b; }
diff --git a/clang/test/CodeGen/PowerPC/ppc-float16-homogeneous-aggregate.c b/clang/test/CodeGen/PowerPC/ppc-float16-homogeneous-aggregate.c
new file mode 100644
index 0000000000000..8aeda736f25a2
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/ppc-float16-homogeneous-aggregate.c
@@ -0,0 +1,93 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+//
+// On PowerPC a _Float16 aggregate is deliberately NOT a homogeneous floating-point
+// aggregate (HFA). Contrast take_f2 below: a struct of float is a real HFA and is
+// passed in FPRs (IR: [2 x float]). A struct/array of _Float16 is instead passed
+// like an integer aggregate -- coerced to iN / [N x i64] in GPRs on ELFv2, and as
+// a byval pointer (memory) on AIX. HFA classification for _Float16 is left to the
+// OpenPOWER ELFv2 psABI.
+//
+// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr9 -mfloat16 \
+// RUN:   -O2 -emit-llvm %s -o - | FileCheck %s --check-prefixes=ELFV2
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix -target-cpu pwr9 -mfloat16 \
+// RUN:   -O2 -emit-llvm %s -o - | FileCheck %s --check-prefixes=AIX
+
+struct F2 { float a, b; };                            // real HFA of float (contrast)
+struct H2 { _Float16 a, b; };
+struct H4 { _Float16 a, b, c, d; };
+struct H8 { _Float16 a, b, c, d, e, f, g, h; };
+
+// Contrast: a float HFA is passed as [2 x float] (FPRs f1, f2).
+// ELFV2-LABEL: define dso_local float @take_f2(
+// ELFV2-SAME: [2 x float] [[S_COERCE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// ELFV2-NEXT:  [[ENTRY:.*:]]
+// ELFV2-NEXT:    [[S_COERCE_FCA_0_EXTRACT:%.*]] = extractvalue [2 x float] [[S_COERCE]], 0
+// ELFV2-NEXT:    ret float [[S_COERCE_FCA_0_EXTRACT]]
+//
+// AIX-LABEL: define float @take_f2(
+// AIX-SAME: ptr nofree noundef readonly byval([[STRUCT_F2:%.*]]) align 8 captures(none) [[S:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// AIX-NEXT:  [[ENTRY:.*:]]
+// AIX-NEXT:    [[TMP0:%.*]] = load float, ptr [[S]], align 8, !tbaa [[FLOAT_TBAA5:![0-9]+]]
+// AIX-NEXT:    ret float [[TMP0]]
+//
+float take_f2(struct F2 s) { return s.a; }
+
+// _Float16 aggregates are NOT HFAs: passed as integer aggregates (GPRs) on ELFv2,
+// byval (memory) on AIX -- never as half values in FPRs.
+// ELFV2-LABEL: define dso_local half @take_h2(
+// ELFV2-SAME: i32 [[S_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// ELFV2-NEXT:  [[ENTRY:.*:]]
+// ELFV2-NEXT:    [[S_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[S_COERCE]] to i16
+// ELFV2-NEXT:    [[TMP0:%.*]] = bitcast i16 [[S_SROA_0_0_EXTRACT_TRUNC]] to half
+// ELFV2-NEXT:    ret half [[TMP0]]
+//
+// AIX-LABEL: define half @take_h2(
+// AIX-SAME: ptr nofree noundef readonly byval([[STRUCT_H2:%.*]]) align 8 captures(none) [[S:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX-NEXT:  [[ENTRY:.*:]]
+// AIX-NEXT:    [[TMP0:%.*]] = load half, ptr [[S]], align 8, !tbaa [[_FLOAT16_TBAA8:![0-9]+]]
+// AIX-NEXT:    ret half [[TMP0]]
+//
+_Float16 take_h2(struct H2 s) { return s.a; }
+// ELFV2-LABEL: define dso_local half @take_h4(
+// ELFV2-SAME: i64 [[S_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// ELFV2-NEXT:  [[ENTRY:.*:]]
+// ELFV2-NEXT:    [[S_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[S_COERCE]] to i16
+// ELFV2-NEXT:    [[TMP0:%.*]] = bitcast i16 [[S_SROA_0_0_EXTRACT_TRUNC]] to half
+// ELFV2-NEXT:    ret half [[TMP0]]
+//
+// AIX-LABEL: define half @take_h4(
+// AIX-SAME: ptr nofree noundef readonly byval([[STRUCT_H4:%.*]]) align 8 captures(none) [[S:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX-NEXT:  [[ENTRY:.*:]]
+// AIX-NEXT:    [[TMP0:%.*]] = load half, ptr [[S]], align 8, !tbaa [[_FLOAT16_TBAA11:![0-9]+]]
+// AIX-NEXT:    ret half [[TMP0]]
+//
+_Float16 take_h4(struct H4 s) { return s.a; }
+// ELFV2-LABEL: define dso_local half @take_h8(
+// ELFV2-SAME: [2 x i64] [[S_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// ELFV2-NEXT:  [[ENTRY:.*:]]
+// ELFV2-NEXT:    [[S_COERCE_FCA_0_EXTRACT:%.*]] = extractvalue [2 x i64] [[S_COERCE]], 0
+// ELFV2-NEXT:    [[S_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i64 [[S_COERCE_FCA_0_EXTRACT]] to i16
+// ELFV2-NEXT:    [[TMP0:%.*]] = bitcast i16 [[S_SROA_0_0_EXTRACT_TRUNC]] to half
+// ELFV2-NEXT:    ret half [[TMP0]]
+//
+// AIX-LABEL: define half @take_h8(
+// AIX-SAME: ptr nofree noundef readonly byval([[STRUCT_H8:%.*]]) align 8 captures(none) [[S:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// AIX-NEXT:  [[ENTRY:.*:]]
+// AIX-NEXT:    [[TMP0:%.*]] = load half, ptr [[S]], align 8, !tbaa [[_FLOAT16_TBAA13:![0-9]+]]
+// AIX-NEXT:    ret half [[TMP0]]
+//
+_Float16 take_h8(struct H8 s) { return s.a; }
+//.
+// AIX: [[META3:![0-9]+]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0}
+// AIX: [[META4]] = !{!"Simple C/C++ TBAA"}
+// AIX: [[FLOAT_TBAA5]] = !{[[META6:![0-9]+]], [[META7:![0-9]+]], i64 0}
+// AIX: [[META6]] = !{!"F2", [[META7]], i64 0, [[META7]], i64 4}
+// AIX: [[META7]] = !{!"float", [[META3]], i64 0}
+// AIX: [[_FLOAT16_TBAA8]] = !{[[META9:![0-9]+]], [[META10:![0-9]+]], i64 0}
+// AIX: [[META9]] = !{!"H2", [[META10]], i64 0, [[META10]], i64 2}
+// AIX: [[META10]] = !{!"_Float16", [[META3]], i64 0}
+// AIX: [[_FLOAT16_TBAA11]] = !{[[META12:![0-9]+]], [[META10]], i64 0}
+// AIX: [[META12]] = !{!"H4", [[META10]], i64 0, [[META10]], i64 2, [[META10]], i64 4, [[META10]], i64 6}
+// AIX: [[_FLOAT16_TBAA13]] = !{[[META14:![0-9]+]], [[META10]], i64 0}
+// AIX: [[META14]] = !{!"H8", [[META10]], i64 0, [[META10]], i64 2, [[META10]], i64 4, [[META10]], i64 6, [[META10]], i64 8, [[META10]], i64 10, [[META10]], i64 12, [[META10]], i64 14}
+//.

>From ef06063d15e4fbecee1c659aa29ac9a41e580d01 Mon Sep 17 00:00:00 2001
From: Tony Varghese <tony.varghese at ibm.com>
Date: Tue, 21 Jul 2026 19:15:58 +0530
Subject: [PATCH 8/8] [PowerPC] Add f16 strict-FP support

Registering f16 as a legal type left every STRICT_* opcode at its Legal
default with no selection pattern, so any strict-FP operation on
_Float16 failed to select. Fix the strict path end to end:

- Promote the strict arithmetic, rounding, transcendental and compare
  opcodes (STRICT_FSETCC/STRICT_FSETCCS) to f32 via F16StrictPromoteOps.
- Switch the P9 conversion patterns to any_fpround/any_fpextend so the
  strict nodes select XSCVDPHP/XSCVHPDP directly.
- Make LowerFP_EXTEND strict-aware (thread the chain) and route P9
  f16 -> f128 through xscvhpdp + xscvdpqp instead of regressing to an
  __extendhfsf2 libcall; register STRICT_FP_EXTEND Custom for the f16
  source cases, re-applied after the generic f32/f64 Legal setting that
  would otherwise clobber it.
- Build STRICT_FP_ROUND in the int-to-fp combine with a target rounding
  mode constant, fixing an "Invalid STRICT_FP_ROUND!" assertion on
  strict sitofp/uitofp to f16.
- Suppress register pressure set generation for VHFRC, which shares the
  physical VSX scalar registers.

Add f16-strictfp.ll (P8 and P9) and update the f128-conv.ll ext() checks
for the native P9 sequence.
---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 269 ++++++++---------
 llvm/lib/Target/PowerPC/PPCInstrVSX.td      |  12 +-
 llvm/lib/Target/PowerPC/PPCRegisterInfo.td  |   4 +-
 llvm/test/CodeGen/PowerPC/f128-conv.ll      |  10 +-
 llvm/test/CodeGen/PowerPC/f16-strictfp.ll   | 319 ++++++++++++++++++++
 5 files changed, 457 insertions(+), 157 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/f16-strictfp.ll

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index b18e218e81e0a..8e8ab39143d35 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -261,19 +261,14 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
     setTruncStoreAction(MVT::f32, MVT::f16, Expand);
   }
 
-  // Make f16 a legal type whenever the hardware can back it (VSX half-
-  // precision registers on Power8+) 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.
+  // Make f16 a legal type when the hardware can back it (VSX half-precision
+  // registers on Power8+ with hard float). This overrides the f16 load/store
+  // and extend actions set above, since a first-class f16 is handled directly.
   if (useFPRegsForHalfType()) {
-    // 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.
+    // PowerPC has no native f16 arithmetic; everything is promoted to f32 and
+    // computed there (xscvhpdp/.../xscvdphp on P9, libcalls on P8).
     static const unsigned F16PromoteOps[] = {
         ISD::FMINNUM,    ISD::FMAXNUM,  ISD::FMAXIMUMNUM, ISD::FMINIMUMNUM,
         ISD::FMAXIMUM,   ISD::FMINIMUM, ISD::FADD,        ISD::FSUB,
@@ -286,33 +281,37 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
         ISD::SELECT,     ISD::FLDEXP,   ISD::FFREXP,      ISD::FMODF,
         ISD::FATAN2,     ISD::FPOWI,    ISD::BR_CC};
 
-    // Promote all the arithmetic operations defined above to f32.
     setOperationAction(F16PromoteOps, MVT::f16, Promote);
 
-    // ISD::LRINT/LLRINT/LROUND/LLROUND have a result type that differs from
-    // their f16 operand (an integer, not f16), and SelectionDAGLegalize's
-    // PromoteNode computes the type to
-    // promote to from the *result* type, so a plain Promote action on the
-    // f16 operand is silently mismatched there and trips an assertion.
-    // Lower them manually instead: extend the f16 operand to f32 and
-    // re-emit the same node, which is already legal/handled for f32.
+    // The strict-FP counterparts must also be promoted: f16 is now legal, so a
+    // strict opcode left untouched would default to Legal and fail selection.
+    // SELECT/SELECT_CC/BR_CC have no strict form; the strict compare opcodes
+    // are STRICT_FSETCC/STRICT_FSETCCS.
+    static const unsigned F16StrictPromoteOps[] = {
+        ISD::STRICT_FMINNUM,    ISD::STRICT_FMAXNUM, ISD::STRICT_FMAXIMUM,
+        ISD::STRICT_FMINIMUM,   ISD::STRICT_FADD,    ISD::STRICT_FSUB,
+        ISD::STRICT_FMUL,       ISD::STRICT_FMA,     ISD::STRICT_FDIV,
+        ISD::STRICT_FSQRT,      ISD::STRICT_FREM,    ISD::STRICT_FPOW,
+        ISD::STRICT_FLOG,       ISD::STRICT_FLOG2,   ISD::STRICT_FLOG10,
+        ISD::STRICT_FEXP,       ISD::STRICT_FEXP2,   ISD::STRICT_FCEIL,
+        ISD::STRICT_FFLOOR,     ISD::STRICT_FTRUNC,  ISD::STRICT_FRINT,
+        ISD::STRICT_FNEARBYINT, ISD::STRICT_FROUND,  ISD::STRICT_FROUNDEVEN,
+        ISD::STRICT_FSIN,       ISD::STRICT_FCOS,    ISD::STRICT_FLDEXP,
+        ISD::STRICT_FATAN2,     ISD::STRICT_FPOWI,   ISD::STRICT_FSETCC,
+        ISD::STRICT_FSETCCS};
+    setOperationAction(F16StrictPromoteOps, MVT::f16, Promote);
+
+    // LRINT/LLRINT/LROUND/LLROUND return an integer, so PromoteNode would key
+    // the promote-to type off the result and mismatch the f16 operand. Lower
+    // by hand instead (extend the operand to f32, re-emit).
     setOperationAction({ISD::LRINT, ISD::LLRINT, ISD::LROUND, ISD::LLROUND},
                        MVT::f16, Custom);
 
-    // ISD::FP_TO_SINT/FP_TO_UINT (and their strict forms) are keyed by the
-    // SelectionDAG legalizer on their integer result type, which is legal, so
-    // a Promote/Custom action on the f16 operand is never consulted. Left
-    // alone, the f16 operand reaches ISel and is mis-selected as a
-    // double-precision convert (f16 and f64 share the VSX registers), producing
-    // a bare xscvdpsxws with no preceding xscvhpdp. Promote the operand to f32
-    // with a DAG combine instead; FP_TO_*INT(f32) and FP_EXTEND(f16->f32) are
-    // both already handled correctly on P8 and P9.
-    //
-    // The reverse, INT_TO_FP with an f16 result, has no direct lowering for
-    // wide integers (i64 falls back to a missing __floatdihf libcall). Round
-    // through f64 (fcfid[u] then xscvdphp) with the same combine. SINT_TO_FP
-    // and UINT_TO_FP are already registered for combine above; add their strict
-    // forms here.
+    // FP_TO_SINT/UINT and INT_TO_FP can't be steered by the action table: the
+    // former is keyed on the legal integer type (so an f16 operand reaches ISel
+    // and is mis-selected as an f64 convert), and i64->f16 would fall to a
+    // nonexistent __floatdihf libcall. A DAG combine promotes the f16 side to
+    // f32/f64 for both directions instead.
     setTargetDAGCombine({ISD::FP_TO_SINT, ISD::FP_TO_UINT,
                          ISD::STRICT_FP_TO_SINT, ISD::STRICT_FP_TO_UINT,
                          ISD::STRICT_SINT_TO_FP, ISD::STRICT_UINT_TO_FP});
@@ -320,46 +319,32 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
     setOperationAction(ISD::LOAD, MVT::f16, Legal);
     setOperationAction(ISD::STORE, MVT::f16, Legal);
 
-    // Legal handling for bit manipulation.
+    // Pure bit ops, not conversion round-trips (NaN-preserving); see
+    // PPCInstrVSX.td.
     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);
     }
 
-    // FP_ROUND/STRICT_FP_ROUND to f16 is Custom on both P8 and P9: f32/f64
-    // sources are hardware-legal on P9 and need a libcall on P8, while an
-    // f128 source needs a libcall either way (no direct f128->f16
-    // instruction even on P9). The action table can't express this
-    // per-source distinction since it is keyed only on the f16 result
-    // type, so LowerFP_ROUND resolves it based on the actual operand type.
+    // Custom (not Legal/Expand) because the right lowering depends on the
+    // source type, which the result-keyed action table can't see: f32/f64->f16
+    // is hardware on P9 but a libcall on P8, and f128->f16 is a libcall always.
     setOperationAction(ISD::FP_ROUND, MVT::f16, Custom);
     setOperationAction(ISD::STRICT_FP_ROUND, MVT::f16, Custom);
 
-    if (Subtarget.hasP9Vector()) {
-      // P9+: Hardware support for conversions.
-    } else {
-      // P8: Conversions via libcalls (__extendhfsf2/__extendhfdf2 etc).
-      // FP_EXTEND/STRICT_FP_EXTEND with an f32 result only ever have f16 as
-      // the source on this target, so it is safe to mark them Expand
-      // directly. An f64 result is ambiguous between f16->f64 (needs a
-      // libcall) and the common, always-legal f32->f64 widening, which the
-      // operation-action table cannot distinguish since it is keyed only on
-      // the result type. Use Custom for the f64 case so LowerFP_EXTEND can
-      // split f16->f64 into f16->f32->f64 while leaving f32->f64 untouched.
-      // FP_EXTEND with f16 as the source is the only case PowerPC needs to
-      // handle here (f32 has no other narrower legal source on this
-      // target; f64's other source, f32, is always legal and must be left
-      // alone). Use Custom rather than Expand:
-      // Custom only intercepts the f16-sourced case in LowerFP_EXTEND and
-      // otherwise defers to the existing (already-legal) default.
+    // On P8, f16->f32/f64 has no hardware convert and goes through a libcall in
+    // LowerFP_EXTEND. f32 has no other narrower source here, and the f32->f64
+    // widening sharing the f64 result is left untouched. P9 selects xscvhpdp
+    // via patterns, so nothing is needed there. (The strict f32/f64 forms are
+    // re-applied after the unconditional STRICT_FP_EXTEND=Legal below clobbers
+    // them.)
+    if (!Subtarget.hasP9Vector()) {
       setOperationAction(ISD::FP_EXTEND, MVT::f32, Custom);
       setOperationAction(ISD::FP_EXTEND, MVT::f64, Custom);
     }
@@ -830,6 +815,13 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
   setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f32, Legal);
   setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f64, Legal);
 
+  // Re-apply after the unconditional Legal above (which would clobber it): on
+  // P8 a strict f16->f32/f64 extend needs the libcall in LowerFP_EXTEND.
+  if (useFPRegsForHalfType() && !Subtarget.hasP9Vector()) {
+    setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f32, Custom);
+    setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f64, Custom);
+  }
+
   if (Subtarget.has64BitSupport()) {
     // They also have instructions for converting between i64 and fp.
     setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i64, Custom);
@@ -1382,10 +1374,9 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::FSUB, MVT::f128, Legal);
       setOperationAction(ISD::FDIV, MVT::f128, Legal);
       setOperationAction(ISD::FMUL, MVT::f128, Legal);
-      // Custom rather than Legal: f16 is also a legal source type (see the
-      // f16 setup above), and there is no direct f16->f128 hardware
-      // instruction, so LowerFP_EXTEND needs to route that case through a
-      // libcall while leaving the genuinely-legal f32/f64 sources alone.
+      // Custom (not Legal): f16 is also a legal source and has no f16->f128
+      // instruction, so LowerFP_EXTEND routes it through f64 while passing the
+      // legal f32/f64 sources through.
       setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom);
 
       setOperationAction(ISD::FMA, MVT::f128, Legal);
@@ -1414,10 +1405,8 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::STRICT_FDIV, MVT::f128, Legal);
       setOperationAction(ISD::STRICT_FMA, MVT::f128, Legal);
       setOperationAction(ISD::STRICT_FSQRT, MVT::f128, Legal);
-      // NOTE: STRICT_FP_EXTEND to f128 is left Legal (not Custom like the
-      // non-strict case above) since LowerOperation has no dispatch case
-      // for it; a strict half->fp128 extend is an unhandled known gap.
-      setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f128, Legal);
+      // Custom for the f16 source, as the non-strict case above.
+      setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f128, Custom);
       setOperationAction(ISD::STRICT_FP_ROUND, MVT::f64, Legal);
       setOperationAction(ISD::STRICT_FP_ROUND, MVT::f32, Legal);
       setOperationAction(ISD::STRICT_FRINT, MVT::f128, Legal);
@@ -1451,14 +1440,11 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::FMA, MVT::f128, Expand);
       setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand);
 
-      // f16 is also a legal source type on this subtarget (see the f16
-      // setup above) and has no usable Expand lowering to f128 (no
-      // libcall handles f16->f128 directly), so this needs Custom rather
-      // than Expand to let LowerFP_EXTEND route it through f32. The
-      // existing f32/f64->f128 behavior is replicated there explicitly
-      // via the same libcalls Expand would have produced.
+      // Custom (not Expand): no libcall handles f16->f128 directly, so
+      // LowerFP_EXTEND routes the f16 source through f32 and replicates the
+      // f32/f64->f128 libcalls Expand would have produced.
       setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom);
-      setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f128, Expand);
+      setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f128, Custom);
 
       // Expand the fp_round if the source type is fp128.
       for (MVT VT : {MVT::f32, MVT::f64}) {
@@ -4847,9 +4833,8 @@ SDValue PPCTargetLowering::LowerFormalArguments_64SVR4(
                                  DAG.getConstant(32, dl, MVT::i32));
           ArgVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, ArgVal);
         } else if (ObjectVT == MVT::f16) {
-          //  The 16 meaningfull bits sit at the byte (ArgOffset % 8) of the 8
-          //  bytes loaded into the ArgVal. Shift it down to the low 16 bits and
-          //  then narrow to i16.
+          // The 16 meaningful bits sit at byte (ArgOffset % 8) of the loaded
+          // doubleword; shift them down to the low 16 bits and narrow to i16.
           unsigned BitInDW = ((ArgOffset % PtrByteSize) * 8);
           unsigned Shift = (isLittleEndian ? BitInDW : 48 - BitInDW);
           if (Shift)
@@ -12739,15 +12724,10 @@ SDValue PPCTargetLowering::LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
   SDLoc dl(Op);
 
   if (DstVT == MVT::f16) {
-    // No source type has a direct hardware rounding path to f16 except
-    // f32/f64 on P9; everything else (f128 on either subtarget, f32/f64
-    // on P8) goes through a libcall. FP_ROUND/f16 is registered Custom
-    // for all of these because the action table can't distinguish them
-    // by source type, being keyed only on the f16 result.
-    if (SrcVT == MVT::f32 || SrcVT == MVT::f64) {
-      if (Subtarget.hasP9Vector())
-        return Op;
-    }
+    // Only f32/f64->f16 on P9 has a hardware path; everything else (f128, or
+    // f32/f64 on P8) is a libcall.
+    if ((SrcVT == MVT::f32 || SrcVT == MVT::f64) && Subtarget.hasP9Vector())
+      return Op;
     RTLIB::Libcall LC;
     if (SrcVT == MVT::f128)
       LC = RTLIB::FPROUND_F128_F16;
@@ -12771,62 +12751,70 @@ SDValue PPCTargetLowering::LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const {
   return Op;
 }
 
-// Custom lowering for fpext vf32 to v2f64
 SDValue PPCTargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
+  assert((Op.getOpcode() == ISD::FP_EXTEND ||
+          Op.getOpcode() == ISD::STRICT_FP_EXTEND) &&
+         "Should only be called for (STRICT_)FP_EXTEND");
 
-  assert(Op.getOpcode() == ISD::FP_EXTEND &&
-         "Should only be called for ISD::FP_EXTEND");
-
-  // On Power8 there is no hardware instruction extending f16 directly to
-  // f32 or f64; route those through the appropriate libcall. FP_EXTEND is
-  // marked Custom (rather than Expand) for f16-sourced cases so that the
-  // common, unrelated extends sharing the same result type (there is no
-  // other legal source for f32; f32->f64 for f64) are left untouched,
-  // since marking the whole opcode Expand would otherwise also divert
-  // those through the generic stack-conversion expansion.
-  if (Op.getOperand(0).getValueType() == MVT::f16) {
-    SDLoc dl(Op);
+  bool IsStrict = Op->isStrictFPOpcode();
+  SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
+  SDValue Src = Op.getOperand(IsStrict ? 1 : 0);
+  EVT SrcVT = Src.getValueType();
+  EVT DstVT = Op.getValueType();
+  SDLoc dl(Op);
+
+  auto extendTo = [&](EVT VT, SDValue In, SDValue InChain) -> SDValue {
+    if (IsStrict)
+      return DAG.getNode(ISD::STRICT_FP_EXTEND, dl,
+                         DAG.getVTList(VT, MVT::Other), {InChain, In});
+    return DAG.getNode(ISD::FP_EXTEND, dl, VT, In);
+  };
+  auto packResult = [&](std::pair<SDValue, SDValue> R) -> SDValue {
+    return IsStrict ? DAG.getMergeValues({R.first, R.second}, dl) : R.first;
+  };
+
+  if (SrcVT == MVT::f16) {
+    // P9 extends f16->f32/f64 in hardware (selected by patterns), so this is
+    // only reached for f16->f128: extend through f64 (xscvhpdp) then to f128.
+    if (Subtarget.hasP9Vector()) {
+      assert(DstVT == MVT::f128 &&
+             "f16->f32/f64 are Legal on P9 and selected by patterns");
+      SDValue Ext64 = extendTo(MVT::f64, Src, Chain);
+      return extendTo(MVT::f128, Ext64,
+                      IsStrict ? Ext64.getValue(1) : SDValue());
+    }
+    // P8 has no hardware f16 extend: __extendhfsf2 to f32, then widen.
     MakeLibCallOptions CallOptions;
-    SDValue Ext32 = makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32,
-                                Op.getOperand(0), CallOptions, dl)
-                        .first;
-    if (Op.getValueType() == MVT::f32)
-      return Ext32;
-    assert((Op.getValueType() == MVT::f64 || Op.getValueType() == MVT::f128) &&
+    std::pair<SDValue, SDValue> Ext32P = makeLibCall(
+        DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Src, CallOptions, dl, Chain);
+    SDValue Ext32 = Ext32P.first;
+    SDValue Ext32Chain = IsStrict ? Ext32P.second : SDValue();
+    if (DstVT == MVT::f32)
+      return packResult(Ext32P);
+    assert((DstVT == MVT::f64 || DstVT == MVT::f128) &&
            "Unexpected f16 extend result");
-    // f32->f64 is always hardware-legal. f32->f128 is hardware-legal only
-    // with P9 IEEE-f128 support; on the older libcall-based f128
-    // emulation (VSX but no P9), it needs an explicit libcall too, since
-    // there is no instruction pattern to select it directly.
-    if (Op.getValueType() == MVT::f128 && !Subtarget.hasP9Vector())
-      return makeLibCall(DAG, RTLIB::FPEXT_F32_F128, MVT::f128, Ext32,
-                         CallOptions, dl)
-          .first;
-    return DAG.getNode(ISD::FP_EXTEND, dl, Op.getValueType(), Ext32);
-  }
-
-  // Reached only on the libcall-based f128 emulation path (VSX but no P9),
-  // where FP_EXTEND/f128 is Custom solely so the f16-sourced case above can
-  // be intercepted; every other source here previously relied on the
-  // generic Expand action, which doesn't have a usable lowering for f128,
-  // so replicate it explicitly via libcall instead.
-  if (Op.getValueType() == MVT::f128 && !Subtarget.hasP9Vector()) {
-    SDLoc dl(Op);
+    // f32->f64 is hardware-legal; f32->f128 on the no-P9 libcall emulation
+    // needs an explicit libcall.
+    if (DstVT == MVT::f128)
+      return packResult(makeLibCall(DAG, RTLIB::FPEXT_F32_F128, MVT::f128,
+                                    Ext32, CallOptions, dl, Ext32Chain));
+    return extendTo(MVT::f64, Ext32, Ext32Chain);
+  }
+
+  // f32/f64->f128 on the no-P9 libcall emulation: Expand has no f128 lowering,
+  // so emit the libcall here (this path exists only because f128 is Custom for
+  // the f16 case above).
+  if (DstVT == MVT::f128 && !Subtarget.hasP9Vector()) {
     MakeLibCallOptions CallOptions;
-    RTLIB::Libcall LC = Op.getOperand(0).getValueType() == MVT::f64
-                            ? RTLIB::FPEXT_F64_F128
-                            : RTLIB::FPEXT_F32_F128;
-    return makeLibCall(DAG, LC, MVT::f128, Op.getOperand(0), CallOptions, dl)
-        .first;
-  }
-
-  // The common, scalar, always-legal widening cases (f32->f64, and
-  // f32/f64->f128 when P9 IEEE-f128 hardware is present) are already fine
-  // as constructed; hand the unchanged node back rather than falling into
-  // Expand. Deliberately scoped to scalar types only: returning the node
-  // unchanged for vector cases below (e.g. widening a <4 x half> extend)
-  // trips a "potential legalization loop" assertion, since the vector
-  // type legalizer expects Custom to actually transform the node.
+    RTLIB::Libcall LC =
+        SrcVT == MVT::f64 ? RTLIB::FPEXT_F64_F128 : RTLIB::FPEXT_F32_F128;
+    return packResult(
+        makeLibCall(DAG, LC, MVT::f128, Src, CallOptions, dl, Chain));
+  }
+
+  // Scalar widenings that are already legal (f32->f64, f32/f64->f128 on P9)
+  // pass through. Vector cases must fall through: returning Op unchanged trips
+  // a "potential legalization loop" assertion in the vector type legalizer.
   if (!Op.getValueType().isVector())
     return Op;
 
@@ -12836,7 +12824,6 @@ SDValue PPCTargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
       Op.getOperand(0).getValueType() != MVT::v2f32)
     return SDValue();
 
-  SDLoc dl(Op);
   SDValue Op0 = Op.getOperand(0);
 
   switch (Op0.getOpcode()) {
@@ -13201,6 +13188,7 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::SCALAR_TO_VECTOR:   return LowerSCALAR_TO_VECTOR(Op, DAG);
   case ISD::INSERT_VECTOR_ELT:  return LowerINSERT_VECTOR_ELT(Op, DAG);
   case ISD::MUL:                return LowerMUL(Op, DAG);
+  case ISD::STRICT_FP_EXTEND:
   case ISD::FP_EXTEND:          return LowerFP_EXTEND(Op, DAG);
   case ISD::STRICT_FP_ROUND:
   case ISD::FP_ROUND:
@@ -18127,9 +18115,10 @@ static SDValue combineF16IntToFP(SDNode *N, SelectionDAG &DAG) {
     SDValue Chain = N->getOperand(0);
     SDValue Wide = DAG.getNode(
         N->getOpcode(), dl, DAG.getVTList(MVT::f64, MVT::Other), {Chain, Src});
-    return DAG.getNode(
-        ISD::STRICT_FP_ROUND, dl, DAG.getVTList(MVT::f16, MVT::Other),
-        {Wide.getValue(1), Wide.getValue(0), DAG.getIntPtrConstant(0, dl)});
+    return DAG.getNode(ISD::STRICT_FP_ROUND, dl,
+                       DAG.getVTList(MVT::f16, MVT::Other),
+                       {Wide.getValue(1), Wide.getValue(0),
+                        DAG.getIntPtrConstant(0, dl, /*isTarget=*/true)});
   }
   SDValue Wide = DAG.getNode(N->getOpcode(), dl, MVT::f64, Src);
   return DAG.getNode(ISD::FP_ROUND, dl, MVT::f16, Wide,
diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
index 5bae3ce988642..7f357bb51353d 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
@@ -4068,21 +4068,21 @@ let Predicates = [HasP9Vector] in {
   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)),
+  // FP_ROUND to f16 container (any_fpround also covers the strict-FP node).
+  def : Pat<(f16 (any_fpround f64:$src)),
             (COPY_TO_REGCLASS (XSCVDPHP $src), VHFRC)>;
 
-  def : Pat<(f16 (fpround f32:$src)),
+  def : Pat<(f16 (any_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)),
+  // FP_EXTEND from f16 container -> f64 (any_fpextend also covers strict).
+  def : Pat<(f64 (any_fpextend f16:$src)),
             (XSCVHPDP (COPY_TO_REGCLASS $src, VHFRC))>;
 
   // FP_EXTEND from f16 container -> f32.
-  def : Pat<(f32 (fpextend f16:$src)),
+  def : Pat<(f32 (any_fpextend f16:$src)),
             (COPY_TO_REGCLASS
               (XSCVHPDP (COPY_TO_REGCLASS $src, VHFRC)),
               VSSRC)>;
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 50b489582be27..06567aaf225a2 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -408,8 +408,8 @@ 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 
+// 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 {
   // f16 occupies the low bits of a 64-bit VSX scalar register (shared with
diff --git a/llvm/test/CodeGen/PowerPC/f128-conv.ll b/llvm/test/CodeGen/PowerPC/f128-conv.ll
index ff46373f59927..36a83309ce839 100644
--- a/llvm/test/CodeGen/PowerPC/f128-conv.ll
+++ b/llvm/test/CodeGen/PowerPC/f128-conv.ll
@@ -1373,16 +1373,8 @@ entry:
 define fp128 @ext(half %a) nounwind {
 ; CHECK-LABEL: ext:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    mflr r0
-; CHECK-NEXT:    stdu r1, -32(r1)
-; CHECK-NEXT:    std r0, 48(r1)
-; CHECK-NEXT:    bl __extendhfsf2
-; CHECK-NEXT:    nop
-; CHECK-NEXT:    xscpsgndp v2, f1, f1
+; CHECK-NEXT:    xscvhpdp v2, f1
 ; CHECK-NEXT:    xscvdpqp v2, v2
-; CHECK-NEXT:    addi r1, r1, 32
-; CHECK-NEXT:    ld r0, 16(r1)
-; CHECK-NEXT:    mtlr r0
 ; CHECK-NEXT:    blr
 ;
 ; CHECK-P8-LABEL: ext:
diff --git a/llvm/test/CodeGen/PowerPC/f16-strictfp.ll b/llvm/test/CodeGen/PowerPC/f16-strictfp.ll
new file mode 100644
index 0000000000000..80b041f9813b0
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/f16-strictfp.ll
@@ -0,0 +1,319 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-unknown \
+; RUN:   -verify-machineinstrs -ppc-asm-full-reg-names < %s \
+; RUN:   | FileCheck %s --check-prefix=P9
+; RUN: llc -mcpu=pwr8 -mtriple=powerpc64le-unknown-unknown \
+; RUN:   -verify-machineinstrs -ppc-asm-full-reg-names < %s \
+; RUN:   | FileCheck %s --check-prefix=P8
+
+; Constrained (strict-FP) _Float16 operations. There are no f16 strict-FP
+; instructions, so arithmetic promotes to f32 (xscvhpdp/.../xscvdphp on P9,
+; __extendhfsf2/__truncsfhf2 libcalls on P8) and the f16<->f128 extends route
+; through f64/f32. Before strict-FP support these hit "Cannot select".
+
+define half @strict_fadd(half %a, half %b) #0 {
+; P9-LABEL: strict_fadd:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp f0, f2
+; P9-NEXT:    xscvhpdp f1, f1
+; P9-NEXT:    xsaddsp f0, f1, f0
+; P9-NEXT:    xscvdphp f1, f0
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fadd:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    .cfi_def_cfa_offset 48
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    .cfi_offset f30, -16
+; P8-NEXT:    .cfi_offset f31, -8
+; P8-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
+; P8-NEXT:    stdu r1, -48(r1)
+; P8-NEXT:    fmr f31, f1
+; P8-NEXT:    fmr f1, f2
+; P8-NEXT:    std r0, 64(r1)
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    fmr f30, f1
+; P8-NEXT:    fmr f1, f31
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    xsaddsp f1, f1, f30
+; P8-NEXT:    bl __truncsfhf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 48
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call half @llvm.experimental.constrained.fadd.f16(half %a, half %b,
+         metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret half %r
+}
+
+define half @strict_fdiv(half %a, half %b) #0 {
+; P9-LABEL: strict_fdiv:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp f0, f2
+; P9-NEXT:    xscvhpdp f1, f1
+; P9-NEXT:    xsdivsp f0, f1, f0
+; P9-NEXT:    xscvdphp f1, f0
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fdiv:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    .cfi_def_cfa_offset 48
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    .cfi_offset f30, -16
+; P8-NEXT:    .cfi_offset f31, -8
+; P8-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
+; P8-NEXT:    stdu r1, -48(r1)
+; P8-NEXT:    fmr f31, f1
+; P8-NEXT:    fmr f1, f2
+; P8-NEXT:    std r0, 64(r1)
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    fmr f30, f1
+; P8-NEXT:    fmr f1, f31
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    xsdivsp f1, f1, f30
+; P8-NEXT:    bl __truncsfhf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 48
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call half @llvm.experimental.constrained.fdiv.f16(half %a, half %b,
+         metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret half %r
+}
+
+define half @strict_fma(half %a, half %b, half %c) #0 {
+; P9-LABEL: strict_fma:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp f0, f3
+; P9-NEXT:    xscvhpdp f2, f2
+; P9-NEXT:    xscvhpdp f1, f1
+; P9-NEXT:    xsmaddadp f0, f1, f2
+; P9-NEXT:    xscvdphp f1, f0
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fma:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    .cfi_def_cfa_offset 64
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    .cfi_offset f29, -24
+; P8-NEXT:    .cfi_offset f30, -16
+; P8-NEXT:    .cfi_offset f31, -8
+; P8-NEXT:    stfd f29, -24(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f30, -16(r1) # 8-byte Folded Spill
+; P8-NEXT:    stfd f31, -8(r1) # 8-byte Folded Spill
+; P8-NEXT:    stdu r1, -64(r1)
+; P8-NEXT:    fmr f30, f1
+; P8-NEXT:    fmr f1, f2
+; P8-NEXT:    std r0, 80(r1)
+; P8-NEXT:    fmr f31, f3
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    fmr f29, f1
+; P8-NEXT:    fmr f1, f31
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    fmr f31, f1
+; P8-NEXT:    fmr f1, f30
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    xsmaddadp f31, f1, f29
+; P8-NEXT:    fmr f1, f31
+; P8-NEXT:    bl __truncdfhf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 64
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    lfd f31, -8(r1) # 8-byte Folded Reload
+; P8-NEXT:    lfd f30, -16(r1) # 8-byte Folded Reload
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    lfd f29, -24(r1) # 8-byte Folded Reload
+; P8-NEXT:    blr
+entry:
+  %r = call half @llvm.experimental.constrained.fma.f16(half %a, half %b, half %c,
+         metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret half %r
+}
+
+define half @strict_fsqrt(half %a) #0 {
+; P9-LABEL: strict_fsqrt:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp f0, f1
+; P9-NEXT:    xssqrtsp f0, f0
+; P9-NEXT:    xscvdphp f1, f0
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fsqrt:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
+; P8-NEXT:    .cfi_def_cfa_offset 32
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    xssqrtsp f1, f1
+; P8-NEXT:    bl __truncsfhf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call half @llvm.experimental.constrained.sqrt.f16(half %a,
+         metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret half %r
+}
+
+define float @strict_fpext_f32(half %a) #0 {
+; P9-LABEL: strict_fpext_f32:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp f1, f1
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fpext_f32:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
+; P8-NEXT:    .cfi_def_cfa_offset 32
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call float @llvm.experimental.constrained.fpext.f32.f16(half %a,
+         metadata !"fpexcept.strict") #0
+  ret float %r
+}
+
+define fp128 @strict_fpext_f128(half %a) #0 {
+; P9-LABEL: strict_fpext_f128:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp vs34, f1
+; P9-NEXT:    xscvdpqp v2, v2
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fpext_f128:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
+; P8-NEXT:    .cfi_def_cfa_offset 32
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    bl __extendsfkf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call fp128 @llvm.experimental.constrained.fpext.f128.f16(half %a,
+         metadata !"fpexcept.strict") #0
+  ret fp128 %r
+}
+
+define half @strict_fptrunc_f64(double %a) #0 {
+; P9-LABEL: strict_fptrunc_f64:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvdphp f1, f1
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fptrunc_f64:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
+; P8-NEXT:    .cfi_def_cfa_offset 32
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    bl __truncdfhf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call half @llvm.experimental.constrained.fptrunc.f16.f64(double %a,
+         metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret half %r
+}
+
+define i32 @strict_fptosi(half %a) #0 {
+; P9-LABEL: strict_fptosi:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    xscvhpdp f0, f1
+; P9-NEXT:    xscvdpsxws f0, f0
+; P9-NEXT:    mffprwz r3, f0
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_fptosi:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
+; P8-NEXT:    .cfi_def_cfa_offset 32
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    bl __extendhfsf2
+; P8-NEXT:    nop
+; P8-NEXT:    xscvdpsxws f0, f1
+; P8-NEXT:    mffprwz r3, f0
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call i32 @llvm.experimental.constrained.fptosi.i32.f16(half %a,
+         metadata !"fpexcept.strict") #0
+  ret i32 %r
+}
+
+define half @strict_sitofp_i64(i64 %a) #0 {
+; P9-LABEL: strict_sitofp_i64:
+; P9:       # %bb.0: # %entry
+; P9-NEXT:    mtfprd f0, r3
+; P9-NEXT:    xscvsxddp f0, f0
+; P9-NEXT:    xscvdphp f1, f0
+; P9-NEXT:    blr
+;
+; P8-LABEL: strict_sitofp_i64:
+; P8:       # %bb.0: # %entry
+; P8-NEXT:    mflr r0
+; P8-NEXT:    stdu r1, -32(r1)
+; P8-NEXT:    std r0, 48(r1)
+; P8-NEXT:    .cfi_def_cfa_offset 32
+; P8-NEXT:    .cfi_offset lr, 16
+; P8-NEXT:    mtfprd f0, r3
+; P8-NEXT:    xscvsxddp f1, f0
+; P8-NEXT:    bl __truncdfhf2
+; P8-NEXT:    nop
+; P8-NEXT:    addi r1, r1, 32
+; P8-NEXT:    ld r0, 16(r1)
+; P8-NEXT:    mtlr r0
+; P8-NEXT:    blr
+entry:
+  %r = call half @llvm.experimental.constrained.sitofp.f16.i64(i64 %a,
+         metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret half %r
+}
+
+attributes #0 = { strictfp }



More information about the cfe-commits mailing list