[llvm] 1372e23 - [PowerPC] Add vector pair load/store instructions and vector pair register class

Baptiste Saleil via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 08:28:01 PDT 2020


Author: Baptiste Saleil
Date: 2020-09-21T10:27:47-05:00
New Revision: 1372e23c7d4b25fd23689842246e66f70c949b46

URL: https://github.com/llvm/llvm-project/commit/1372e23c7d4b25fd23689842246e66f70c949b46
DIFF: https://github.com/llvm/llvm-project/commit/1372e23c7d4b25fd23689842246e66f70c949b46.diff

LOG: [PowerPC] Add vector pair load/store instructions and vector pair register class

This patch adds support for the lxvp, lxvpx, plxvp, stxvp, stxvpx and pstxvp
instructions in the PowerPC backend. These instructions allow loading and
storing VSX register pairs. This patch also adds the VSRp register class
definition needed for these instructions.

Differential Revision: https://reviews.llvm.org/D84359

Added: 
    

Modified: 
    llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
    llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
    llvm/lib/Target/PowerPC/PPCInstrPrefix.td
    llvm/lib/Target/PowerPC/PPCRegisterInfo.h
    llvm/lib/Target/PowerPC/PPCRegisterInfo.td
    llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
    llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s
    llvm/utils/TableGen/CodeGenTarget.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index ef1947692960..4a35a6548a40 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -290,6 +290,11 @@ struct PPCOperand : public MCParsedAsmOperand {
     return (unsigned) Imm.Val;
   }
 
+  unsigned getVSRpEvenReg() const {
+    assert(isVSRpEvenRegNumber() && "Invalid access!");
+    return (unsigned) Imm.Val >> 1;
+  }
+
   unsigned getCCReg() const {
     assert(isCCRegNumber() && "Invalid access!");
     return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal);
@@ -402,6 +407,9 @@ struct PPCOperand : public MCParsedAsmOperand {
                                   (getImm() & 3) == 0); }
   bool isImmZero() const { return Kind == Immediate && getImm() == 0; }
   bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); }
+  bool isVSRpEvenRegNumber() const {
+    return Kind == Immediate && isUInt<6>(getImm()) && ((getImm() & 1) == 0);
+  }
   bool isVSRegNumber() const {
     return Kind == Immediate && isUInt<6>(getImm());
   }
@@ -502,6 +510,11 @@ struct PPCOperand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createReg(SPERegs[getReg()]));
   }
 
+  void addRegVSRpRCOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createReg(VSRpRegs[getVSRpEvenReg()]));
+  }
+
   void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::createReg(CRBITRegs[getCRBit()]));

diff  --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
index 362ddf720455..ddb372756333 100644
--- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
+++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
@@ -173,6 +173,12 @@ static DecodeStatus DecodeSPERCRegisterClass(MCInst &Inst, uint64_t RegNo,
   return decodeRegisterClass(Inst, RegNo, SPERegs);
 }
 
+static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                              uint64_t Address,
+                                              const void *Decoder) {
+  return decodeRegisterClass(Inst, RegNo, VSRpRegs);
+}
+
 #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass
 #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass
 

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index 325ede0fc17a..f7591d2249a4 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -156,6 +156,7 @@ using llvm::MCPhysReg;
   static const MCPhysReg RRegs[32] = PPC_REGS0_31(PPC::R); \
   static const MCPhysReg XRegs[32] = PPC_REGS0_31(PPC::X); \
   static const MCPhysReg FRegs[32] = PPC_REGS0_31(PPC::F); \
+  static const MCPhysReg VSRpRegs[32] = PPC_REGS0_31(PPC::VSRp); \
   static const MCPhysReg SPERegs[32] = PPC_REGS0_31(PPC::S); \
   static const MCPhysReg VFRegs[32] = PPC_REGS0_31(PPC::VF); \
   static const MCPhysReg VRegs[32] = PPC_REGS0_31(PPC::V); \

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td
index 23b641f00cc9..00fd756fe46d 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td
@@ -517,10 +517,79 @@ multiclass 8LS_DForm_R_SI34_XT6_RA5_p<bits<5> opcode, dag OOL, dag IOL,
                                     isPCRel;
 }
 
