[llvm] [IA] Use a single callback for lowerDeinterleaveIntrinsic [nfc] (PR #148978)
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 16 12:06:16 PDT 2025
================
@@ -234,53 +234,100 @@ bool RISCVTargetLowering::lowerInterleavedStore(StoreInst *SI,
return true;
}
+static bool isMultipleOfN(const Value *V, const DataLayout &DL, unsigned N) {
+ assert(N);
+ if (N == 1)
+ return true;
+
+ using namespace PatternMatch;
+ // Right now we're only recognizing the simplest pattern.
+ uint64_t C;
+ if (match(V, m_CombineOr(m_ConstantInt(C),
+ m_c_Mul(m_Value(), m_ConstantInt(C)))) &&
+ C && C % N == 0)
+ return true;
+
+ if (isPowerOf2_32(N)) {
+ KnownBits KB = llvm::computeKnownBits(V, DL);
+ return KB.countMinTrailingZeros() >= Log2_32(N);
+ }
+
+ return false;
+}
+
bool RISCVTargetLowering::lowerDeinterleaveIntrinsicToLoad(
- LoadInst *LI, ArrayRef<Value *> DeinterleaveValues) const {
+ Instruction *Load, Value *Mask,
+ ArrayRef<Value *> DeinterleaveValues) const {
const unsigned Factor = DeinterleaveValues.size();
if (Factor > 8)
return false;
- assert(LI->isSimple());
- IRBuilder<> Builder(LI);
+ IRBuilder<> Builder(Load);
Value *FirstActive =
*llvm::find_if(DeinterleaveValues, [](Value *V) { return V != nullptr; });
VectorType *ResVTy = cast<VectorType>(FirstActive->getType());
- const DataLayout &DL = LI->getDataLayout();
+ const DataLayout &DL = Load->getDataLayout();
+ auto *XLenTy = Type::getIntNTy(Load->getContext(), Subtarget.getXLen());
- if (!isLegalInterleavedAccessType(ResVTy, Factor, LI->getAlign(),
- LI->getPointerAddressSpace(), DL))
+ Value *Ptr, *VL;
+ Align Alignment;
+ if (auto *LI = dyn_cast<LoadInst>(Load)) {
+ assert(LI->isSimple());
+ Ptr = LI->getPointerOperand();
+ Alignment = LI->getAlign();
+ assert(!Mask && "Unexpected mask on a load\n");
+ Mask = Builder.getAllOnesMask(ResVTy->getElementCount());
+ VL = isa<FixedVectorType>(ResVTy)
+ ? Builder.CreateElementCount(XLenTy, ResVTy->getElementCount())
+ : Constant::getAllOnesValue(XLenTy);
+ } else {
+ auto *VPLoad = cast<VPIntrinsic>(Load);
+ assert(VPLoad->getIntrinsicID() == Intrinsic::vp_load &&
+ "Unexpected intrinsic");
+ Ptr = VPLoad->getArgOperand(0);
+ Alignment = VPLoad->getParamAlign(0).value_or(
+ DL.getABITypeAlign(ResVTy->getElementType()));
+
+ assert(Mask && "vp.load needs a mask!");
+
+ Value *WideEVL = VPLoad->getVectorLengthParam();
+ // Conservatively check if EVL is a multiple of factor, otherwise some
+ // (trailing) elements might be lost after the transformation.
+ if (!isMultipleOfN(WideEVL, Load->getDataLayout(), Factor))
+ return false;
+
+ VL = Builder.CreateZExt(
+ Builder.CreateUDiv(WideEVL,
+ ConstantInt::get(WideEVL->getType(), Factor)),
----------------
preames wrote:
It probably should be, but doing this revealed a deeper problem in the EVL recognition. We're not checking for overflow in the multiply check, and I believe that to be unsound. I am going to return to this, but want to get a few things off my queue first.
https://github.com/llvm/llvm-project/pull/148978
More information about the llvm-commits
mailing list