-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[RISCV] Use slideup to lower build_vector when all operand are (extract_element X, 0) #154450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
f74a607
c5b56c2
217402a
3dec8ff
1d8b13e
ac83561
ed3f456
41f1a97
83f1747
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -4512,42 +4512,98 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, | |||||
"Illegal type which will result in reserved encoding"); | ||||||
|
||||||
const unsigned Policy = RISCVVType::TAIL_AGNOSTIC | RISCVVType::MASK_AGNOSTIC; | ||||||
auto getVSlide = [&](bool SlideUp, EVT ContainerVT, SDValue Passthru, | ||||||
SDValue Vec, SDValue Offset, SDValue Mask, | ||||||
SDValue VL) -> SDValue { | ||||||
if (SlideUp) | ||||||
return getVSlideup(DAG, Subtarget, DL, ContainerVT, Passthru, Vec, Offset, | ||||||
Mask, VL, Policy); | ||||||
return getVSlidedown(DAG, Subtarget, DL, ContainerVT, Passthru, Vec, Offset, | ||||||
Mask, VL, Policy); | ||||||
}; | ||||||
|
||||||
// General case: splat the first operand and slide other operands down one | ||||||
// by one to form a vector. Alternatively, if the last operand is an | ||||||
// extraction from element 0 of a vector, we can use the original vector | ||||||
// reduction result as the start value and slide up instead of slide down. | ||||||
lukel97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
// Such that we can avoid the splat. | ||||||
SmallVector<SDValue> Operands(Op->op_begin(), Op->op_end()); | ||||||
SDValue EVec; | ||||||
bool SlideUp = false; | ||||||
// Find the first first non-undef from the tail. | ||||||
auto ItLastNonUndef = find_if(Operands.rbegin(), Operands.rend(), | ||||||
[](SDValue V) { return !V.isUndef(); }); | ||||||
if (ItLastNonUndef != Operands.rend()) { | ||||||
using namespace SDPatternMatch; | ||||||
// Check if the last non-undef operand was an extraction. | ||||||
SlideUp = sd_match(*ItLastNonUndef, m_ExtractElt(m_Value(EVec), m_Zero())); | ||||||
} | ||||||
|
||||||
if (SlideUp) { | ||||||
MVT EVecContainerVT = EVec.getSimpleValueType(); | ||||||
// Make sure the original vector has scalable vector type. | ||||||
if (EVecContainerVT.isFixedLengthVector()) { | ||||||
EVecContainerVT = | ||||||
getContainerForFixedLengthVector(DAG, EVecContainerVT, Subtarget); | ||||||
EVec = convertToScalableVector(EVecContainerVT, EVec, DAG, Subtarget); | ||||||
} | ||||||
|
||||||
// Adapt EVec's type into ContainerVT. | ||||||
if (EVecContainerVT.getVectorMinNumElements() < | ||||||
ContainerVT.getVectorMinNumElements()) | ||||||
EVec = DAG.getInsertSubvector(DL, DAG.getUNDEF(ContainerVT), EVec, 0); | ||||||
else | ||||||
EVec = DAG.getExtractSubvector(DL, ContainerVT, EVec, 0); | ||||||
|
||||||
// Reverse the elements as we're going to slide up from the last element. | ||||||
std::reverse(Operands.begin(), Operands.end()); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit, does llvm::reverse work here?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That was actually what I thought, but unfortunately, |
||||||
} | ||||||
|
||||||
SDValue Vec; | ||||||
UndefCount = 0; | ||||||
for (SDValue V : Op->ops()) { | ||||||
for (SDValue V : Operands) { | ||||||
if (V.isUndef()) { | ||||||
UndefCount++; | ||||||
continue; | ||||||
} | ||||||
|
||||||
// Start our sequence with a TA splat in the hopes that hardware is able to | ||||||
// recognize there's no dependency on the prior value of our temporary | ||||||
// register. | ||||||
// Start our sequence with either a TA splat or a reduction result in the | ||||||
lukel97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
// hopes that hardware is able to recognize there's no dependency on the | ||||||
// prior value of our temporary register. | ||||||
if (!Vec) { | ||||||
Vec = DAG.getSplatVector(VT, DL, V); | ||||||
Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget); | ||||||
if (SlideUp) { | ||||||
Vec = EVec; | ||||||
} else { | ||||||
Vec = DAG.getSplatVector(VT, DL, V); | ||||||
Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget); | ||||||
} | ||||||
|
||||||
UndefCount = 0; | ||||||
continue; | ||||||
} | ||||||
|
||||||
if (UndefCount) { | ||||||
const SDValue Offset = DAG.getConstant(UndefCount, DL, Subtarget.getXLenVT()); | ||||||
Vec = getVSlidedown(DAG, Subtarget, DL, ContainerVT, DAG.getUNDEF(ContainerVT), | ||||||
Vec, Offset, Mask, VL, Policy); | ||||||
Vec = getVSlide(SlideUp, ContainerVT, DAG.getUNDEF(ContainerVT), Vec, | ||||||
Offset, Mask, VL); | ||||||
UndefCount = 0; | ||||||
} | ||||||
auto OpCode = | ||||||
VT.isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL; | ||||||
|
||||||
unsigned OpCode; | ||||||
lukel97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
if (VT.isFloatingPoint()) | ||||||
OpCode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL; | ||||||
else | ||||||
OpCode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL; | ||||||
|
||||||
if (!VT.isFloatingPoint()) | ||||||
V = DAG.getNode(ISD::ANY_EXTEND, DL, Subtarget.getXLenVT(), V); | ||||||
Vec = DAG.getNode(OpCode, DL, ContainerVT, DAG.getUNDEF(ContainerVT), Vec, | ||||||
V, Mask, VL); | ||||||
} | ||||||
if (UndefCount) { | ||||||
const SDValue Offset = DAG.getConstant(UndefCount, DL, Subtarget.getXLenVT()); | ||||||
Vec = getVSlidedown(DAG, Subtarget, DL, ContainerVT, DAG.getUNDEF(ContainerVT), | ||||||
Vec, Offset, Mask, VL, Policy); | ||||||
Vec = getVSlide(SlideUp, ContainerVT, DAG.getUNDEF(ContainerVT), Vec, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we have test coverage for emitting a vslideup. I think we can add a test for an undef in the middle of the build_vector, and another test with an undef at the start of the build_vector? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added tests for both cases |
||||||
Offset, Mask, VL); | ||||||
} | ||||||
return convertFromScalableVector(VT, Vec, DAG, Subtarget); | ||||||
} | ||||||
|
Uh oh!
There was an error while loading. Please reload this page.