[llvm] 47b819b - [LoongArch] Fix vpermi.w legalization with undef elements (#207751)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 7 00:30:15 PDT 2026


Author: Nikita Popov
Date: 2026-07-07T09:30:10+02:00
New Revision: 47b819b866636fb1770f78da3f45ebd64d5f9875

URL: https://github.com/llvm/llvm-project/commit/47b819b866636fb1770f78da3f45ebd64d5f9875
DIFF: https://github.com/llvm/llvm-project/commit/47b819b866636fb1770f78da3f45ebd64d5f9875.diff

LOG: [LoongArch] Fix vpermi.w legalization with undef elements (#207751)

For the MaskSize==8 case, the code was comparing mask elements that
could be undef (-1). This could result in a miscompile (where -1 + 4 ==
3, which crosses from the high half to the low half) or the pattern not
matching (because -1 doesn't match the other mask element).

Fix this by explicitly handling undef elements in the code. If the high
half is undef, we can just ignore. If the low half is undef, we need to
use the value from the high half shifted down by 4. If neither are
undef, use the original check.

Added: 
    

Modified: 
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/test/CodeGen/LoongArch/lasx/ir-instruction/shuffle-as-xvpermi.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index bdbfe6f0918d1..b9f27ad62ecd8 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -2518,9 +2518,22 @@ static bool buildVPERMIInfo(ArrayRef<int> Mask, SDValue V1, SDValue V2,
     int MHi = Mask[i + 1];
 
     if (MaskSize == 8) { // Only v8i32/v8f32 need this check.
-      int M2Lo = Mask[i + 4];
-      int M2Hi = Mask[i + 5];
-      if (M2Lo != MLo + 4 || M2Hi != MHi + 4)
+      auto isValid2 = [&](int &M, int M2) {
+        // If high half index is undef, it's always valid.
+        if (M2 == -1)
+          return true;
+        if (M == -1) {
+          // If low half index is undef, use index from high half,
+          // remapped to low half.
+          if ((M2 % MaskSize) < 4)
+            return false;
+          M = M2 - 4;
+          return true;
+        }
+        // Index in low half must be same as index in high half.
+        return M2 == M + 4;
+      };
+      if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
         return false;
     }
 

diff  --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/shuffle-as-xvpermi.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/shuffle-as-xvpermi.ll
index a2e3a280f8db4..cd37286899723 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/shuffle-as-xvpermi.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/shuffle-as-xvpermi.ll
@@ -19,6 +19,38 @@ entry:
   ret void
 }
 
+define void @shufflevector_xvpermi_v8i32_poison1(ptr %res, ptr %a, ptr %b) nounwind {
+; CHECK-LABEL: shufflevector_xvpermi_v8i32_poison1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xvld $xr0, $a1, 0
+; CHECK-NEXT:    xvld $xr1, $a2, 0
+; CHECK-NEXT:    xvpermi.w $xr1, $xr0, 78
+; CHECK-NEXT:    xvst $xr1, $a0, 0
+; CHECK-NEXT:    ret
+entry:
+  %va = load <8 x i32>, ptr %a
+  %vb = load <8 x i32>, ptr %b
+  %c = shufflevector <8 x i32> %va, <8 x i32> %vb, <8 x i32> <i32 poison, i32 3, i32 8, i32 9, i32 6, i32 7, i32 12, i32 13>
+  store <8 x i32> %c, ptr %res
+  ret void
+}
+
+define void @shufflevector_xvpermi_v8i32_poison2(ptr %res, ptr %a, ptr %b) nounwind {
+; CHECK-LABEL: shufflevector_xvpermi_v8i32_poison2:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xvld $xr0, $a1, 0
+; CHECK-NEXT:    xvld $xr1, $a2, 0
+; CHECK-NEXT:    xvpermi.w $xr1, $xr0, 78
+; CHECK-NEXT:    xvst $xr1, $a0, 0
+; CHECK-NEXT:    ret
+entry:
+  %va = load <8 x i32>, ptr %a
+  %vb = load <8 x i32>, ptr %b
+  %c = shufflevector <8 x i32> %va, <8 x i32> %vb, <8 x i32> <i32 2, i32 3, i32 8, i32 9, i32 poison, i32 7, i32 12, i32 13>
+  store <8 x i32> %c, ptr %res
+  ret void
+}
+
 ;; xvpermi.w
 define void @shufflevector_xvpermi_v8f32(ptr %res, ptr %a, ptr %b) nounwind {
 ; CHECK-LABEL: shufflevector_xvpermi_v8f32:
@@ -35,3 +67,18 @@ entry:
   store <8 x float> %c, ptr %res
   ret void
 }
+
+define void @shufflevector_xvpermi_v8i32_poison_invalid(ptr %res, ptr %a) nounwind {
+; CHECK-LABEL: shufflevector_xvpermi_v8i32_poison_invalid:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a1, 0
+; CHECK-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI4_0)
+; CHECK-NEXT:    xvld $xr1, $a1, %pc_lo12(.LCPI4_0)
+; CHECK-NEXT:    xvperm.w $xr0, $xr0, $xr1
+; CHECK-NEXT:    xvst $xr0, $a0, 0
+; CHECK-NEXT:    ret
+  %va = load <8 x i32>, ptr %a
+  %c = shufflevector <8 x i32> %va, <8 x i32> poison, <8 x i32> <i32 poison, i32 1, i32 2, i32 3, i32 3, i32 5, i32 6, i32 7>
+  store <8 x i32> %c, ptr %res
+  ret void
+}


        


More information about the llvm-commits mailing list