[llvm] [AArch64][ISel] Fix interleave3 crash (PR #192046)

Matthew Devereau via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 05:57:18 PDT 2026


================
@@ -32322,6 +32322,78 @@ SDValue AArch64TargetLowering::LowerVECTOR_INTERLEAVE(SDValue Op,
     return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Op->getVTList(), Ops);
   }
 
+  // For v2f64 and v2i64, each vector part of the interleaved v6f64 vector can
+  // be made with one shuffle only, as the interleave factor is greater than the
+  // number of elements in the vector. a0, a1 | b0, b1 | c0, c1
+  //  ->
+  // a0, b0 | c0, a1 | b1, c1
+  if (Op->getNumOperands() == 3 && (OpVT == MVT::v2f64 || OpVT == MVT::v2i64)) {
+    SDValue A = Op->getOperand(0);
+    SDValue B = Op->getOperand(1);
+    SDValue C = Op->getOperand(2);
+    SDValue Shuffle0 = DAG.getVectorShuffle(OpVT, DL, A, B, {0, 2});
+    SDValue Shuffle1 = DAG.getVectorShuffle(OpVT, DL, A, C, {2, 1});
+    SDValue Shuffle2 = DAG.getVectorShuffle(OpVT, DL, B, C, {1, 3});
+
+    return DAG.getMergeValues({Shuffle0, Shuffle1, Shuffle2}, DL);
+  }
+
+  // When the interleave factor is less than the number of vector elements we
+  // need two shuffles to mix three vector's elements together:
+  //  step1: a0, b0, __, a1, | b1, __, a2, b2 | ...
+  //  step2: a0, b0, c0, a1  | b1, c1, a2, b2 | ...
+  if (Op->getNumOperands() == 3 && OpVT.isFixedLengthVector()) {
+    unsigned NElements = OpVT.getVectorNumElements();
+    SDValue A = Op->getOperand(0);
+    SDValue B = Op->getOperand(1);
+    SDValue C = Op->getOperand(2);
+    //  Build two masks for the two shuffles. The first mask shuffles elements
+    //  from A and B, and with elements of C represented with -1 to be ignored.
----------------
MDevereau wrote:

@paulwalker-arm  I have a patch locally which does as you've asked.

Here's the results of basic testing that just hammers a function that only calls interleave3 1 billion times:

| | st3(ms) | shuffle(ms) |
|--------|--------|--------|
| v6i64 | 3385 | 2154 |
| v12i32 | 3363 | 2188 |
| v24i16 | 3275 | 2908 |
| v48i8 | 3368 | 2720 | 

So the shuffle lowering looks to be faster across all types. Do you still want me to go ahead with the st3 patch? I would personally prefer to cut out the middle man and just go ahead with the shuffle patch since it's already up for review, its functionally faster, and nobody is currently using fixed interleave3 intrinsics, but I'll leave it for you to decide.

https://github.com/llvm/llvm-project/pull/192046


More information about the llvm-commits mailing list