[llvm] [IA]: Construct (de)interleave4 out of (de)interleave2 (PR #89276)
Paul Walker via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 5 10:40:11 PDT 2024
================
@@ -16493,39 +16529,71 @@ bool AArch64TargetLowering::lowerDeinterleaveIntrinsicToLoad(
LdN = Builder.CreateCall(LdNFunc, {Pred, Address}, "ldN");
else
LdN = Builder.CreateCall(LdNFunc, Address, "ldN");
-
Value *Idx =
Builder.getInt64(I * LdTy->getElementCount().getKnownMinValue());
- Left = Builder.CreateInsertVector(
- VTy, Left, Builder.CreateExtractValue(LdN, 0), Idx);
- Right = Builder.CreateInsertVector(
- VTy, Right, Builder.CreateExtractValue(LdN, 1), Idx);
+ for (int J = 0; J < Factor; ++J) {
+ WideValues[J] = Builder.CreateInsertVector(
+ VTy, WideValues[J], Builder.CreateExtractValue(LdN, J), Idx);
+ }
+ }
+ // FIXME: the types should NOT be added manually.
+ if (2 == Factor)
+ Result = PoisonValue::get(StructType::get(VTy, VTy));
+ else
+ Result = PoisonValue::get(StructType::get(VTy, VTy, VTy, VTy));
+ // Construct the wide result out of the small results.
+ for (int J = 0; J < Factor; ++J) {
+ Result = Builder.CreateInsertValue(Result, WideValues[J], J);
}
-
- Result = PoisonValue::get(DI->getType());
- Result = Builder.CreateInsertValue(Result, Left, 0);
- Result = Builder.CreateInsertValue(Result, Right, 1);
} else {
if (UseScalable)
Result = Builder.CreateCall(LdNFunc, {Pred, BaseAddr}, "ldN");
else
Result = Builder.CreateCall(LdNFunc, BaseAddr, "ldN");
}
+ if (Factor > 2) {
+ for (unsigned I = 0; I < ValuesToDeinterleave.size(); I++) {
+ llvm::Value *CurrentExtract = ValuesToDeinterleave[I];
+ Value *NewExtract = Builder.CreateExtractValue(Result, I);
+ CurrentExtract->replaceAllUsesWith(NewExtract);
+ cast<Instruction>(CurrentExtract)->eraseFromParent();
+ }
+ for (auto &dead : DeadInsts)
+ dead->eraseFromParent();
+ return true;
+ }
DI->replaceAllUsesWith(Result);
return true;
}
+bool GetInterleaveLeaves(Value *II, SmallVectorImpl<Value *> &InterleaveOps) {
+ Value *Op0, *Op1;
+ if (!match(II, m_Interleave2(m_Value(Op0), m_Value(Op1))))
+ return false;
+
+ if (!GetInterleaveLeaves(Op0, InterleaveOps)) {
+ InterleaveOps.push_back(Op0);
+ }
+
+ if (!GetInterleaveLeaves(Op1, InterleaveOps)) {
+ InterleaveOps.push_back(Op1);
+ }
+ return true;
+}
+
bool AArch64TargetLowering::lowerInterleaveIntrinsicToStore(
IntrinsicInst *II, StoreInst *SI) const {
// Only interleave2 supported at present.
if (II->getIntrinsicID() != Intrinsic::vector_interleave2)
return false;
- // Only a factor of 2 supported at present.
- const unsigned Factor = 2;
+ SmallVector<Value *, 4> ValuesToInterleave;
+ GetInterleaveLeaves(II, ValuesToInterleave);
+ unsigned Factor = ValuesToInterleave.size();
+ assert(Factor >= 2 && "Expected Interleave Factor >= 2");
----------------
paulwalker-arm wrote:
Is an assert sufficient? What happens when `Factor` is 3 or 5?
https://github.com/llvm/llvm-project/pull/89276
More information about the llvm-commits
mailing list