aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ConstantFolding.cpp
diff options
context:
space:
mode:
authorNikolay Panchenko <nicholas.panchenko@gmail.com>2025-06-11 19:00:29 -0400
committerGitHub <noreply@github.com>2025-06-11 19:00:29 -0400
commitee35e342945d6825c9b2b004fd135cf16c84ea0e (patch)
treeb764210b8750940587fc81a98b2b545facecf6c4 /llvm/lib/Analysis/ConstantFolding.cpp
parent0e457315f55889878ccbc3e35d4beb04e277733f (diff)
downloadllvm-ee35e342945d6825c9b2b004fd135cf16c84ea0e.zip
llvm-ee35e342945d6825c9b2b004fd135cf16c84ea0e.tar.gz
llvm-ee35e342945d6825c9b2b004fd135cf16c84ea0e.tar.bz2
[ConstantFolding] Add folding for [de]interleave2, insert and extract (#141301)
The change adds folding for 4 vector intrinsics: `interleave2`, `deinterleave2`, `vector_extract` and `vector_insert`. For the last 2 intrinsics the change does not use `ShuffleVector` fold mechanism as it's much simpler to construct result vector explicitly.
Diffstat (limited to 'llvm/lib/Analysis/ConstantFolding.cpp')
-rw-r--r--llvm/lib/Analysis/ConstantFolding.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 1ef0bad..139a0b8 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1635,6 +1635,10 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case Intrinsic::vector_reduce_smax:
case Intrinsic::vector_reduce_umin:
case Intrinsic::vector_reduce_umax:
+ case Intrinsic::vector_extract:
+ case Intrinsic::vector_insert:
+ case Intrinsic::vector_interleave2:
+ case Intrinsic::vector_deinterleave2:
// Target intrinsics
case Intrinsic::amdgcn_perm:
case Intrinsic::amdgcn_wave_reduce_umin:
@@ -3758,6 +3762,72 @@ 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;
+
+ for (unsigned I = StartingIndex, E = StartingIndex + NumElements; I < E;
+ ++I) {
+ Constant *Elt = Vec->getAggregateElement(I);
+ if (!Elt)
+ return nullptr;
+ Result[I - StartingIndex] = Elt;
+ }
+
+ 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;
+
+ for (unsigned I = 0; I < VecNumElements; ++I) {
+ Constant *Elt;
+ if (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();
+ for (unsigned I = 0; I < NumElements; ++I) {
+ Constant *Elt0 = Operands[0]->getAggregateElement(I);
+ Constant *Elt1 = Operands[1]->getAggregateElement(I);
+ if (!Elt0 || !Elt1)
+ return nullptr;
+ Result[2 * I] = Elt0;
+ Result[2 * I + 1] = Elt1;
+ }
+ return ConstantVector::get(Result);
+ }
default:
break;
}
@@ -3919,6 +3989,33 @@ ConstantFoldStructCall(StringRef Name, Intrinsic::ID IntrinsicID,
return nullptr;
return ConstantStruct::get(StTy, SinResult, CosResult);
}
+ case Intrinsic::vector_deinterleave2: {
+ auto *Vec = dyn_cast<Constant>(Operands[0]);
+ if (!Vec)
+ return nullptr;
+
+ auto *VecTy = cast<VectorType>(Vec->getType());
+ unsigned NumElements = VecTy->getElementCount().getKnownMinValue() / 2;
+ if (isa<ConstantAggregateZero>(Vec)) {
+ auto *HalfVecTy = VectorType::getHalfElementsVectorType(VecTy);
+ return ConstantStruct::get(StTy, ConstantAggregateZero::get(HalfVecTy),
+ ConstantAggregateZero::get(HalfVecTy));
+ }
+ if (isa<FixedVectorType>(Vec->getType())) {
+ SmallVector<Constant *, 4> Res0(NumElements), Res1(NumElements);
+ for (unsigned I = 0; I < NumElements; ++I) {
+ Constant *Elt0 = Vec->getAggregateElement(2 * I);
+ Constant *Elt1 = Vec->getAggregateElement(2 * I + 1);
+ if (!Elt0 || !Elt1)
+ return nullptr;
+ Res0[I] = Elt0;
+ Res1[I] = Elt1;
+ }
+ return ConstantStruct::get(StTy, ConstantVector::get(Res0),
+ ConstantVector::get(Res1));
+ }
+ return nullptr;
+ }
default:
// TODO: Constant folding of vector intrinsics that fall through here does
// not work (e.g. overflow intrinsics)