Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions llvm/include/llvm/CodeGen/TargetLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -3262,10 +3262,14 @@ class LLVM_ABI TargetLoweringBase {
/// Return true on success. Currently only supports
/// llvm.vector.interleave{2,3,5,7}
///
/// \p SI is the accompanying store instruction
/// \p Store is the accompanying store instruction. Can be either a plain
/// store or a vp.store intrinsic.
/// \p Mask is a per-segment (i.e. number of lanes equal to that of one
/// component being interwoven) mask. Can be nullptr, in which case the
/// result is uncondiitional.
/// \p InterleaveValues contains the interleaved values.
virtual bool
lowerInterleaveIntrinsicToStore(StoreInst *SI,
lowerInterleaveIntrinsicToStore(Instruction *Store, Value *Mask,
ArrayRef<Value *> InterleaveValues) const {
return false;
}
Expand Down
19 changes: 8 additions & 11 deletions llvm/lib/CodeGen/InterleavedAccessPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,36 +681,33 @@ bool InterleavedAccessImpl::lowerInterleaveIntrinsic(
const unsigned Factor = getInterleaveIntrinsicFactor(II->getIntrinsicID());
assert(Factor && "unexpected interleave intrinsic");

Value *Mask = nullptr;
if (auto *VPStore = dyn_cast<VPIntrinsic>(StoredBy)) {
if (VPStore->getIntrinsicID() != Intrinsic::vp_store)
return false;

Value *WideMask = VPStore->getOperand(2);
Value *Mask = getMask(WideMask, Factor,
cast<VectorType>(InterleaveValues[0]->getType()));
Mask = getMask(WideMask, Factor,
cast<VectorType>(InterleaveValues[0]->getType()));
if (!Mask)
return false;

LLVM_DEBUG(dbgs() << "IA: Found a vp.store with interleave intrinsic "
<< *II << " and factor = " << Factor << "\n");

// Since lowerInterleavedStore expects Shuffle and StoreInst, use special
// TLI function to emit target-specific interleaved instruction.
if (!TLI->lowerInterleavedVPStore(VPStore, Mask, InterleaveValues))
return false;
} else {
auto *SI = cast<StoreInst>(StoredBy);
if (!SI->isSimple())
return false;

LLVM_DEBUG(dbgs() << "IA: Found a store with interleave intrinsic " << *II
<< " and factor = " << Factor << "\n");

// Try and match this with target specific intrinsics.
if (!TLI->lowerInterleaveIntrinsicToStore(SI, InterleaveValues))
return false;
}

// Try and match this with target specific intrinsics.
if (!TLI->lowerInterleaveIntrinsicToStore(cast<Instruction>(StoredBy), Mask,
InterleaveValues))
return false;

// We now have a target-specific store, so delete the old one.
DeadInsts.insert(cast<Instruction>(StoredBy));
DeadInsts.insert(II);
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17561,12 +17561,17 @@ bool AArch64TargetLowering::lowerDeinterleaveIntrinsicToLoad(
}

bool AArch64TargetLowering::lowerInterleaveIntrinsicToStore(
StoreInst *SI, ArrayRef<Value *> InterleavedValues) const {
Instruction *Store, Value *Mask,
ArrayRef<Value *> InterleavedValues) const {
unsigned Factor = InterleavedValues.size();
if (Factor != 2 && Factor != 4) {
LLVM_DEBUG(dbgs() << "Matching st2 and st4 patterns failed\n");
return false;
}
StoreInst *SI = dyn_cast<StoreInst>(Store);
if (!SI)
return false;
assert(!Mask && "Unexpected mask on plain store");

VectorType *VTy = cast<VectorType>(InterleavedValues[0]->getType());
const DataLayout &DL = SI->getModule()->getDataLayout();
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64ISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ class AArch64TargetLowering : public TargetLowering {
ArrayRef<Value *> DeinterleaveValues) const override;

bool lowerInterleaveIntrinsicToStore(
StoreInst *SI, ArrayRef<Value *> InterleaveValues) const override;
Instruction *Store, Value *Mask,
ArrayRef<Value *> InterleaveValues) const override;

bool isLegalAddImmediate(int64_t) const override;
bool isLegalAddScalableImmediate(int64_t) const override;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,8 @@ class RISCVTargetLowering : public TargetLowering {
ArrayRef<Value *> DeinterleaveValues) const override;

bool lowerInterleaveIntrinsicToStore(
StoreInst *SI, ArrayRef<Value *> InterleaveValues) const override;
Instruction *Store, Value *Mask,
ArrayRef<Value *> InterleaveValues) const override;

bool lowerInterleavedVPLoad(VPIntrinsic *Load, Value *Mask,
ArrayRef<Value *> DeinterleaveRes) const override;
Expand Down
68 changes: 46 additions & 22 deletions llvm/lib/Target/RISCV/RISCVInterleavedAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,58 +360,82 @@ bool RISCVTargetLowering::lowerDeinterleaveIntrinsicToLoad(
}

bool RISCVTargetLowering::lowerInterleaveIntrinsicToStore(
StoreInst *SI, ArrayRef<Value *> InterleaveValues) const {
Instruction *Store, Value *Mask, ArrayRef<Value *> InterleaveValues) const {
unsigned Factor = InterleaveValues.size();
if (Factor > 8)
return false;

assert(SI->isSimple());
IRBuilder<> Builder(SI);
IRBuilder<> Builder(Store);

auto *InVTy = cast<VectorType>(InterleaveValues[0]->getType());
auto *PtrTy = SI->getPointerOperandType();
const DataLayout &DL = SI->getDataLayout();
const DataLayout &DL = Store->getDataLayout();
Type *XLenTy = Type::getIntNTy(Store->getContext(), Subtarget.getXLen());

if (!isLegalInterleavedAccessType(InVTy, Factor, SI->getAlign(),
SI->getPointerAddressSpace(), DL))
return false;
Value *Ptr, *VL;
Align Alignment;
if (auto *SI = dyn_cast<StoreInst>(Store)) {
assert(SI->isSimple());
Ptr = SI->getPointerOperand();
Alignment = SI->getAlign();
assert(!Mask && "Unexpected mask on a store");
Mask = Builder.getAllOnesMask(InVTy->getElementCount());
VL = isa<FixedVectorType>(InVTy)
? Builder.CreateElementCount(XLenTy, InVTy->getElementCount())
: Constant::getAllOnesValue(XLenTy);
} else {
auto *VPStore = cast<VPIntrinsic>(Store);
assert(VPStore->getIntrinsicID() == Intrinsic::vp_store &&
"Unexpected intrinsic");
Ptr = VPStore->getMemoryPointerParam();
Alignment = VPStore->getPointerAlignment().value_or(
DL.getABITypeAlign(InVTy->getElementType()));

assert(Mask && "vp.store needs a mask!");

Value *WideEVL = VPStore->getVectorLengthParam();
// Conservatively check if EVL is a multiple of factor, otherwise some
// (trailing) elements might be lost after the transformation.
if (!isMultipleOfN(WideEVL, DL, Factor))
return false;

Type *XLenTy = Type::getIntNTy(SI->getContext(), Subtarget.getXLen());
VL = Builder.CreateZExt(
Builder.CreateUDiv(WideEVL,
ConstantInt::get(WideEVL->getType(), Factor)),
XLenTy);
}
Type *PtrTy = Ptr->getType();
unsigned AS = Ptr->getType()->getPointerAddressSpace();
if (!isLegalInterleavedAccessType(InVTy, Factor, Alignment, AS, DL))
return false;

if (isa<FixedVectorType>(InVTy)) {
Function *VssegNFunc = Intrinsic::getOrInsertDeclaration(
SI->getModule(), FixedVssegIntrIds[Factor - 2], {InVTy, PtrTy, XLenTy});

Store->getModule(), FixedVssegIntrIds[Factor - 2],
{InVTy, PtrTy, XLenTy});
SmallVector<Value *, 10> Ops(InterleaveValues);
Value *VL = Builder.CreateElementCount(XLenTy, InVTy->getElementCount());
Value *Mask = Builder.getAllOnesMask(InVTy->getElementCount());
Ops.append({SI->getPointerOperand(), Mask, VL});

Ops.append({Ptr, Mask, VL});
Builder.CreateCall(VssegNFunc, Ops);
return true;
}
unsigned SEW = DL.getTypeSizeInBits(InVTy->getElementType());
unsigned NumElts = InVTy->getElementCount().getKnownMinValue();
Type *VecTupTy = TargetExtType::get(
SI->getContext(), "riscv.vector.tuple",
ScalableVectorType::get(Type::getInt8Ty(SI->getContext()),
Store->getContext(), "riscv.vector.tuple",
ScalableVectorType::get(Type::getInt8Ty(Store->getContext()),
NumElts * SEW / 8),
Factor);

Value *VL = Constant::getAllOnesValue(XLenTy);
Value *Mask = Builder.getAllOnesMask(InVTy->getElementCount());

Value *StoredVal = PoisonValue::get(VecTupTy);
for (unsigned i = 0; i < Factor; ++i)
StoredVal = Builder.CreateIntrinsic(
Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
{StoredVal, InterleaveValues[i], Builder.getInt32(i)});

Function *VssegNFunc = Intrinsic::getOrInsertDeclaration(
SI->getModule(), ScalableVssegIntrIds[Factor - 2],
Store->getModule(), ScalableVssegIntrIds[Factor - 2],
{VecTupTy, PtrTy, Mask->getType(), VL->getType()});

Value *Operands[] = {StoredVal, SI->getPointerOperand(), Mask, VL,
Value *Operands[] = {StoredVal, Ptr, Mask, VL,
ConstantInt::get(XLenTy, Log2_64(SEW))};
Builder.CreateCall(VssegNFunc, Operands);
return true;
Expand Down
Loading