[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