[llvm] [GlobalISel] Fix G_SHUFFLE_VECTOR in computeKnownFPClass after d012e0380a8f (PR #192385)

Jinsong Ji via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 21:17:13 PDT 2026


https://github.com/jsji created https://github.com/llvm/llvm-project/pull/192385

Fix crash in computeKnownFPClass when processing G_SHUFFLE_VECTOR that
shuffles from a large vector to a smaller one (e.g., <64 x s32> to <8 x s32>).

The bug was introduced in commit d012e0380a8f which added G_SHUFFLE_VECTOR
handling to computeKnownFPClass. The code incorrectly passed the destination
vector's element count (DstTy.getNumElements()) to getShuffleDemandedElts,
but that function expects the source vector's element count.

This caused an assertion failure:
  Assertion `(-1 <= M) && (M < (SrcWidth * 2))' failed
when mask indices were larger than the destination size.

The fix follows the pattern used in computeKnownBits (line 836) which
correctly gets the source type's element count via:
  MRI.getType(MI.getOperand(1).getReg()).getNumElements()

Added a regression test to verify the fix.


>From 694a26018a075506448761342e81844247cce769 Mon Sep 17 00:00:00 2001
From: Jinsong Ji <jinsong.ji at intel.com>
Date: Wed, 15 Apr 2026 20:17:08 -0700
Subject: [PATCH] [GlobalISel] Fix G_SHUFFLE_VECTOR in computeKnownFPClass
 after d012e0380a8f

Fix crash in computeKnownFPClass when processing G_SHUFFLE_VECTOR that
shuffles from a large vector to a smaller one (e.g., <64 x s32> to <8 x s32>).

The bug was introduced in commit d012e0380a8f which added G_SHUFFLE_VECTOR
handling to computeKnownFPClass. The code incorrectly passed the destination
vector's element count (DstTy.getNumElements()) to getShuffleDemandedElts,
but that function expects the source vector's element count.

This caused an assertion failure:
  Assertion `(-1 <= M) && (M < (SrcWidth * 2))' failed
when mask indices were larger than the destination size.

The fix follows the pattern used in computeKnownBits (line 836) which
correctly gets the source type's element count via:
  MRI.getType(MI.getOperand(1).getReg()).getNumElements()

Added a regression test to verify the fix.
---
 .../CodeGen/GlobalISel/GISelValueTracking.cpp |  3 +-
 .../CodeGen/GlobalISel/KnownFPClassTest.cpp   | 30 +++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 0a58b611c0eca..edf040dc2dd70 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1790,7 +1790,8 @@ void GISelValueTracking::computeKnownFPClass(Register R,
       assert(DemandedElts == APInt(1, 1));
       DemandedLHS = DemandedRHS = DemandedElts;
     } else {
-      if (!llvm::getShuffleDemandedElts(DstTy.getNumElements(), Shuf.getMask(),
+      unsigned SrcNumElts = MRI.getType(Shuf.getSrc1Reg()).getNumElements();
+      if (!llvm::getShuffleDemandedElts(SrcNumElts, Shuf.getMask(),
                                         DemandedElts, DemandedLHS,
                                         DemandedRHS)) {
         Known.resetAll();
diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
index b10fd4621b0fd..33dcf0db32f90 100644
--- a/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
@@ -1643,3 +1643,33 @@ TEST_F(AArch64GISelMITest, TestFPClassFMASelfSquare) {
   EXPECT_EQ(fcNan | fcPosInf | fcPosNormal, Known.KnownFPClasses);
   EXPECT_EQ(std::nullopt, Known.SignBit);
 }
+
+// Regression test for crash when shuffling from large vector to small vector.
+// This was causing an assertion failure in getShuffleDemandedElts because
+// the destination width was incorrectly used instead of source width.
+TEST_F(AArch64GISelMITest, TestFPClassShuffleVecLargeToSmall) {
+  StringRef MIRString = R"(
+    %ptr:_(p0) = G_IMPLICIT_DEF
+    %vec:_(<64 x s32>) = G_LOAD %ptr(p0) :: (load (<64 x s32>))
+    %undef:_(<64 x s32>) = G_IMPLICIT_DEF
+    %shuf:_(<8 x s32>) = G_SHUFFLE_VECTOR %vec(<64 x s32>), %undef, shufflemask(0, 8, 16, 24, 32, 40, 48, 56)
+    %copy_shuf:_(<8 x s32>) = COPY %shuf
+)";
+
+  setUp(MIRString);
+  if (!TM)
+    GTEST_SKIP();
+
+  Register CopyReg = Copies[Copies.size() - 1];
+  MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
+  Register SrcReg = FinalCopy->getOperand(1).getReg();
+
+  GISelValueTracking Info(*MF);
+
+  // This should not crash
+  KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
+
+  // We don't know anything about the FP classes since vec is a load
+  EXPECT_EQ(fcAllFlags, Known.KnownFPClasses);
+  EXPECT_EQ(std::nullopt, Known.SignBit);
+}



More information about the llvm-commits mailing list