diff options
author | Philip Reames <preames@rivosinc.com> | 2025-01-10 07:12:24 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-10 07:12:24 -0800 |
commit | 24bb180e8aeae95cb830e5c3da73e750edaa139f (patch) | |
tree | c6d8cedb806ba09ada47129c5980cf3dca666693 /llvm/lib/Analysis/VectorUtils.cpp | |
parent | 9c85cdec4ad29389c27cc2372d45f73d1ca8053a (diff) | |
download | llvm-24bb180e8aeae95cb830e5c3da73e750edaa139f.zip llvm-24bb180e8aeae95cb830e5c3da73e750edaa139f.tar.gz llvm-24bb180e8aeae95cb830e5c3da73e750edaa139f.tar.bz2 |
[RISCV] Attempt to widen SEW before generic shuffle lowering (#122311)
This takes inspiration from AArch64 which does the same thing to assist
with zip/trn/etc.. Doing this recursion unconditionally when the mask
allows is slightly questionable, but seems to work out okay in practice.
As a bit of context, it's helpful to realize that we have existing logic
in both DAGCombine and InstCombine which mutates the element width of in
an analogous manner. However, that code has two restriction which
prevent it from handling the motivating cases here. First, it only
triggers if there is a bitcast involving a different element type.
Second, the matcher used considers a partially undef wide element to be
a non-match. I considered trying to relax those assumptions, but the
information loss for undef in mid-level opt seemed more likely to open a
can of worms than I wanted.
Diffstat (limited to 'llvm/lib/Analysis/VectorUtils.cpp')
-rw-r--r-- | llvm/lib/Analysis/VectorUtils.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp index 6c2502c..b4b311c 100644 --- a/llvm/lib/Analysis/VectorUtils.cpp +++ b/llvm/lib/Analysis/VectorUtils.cpp @@ -479,6 +479,41 @@ bool llvm::widenShuffleMaskElts(int Scale, ArrayRef<int> Mask, return true; } +bool llvm::widenShuffleMaskElts(ArrayRef<int> M, + SmallVectorImpl<int> &NewMask) { + unsigned NumElts = M.size(); + if (NumElts % 2 != 0) + return false; + + NewMask.clear(); + for (unsigned i = 0; i < NumElts; i += 2) { + int M0 = M[i]; + int M1 = M[i + 1]; + + // If both elements are undef, new mask is undef too. + if (M0 == -1 && M1 == -1) { + NewMask.push_back(-1); + continue; + } + + if (M0 == -1 && M1 != -1 && (M1 % 2) == 1) { + NewMask.push_back(M1 / 2); + continue; + } + + if (M0 != -1 && (M0 % 2) == 0 && ((M0 + 1) == M1 || M1 == -1)) { + NewMask.push_back(M0 / 2); + continue; + } + + NewMask.clear(); + return false; + } + + assert(NewMask.size() == NumElts / 2 && "Incorrect size for mask!"); + return true; +} + bool llvm::scaleShuffleMaskElts(unsigned NumDstElts, ArrayRef<int> Mask, SmallVectorImpl<int> &ScaledMask) { unsigned NumSrcElts = Mask.size(); |