[llvm] [AArch64][GlobalISel] Perfect Shuffles (PR #106446)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 21 11:54:45 PDT 2025
================
@@ -6723,6 +6742,110 @@ inline bool isREVMask(ArrayRef<int> M, unsigned EltSize, unsigned NumElts,
return true;
}
+/// Generate perfect shuffles, shared between SDAG and GISel.
+
+/// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit
+/// the specified operations to build the shuffle. ID is the perfect-shuffle
+/// ID, V1 and V2 are the original shuffle inputs. PFEntry is the Perfect
+/// shuffle table entry and LHS/RHS are the immediate inputs for this stage of
+/// the shuffle. The implementations is shared between SDAG and GISel.
+template <class Val, class Ty, typename ExtInsFn64, typename ExtInsFn32,
+ typename ValFn, typename ValImmFn, typename ValValFn,
+ typename ValValFn2>
+inline Val generatePerfectShuffle(unsigned ID, Val V1, Val V2, unsigned PFEntry,
+ Val LHS, Val RHS,
+ ExtInsFn64 BuildExtractInsert64,
+ ExtInsFn32 BuildExtractInsert32,
+ ValFn BuildRev, ValImmFn BuildDup,
+ ValValFn BuildExt, ValValFn2 BuildZip) {
+ unsigned OpNum = (PFEntry >> 26) & 0x0F;
+ unsigned LHSID = (PFEntry >> 13) & ((1 << 13) - 1);
+ unsigned RHSID = (PFEntry >> 0) & ((1 << 13) - 1);
+
+ if (OpNum == OP_COPY) {
+ if (LHSID == (1 * 9 + 2) * 9 + 3)
+ return LHS;
+ assert(LHSID == ((4 * 9 + 5) * 9 + 6) * 9 + 7 && "Illegal OP_COPY!");
+ return RHS;
+ }
+
+ if (OpNum == OP_MOVLANE) {
+ // Decompose a PerfectShuffle ID to get the Mask for lane Elt
+ auto getPFIDLane = [](unsigned ID, int Elt) -> int {
+ assert(Elt < 4 && "Expected Perfect Lanes to be less than 4");
+ Elt = 3 - Elt;
+ while (Elt > 0) {
+ ID /= 9;
+ Elt--;
+ }
+ return (ID % 9 == 8) ? -1 : ID % 9;
+ };
+
+ // For OP_MOVLANE shuffles, the RHSID represents the lane to move into. We
+ // get the lane to move from the PFID, which is always from the
+ // original vectors (V1 or V2).
+ Val OpLHS = generatePerfectShuffle<Val, Ty>(
+ LHSID, V1, V2, PerfectShuffleTable[LHSID], LHS, RHS,
+ BuildExtractInsert64, BuildExtractInsert32, BuildRev, BuildDup,
+ BuildExt, BuildZip);
+ assert(RHSID < 8 && "Expected a lane index for RHSID!");
+ unsigned ExtLane = 0;
+ Val Input;
+
+ // OP_MOVLANE are either D movs (if bit 0x4 is set) or S movs. D movs
+ // convert into a higher type.
+ if (RHSID & 0x4) {
+ int MaskElt = getPFIDLane(ID, (RHSID & 0x01) << 1) >> 1;
+ if (MaskElt == -1)
+ MaskElt = (getPFIDLane(ID, ((RHSID & 0x01) << 1) + 1) - 1) >> 1;
+ assert(MaskElt >= 0 && "Didn't expect an undef movlane index!");
+ ExtLane = MaskElt < 2 ? MaskElt : (MaskElt - 2);
+ Input = MaskElt < 2 ? V1 : V2;
+ return BuildExtractInsert64(Input, ExtLane, OpLHS, RHSID & 0x3);
+ } else {
----------------
arsenm wrote:
No else after return
https://github.com/llvm/llvm-project/pull/106446
More information about the llvm-commits
mailing list