[llvm] [ConstantFolding] Add folding for [de]interleave2, insert and extract (PR #141301)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Fri May 30 07:39:43 PDT 2025
================
@@ -3734,6 +3738,98 @@ static Constant *ConstantFoldFixedVectorCall(
}
return nullptr;
}
+ case Intrinsic::vector_extract: {
+ auto *Vec = dyn_cast<Constant>(Operands[0]);
+ auto *Idx = cast<ConstantInt>(Operands[1]);
+ if (!Vec || !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: {
+ auto *Vec = dyn_cast<Constant>(Operands[0]);
+ auto *SubVec = dyn_cast<Constant>(Operands[1]);
+ auto *Idx = dyn_cast<ConstantInt>(Operands[2]);
+ if (!Vec || !SubVec || !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 % IdxN) != 0))
+ return PoisonValue::get(FVTy);
+
+ unsigned I = 0;
+ for (; I < IdxN; ++I) {
+ Constant *Elt = Vec->getAggregateElement(I);
+ if (!Elt)
+ return nullptr;
+ Result[I] = Elt;
+ }
+ for (; I < IdxN + SubVecNumElements; ++I) {
+ Constant *Elt = SubVec->getAggregateElement(I - IdxN);
+ if (!Elt)
+ return nullptr;
+ Result[I] = Elt;
+ }
+ for (; I < VecNumElements; ++I) {
+ Constant *Elt = Vec->getAggregateElement(I);
+ if (!Elt)
+ return nullptr;
+ Result[I] = Elt;
+ }
+ return ConstantVector::get(Result);
+ }
+ case Intrinsic::vector_interleave2: {
+ auto *Vec0 = dyn_cast<Constant>(Operands[0]);
+ auto *Vec1 = dyn_cast<Constant>(Operands[1]);
+ if (!Vec0 || !Vec1)
+ return nullptr;
----------------
lukel97 wrote:
Operands is an `ArrayRef<Constant *>` already, are the dyn_casts redundant?
https://github.com/llvm/llvm-project/pull/141301
More information about the llvm-commits
mailing list