Skip to content

Commit 907871d

Browse files
committed
[llvm] [CodeGen] Fixed vector halving bug for masked load
Summary: Given a VL=14 that is enveloped by a proper VL=16, splitting the masked load using the enveloping halving VL=8/8 should yields should eventually yield V=8/5. This fixes various assert failures in getHalfNumVectorElementsVT() and IncrementMemoryAddress(). Note, I suspect similar fixes will be needed for other masked operations, but for now I send out a fix for masked load only. Bugzilla issue 45563 https://bugs.llvm.org/show_bug.cgi?id=45563 Reviewers: craig.topper, mehdi_amini, nicolasvasilache Reviewed By: craig.topper Subscribers: hiraditya, dmgreen, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D78608
1 parent e4e187d commit 907871d

File tree

4 files changed

+423
-12
lines changed

4 files changed

+423
-12
lines changed

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,12 @@ class SelectionDAG {
18311831
/// which is split (or expanded) into two not necessarily identical pieces.
18321832
std::pair<EVT, EVT> GetSplitDestVTs(const EVT &VT) const;
18331833

1834+
/// Compute the VTs needed for the low/hi parts of a type, dependent on an
1835+
/// enveloping VT that has been split into two identical pieces. Sets the
1836+
/// HisIsEmpty flag when hi type has zero storage size.
1837+
std::pair<EVT, EVT> GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT,
1838+
bool *HiIsEmpty) const;
1839+
18341840
/// Split the vector with EXTRACT_SUBVECTOR using the provides
18351841
/// VTs and return the low/high part.
18361842
std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL,

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,7 +1571,9 @@ void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
15711571

15721572
EVT MemoryVT = MLD->getMemoryVT();
15731573
EVT LoMemVT, HiMemVT;
1574-
std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
1574+
bool HiIsEmpty = false;
1575+
std::tie(LoMemVT, HiMemVT) =
1576+
DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
15751577

15761578
SDValue PassThruLo, PassThruHi;
15771579
if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
@@ -1587,17 +1589,25 @@ void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
15871589
MMO, MLD->getAddressingMode(), ExtType,
15881590
MLD->isExpandingLoad());
15891591

1590-
Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
1591-
MLD->isExpandingLoad());
1592-
unsigned HiOffset = LoMemVT.getStoreSize();
1593-
1594-
MMO = DAG.getMachineFunction().getMachineMemOperand(
1595-
MLD->getPointerInfo().getWithOffset(HiOffset), MachineMemOperand::MOLoad,
1596-
HiMemVT.getStoreSize(), Alignment, MLD->getAAInfo(), MLD->getRanges());
1597-
1598-
Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi, HiMemVT,
1599-
MMO, MLD->getAddressingMode(), ExtType,
1600-
MLD->isExpandingLoad());
1592+
if (HiIsEmpty) {
1593+
// The hi masked load has zero storage size. We therefore simply set it to
1594+
// the low masked load and rely on subsequent removal from the chain.
1595+
Hi = Lo;
1596+
} else {
1597+
// Generate hi masked load.
1598+
Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
1599+
MLD->isExpandingLoad());
1600+
unsigned HiOffset = LoMemVT.getStoreSize();
1601+
1602+
MMO = DAG.getMachineFunction().getMachineMemOperand(
1603+
MLD->getPointerInfo().getWithOffset(HiOffset),
1604+
MachineMemOperand::MOLoad, HiMemVT.getStoreSize(), Alignment,
1605+
MLD->getAAInfo(), MLD->getRanges());
1606+
1607+
Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
1608+
HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
1609+
MLD->isExpandingLoad());
1610+
}
16011611

16021612
// Build a factor node to remember that this load is independent of the
16031613
// other one.

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9461,6 +9461,37 @@ std::pair<EVT, EVT> SelectionDAG::GetSplitDestVTs(const EVT &VT) const {
94619461
return std::make_pair(LoVT, HiVT);
94629462
}
94639463

9464+
/// GetDependentSplitDestVTs - Compute the VTs needed for the low/hi parts of a
9465+
/// type, dependent on an enveloping VT that has been split into two identical
9466+
/// pieces. Sets the HiIsEmpty flag when hi type has zero storage size.
9467+
std::pair<EVT, EVT>
9468+
SelectionDAG::GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT,
9469+
bool *HiIsEmpty) const {
9470+
EVT EltTp = VT.getVectorElementType();
9471+
bool IsScalable = VT.isScalableVector();
9472+
// Examples:
9473+
// custom VL=8 with enveloping VL=8/8 yields 8/0 (hi empty)
9474+
// custom VL=9 with enveloping VL=8/8 yields 8/1
9475+
// custom VL=10 with enveloping VL=8/8 yields 8/2
9476+
// etc.
9477+
unsigned VTNumElts = VT.getVectorNumElements();
9478+
unsigned EnvNumElts = EnvVT.getVectorNumElements();
9479+
EVT LoVT, HiVT;
9480+
if (VTNumElts > EnvNumElts) {
9481+
LoVT = EnvVT;
9482+
HiVT = EVT::getVectorVT(*getContext(), EltTp, VTNumElts - EnvNumElts,
9483+
IsScalable);
9484+
*HiIsEmpty = false;
9485+
} else {
9486+
// Flag that hi type has zero storage size, but return split envelop type
9487+
// (this would be easier if vector types with zero elements were allowed).
9488+
LoVT = EVT::getVectorVT(*getContext(), EltTp, VTNumElts, IsScalable);
9489+
HiVT = EnvVT;
9490+
*HiIsEmpty = true;
9491+
}
9492+
return std::make_pair(LoVT, HiVT);
9493+
}
9494+
94649495
/// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the
94659496
/// low/high part.
94669497
std::pair<SDValue, SDValue>

0 commit comments

Comments
 (0)