[llvm] [RISCV] Fold Bitcast long bitwidth int to vector type (PR #194788)

Zaky Hermawan via llvm-commits llvm-commits at lists.llvm.org
Thu May 21 09:16:45 PDT 2026


https://github.com/ZakyHermawan updated https://github.com/llvm/llvm-project/pull/194788

>From e573784962c831590c62e96465e519ce04603e85 Mon Sep 17 00:00:00 2001
From: ZakyHermawan <zaky.hermawan9615 at gmail.com>
Date: Tue, 19 May 2026 13:11:24 +0700
Subject: [PATCH 1/7] Precommit test

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll | 75 ++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll

diff --git a/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
new file mode 100644
index 0000000000000..c4810e7e2201d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
@@ -0,0 +1,75 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+rva23u64 %s -o - | FileCheck %s
+
+define { i1, <32 x i8> } @bitcast_v32i8(ptr %a0) {
+; CHECK-LABEL: bitcast_v32i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a1, 32
+; CHECK-NEXT:    vsetvli zero, a1, e8, m2, ta, ma
+; CHECK-NEXT:    vle8.v v8, (a0)
+; CHECK-NEXT:    vmsne.vi v10, v8, 0
+; CHECK-NEXT:    vcpop.m a0, v10
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %src256 = load i256, ptr %a0, align 32
+  %src256.bitcast = bitcast i256 %src256 to <32 x i8>
+  %iszero = icmp eq i256 %src256, 0
+
+  %res1 = insertvalue { i1, <32 x i8> } poison, i1 %iszero, 0
+  %res2 = insertvalue { i1, <32 x i8> } %res1, <32 x i8> %src256.bitcast, 1
+  ret { i1, <32 x i8> } %res2
+}
+
+define { i1, <16 x i16> } @bitcast_v16i16(ptr %a0) {
+; CHECK-LABEL: bitcast_v16i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    ld a1, 0(a0)
+; CHECK-NEXT:    ld a2, 8(a0)
+; CHECK-NEXT:    ld a3, 16(a0)
+; CHECK-NEXT:    ld a0, 24(a0)
+; CHECK-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
+; CHECK-NEXT:    vmv.v.x v8, a1
+; CHECK-NEXT:    vslide1down.vx v8, v8, a2
+; CHECK-NEXT:    vslide1down.vx v8, v8, a3
+; CHECK-NEXT:    vslide1down.vx v8, v8, a0
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:    vsetvli zero, a0, e8, m2, ta, ma
+; CHECK-NEXT:    vmsne.vi v10, v8, 0
+; CHECK-NEXT:    vcpop.m a0, v10
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %src256 = load i256, ptr %a0, align 32
+  %src256.bitcast = bitcast i256 %src256 to <16 x i16>
+  %iszero = icmp eq i256 %src256, 0
+
+  %res1 = insertvalue { i1, <16 x i16> } poison, i1 %iszero, 0
+  %res2 = insertvalue { i1, <16 x i16> } %res1, <16 x i16> %src256.bitcast, 1
+  ret { i1, <16 x i16> } %res2
+}
+
+define { i1, <8 x i32> } @bitcast_v8i32(ptr %a0) {
+; CHECK-LABEL: bitcast_v8i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    ld a1, 0(a0)
+; CHECK-NEXT:    ld a2, 8(a0)
+; CHECK-NEXT:    ld a3, 16(a0)
+; CHECK-NEXT:    ld a0, 24(a0)
+; CHECK-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
+; CHECK-NEXT:    vmv.v.x v8, a1
+; CHECK-NEXT:    vslide1down.vx v8, v8, a2
+; CHECK-NEXT:    vslide1down.vx v8, v8, a3
+; CHECK-NEXT:    vslide1down.vx v8, v8, a0
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:    vsetvli zero, a0, e8, m2, ta, ma
+; CHECK-NEXT:    vmsne.vi v10, v8, 0
+; CHECK-NEXT:    vcpop.m a0, v10
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %src256 = load i256, ptr %a0, align 32
+  %src256.bitcast = bitcast i256 %src256 to <8 x i32>
+  %iszero = icmp eq i256 %src256, 0
+
+  %res1 = insertvalue { i1, <8 x i32> } poison, i1 %iszero, 0
+  %res2 = insertvalue { i1, <8 x i32> } %res1, <8 x i32> %src256.bitcast, 1
+  ret { i1, <8 x i32> } %res2
+}

>From a7b9d881f8781a233cbe9bb8bab3bf1fd8d08e2c Mon Sep 17 00:00:00 2001
From: ZakyHermawan <zaky.hermawan9615 at gmail.com>
Date: Tue, 19 May 2026 13:15:08 +0700
Subject: [PATCH 2/7] [RISCV] Apply fix

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 51 +++++++++++++++++++--
 llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll  | 26 ++---------
 2 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 26281a8976fcf..8b657a719804e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17625,14 +17625,57 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
   if (!OpVT.isByteSized())
     return SDValue();
 
-  unsigned VecSize = OpSize / 8;
-  EVT VecVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, VecSize);
-  EVT CmpVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, VecSize);
+  // Find a preferred vector element type by inspecting how the value is used.
+  auto GetPreferredEltVT = [](SDValue V) -> MVT {
+    // Look backwards: check if V itself is derived from a vector
+    SDValue Peek = peekThroughBitcasts(V);
+    if (Peek.getValueType().isVector() && Peek.getValueType().isInteger())
+      return Peek.getSimpleValueType().getVectorElementType();
+
+    // Look forwards: check if V is bitcasted to a vector elsewhere in the DAG
+    for (SDUse &Use : V->uses()) {
+      // Ensure we are checking the use of the specific value result, not the
+      // node's chain
+      if (Use.getResNo() != V.getResNo())
+        continue;
+
+      SDNode *User = Use.getUser();
+      if (User->getOpcode() == ISD::BITCAST) {
+        EVT CastVT = User->getValueType(0);
+        if (CastVT.isVector() && CastVT.isInteger())
+          return CastVT.getVectorElementType().getSimpleVT();
+      }
+    }
+    return MVT::INVALID_SIMPLE_VALUE_TYPE;
+  };
+
+  auto IsValidEltVT = [&](MVT VT) {
+    return VT != MVT::INVALID_SIMPLE_VALUE_TYPE && VT.isInteger() &&
+           VT.getSizeInBits() >= 8 &&
+           VT.getSizeInBits() <= Subtarget.getXLen() &&
+           OpSize % VT.getSizeInBits() == 0;
+  };
+
+  // Get preferred VT from either X or Y.
+  MVT EltVT = GetPreferredEltVT(X);
+  if (!IsValidEltVT(EltVT)) {
+    EltVT = GetPreferredEltVT(Y);
+  }
+
+  // If both are unsuitable, use the safe default (i8)
+  if (!IsValidEltVT(EltVT)) {
+    EltVT = MVT::i8;
+  }
+
+  unsigned EltSize = EltVT.getSizeInBits();
+  unsigned NumElts = OpSize / EltSize;
+  EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts);
+  EVT CmpVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, NumElts);
 
   SDValue VecX = DAG.getBitcast(VecVT, X);
   SDValue VecY = DAG.getBitcast(VecVT, Y);
   SDValue Mask = DAG.getAllOnesConstant(DL, CmpVT);
