[llvm] [ConstantFolding] Add folding for [de]interleave2, insert and extract (PR #141301)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 9 13:02:27 PDT 2025


================
@@ -3750,6 +3754,84 @@ static Constant *ConstantFoldFixedVectorCall(
     }
     return nullptr;
   }
+  case Intrinsic::vector_extract: {
+    auto *Idx = dyn_cast<ConstantInt>(Operands[1]);
+    Constant *Vec = Operands[0];
+    if (!Idx || !isa<FixedVectorType>(Vec->getType()))
+      return nullptr;
+
+    unsigned NumElements = FVTy->getNumElements();
+    unsigned VecNumElements =
+        cast<FixedVectorType>(Vec->getType())->getNumElements();
+    unsigned StartingIndex = Idx->getZExtValue();
+
+    // Extracting entire vector is nop
+    if (NumElements == VecNumElements && StartingIndex == 0)
+      return Vec;
+
+    const unsigned NonPoisonNumElements =
+        std::min(StartingIndex + NumElements, VecNumElements);
+    for (unsigned I = StartingIndex; I < NonPoisonNumElements; ++I) {
+      Constant *Elt = Vec->getAggregateElement(I);
+      if (!Elt)
+        return nullptr;
+      Result[I - StartingIndex] = Elt;
+    }
+
+    // Remaining elements are poison since they are out of bounds.
+    for (unsigned I = NonPoisonNumElements, E = StartingIndex + NumElements;
+         I < E; ++I)
+      Result[I - StartingIndex] = PoisonValue::get(FVTy->getElementType());
+
+    return ConstantVector::get(Result);
+  }
+  case Intrinsic::vector_insert: {
+    Constant *Vec = Operands[0];
+    Constant *SubVec = Operands[1];
+    auto *Idx = dyn_cast<ConstantInt>(Operands[2]);
+    if (!Idx || !isa<FixedVectorType>(Vec->getType()))
+      return nullptr;
+
+    unsigned SubVecNumElements =
+        cast<FixedVectorType>(SubVec->getType())->getNumElements();
+    unsigned VecNumElements =
+        cast<FixedVectorType>(Vec->getType())->getNumElements();
+    unsigned IdxN = Idx->getZExtValue();
+    // Replacing entire vector with a subvec is nop
+    if (SubVecNumElements == VecNumElements && IdxN == 0)
+      return SubVec;
+
+    // Make sure indices are in the range [0, VecNumElements), otherwise the
+    // result is a poison value.
+    if (IdxN >= VecNumElements || IdxN + SubVecNumElements > VecNumElements ||
+        (IdxN % SubVecNumElements) != 0)
+      return PoisonValue::get(FVTy);
+
+    for (unsigned I = 0; I < VecNumElements; ++I) {
+      Constant *Elt;
+      if (I >= IdxN && I < IdxN + SubVecNumElements)
+        Elt = SubVec->getAggregateElement(I - IdxN);
+      else
+        Elt = Vec->getAggregateElement(I);
+      if (!Elt)
+        return nullptr;
+      Result[I] = Elt;
+    }
+    return ConstantVector::get(Result);
+  }
+  case Intrinsic::vector_interleave2: {
+    unsigned NumElements =
+        cast<FixedVectorType>(Operands[0]->getType())->getNumElements();
----------------
topperc wrote:

What guarantees the input is a fixed vector?

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


More information about the llvm-commits mailing list