[llvm] [RISCV] Handle fixed length vectors with exact VLEN in loweringEXTRACT_SUBVECTOR (PR #79949)

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 7 13:06:01 PST 2024


================
@@ -9653,19 +9656,46 @@ SDValue RISCVTargetLowering::lowerEXTRACT_SUBVECTOR(SDValue Op,
     return DAG.getBitcast(Op.getValueType(), Slidedown);
   }
 
+  if (VecVT.isFixedLengthVector()) {
+    VecVT = getContainerForFixedLengthVector(VecVT);
+    Vec = convertToScalableVector(VecVT, Vec, DAG, Subtarget);
+  }
+
+  MVT ContainerSubVecVT = SubVecVT;
   unsigned SubRegIdx, RemIdx;
-  std::tie(SubRegIdx, RemIdx) =
-      RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs(
-          VecVT, SubVecVT, OrigIdx, TRI);
+
+  // extract_subvector scales the index by vscale is the subvector is scalable,
+  // and decomposeSubvectorInsertExtractToSubRegs takes this into account. So if
+  // we have a fixed length subvector, we need to adjust the index by 1/vscale.
+  if (SubVecVT.isFixedLengthVector()) {
+    assert(MinVLen == MaxVLen);
+    ContainerSubVecVT = getContainerForFixedLengthVector(SubVecVT);
+    unsigned Vscale = MinVLen / RISCV::RVVBitsPerBlock;
+    std::tie(SubRegIdx, RemIdx) =
+        RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs(
+            VecVT, ContainerSubVecVT, OrigIdx / Vscale, TRI);
+    RemIdx = (RemIdx * Vscale) + (OrigIdx % Vscale);
+  } else {
+    std::tie(SubRegIdx, RemIdx) =
+        RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs(
+            VecVT, ContainerSubVecVT, OrigIdx, TRI);
+  }
 
   // If the Idx has been completely eliminated then this is a subvector extract
   // which naturally aligns to a vector register. These can easily be handled
   // using subregister manipulation.
-  if (RemIdx == 0)
+  if (RemIdx == 0) {
+    if (SubVecVT.isFixedLengthVector()) {
+      Vec = DAG.getTargetExtractSubreg(SubRegIdx, DL, ContainerSubVecVT, Vec);
+      return convertFromScalableVector(SubVecVT, Vec, DAG, Subtarget);
+    }
     return Op;
+  }
 
-  // Else SubVecVT is a fractional LMUL and may need to be slid down.
-  assert(RISCVVType::decodeVLMUL(getLMUL(SubVecVT)).second);
+  // Else SubVecVT is a fractional LMUL and may need to be slid down: if
+  // SubVecVT was > M1 then the index would need to be a multiple of VLMAX, and
+  // so would divide exactly.
+  assert(RISCVVType::decodeVLMUL(getLMUL(ContainerSubVecVT)).second);
 
   // If the vector type is an LMUL-group type, extract a subvector equal to the
   // nearest full vector register type.
----------------
preames wrote:

I'm not sure the if-clause here is correct when generalized for fixed length vectors.  (Well, I'm actually unsure for scalable too now, but let's focus on the fixed length case for a second.)

VLEN = 128
VecVT = <16 x i64> (aka. container is m8)
SubVT = <4 x i64> (aka container is m2)
OrigIdx = 3 (so we need contents from vreg b, c, and d from the original input)

Wouldn't our subregidx here be the m4 first half of VecVT?  And RemIdx = 3?

If so, how is writing over InterSubVT m1 valid right here?  Doesn't that throw away the last few elements of the requested extract?

It's entirely possible I'm just forgetting something here.  Help me out?  I'm suspecting I'm just missing something here as I've checked your test cases carefully, and they all look correct.  I'd have expected this to show up in the tests if we actually wrong.



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


More information about the llvm-commits mailing list