+def PPCRegVSRpRCAsmOperand : AsmOperandClass {
+  let Name = "RegVSRpRC"; let PredicateMethod = "isVSRpEvenRegNumber";
+}
+
+def vsrprc : RegisterOperand<VSRpRC> {
+  let ParserMatchClass = PPCRegVSRpRCAsmOperand;
+}
+
+class DQForm_XTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
+                           string asmstr, InstrItinClass itin, list<dag> pattern>
+  : I<opcode, OOL, IOL, asmstr, itin> {
+  bits<5> XTp;
+  bits<17> DQ_RA;
+  let Pattern = pattern;
+
+  let Inst{6-9} = XTp{3-0};
+  let Inst{10} = XTp{4};
+  let Inst{11-15} = DQ_RA{16-12};  // Register #
+  let Inst{16-27} = DQ_RA{11-0};   // Displacement.
+  let Inst{28-31} = xo;
+}
+
+class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
+                      string asmstr, InstrItinClass itin, list<dag> pattern>
+  : I<opcode, OOL, IOL, asmstr, itin>, XFormMemOp {
+  bits<5> XTp;
+  bits<5> A;
+  bits<5> B;
+
+  let Pattern = pattern;
+  let Inst{6-9} = XTp{3-0};
+  let Inst{10} = XTp{4};
+  let Inst{11-15} = A;
+  let Inst{16-20} = B;
+  let Inst{21-30} = xo;
+  let Inst{31} = 0;
+}
+
+class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
+                                InstrItinClass itin, list<dag> pattern>
+  : PI<1, opcode, OOL, IOL, asmstr, itin> {
+  bits<5> XTp;
+  bits<39> D_RA;
+
+  let Pattern = pattern;
+
+  // The prefix.
+  let Inst{6-10} = 0;
+  let Inst{11} = PCRel;
+  let Inst{12-13} = 0;
+  let Inst{14-31} = D_RA{33-16}; // Imm18
+
+  // The instruction.
+  let Inst{38-41} = XTp{3-0};
+  let Inst{42}    = XTp{4};
+  let Inst{43-47} = D_RA{38-34};   // Register #
+  let Inst{48-63} = D_RA{15-0};    // D
+}
+
+multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> pref, bits<6> opcode, dag OOL,
+                                       dag IOL, dag PCRel_IOL,
+                                       string asmstr, InstrItinClass itin> {
+  def NAME : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL,
+                                       !strconcat(asmstr, ", 0"), itin, []>;
+  def pc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRel_IOL,
+                                     !strconcat(asmstr, ", 1"), itin, []>,
+                                     isPCRel;
+}
+
 def PrefixInstrs : Predicate<"Subtarget->hasPrefixInstrs()">;
 def IsISA3_1 : Predicate<"Subtarget->isISA3_1()">;
-def PairedVectorMemops : Predicate<"PPCSubTarget->pairedVectorMemops()">;
-def MMA : Predicate<"PPCSubTarget->hasMMA()">;
+def PairedVectorMemops : Predicate<"Subtarget->pairedVectorMemops()">;
+def MMA : Predicate<"Subtarget->hasMMA()">;
 
 def RCCp {
   dag AToVSRC = (COPY_TO_REGCLASS $XA, VSRC);
@@ -672,6 +741,36 @@ let Predicates = [PrefixInstrs] in {
   }
 }
 