-  SDValue VL = DAG.getConstant(VecSize, DL, XLenVT);
+  SDValue VL = DAG.getConstant(NumElts, DL, XLenVT);
 
   SDValue Cmp = DAG.getSetCC(DL, CmpVT, VecX, VecY, ISD::SETNE);
   return DAG.getSetCC(DL, VT,
diff --git a/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
index c4810e7e2201d..2d9100da4f5e0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
@@ -23,17 +23,8 @@ define { i1, <32 x i8> } @bitcast_v32i8(ptr %a0) {
 define { i1, <16 x i16> } @bitcast_v16i16(ptr %a0) {
 ; CHECK-LABEL: bitcast_v16i16:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    ld a1, 0(a0)
-; CHECK-NEXT:    ld a2, 8(a0)
-; CHECK-NEXT:    ld a3, 16(a0)
-; CHECK-NEXT:    ld a0, 24(a0)
-; CHECK-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
-; CHECK-NEXT:    vmv.v.x v8, a1
-; CHECK-NEXT:    vslide1down.vx v8, v8, a2
-; CHECK-NEXT:    vslide1down.vx v8, v8, a3
-; CHECK-NEXT:    vslide1down.vx v8, v8, a0
-; CHECK-NEXT:    li a0, 32
-; CHECK-NEXT:    vsetvli zero, a0, e8, m2, ta, ma
+; CHECK-NEXT:    vsetivli zero, 16, e16, m2, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
 ; CHECK-NEXT:    vmsne.vi v10, v8, 0
 ; CHECK-NEXT:    vcpop.m a0, v10
 ; CHECK-NEXT:    seqz a0, a0
@@ -50,17 +41,8 @@ define { i1, <16 x i16> } @bitcast_v16i16(ptr %a0) {
 define { i1, <8 x i32> } @bitcast_v8i32(ptr %a0) {
 ; CHECK-LABEL: bitcast_v8i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    ld a1, 0(a0)
-; CHECK-NEXT:    ld a2, 8(a0)
-; CHECK-NEXT:    ld a3, 16(a0)
-; CHECK-NEXT:    ld a0, 24(a0)
-; CHECK-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
-; CHECK-NEXT:    vmv.v.x v8, a1
-; CHECK-NEXT:    vslide1down.vx v8, v8, a2
-; CHECK-NEXT:    vslide1down.vx v8, v8, a3
-; CHECK-NEXT:    vslide1down.vx v8, v8, a0
-; CHECK-NEXT:    li a0, 32
-; CHECK-NEXT:    vsetvli zero, a0, e8, m2, ta, ma
+; CHECK-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
+; CHECK-NEXT:    vle32.v v8, (a0)
 ; CHECK-NEXT:    vmsne.vi v10, v8, 0
 ; CHECK-NEXT:    vcpop.m a0, v10
 ; CHECK-NEXT:    seqz a0, a0

>From 1481c548826fbc17902b2c41db8231202c16f43c Mon Sep 17 00:00:00 2001
From: ZakyHermawan <zaky.hermawan9615 at gmail.com>
Date: Tue, 19 May 2026 13:30:55 +0700
Subject: [PATCH 3/7] sanity check for EVT to become MVT

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 8b657a719804e..eb1ff7149fd47 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17629,8 +17629,13 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
   auto GetPreferredEltVT = [](SDValue V) -> MVT {
     // Look backwards: check if V itself is derived from a vector
     SDValue Peek = peekThroughBitcasts(V);
-    if (Peek.getValueType().isVector() && Peek.getValueType().isInteger())
-      return Peek.getSimpleValueType().getVectorElementType();
+    EVT PeekVT = Peek.getValueType();
+
+    if (PeekVT.isVector() && PeekVT.isInteger()) {
+      EVT EltVT = PeekVT.getVectorElementType();
+      if (EltVT.isSimple())
+        return EltVT.getSimpleVT();
+    }
 
     // Look forwards: check if V is bitcasted to a vector elsewhere in the DAG
     for (SDUse &Use : V->uses()) {
@@ -17642,8 +17647,11 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
       SDNode *User = Use.getUser();
       if (User->getOpcode() == ISD::BITCAST) {
         EVT CastVT = User->getValueType(0);
-        if (CastVT.isVector() && CastVT.isInteger())
-          return CastVT.getVectorElementType().getSimpleVT();
+        if (CastVT.isVector() && CastVT.isInteger()) {
+          EVT EltVT = CastVT.getVectorElementType();
+          if (EltVT.isSimple())
+            return EltVT.getSimpleVT();
+        }
       }
     }
     return MVT::INVALID_SIMPLE_VALUE_TYPE;
@@ -17663,9 +17671,8 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
   }
 
   // If both are unsuitable, use the safe default (i8)
-  if (!IsValidEltVT(EltVT)) {
+  if (!IsValidEltVT(EltVT))
     EltVT = MVT::i8;
-  }
 
   unsigned EltSize = EltVT.getSizeInBits();
   unsigned NumElts = OpSize / EltSize;

>From 93d9431883276a0f19e2021fb8e901bcf1de792a Mon Sep 17 00:00:00 2001
From: ZakyHermawan <zaky.hermawan9615 at gmail.com>
Date: Wed, 20 May 2026 03:48:49 +0700
Subject: [PATCH 4/7] [RISCV] use isTypeLegal to simplify EVT validation

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index eb1ff7149fd47..e5cd68cc7785c 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17658,10 +17658,19 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
   };
 
   auto IsValidEltVT = [&](MVT VT) {
-    return VT != MVT::INVALID_SIMPLE_VALUE_TYPE && VT.isInteger() &&
-           VT.getSizeInBits() >= 8 &&
-           VT.getSizeInBits() <= Subtarget.getXLen() &&
-           OpSize % VT.getSizeInBits() == 0;
+    if (VT == MVT::INVALID_SIMPLE_VALUE_TYPE || !VT.isInteger())
+      return false;
+
+    // Make sure we don't try to create an impossible vector type where the
+    // elements don't perfectly fill up the OpSize boundary.
+    unsigned EltSize = VT.getSizeInBits();
+    if (EltSize == 0 || OpSize % EltSize != 0)
+      return false;
+
+    // Construct the proposed vector type to check its legality
+    unsigned NumElts = OpSize / EltSize;
+    EVT TestVecVT = EVT::getVectorVT(*DAG.getContext(), VT, NumElts);
+    return Subtarget.getTargetLowering()->isTypeLegal(TestVecVT);
   };
 
   // Get preferred VT from either X or Y.

>From ac67b3e02330b18ecce5305f33eaf766232e66fb Mon Sep 17 00:00:00 2001
From: Zaky Hermawan <44158147+ZakyHermawan at users.noreply.github.com>
Date: Thu, 21 May 2026 01:18:09 +0700
Subject: [PATCH 5/7] Remove redundant check for zero element size

The minimum size of MVT is i1, so i0 will never happened, hence, the check is unnecessary.

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index e5cd68cc7785c..d936b7b28289c 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17664,7 +17664,7 @@ combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC,
     // Make sure we don't try to create an impossible vector type where the
     // elements don't perfectly fill up the OpSize boundary.
     unsigned EltSize = VT.getSizeInBits();
-    if (EltSize == 0 || OpSize % EltSize != 0)
+    if (OpSize % EltSize != 0)
       return false;
 
     // Construct the proposed vector type to check its legality

>From 796bcafa34eadba3bed9fbfe4ae25477e60aa64c Mon Sep 17 00:00:00 2001
From: ZakyHermawan <zaky.hermawan9615 at gmail.com>
Date: Thu, 21 May 2026 22:36:08 +0700
Subject: [PATCH 6/7] [RISCV] Add test when the casted operand is a vector of
 simple VT

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
index 2d9100da4f5e0..61b54c7fc5e2e 100644
--- a/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
@@ -55,3 +55,49 @@ define { i1, <8 x i32> } @bitcast_v8i32(ptr %a0) {
   %res2 = insertvalue { i1, <8 x i32> } %res1, <8 x i32> %src256.bitcast, 1
   ret { i1, <8 x i32> } %res2
 }
+
+define i1 @bitcast_from_v32i8(ptr %a0) {
+; CHECK-LABEL: bitcast_from_v32i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a1, 32
+; CHECK-NEXT:    vsetvli zero, a1, e8, m2, ta, ma
+; CHECK-NEXT:    vle8.v v8, (a0)
+; CHECK-NEXT:    vmsne.vi v10, v8, 0
+; CHECK-NEXT:    vcpop.m a0, v10
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %vec = load <32 x i8>, ptr %a0, align 32
+  %int = bitcast <32 x i8> %vec to i256
+  %iszero = icmp eq i256 %int, 0
+  ret i1 %iszero
+}
+
+define i1 @bitcast_from_v16i16(ptr %a0) {
+; CHECK-LABEL: bitcast_from_v16i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 16, e16, m2, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
+; CHECK-NEXT:    vmsne.vi v10, v8, 0
+; CHECK-NEXT:    vcpop.m a0, v10
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %vec = load <16 x i16>, ptr %a0, align 32
+  %int = bitcast <16 x i16> %vec to i256
+  %iszero = icmp eq i256 %int, 0
+  ret i1 %iszero
+}
+
+define i1 @bitcast_from_v8i32(ptr %a0) {
+; CHECK-LABEL: bitcast_from_v8i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
+; CHECK-NEXT:    vle32.v v8, (a0)
+; CHECK-NEXT:    vmsne.vi v10, v8, 0
+; CHECK-NEXT:    vcpop.m a0, v10
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %vec = load <8 x i32>, ptr %a0, align 32
+  %int = bitcast <8 x i32> %vec to i256
+  %iszero = icmp eq i256 %int, 0
+  ret i1 %iszero
+}

>From 2489f4ee8181a1af0b3b7f4e39feffcbe666d2d6 Mon Sep 17 00:00:00 2001
From: ZakyHermawan <zaky.hermawan9615 at gmail.com>
Date: Thu, 21 May 2026 23:15:44 +0700
Subject: [PATCH 7/7] [RISCV] Add test for comparison between large int and
 vector

This will make sure at least one of them failed on GetPreferredEltVT (because it is not a simple type)

nit: Use getValueType() instead of getValueType(0) for more consistency, because bitcase will only produce one value anyway.

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll | 36 ++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
index 61b54c7fc5e2e..a94ddac083705 100644
--- a/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/bitcast-cmp.ll
@@ -101,3 +101,39 @@ define i1 @bitcast_from_v8i32(ptr %a0) {
   %iszero = icmp eq i256 %int, 0
   ret i1 %iszero
 }
+
+; Compare a plain i256 against a bitcasted vector.
+define i1 @cmp_plain_to_v16i16(ptr %a0, ptr %a1) {
+; CHECK-LABEL: cmp_plain_to_v16i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 16, e16, m2, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
+; CHECK-NEXT:    vle16.v v10, (a1)
+; CHECK-NEXT:    vmsne.vv v12, v8, v10
+; CHECK-NEXT:    vcpop.m a0, v12
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %x = load i256, ptr %a0, align 32
+  %y_vec = load <16 x i16>, ptr %a1, align 32
+  %y = bitcast <16 x i16> %y_vec to i256
+  %cmp = icmp eq i256 %x, %y
+  ret i1 %cmp
+}
+
+; Flipped operands to guarantee the Y-path is covered regardless of DAG sorting.
+define i1 @cmp_v16i16_to_plain(ptr %a0, ptr %a1) {
+; CHECK-LABEL: cmp_v16i16_to_plain:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 16, e16, m2, ta, ma
+; CHECK-NEXT:    vle16.v v8, (a0)
+; CHECK-NEXT:    vle16.v v10, (a1)
+; CHECK-NEXT:    vmsne.vv v12, v8, v10
+; CHECK-NEXT:    vcpop.m a0, v12
+; CHECK-NEXT:    seqz a0, a0
+; CHECK-NEXT:    ret
+  %x_vec = load <16 x i16>, ptr %a0, align 32
+  %x = bitcast <16 x i16> %x_vec to i256
+  %y = load i256, ptr %a1, align 32
+  %cmp = icmp eq i256 %x, %y
+  ret i1 %cmp
+}



More information about the llvm-commits mailing list