[llvm] [AArch64][GlobalISel] Perfect Shuffles (PR #106446)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 28 20:16:33 PDT 2024
================
@@ -504,6 +504,189 @@ void applyINS(MachineInstr &MI, MachineRegisterInfo &MRI,
MI.eraseFromParent();
}
+/// Match 4 elemental G_SHUFFLE_VECTOR
+bool matchPerfectShuffle(MachineInstr &MI, MachineRegisterInfo &MRI) {
+ assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
+ return MRI.getType(MI.getOperand(0).getReg()).getNumElements() == 4;
+}
+
+static Register GeneratePerfectShuffle(unsigned ID, Register V1, Register V2,
+ unsigned PFEntry, Register LHS,
+ Register RHS, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) {
+ 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).
+ Register OpLHS = GeneratePerfectShuffle(
+ LHSID, V1, V2, PerfectShuffleTable[LHSID], LHS, RHS, MIB, MRI);
+ LLT VT = MRI.getType(OpLHS);
+ assert(RHSID < 8 && "Expected a lane index for RHSID!");
+ unsigned ExtLane = 0;
+ Register 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;
+ if (VT.getScalarSizeInBits() == 16 && VT != LLT::fixed_vector(2, 32)) {
+ Input = MIB.buildInstr(TargetOpcode::G_BITCAST,
+ {LLT::fixed_vector(2, 32)}, {Input})
+ .getReg(0);
+ OpLHS = MIB.buildInstr(TargetOpcode::G_BITCAST,
+ {LLT::fixed_vector(2, 32)}, {OpLHS})
+ .getReg(0);
+ }
+ if (VT.getScalarSizeInBits() == 32 && VT != LLT::fixed_vector(2, 64)) {
+ Input = MIB.buildInstr(TargetOpcode::G_BITCAST,
+ {LLT::fixed_vector(2, 64)}, {Input})
+ .getReg(0);
+ OpLHS = MIB.buildInstr(TargetOpcode::G_BITCAST,
+ {LLT::fixed_vector(2, 64)}, {OpLHS})
+ .getReg(0);
+ }
+ } else {
+ int MaskElt = getPFIDLane(ID, RHSID);
+ assert(MaskElt >= 0 && "Didn't expect an undef movlane index!");
+ ExtLane = MaskElt < 4 ? MaskElt : (MaskElt - 4);
+ Input = MaskElt < 4 ? V1 : V2;
+ if (VT.getScalarSizeInBits() == 16 && VT != LLT::fixed_vector(4, 16)) {
+ Input = MIB.buildInstr(TargetOpcode::G_BITCAST,
+ {LLT::fixed_vector(4, 16)}, {Input})
+ .getReg(0);
+ OpLHS = MIB.buildInstr(TargetOpcode::G_BITCAST,
----------------
arsenm wrote:
buildBitcast
https://github.com/llvm/llvm-project/pull/106446
More information about the llvm-commits
mailing list