+let mayLoad = 1, mayStore = 0, Predicates = [PairedVectorMemops] in {
+  def LXVP : DQForm_XTp5_RA17_MEM<6, 0, (outs vsrprc:$XTp),
+                                  (ins memrix16:$DQ_RA), "lxvp $XTp, $DQ_RA",
+                                  IIC_LdStLFD, []>;
+  def LXVPX : XForm_XTp5_XAB5<31, 333, (outs vsrprc:$XTp), (ins memrr:$src),
+                              "lxvpx $XTp, $src", IIC_LdStLFD,
+                              [(set v4i64:$XTp, (load xaddr:$src))]>;
+  let Predicates = [PrefixInstrs] in {
+    defm PLXVP :
+      8LS_DForm_R_XTp5_SI34_MEM_p<1, 58, (outs vsrprc:$XTp), (ins memri34:$D_RA),
+                                  (ins memri34_pcrel:$D_RA), "plxvp $XTp, $D_RA",
+                                  IIC_LdStLFD>;
+  }
+}
+
+let mayLoad = 0, mayStore = 1, Predicates = [PairedVectorMemops] in {
+  def STXVP : DQForm_XTp5_RA17_MEM<6, 1, (outs), (ins vsrprc:$XTp,
+                                   memrix16:$DQ_RA), "stxvp $XTp, $DQ_RA",
+                                   IIC_LdStLFD, []>;
+  def STXVPX : XForm_XTp5_XAB5<31, 461, (outs), (ins vsrprc:$XTp, memrr:$dst),
+                               "stxvpx $XTp, $dst", IIC_LdStLFD,
+                               [(store v4i64:$XTp, xaddr:$dst)]>;
+  let Predicates = [PrefixInstrs] in {
+    defm PSTXVP :
+      8LS_DForm_R_XTp5_SI34_MEM_p<1, 62, (outs), (ins vsrprc:$XTp, memri34:$D_RA),
+                                  (ins vsrprc:$XTp, memri34_pcrel:$D_RA),
+                                  "pstxvp $XTp, $D_RA", IIC_LdStLFD>;
+  }
+}
+
 // TODO: We have an added complexity of 500 here. This is only a temporary
 // solution to have tablegen consider these patterns first. The way we do
 // addressing for PowerPC is complex depending on available D form, X form, or

diff  --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
index a931967862c7..50b2489c8abd 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -154,8 +154,11 @@ class PPCRegisterInfo : public PPCGenRegisterInfo {
       case 'r':
       case 'f':
       case 'v':
-        if (RegName[1] == 's')
+        if (RegName[1] == 's') {
+          if (RegName[2] == 'p')
+            return RegName + 3;
           return RegName + 2;
+        }
         return RegName + 1;
       case 'c': if (RegName[1] == 'r') return RegName + 2;
     }

diff  --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index e07b960ae305..3a5df2585ebc 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -16,6 +16,8 @@ def sub_eq : SubRegIndex<1, 2>;
 def sub_un : SubRegIndex<1, 3>;
 def sub_32 : SubRegIndex<32>;
 def sub_64 : SubRegIndex<64>;
+def sub_vsx0 : SubRegIndex<128>;
+def sub_vsx1 : SubRegIndex<128>;
 }
 
 
@@ -94,6 +96,12 @@ class CRBIT<bits<5> num, string n> : PPCReg<n> {
   let HWEncoding{4-0} = num;
 }
 
