diff options
author | Nikolay Panchenko <nicholas.panchenko@gmail.com> | 2025-06-11 19:00:29 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-11 19:00:29 -0400 |
commit | ee35e342945d6825c9b2b004fd135cf16c84ea0e (patch) | |
tree | b764210b8750940587fc81a98b2b545facecf6c4 /llvm/lib/Analysis/ConstantFolding.cpp | |
parent | 0e457315f55889878ccbc3e35d4beb04e277733f (diff) | |
download | llvm-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.cpp | 97 |
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) |