[llvm] [Hexagon] Lower fcmp oeq to vcmp_(s|h)f_eq. (PR #211570)

Fateme Hosseini via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 23 07:50:31 PDT 2026


https://github.com/fhossein-quic created https://github.com/llvm/llvm-project/pull/211570

Before this commit, the following error persisted in the hexagon backend.

Consider the `file.ll` with the following contents.
```
define <32 x float> @setoeq_v32f32(<32 x float> %a, <32 x float> %b,
                                    <32 x float> %c, <32 x float> %d) {
  %cmp = fcmp oeq <32 x float> %a, %b
  %r   = select <32 x i1> %cmp, <32 x float> %c, <32 x float> %d
  ret <32 x float> %r
}
```

Compiling it as `hexagon-llc -march=hexagon
-mattr=+hvxv81,+hvx-length128b file.ll`, we get

```
setoeq_v32f32:
        .cfi_startproc
        {
                q0 = vcmp.eq(v0.w,v1.w)
        }
        {
                v0 = vmux(q0,v2,v3)
                jumpr r31
        }
.Lfunc_end0:
        .size   setoeq_v32f32, .Lfunc_end0-setoeq_v32f32
        .cfi_endproc
```

It must be noted that the resulting code is using a bitwise comparison leading to incorrect quiet-NaN behavior. In this patch, we use vcmp_sf_eq function for the equality check to correctly handle the NaN comparison behavior.

For Pre-v81, we synthesize oeq(a,b) as NOT(ogt(a,b) OR ogt(b,a) OR isNaN(a) OR isNaN(b)) using the available float-GT instructions.

Co-authored-by: Kaushik Kulkarni <kauskulk at qti.qualcomm.com>
Co-authored-by: Sergei Larin <slarin at codeaurora.org>

>From c377d0eb950bd937792283f0df2ce0ab1ad044fd Mon Sep 17 00:00:00 2001
From: Fateme Hosseini <fhossein at qti.qualcomm.com>
Date: Wed, 22 Jul 2026 14:45:25 -0700
Subject: [PATCH] [Hexagon] Lower fcmp oeq to vcmp_(s|h)f_eq.

Before this commit, the following error persisted in the hexagon
backend.

Consider the `file.ll` with the following contents.
```
define <32 x float> @setoeq_v32f32(<32 x float> %a, <32 x float> %b,
                                    <32 x float> %c, <32 x float> %d) {
  %cmp = fcmp oeq <32 x float> %a, %b
  %r   = select <32 x i1> %cmp, <32 x float> %c, <32 x float> %d
  ret <32 x float> %r
}
```

Compiling it as `hexagon-llc -march=hexagon
-mattr=+hvxv81,+hvx-length128b file.ll`, we get

```
setoeq_v32f32:
        .cfi_startproc
        {
                q0 = vcmp.eq(v0.w,v1.w)
        }
        {
                v0 = vmux(q0,v2,v3)
                jumpr r31
        }
.Lfunc_end0:
        .size   setoeq_v32f32, .Lfunc_end0-setoeq_v32f32
        .cfi_endproc
```

It must be noted that the resulting code is using a bitwise comparison
leading to incorrect quiet-NaN behavior. In this patch, we use vcmp_sf_eq
function for the equality check to correctly handle the NaN comparison
behavior.

For Pre-v81, we synthesize oeq(a,b) as NOT(ogt(a,b) OR ogt(b,a) OR
isNaN(a) OR isNaN(b)) using the available float-GT instructions.

Co-authored-by: Kaushik Kulkarni <kauskulk at qti.qualcomm.com>
Co-authored-by: Sergei Larin <slarin at codeaurora.org>
---
 llvm/lib/Target/Hexagon/HexagonISelLowering.h |   1 +
 .../Target/Hexagon/HexagonISelLoweringHVX.cpp | 105 +++++++++++++-
 llvm/lib/Target/Hexagon/HexagonPatternsHVX.td |  24 ++--
 .../Hexagon/autohvx/vector-compare-128b.ll    | 135 +++++++++++++++++-
 .../Hexagon/autohvx/vector-compare-float.ll   |  16 +--
 .../CodeGen/Hexagon/hvx-float-setoeq-v68.ll   |  64 +++++++++
 llvm/test/CodeGen/Hexagon/hvx-float-setoeq.ll |  46 ++++++
 .../test/CodeGen/Hexagon/inst_setcc_uno_uo.ll |  78 +++++-----
 8 files changed, 417 insertions(+), 52 deletions(-)
 create mode 100644 llvm/test/CodeGen/Hexagon/hvx-float-setoeq-v68.ll
 create mode 100644 llvm/test/CodeGen/Hexagon/hvx-float-setoeq.ll

diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
index 53aff87091775..9ed6e95e3c44f 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
@@ -497,6 +497,7 @@ class HexagonTargetLowering : public TargetLowering {
   SDValue LowerHvxPred32ToFp(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerHvxPred64ToFp(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerHvxPartialReduceMLA(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerHvxFpSetoeq(SDValue Op, SelectionDAG &DAG) const;
   SDValue ExpandHvxFpToInt(SDValue Op, SelectionDAG &DAG) const;
   SDValue ExpandHvxIntToFp(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerHvxStore(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index 22fe067efa6d9..7a2373c32b272 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -180,6 +180,16 @@ HexagonTargetLowering::initializeHVXLowering() {
     setPromoteTo(ISD::VECTOR_SHUFFLE,  MVT::v64f32, ByteW);
     setPromoteTo(ISD::VECTOR_SHUFFLE,  MVT::v32f32, ByteV);
 
+    // For HVX <v81 there is no hardware float-equality instruction; only
+    // float-GT (V6_vgtsf/V6_vgthf) is available.  The integer-equality
+    // fallback (V6_veqw/V6_veqh) silently treats NaN as equal to itself
+    // because the bit patterns match.  Mark SETCC as Custom for the
+    // single-vector float types so we can synthesise the correct
+    // ordered-equal predicate in LowerHvxFpSetoeq.
+    if (!Subtarget.useHVXV81Ops())
+      for (MVT T : FloatV)
+        setOperationAction(ISD::SETCC, T, Custom);
+
     if (Subtarget.useHVXV81Ops()) {
       setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v128bf16, ByteW);
       setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v64bf16, ByteV);
@@ -3806,7 +3816,13 @@ HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const {
     case ISD::SMUL_LOHI:
     case ISD::UMUL_LOHI:               return LowerHvxMulLoHi(Op, DAG);
     case ISD::ANY_EXTEND_VECTOR_INREG: return LowerHvxExtend(Op, DAG);
-    case ISD::SETCC:
+    case ISD::SETCC: {
+      ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
+      if (CC == ISD::SETOEQ &&
+          ty(Op.getOperand(0)).getScalarType().isFloatingPoint())
+        return LowerHvxFpSetoeq(Op, DAG);
+      return Op;
+    }
     case ISD::INTRINSIC_VOID:          return Op;
     case ISD::INTRINSIC_WO_CHAIN:      return LowerHvxIntrinsic(Op, DAG);
     case ISD::MLOAD:
@@ -4448,6 +4464,93 @@ HexagonTargetLowering::LowerHvxPartialReduceMLA(SDValue Op,
   return DAG.getNode(ISD::CONCAT_VECTORS, DL, AccType, Subvectors);
 }
 
+// Lower fcmp oeq on HVX float vectors for architectures before v81, which
+// lack a dedicated floating-point equality instruction.
+//
+// Correct IEEE-754 semantics: oeq(a,b) is true iff a==b and neither is NaN.
+// We use the available float-GT instruction (V6_vgtsf/V6_vgthf) for the
+// inequality check and bit manipulation for NaN detection:
+//
+//   oeq(a, b) = NOT(ogt(a,b) OR ogt(b,a) OR isNaN(a) OR isNaN(b))
+//
+// where  isNaN(x) = ((int_bits(x) & AbsMask) > NaNThreshold)
+//   f32: AbsMask=0x7FFFFFFF, NaNThreshold=0x7F800000
+//   f16: AbsMask=0x7FFF,     NaNThreshold=0x7C00
+//
+// This handles +0/-0 correctly because float-GT treats them as equal, so
+// neither ogt(+0,-0) nor ogt(-0,+0) is ever true.
+//
+// Example f32 assembly (no NaNs case):
+// q0 = vcmp.eq(v0.w, v1.w) // bitwise comparison should just work
+//
+// Example f32 assembly (NaN-present case):
+//   q0  = vcmp.gt(v0.sf, v1.sf)    // ogt(a,b)
+//   q0 |= vcmp.gt(v1.sf, v0.sf)    // |= ogt(b,a)
+//   r0  = ##0x7FFFFFFF
+//   v2  = vsplat(r0)               // AbsMask broadcast
+//   r1  = ##0x7F800000
+//   v3  = vsplat(r1)               // NaNThresh broadcast
+//   v4  = vand(v0, v2)             // int_bits(a) & AbsMask
+//   v5  = vand(v1, v2)             // int_bits(b) & AbsMask
+//   q0 |= vcmp.gt(v4.w, v3.w)     // |= isNaN(a)
+//   q0 |= vcmp.gt(v5.w, v3.w)     // |= isNaN(b)
+//   // q0 now holds AnyFalse; result = XOR(q0, allones) = oeq
+SDValue HexagonTargetLowering::LowerHvxFpSetoeq(SDValue Op,
+                                                SelectionDAG &DAG) const {
+  auto ResTy = ty(Op);
+  auto A = Op.getOperand(0), B = Op->getOperand(1);
+  MVT FloatTy = ty(A);
+  MVT ElemTy = FloatTy.getVectorElementType();
+  bool IsF32 = (ElemTy == MVT::f32);
+  if (!IsF32) {
+    assert((ElemTy == MVT::f16));
+  }
+  const SDLoc &DL(Op);
+  MVT IntElemTy = IsF32 ? MVT::i32 : MVT::i16;
+  MVT IntVecTy = tyVector(FloatTy, IntElemTy);
+
+  // Under nnan semantics NaN cannot appear, so integer equality is both
+  // correct and cheaper (one instruction vs the float-GT sequence).
+  bool NoNaN = Op->getFlags().hasNoNaNs();
+  if (NoNaN) {
+    SDValue IA = DAG.getNode(ISD::BITCAST, DL, IntVecTy, A);
+    SDValue IB = DAG.getNode(ISD::BITCAST, DL, IntVecTy, B);
+    return DAG.getSetCC(DL, ResTy, IA, IB, ISD::SETEQ);
+  }
+
+  // Float GT comparisons (IEEE-754: false whenever either operand is NaN).
+  SDValue QAgtB = DAG.getSetCC(DL, ResTy, A, B, ISD::SETOGT);
+  SDValue QBgtA = DAG.getSetCC(DL, ResTy, B, A, ISD::SETOGT);
+
+  // OR all "false" conditions together, then invert.
+  SDValue AnyFalse = DAG.getNode(ISD::OR, DL, ResTy, QAgtB, QBgtA);
+
+  // Detect NaN by checking whether the unbiased exponent/mantissa field
+  // exceeds the largest finite value.
+  //   f32: (bits & 0x7FFFFFFF) > 0x7F800000
+  //   f16: (bits & 0x7FFF)     > 0x7C00
+  uint64_t AbsMask = IsF32 ? 0x7FFFFFFFull : 0x7FFFull;
+  uint64_t NaNThresh = IsF32 ? 0x7F800000ull : 0x7C00ull;
+
+  SDValue IA = DAG.getNode(ISD::BITCAST, DL, IntVecTy, A);
+  SDValue IB = DAG.getNode(ISD::BITCAST, DL, IntVecTy, B);
+  SDValue MaskVec = DAG.getConstant(AbsMask, DL, IntVecTy);
+  SDValue ThreshVec = DAG.getConstant(NaNThresh, DL, IntVecTy);
+  SDValue QNanA =
+      DAG.getSetCC(DL, ResTy, DAG.getNode(ISD::AND, DL, IntVecTy, IA, MaskVec),
+                   ThreshVec, ISD::SETGT);
+  SDValue QNanB =
+      DAG.getSetCC(DL, ResTy, DAG.getNode(ISD::AND, DL, IntVecTy, IB, MaskVec),
+                   ThreshVec, ISD::SETGT);
+  AnyFalse = DAG.getNode(ISD::OR, DL, ResTy, AnyFalse, QNanA);
+  AnyFalse = DAG.getNode(ISD::OR, DL, ResTy, AnyFalse, QNanB);
+
+  // Result = NOT(<Is A gt B>, <IS B gt A>, <IS A NaN>, <IS B NaN>)
+  // Use XOR with ones to simulate logical not.
+  return DAG.getNode(ISD::XOR, DL, ResTy, AnyFalse,
+                     DAG.getConstant(1, DL, ResTy));
+}
+
 SDValue
 HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
       const {
diff --git a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
index df94610604692..fa13bd013bc7c 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
@@ -678,6 +678,22 @@ let Predicates = [UseHVXV68, UseHVX128B, UseHVXQFloat] in {
   def: OpR_RR_pat<V6_vmax_sf, pf2<fmaxnum>, VecF32, HVF32>;
 }
 
+// V6_veqsf/V6_veqhf use IEEE-754 float equality (NaN != NaN), which correctly
+// detects NaN. Override the integer V6_veqw/V6_veqh setoeq patterns on
+// v81+QFloat so that NaN handling works correctly.
+let Predicates = [UseHVXV81, UseHVXQFloat] in {
+  let AddedComplexity = 10 in {
+    def: OpR_RR_pat<V6_veqsf, setoeq, VecQ32, HVF32>;
+    def: OpR_RR_pat<V6_veqhf, setoeq, VecQ16, HVF16>;
+    def: AccRRR_pat<V6_veqhf_and,    And,         setoeq,  HQ16, HVF16, HVF16>;
+    def: AccRRR_pat<V6_veqhf_or,      Or,         setoeq,  HQ16, HVF16, HVF16>;
+    def: AccRRR_pat<V6_veqhf_xor,    Xor,         setoeq,  HQ16, HVF16, HVF16>;
+    def: AccRRR_pat<V6_veqsf_and,    And,         setoeq,  HQ32, HVF32, HVF32>;
+    def: AccRRR_pat<V6_veqsf_or,      Or,         setoeq,  HQ32, HVF32, HVF32>;
+    def: AccRRR_pat<V6_veqsf_xor,    Xor,         setoeq,  HQ32, HVF32, HVF32>;
+  }
+}
+
 let Predicates = [UseHVXV68, UseHVX128B, UseHVXIEEEFP] in {
   let AddedComplexity = 220 in {
     defm: MinMax_pats<V6_vfmin_hf, V6_vfmax_hf, vselect,  setgt, VecQ16, HVF16>;
@@ -1037,14 +1053,12 @@ let Predicates = [UseHVX] in {
 
 let Predicates = [UseHVXV68, UseHVXFloatingPoint] in {
   def: OpR_RR_pat<V6_veqh,              seteq,  VecQ16, HVF16>;
-  def: OpR_RR_pat<V6_veqh,             setoeq,  VecQ16, HVF16>;
   def: OpR_RR_pat<V6_veqh,             setueq,  VecQ16, HVF16>;
   def: OpR_RR_pat<V6_vgthf,             setgt,  VecQ16, HVF16>;
   def: OpR_RR_pat<V6_vgthf,            setogt,  VecQ16, HVF16>;
   def: OpR_RR_pat<V6_vgthf,            setugt,  VecQ16, HVF16>;
 
   def: OpR_RR_pat<V6_veqw,              seteq,  VecQ32, HVF32>;
-  def: OpR_RR_pat<V6_veqw,             setoeq,  VecQ32, HVF32>;
   def: OpR_RR_pat<V6_veqw,             setueq,  VecQ32, HVF32>;
   def: OpR_RR_pat<V6_vgtsf,             setgt,  VecQ32, HVF32>;
   def: OpR_RR_pat<V6_vgtsf,            setogt,  VecQ32, HVF32>;
@@ -1053,9 +1067,6 @@ let Predicates = [UseHVXV68, UseHVXFloatingPoint] in {
   def: AccRRR_pat<V6_veqh_and,    And,          seteq,  HQ16, HVF16, HVF16>;
   def: AccRRR_pat<V6_veqh_or,      Or,          seteq,  HQ16, HVF16, HVF16>;
   def: AccRRR_pat<V6_veqh_xor,    Xor,          seteq,  HQ16, HVF16, HVF16>;
-  def: AccRRR_pat<V6_veqh_and,    And,         setoeq,  HQ16, HVF16, HVF16>;
-  def: AccRRR_pat<V6_veqh_or,      Or,         setoeq,  HQ16, HVF16, HVF16>;
-  def: AccRRR_pat<V6_veqh_xor,    Xor,         setoeq,  HQ16, HVF16, HVF16>;
   def: AccRRR_pat<V6_veqh_and,    And,         setueq,  HQ16, HVF16, HVF16>;
   def: AccRRR_pat<V6_veqh_or,      Or,         setueq,  HQ16, HVF16, HVF16>;
   def: AccRRR_pat<V6_veqh_xor,    Xor,         setueq,  HQ16, HVF16, HVF16>;
@@ -1072,9 +1083,6 @@ let Predicates = [UseHVXV68, UseHVXFloatingPoint] in {
   def: AccRRR_pat<V6_veqw_and,    And,          seteq,  HQ32, HVF32, HVF32>;
   def: AccRRR_pat<V6_veqw_or,      Or,          seteq,  HQ32, HVF32, HVF32>;
   def: AccRRR_pat<V6_veqw_xor,    Xor,          seteq,  HQ32, HVF32, HVF32>;
-  def: AccRRR_pat<V6_veqw_and,    And,         setoeq,  HQ32, HVF32, HVF32>;
-  def: AccRRR_pat<V6_veqw_or,      Or,         setoeq,  HQ32, HVF32, HVF32>;
-  def: AccRRR_pat<V6_veqw_xor,    Xor,         setoeq,  HQ32, HVF32, HVF32>;
   def: AccRRR_pat<V6_veqw_and,    And,         setueq,  HQ32, HVF32, HVF32>;
   def: AccRRR_pat<V6_veqw_or,      Or,         setueq,  HQ32, HVF32, HVF32>;
   def: AccRRR_pat<V6_veqw_xor,    Xor,         setueq,  HQ32, HVF32, HVF32>;
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-128b.ll b/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-128b.ll
index a9483037e14b1..a13db57efc2a8 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-128b.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-128b.ll
@@ -573,4 +573,137 @@ define <32 x i32> @test_2i(<32 x i32> %v0, <32 x i32> %v1, <32 x i32> %v2) #0 {
   ret <32 x i32> %t1
 }
 
-attributes #0 = { nounwind readnone "target-cpu"="hexagonv60" "target-features"="+hvx,+hvx-length128b" }
+; --- Float32
+
+; CHECK-LABEL: test_2j:
+; CHECK: q[[Q2J0:[0-3]]] = vcmp.eq(v0.w,v1.w)
+; CHECK: v0 = vmux(q[[Q2J0]],v0,v1)
+define <32 x float> @test_2j(<32 x float> %v0, <32 x float> %v1) #1 {
+  %t0 = fcmp nnan oeq <32 x float> %v0, %v1
+  %t1 = select <32 x i1> %t0, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2k:
+; CHECK: q[[Q2K0:[0-3]]] = vcmp.eq(v0.w,v1.w)
+; CHECK: v0 = vmux(q[[Q2K0]],v1,v0)
+define <32 x float> @test_2k(<32 x float> %v0, <32 x float> %v1) #1 {
+  %t0 = fcmp one <32 x float> %v0, %v1
+  %t1 = select <32 x i1> %t0, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2l:
+; CHECK: v0.sf = vmin(v1.sf,v0.sf)
+define <32 x float> @test_2l(<32 x float> %v0, <32 x float> %v1) #1 {
+  %t0 = fcmp olt <32 x float> %v0, %v1
+  %t1 = select <32 x i1> %t0, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2m:
+; CHECK: q[[Q2M0:[0-3]]] = vcmp.gt(v0.sf,v1.sf)
+; CHECK: v0 = vmux(q[[Q2M0]],v1,v0)
+define <32 x float> @test_2m(<32 x float> %v0, <32 x float> %v1) #1 {
+  %t0 = fcmp ole <32 x float> %v0, %v1
+  %t1 = select <32 x i1> %t0, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2n:
+; CHECK: v0.sf = vmax(v0.sf,v1.sf)
+define <32 x float> @test_2n(<32 x float> %v0, <32 x float> %v1) #1 {
+  %t0 = fcmp ogt <32 x float> %v0, %v1
+  %t1 = select <32 x i1> %t0, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2o:
+; CHECK: q[[Q2O0:[0-3]]] = vcmp.gt(v1.sf,v0.sf)
+; CHECK: v0 = vmux(q[[Q2O0]],v1,v0)
+define <32 x float> @test_2o(<32 x float> %v0, <32 x float> %v1) #1 {
+  %t0 = fcmp oge <32 x float> %v0, %v1
+  %t1 = select <32 x i1> %t0, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2p:
+; CHECK: r[[R2P0:[0-9]*]] = ##16843009
+; CHECK: q[[Q2P1:[0-3]]] = vand(v2,r[[R2P0]])
+; CHECK: q[[Q2P1:[0-3]]] &= vcmp.eq(v0.w,v1.w)
+; CHECK: v0 = vmux(q[[Q2P1]],v0,v1)
+define <32 x float> @test_2p(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2) #1 {
+  %q0 = fcmp nnan oeq <32 x float> %v0, %v1
+  %q1 = trunc <32 x i32> %v2 to <32 x i1>
+  %q2 = and <32 x i1> %q0, %q1
+  %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2q:
+; CHECK: r[[R2Q0:[0-9]*]] = ##16843009
+; CHECK: q[[Q2Q1:[0-3]]] = vand(v2,r[[R2Q0]])
+; CHECK: q[[Q2Q1:[0-3]]] |= vcmp.eq(v0.w,v1.w)
+; CHECK: v0 = vmux(q[[Q2Q1]],v0,v1)
+define <32 x float> @test_2q(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2) #1 {
+  %q0 = fcmp nnan oeq <32 x float> %v0, %v1
+  %q1 = trunc <32 x i32> %v2 to <32 x i1>
+  %q2 = or <32 x i1> %q0, %q1
+  %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2r:
+; CHECK: r[[R2R0:[0-9]*]] = ##16843009
+; CHECK: q[[Q2R1:[0-3]]] = vand(v2,r[[R2R0]])
+; CHECK: q[[Q2R1:[0-3]]] ^= vcmp.eq(v0.w,v1.w)
+; CHECK: v0 = vmux(q[[Q2R1]],v0,v1)
+define <32 x float> @test_2r(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2) #1 {
+  %q0 = fcmp nnan oeq <32 x float> %v0, %v1
+  %q1 = trunc <32 x i32> %v2 to <32 x i1>
+  %q2 = xor <32 x i1> %q0, %q1
+  %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2s:
+; CHECK: r[[R2S0:[0-9]*]] = ##16843009
+; CHECK: q[[Q2S1:[0-3]]] = vand(v2,r[[R2S0]])
+; CHECK: q[[Q2S1:[0-3]]] &= vcmp.gt(v0.sf,v1.sf)
+; CHECK: v0 = vmux(q[[Q2R1]],v0,v1)
+define <32 x float> @test_2s(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2) #1 {
+  %q0 = fcmp ogt <32 x float> %v0, %v1
+  %q1 = trunc <32 x i32> %v2 to <32 x i1>
+  %q2 = and <32 x i1> %q0, %q1
+  %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2t:
+; CHECK: r[[R2T0:[0-9]*]] = ##16843009
+; CHECK: q[[Q2T1:[0-3]]] = vand(v2,r[[R2T0]])
+; CHECK: q[[Q2T1:[0-3]]] |= vcmp.gt(v0.sf,v1.sf)
+; CHECK: v0 = vmux(q[[Q2T1]],v0,v1)
+define <32 x float> @test_2t(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2) #1 {
+  %q0 = fcmp ogt <32 x float> %v0, %v1
+  %q1 = trunc <32 x i32> %v2 to <32 x i1>
+  %q2 = or <32 x i1> %q0, %q1
+  %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+; CHECK-LABEL: test_2u:
+; CHECK: r[[R2U0:[0-9]*]] = ##16843009
+; CHECK: q[[Q2U1:[0-3]]] = vand(v2,r[[R2U0]])
+; CHECK: q[[Q2U1:[0-3]]] ^= vcmp.gt(v0.sf,v1.sf)
+; CHECK: v0 = vmux(q[[Q2U1]],v0,v1)
+define <32 x float> @test_2u(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2) #1 {
+  %q0 = fcmp ogt <32 x float> %v0, %v1
+  %q1 = trunc <32 x i32> %v2 to <32 x i1>
+  %q2 = xor <32 x i1> %q0, %q1
+  %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
+  ret <32 x float> %t1
+}
+
+attributes #0 = { nounwind readnone "target-cpu"="hexagonv73" "target-features"="+hvxv73,+hvx-length128b" }
+attributes #1 = { nounwind readnone "target-cpu"="hexagonv68" "target-features"="+hvxv68,+hvx-length128b,+hvx-qfloat" }
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-float.ll b/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-float.ll
index f7e72b26b7ebd..00f410c55f70f 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-float.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/vector-compare-float.ll
@@ -14,7 +14,7 @@ define <64 x half> @test_00(<64 x half> %v0, <64 x half> %v1, <64 x half> %v2) #
 ; CHECK-NEXT:     v0 = vmux(q0,v1,v2)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %t0 = fcmp oeq <64 x half> %v0, %v1
+  %t0 = fcmp nnan oeq <64 x half> %v0, %v1
   %t1 = select <64 x i1> %t0, <64 x half> %v1, <64 x half> %v2
   ret <64 x half> %t1
 }
@@ -110,7 +110,7 @@ define <64 x half> @test_0a(<64 x half> %v0, <64 x half> %v1, <64 x i16> %v2) #0
 ; CHECK-NEXT:     v0 = vmux(q0,v0,v1)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %q0 = fcmp oeq <64 x half> %v0, %v1
+  %q0 = fcmp nnan oeq <64 x half> %v0, %v1
   %q1 = trunc <64 x i16> %v2 to <64 x i1>
   %q2 = and <64 x i1> %q0, %q1
   %t1 = select <64 x i1> %q2, <64 x half> %v0, <64 x half> %v1
@@ -133,7 +133,7 @@ define <64 x half> @test_0b(<64 x half> %v0, <64 x half> %v1, <64 x i16> %v2) #0
 ; CHECK-NEXT:     v0 = vmux(q0,v0,v1)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %q0 = fcmp oeq <64 x half> %v0, %v1
+  %q0 = fcmp nnan oeq <64 x half> %v0, %v1
   %q1 = trunc <64 x i16> %v2 to <64 x i1>
   %q2 = or <64 x i1> %q0, %q1
   %t1 = select <64 x i1> %q2, <64 x half> %v0, <64 x half> %v1
@@ -156,7 +156,7 @@ define <64 x half> @test_0c(<64 x half> %v0, <64 x half> %v1, <64 x i16> %v2) #0
 ; CHECK-NEXT:     v0 = vmux(q0,v0,v1)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %q0 = fcmp oeq <64 x half> %v0, %v1
+  %q0 = fcmp nnan oeq <64 x half> %v0, %v1
   %q1 = trunc <64 x i16> %v2 to <64 x i1>
   %q2 = xor <64 x i1> %q0, %q1
   %t1 = select <64 x i1> %q2, <64 x half> %v0, <64 x half> %v1
@@ -245,7 +245,7 @@ define <32 x float> @test_10(<32 x float> %v0, <32 x float> %v1, <32 x float> %v
 ; CHECK-NEXT:     v0 = vmux(q0,v1,v2)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %t0 = fcmp oeq <32 x float> %v0, %v1
+  %t0 = fcmp nnan oeq <32 x float> %v0, %v1
   %t1 = select <32 x i1> %t0, <32 x float> %v1, <32 x float> %v2
   ret <32 x float> %t1
 }
@@ -341,7 +341,7 @@ define <32 x float> @test_1a(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2)
 ; CHECK-NEXT:     v0 = vmux(q0,v0,v1)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %q0 = fcmp oeq <32 x float> %v0, %v1
+  %q0 = fcmp nnan oeq <32 x float> %v0, %v1
   %q1 = trunc <32 x i32> %v2 to <32 x i1>
   %q2 = and <32 x i1> %q0, %q1
   %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
@@ -364,7 +364,7 @@ define <32 x float> @test_1b(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2)
 ; CHECK-NEXT:     v0 = vmux(q0,v0,v1)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %q0 = fcmp oeq <32 x float> %v0, %v1
+  %q0 = fcmp nnan oeq <32 x float> %v0, %v1
   %q1 = trunc <32 x i32> %v2 to <32 x i1>
   %q2 = or <32 x i1> %q0, %q1
   %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
@@ -387,7 +387,7 @@ define <32 x float> @test_1c(<32 x float> %v0, <32 x float> %v1, <32 x i32> %v2)
 ; CHECK-NEXT:     v0 = vmux(q0,v0,v1)
 ; CHECK-NEXT:     jumpr r31
 ; CHECK-NEXT:    }
-  %q0 = fcmp oeq <32 x float> %v0, %v1
+  %q0 = fcmp nnan oeq <32 x float> %v0, %v1
   %q1 = trunc <32 x i32> %v2 to <32 x i1>
   %q2 = xor <32 x i1> %q0, %q1
   %t1 = select <32 x i1> %q2, <32 x float> %v0, <32 x float> %v1
diff --git a/llvm/test/CodeGen/Hexagon/hvx-float-setoeq-v68.ll b/llvm/test/CodeGen/Hexagon/hvx-float-setoeq-v68.ll
new file mode 100644
index 0000000000000..29dba6190a7bd
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/hvx-float-setoeq-v68.ll
@@ -0,0 +1,64 @@
+; RUN: llc -march=hexagon -mattr=+hvxv68,+hvx-length128b,+hvx-ieee-fp %s -o - | FileCheck %s
+;
+; Verify that ordered-equal (setoeq) on HVX float vectors uses IEEE-754 float
+; greater-than (V6_vgtsf/V6_vgthf) combined with integer NaN detection rather
+; than the integer word/half comparison V6_veqw/V6_veqh.
+;
+; The integer variants treat NaN as equal to itself (same bit pattern), which
+; breaks NaN detection.  The correct expansion is:
+;   oeq(a, b) = NOT(ogt(a,b) OR ogt(b,a) OR isNaN(a) OR isNaN(b))
+; where isNaN uses integer bit manipulation.
+;
+
+; Single-register f32: result predicate is v32i1
+define <32 x float> @setoeq_v32f32(<32 x float> %a, <32 x float> %b,
+                                    <32 x float> %c, <32 x float> %d) {
+  %cmp = fcmp oeq <32 x float> %a, %b
+  %r   = select <32 x i1> %cmp, <32 x float> %c, <32 x float> %d
+  ret <32 x float> %r
+}
+; CHECK-LABEL: setoeq_v32f32
+; Float GT comparisons (a > b) and (b > a)
+; CHECK-DAG: vcmp.gt({{.*}}.sf,{{.*}}.sf)
+; Integer AND to mask sign bit for NaN detection
+; CHECK-DAG: vand(
+; Integer GT against NaN threshold
+; CHECK-DAG: vcmp.gt({{.*}}.w,{{.*}}.w)
+; Must NOT use integer equality for the comparison
+; CHECK-NOT: vcmp.eq({{.*}}.w,{{.*}}.w)
+
+; Double-register f32: split into two single-register operations
+define <64 x float> @setoeq_v64f32(<64 x float> %a, <64 x float> %b,
+                                    <64 x float> %c, <64 x float> %d) {
+  %cmp = fcmp oeq <64 x float> %a, %b
+  %r   = select <64 x i1> %cmp, <64 x float> %c, <64 x float> %d
+  ret <64 x float> %r
+}
+; CHECK-LABEL: setoeq_v64f32
+; CHECK-COUNT-2: vcmp.gt({{.*}}.sf,{{.*}}.sf)
+; CHECK-NOT: vcmp.eq({{.*}}.w,{{.*}}.w)
+
+; Single-register f16
+define <64 x half> @setoeq_v64f16(<64 x half> %a, <64 x half> %b,
+                                   <64 x half> %c, <64 x half> %d) {
+  %cmp = fcmp oeq <64 x half> %a, %b
+  %r   = select <64 x i1> %cmp, <64 x half> %c, <64 x half> %d
+  ret <64 x half> %r
+}
+; CHECK-LABEL: setoeq_v64f16
+; CHECK-DAG: vcmp.gt({{.*}}.hf,{{.*}}.hf)
+; CHECK-DAG: vand(
+; CHECK-DAG: vcmp.gt({{.*}}.h,{{.*}}.h)
+; CHECK-NOT: vcmp.eq({{.*}}.h,{{.*}}.h)
+
+; Double-register f16
+define <128 x half> @setoeq_v128f16(<128 x half> %a, <128 x half> %b,
+                                     <128 x half> %c, <128 x half> %d) {
+  %cmp = fcmp oeq <128 x half> %a, %b
+  %r   = select <128 x i1> %cmp, <128 x half> %c, <128 x half> %d
+  ret <128 x half> %r
+}
+; CHECK-LABEL: setoeq_v128f16
+; CHECK-COUNT-2: vcmp.gt({{.*}}.hf,{{.*}}.hf)
+; CHECK-NOT: vcmp.eq({{.*}}.h,{{.*}}.h)
+
diff --git a/llvm/test/CodeGen/Hexagon/hvx-float-setoeq.ll b/llvm/test/CodeGen/Hexagon/hvx-float-setoeq.ll
new file mode 100644
index 0000000000000..48027b9817d7d
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/hvx-float-setoeq.ll
@@ -0,0 +1,46 @@
+; RUN: llc -march=hexagon -mattr=+hvxv81,+hvx-length128b %s -o - | FileCheck %s
+;
+; Verify that ordered-equal (setoeq) on HVX float vectors uses the float
+; comparison instruction V6_veqsf/V6_veqhf rather than the integer word/half
+; comparison V6_veqw/V6_veqh.  The integer variants treat NaN as equal to
+; itself (same bit pattern), which breaks NaN detection in vector reductions.
+
+define <32 x float> @setoeq_v32f32(<32 x float> %a, <32 x float> %b,
+                                    <32 x float> %c, <32 x float> %d) {
+  %cmp = fcmp oeq <32 x float> %a, %b
+  %r   = select <32 x i1> %cmp, <32 x float> %c, <32 x float> %d
+  ret <32 x float> %r
+}
+; CHECK-LABEL: setoeq_v32f32
+; CHECK: vcmp.eq({{.*}}.sf,{{.*}}.sf)
+; CHECK-NOT: vcmp.eq({{.*}}.w,{{.*}}.w)
+
+define <64 x float> @setoeq_v64f32(<64 x float> %a, <64 x float> %b,
+                                    <64 x float> %c, <64 x float> %d) {
+  %cmp = fcmp oeq <64 x float> %a, %b
+  %r   = select <64 x i1> %cmp, <64 x float> %c, <64 x float> %d
+  ret <64 x float> %r
+}
+; CHECK-LABEL: setoeq_v64f32
+; CHECK-COUNT-2: vcmp.eq({{.*}}.sf,{{.*}}.sf)
+; CHECK-NOT: vcmp.eq({{.*}}.w,{{.*}}.w)
+
+define <64 x half> @setoeq_v64f16(<64 x half> %a, <64 x half> %b,
+                                   <64 x half> %c, <64 x half> %d) {
+  %cmp = fcmp oeq <64 x half> %a, %b
+  %r   = select <64 x i1> %cmp, <64 x half> %c, <64 x half> %d
+  ret <64 x half> %r
+}
+; CHECK-LABEL: setoeq_v64f16
+; CHECK: vcmp.eq({{.*}}.hf,{{.*}}.hf)
+; CHECK-NOT: vcmp.eq({{.*}}.h,{{.*}}.h)
+
+define <128 x half> @setoeq_v128f16(<128 x half> %a, <128 x half> %b,
+                                     <128 x half> %c, <128 x half> %d) {
+  %cmp = fcmp oeq <128 x half> %a, %b
+  %r   = select <128 x i1> %cmp, <128 x half> %c, <128 x half> %d
+  ret <128 x half> %r
+}
+; CHECK-LABEL: setoeq_v128f16
+; CHECK-COUNT-2: vcmp.eq({{.*}}.hf,{{.*}}.hf)
+; CHECK-NOT: vcmp.eq({{.*}}.h,{{.*}}.h)
diff --git a/llvm/test/CodeGen/Hexagon/inst_setcc_uno_uo.ll b/llvm/test/CodeGen/Hexagon/inst_setcc_uno_uo.ll
index 263dc04f090f1..25bc17849e287 100644
--- a/llvm/test/CodeGen/Hexagon/inst_setcc_uno_uo.ll
+++ b/llvm/test/CodeGen/Hexagon/inst_setcc_uno_uo.ll
@@ -1,4 +1,4 @@
-;; RUN: llc --mtriple=hexagon -mattr=+hvxv79,+hvx-length128b %s -o - | FileCheck --enable-var-scope %s
+; RUN: llc --mtriple=hexagon -mattr=+hvxv79,+hvx-length128b %s -o - | FileCheck --enable-var-scope %s
 
 define dso_local void @store_isnan_f32(ptr %a, ptr %b, ptr %isnan_cmp) local_unnamed_addr {
 entry:
@@ -12,17 +12,19 @@ entry:
   store <32 x i32> %.LS.instance, ptr %arrayidx1, align 4
   ret void
 }
-
-; CHECK-LABEL:store_isnan_f32
-; CHECK:      [[RONE32:r[0-9]+]] = #1
-; CHECK:      [[VOP2_F32:v[0-9]+]] = vxor([[VOP2_F32]],[[VOP2_F32]])
-; CHECK:      [[VOP1_F32:v[0-9]+]] = vmemu(r0+#0)
-; CHECK:      [[VONES32:v[0-9]+]] = vsplat([[RONE32]])
-; CHECK:      [[Q1_F32:q[0-9]+]] = vcmp.eq([[VOP1_F32]].w,[[VOP1_F32]].w)
-; CHECK:      [[VOP3_F32:v[0-9]+]] = vmemu(r1+#0)
-; CHECK:      [[Q1_F32]] &= vcmp.eq([[VOP3_F32]].w,[[VOP3_F32]].w)
-; CHECK:      [[VOUT_F32:v[0-9]+]] = vmux([[Q1_F32]],[[VOP2_F32]],[[VONES32]])
-; CHECK:      vmemu(r2+#0) = [[VOUT_F32]]
+; CHECK-LABEL: store_isnan_f32
+; CHECK:       [[VMASK_F32:v[0-9]+]] = vsplat({{r[0-9]+}})
+; CHECK:       [[VMAX_F32:v[0-9]+]] = vsplat({{r[0-9]+}})
+; CHECK:       [[VOP1_F32:v[0-9]+]] = vmemu(r0+#0)
+; CHECK:       [[VABS1_F32:v[0-9]+]] = vand([[VOP1_F32]],[[VMASK_F32]])
+; CHECK:       [[VOP2_F32:v[0-9]+]] = vmemu(r1+#0)
+; CHECK:       [[VABS2_F32:v[0-9]+]] = vand([[VOP2_F32]],[[VMASK_F32]])
+; CHECK:       [[VZERO_F32:v[0-9]+]] = vxor([[VZERO_F32]],[[VZERO_F32]])
+; CHECK:       vcmp.gt([[VABS1_F32]].w,[[VMAX_F32]].w)
+; CHECK:       [[VONES_F32:v[0-9]+]] = vsplat({{r[0-9]+}})
+; CHECK:       vcmp.gt([[VABS2_F32]].w,[[VMAX_F32]].w)
+; CHECK:       [[VOUT_F32:v[0-9]+]] = vmux({{q[0-9]+}},[[VZERO_F32]],[[VONES_F32]])
+; CHECK:       vmemu(r2+#0) = [[VOUT_F32]]
 
 define dso_local void @store_isnan_f16(ptr %a, ptr %b, ptr %isnan_cmp) local_unnamed_addr {
 entry:
@@ -37,14 +39,17 @@ entry:
   ret void
 }
 ; CHECK-LABEL: store_isnan_f16
-; CHECK:       [[RONE16:r[0-9]+]] = #1
-; CHECK:       [[VOP2_F16:v[0-9]+]] = vxor([[VOP2_F16]],[[VOP2_F16]])
 ; CHECK:       [[VOP1_F16:v[0-9]+]] = vmemu(r0+#0)
-; CHECK:       [[VONES16:v[0-9]+]].h = vsplat([[RONE16]])
-; CHECK:       [[Q1_F16:q[0-9]+]] = vcmp.eq([[VOP1_F16]].h,[[VOP1_F16]].h)
-; CHECK:       [[VOP3_F16:v[0-9]+]] = vmemu(r1+#0)
-; CHECK:       [[Q1_F16]] &= vcmp.eq([[VOP3_F16]].h,[[VOP3_F16]].h)
-; CHECK:       [[VOUT_F16:v[0-9]+]] = vmux([[Q1_F16]],[[VOP2_F16]],[[VONES16]])
+; CHECK:       [[VMASK_F16:v[0-9]+]].h = vsplat({{r[0-9]+}})
+; CHECK:       [[VMAX_F16:v[0-9]+]].h = vsplat({{r[0-9]+}})
+; CHECK:       [[VOP2_F16:v[0-9]+]] = vmemu(r1+#0)
+; CHECK:       [[VABS1_F16:v[0-9]+]] = vand([[VOP1_F16]],[[VMASK_F16]])
+; CHECK:       [[VABS2_F16:v[0-9]+]] = vand([[VOP2_F16]],[[VMASK_F16]])
+; CHECK:       [[VZERO_F16:v[0-9]+]] = vxor([[VZERO_F16]],[[VZERO_F16]])
+; CHECK:       [[VONES_F16:v[0-9]+]].h = vsplat({{r[0-9]+}})
+; CHECK:       vcmp.gt([[VABS1_F16]].h,[[VMAX_F16]].h)
+; CHECK:       vcmp.gt([[VABS2_F16]].h,[[VMAX_F16]].h)
+; CHECK:       [[VOUT_F16:v[0-9]+]] = vmux({{q[0-9]+}},[[VZERO_F16]],[[VONES_F16]])
 ; CHECK:       vmemu(r2+#0) = [[VOUT_F16]]
 
 define dso_local void @store_isordered_f32(ptr %a, ptr %b, ptr %isordered_cmp) local_unnamed_addr {
@@ -60,17 +65,19 @@ entry:
   ret void
 }
 ; CHECK-LABEL: store_isordered_f32
-; CHECK:       [[RONE32:r[0-9]+]] = #1
-; CHECK:       [[VOP2_ORD_F32:v[0-9]+]] = vxor([[VOP2_ORD_F32]],[[VOP2_ORD_F32]])
+; CHECK:       [[VMASK_ORD_F32:v[0-9]+]] = vsplat({{r[0-9]+}})
+; CHECK:       [[VMAX_ORD_F32:v[0-9]+]] = vsplat({{r[0-9]+}})
 ; CHECK:       [[VOP1_ORD_F32:v[0-9]+]] = vmemu(r0+#0)
-; CHECK:       [[VONES_ORD_F32:v[0-9]+]] = vsplat([[RONE32]])
-; CHECK:       [[Q1_ORD_F32:q[0-9]+]] = vcmp.eq([[VOP1_ORD_F32]].w,[[VOP1_ORD_F32]].w)
-; CHECK:       [[VOP3_ORD_F32:v[0-9]+]] = vmemu(r1+#0)
-; CHECK:       [[Q1_ORD_F32]] &= vcmp.eq([[VOP3_ORD_F32]].w,[[VOP3_ORD_F32]].w)
-; CHECK:       [[VOUT_ORD_F32:v[0-9]+]] = vmux([[Q1_ORD_F32]],[[VONES_ORD_F32]],[[VOP2_ORD_F32]])
+; CHECK:       [[VABS1_ORD_F32:v[0-9]+]] = vand([[VOP1_ORD_F32]],[[VMASK_ORD_F32]])
+; CHECK:       [[VOP2_ORD_F32:v[0-9]+]] = vmemu(r1+#0)
+; CHECK:       [[VABS2_ORD_F32:v[0-9]+]] = vand([[VOP2_ORD_F32]],[[VMASK_ORD_F32]])
+; CHECK:       [[VZERO_ORD_F32:v[0-9]+]] = vxor([[VZERO_ORD_F32]],[[VZERO_ORD_F32]])
+; CHECK:       vcmp.gt([[VABS1_ORD_F32]].w,[[VMAX_ORD_F32]].w)
+; CHECK:       [[VONES_ORD_F32:v[0-9]+]] = vsplat({{r[0-9]+}})
+; CHECK:       vcmp.gt([[VABS2_ORD_F32]].w,[[VMAX_ORD_F32]].w)
+; CHECK:       [[VOUT_ORD_F32:v[0-9]+]] = vmux({{q[0-9]+}},[[VONES_ORD_F32]],[[VZERO_ORD_F32]])
 ; CHECK:       vmemu(r2+#0) = [[VOUT_ORD_F32]]
 
-
 define dso_local void @store_isordered_f16(ptr %a, ptr %b, ptr %isordered_cmp) local_unnamed_addr {
 entry:
   %arrayidx_a = getelementptr inbounds nuw half, ptr %a, i32 0
@@ -84,12 +91,15 @@ entry:
   ret void
 }
 ; CHECK-LABEL: store_isordered_f16
-; CHECK:       [[RONE16:r[0-9]+]] = #1
-; CHECK:       [[VOP2_ORD_F16:v[0-9]+]] = vxor([[VOP2_ORD_F16]],[[VOP2_ORD_F16]])
 ; CHECK:       [[VOP1_ORD_F16:v[0-9]+]] = vmemu(r0+#0)
-; CHECK:       [[VONES_ORD_F16:v[0-9]+]].h = vsplat([[RONE16]])
-; CHECK:       [[Q1_ORD_F16:q[0-9]+]] = vcmp.eq([[VOP1_ORD_F16]].h,[[VOP1_ORD_F16]].h)
-; CHECK:       [[VOP3_ORD_F16:v[0-9]+]] = vmemu(r1+#0)
-; CHECK:       [[Q1_ORD_F16]] &= vcmp.eq([[VOP3_ORD_F16]].h,[[VOP3_ORD_F16]].h)
-; CHECK:       [[VOUT_ORD_F16:v[0-9]+]] = vmux([[Q1_ORD_F16]],[[VONES_ORD_F16]],[[VOP2_ORD_F16]])
+; CHECK:       [[VMASK_ORD_F16:v[0-9]+]].h = vsplat({{r[0-9]+}})
+; CHECK:       [[VMAX_ORD_F16:v[0-9]+]].h = vsplat({{r[0-9]+}})
+; CHECK:       [[VOP2_ORD_F16:v[0-9]+]] = vmemu(r1+#0)
+; CHECK:       [[VABS1_ORD_F16:v[0-9]+]] = vand([[VOP1_ORD_F16]],[[VMASK_ORD_F16]])
+; CHECK:       [[VABS2_ORD_F16:v[0-9]+]] = vand([[VOP2_ORD_F16]],[[VMASK_ORD_F16]])
+; CHECK:       [[VZERO_ORD_F16:v[0-9]+]] = vxor([[VZERO_ORD_F16]],[[VZERO_ORD_F16]])
+; CHECK:       [[VONES_ORD_F16:v[0-9]+]].h = vsplat({{r[0-9]+}})
+; CHECK:       vcmp.gt([[VABS1_ORD_F16]].h,[[VMAX_ORD_F16]].h)
+; CHECK:       vcmp.gt([[VABS2_ORD_F16]].h,[[VMAX_ORD_F16]].h)
+; CHECK:       [[VOUT_ORD_F16:v[0-9]+]] = vmux({{q[0-9]+}},[[VONES_ORD_F16]],[[VZERO_ORD_F16]])
 ; CHECK:       vmemu(r2+#0) = [[VOUT_ORD_F16]]



More information about the llvm-commits mailing list