+// VSR Pairs - One of the 32 paired even-odd consecutive VSRs.
+class VSRPair<bits<5> num, string n, list<Register> subregs> : PPCReg<n> {
+  let HWEncoding{4-0} = num;
+  let SubRegs = subregs;
+}
+
 // General-purpose registers
 foreach Index = 0-31 in {
   def R#Index : GPR<Index, "r"#Index>, DwarfRegNum<[-2, Index]>;
@@ -143,6 +151,23 @@ foreach Index = 32-63 in {
   def VSX#Index : VSXReg<Index, "vs"#Index>;
 }
 
+let SubRegIndices = [sub_vsx0, sub_vsx1] in {
+  // VSR pairs 0 - 15 (corresponding to VSRs 0 - 30 paired with 1 - 31).
+  foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in {
+    def VSRp#!srl(Index, 1) : VSRPair<!srl(Index, 1), "vsp"#Index,
+                                      [!cast<VSRL>("VSL"#Index), !cast<VSRL>("VSL"#!add(Index, 1))]>,
+                              DwarfRegNum<[0, 0]>;
+  }
+
+  // VSR pairs 16 - 31 (corresponding to VSRs 32 - 62 paired with 33 - 63).
+  foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in {
+    def VSRp#!add(!srl(Index, 1), 16) :
+      VSRPair<!add(!srl(Index, 1), 16), "vsp"#!add(Index, 32),
+              [!cast<VR>("V"#Index), !cast<VR>("V"#!add(Index, 1))]>,
+      DwarfRegNum<[0, 0]>;
+  }
+}
+
 // The representation of r0 when treated as the constant 0.
 def ZERO  : GPR<0, "0">,    DwarfRegAlias<R0>;
 def ZERO8 : GP8<ZERO, "0">, DwarfRegAlias<X0>;
@@ -372,3 +397,13 @@ def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY, XER)> {
   let CopyCost = -1;
 }
 
+// Allocate in the same order as the underlying VSX registers.
+def VSRpRC :
+  RegisterClass<"PPC", [v4i64,v4f64,v8i32,v8f32,v16i16,v32i8,v256i1], 128,
+                (add (sequence "VSRp%u", 0, 6),
+                     (sequence "VSRp%u", 15, 7), VSRp17, VSRp18,
+                     VSRp16, VSRp19, VSRp20, VSRp21, VSRp22, VSRp23,
+                     VSRp24, VSRp25, VSRp31, VSRp30, VSRp29, VSRp28,
+                     VSRp27, VSRp26)> {
+  let Size = 256;
+}

diff  --git a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
index a9c70b713538..18437d8e5c95 100644
--- a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
+++ b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
@@ -25,6 +25,30 @@
 # CHECK: pstxv 33, 8589934591(0), 1
 0x04 0x11 0xff 0xff 0xdc 0x20 0xff 0xff
 
+# CHECK: lxvp 2, 32(4)
+0x18 0x44 0x00 0x20
+
+# CHECK: plxvp 2, -8589934592(0), 1
+0x04 0x12 0x00 0x00 0xe8 0x40 0x00 0x00
+
+# CHECK: plxvp 34, 8589934591(3), 0
+0x04 0x01 0xff 0xff 0xe8 0x63 0xff 0xff
+
+# CHECK: stxvp 2, 32(4)
+0x18 0x44 0x00 0x21
+
+# CHECK: pstxvp 2, -8589934592(0), 1
+0x04 0x12 0x00 0x00 0xf8 0x40 0x00 0x00
+
+# CHECK: pstxvp 34, 8589934591(3), 0
+0x04 0x01 0xff 0xff 0xf8 0x63 0xff 0xff
+
+# CHECK: lxvpx 2, 3, 4
+0x7c 0x43 0x22 0x9a
+
+# CHECK: stxvpx 34, 6, 4
+0x7c 0x66 0x23 0x9a
+
 # CHECK: pstfs 1, -134217728(3), 0
 0x06 0x03 0xf8 0x00 0xd0 0x23 0x00 0x00
 

diff  --git a/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s b/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s
index 08cdcc74dc42..7d1b1dc697bb 100644
--- a/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s
+++ b/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s
@@ -23,6 +23,44 @@
 # CHECK-LE: pstxv 33, -8589934592(31), 0    # encoding: [0x00,0x00,0x02,0x04
 # CHECK-LE-SAME:                                         0x00,0x00,0x3f,0xdc]
             pstxv 33, -8589934592(31), 0
+# CHECK-BE: lxvp 2, 32(4)                      # encoding: [0x18,0x44,0x00,0x20]
+# CHECK-LE: lxvp 2, 32(4)                      # encoding: [0x20,0x00,0x44,0x18]
+            lxvp 2, 32(4)
+# CHECK-BE: lxvp 34, 64(4)                     # encoding: [0x18,0x64,0x00,0x40]
+# CHECK-LE: lxvp 34, 64(4)                     # encoding: [0x40,0x00,0x64,0x18]
+            lxvp 34, 64(4)
+# CHECK-BE: plxvp 2, -8589934592(0), 1         # encoding: [0x04,0x12,0x00,0x00,
+# CHECK-BE-SAME:                                            0xe8,0x40,0x00,0x00]
+# CHECK-LE: plxvp 2, -8589934592(0), 1         # encoding: [0x00,0x00,0x12,0x04,
+# CHECK-LE-SAME:                                            0x00,0x00,0x40,0xe8]
+            plxvp 2, -8589934592(0), 1
+# CHECK-BE: plxvp 34, 8589934591(3), 0         # encoding: [0x04,0x01,0xff,0xff,
+# CHECK-BE-SAME:                                            0xe8,0x63,0xff,0xff]
+# CHECK-LE: plxvp 34, 8589934591(3), 0         # encoding: [0xff,0xff,0x01,0x04,
+# CHECK-LE-SAME:                                            0xff,0xff,0x63,0xe8]
+            plxvp 34, 8589934591(3), 0
+# CHECK-BE: stxvp 2, 32(4)                     # encoding: [0x18,0x44,0x00,0x21]
+# CHECK-LE: stxvp 2, 32(4)                     # encoding: [0x21,0x00,0x44,0x18]
+            stxvp 2, 32(4)
+# CHECK-BE: stxvp 34, 64(4)                    # encoding: [0x18,0x64,0x00,0x41]
+# CHECK-LE: stxvp 34, 64(4)                    # encoding: [0x41,0x00,0x64,0x18]
+            stxvp 34, 64(4)
+# CHECK-BE: pstxvp 2, -8589934592(0), 1        # encoding: [0x04,0x12,0x00,0x00,
+# CHECK-BE-SAME:                                            0xf8,0x40,0x00,0x00]
+# CHECK-LE: pstxvp 2, -8589934592(0), 1        # encoding: [0x00,0x00,0x12,0x04
+# CHECK-LE-SAME:                                            0x00,0x00,0x40,0xf8]
+            pstxvp 2, -8589934592(0), 1
+# CHECK-BE: pstxvp 34, 8589934591(3), 0        # encoding: [0x04,0x01,0xff,0xff
+# CHECK-BE-SAME:                                            0xf8,0x63,0xff,0xff]
+# CHECK-LE: pstxvp 34, 8589934591(3), 0        # encoding: [0xff,0xff,0x01,0x04
+# CHECK-LE-SAME:                                            0xff,0xff,0x63,0xf8]
+            pstxvp 34, 8589934591(3), 0
+# CHECK-BE: lxvpx 2, 3, 4                      # encoding: [0x7c,0x43,0x22,0x9a]
+# CHECK-LE: lxvpx 2, 3, 4                      # encoding: [0x9a,0x22,0x43,0x7c]
+            lxvpx 2, 3, 4
+# CHECK-BE: stxvpx 34, 6, 4                    # encoding: [0x7c,0x66,0x23,0x9a]
+# CHECK-LE: stxvpx 34, 6, 4                    # encoding: [0x9a,0x23,0x66,0x7c]
+            stxvpx 34, 6, 4
 # CHECK-BE: paddi 1, 2, 8589934591, 0             # encoding: [0x06,0x01,0xff,0xff
 # CHECK-BE-SAME:                                               0x38,0x22,0xff,0xff]
 # CHECK-LE: paddi 1, 2, 8589934591, 0             # encoding: [0xff,0xff,0x01,0x06

diff  --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp
index 302d3e9098d4..e55cf7f64f76 100644
--- a/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -86,6 +86,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
   case MVT::v32i1:    return "MVT::v32i1";
   case MVT::v64i1:    return "MVT::v64i1";
   case MVT::v128i1:   return "MVT::v128i1";
+  case MVT::v256i1:   return "MVT::v256i1";
   case MVT::v512i1:   return "MVT::v512i1";
   case MVT::v1024i1:  return "MVT::v1024i1";
   case MVT::v1i8:     return "MVT::v1i8";


        


More information about the llvm-commits mailing list