From: Baptiste Saleil Date: Mon, 21 Sep 2020 15:23:51 +0000 (-0500) Subject: [PowerPC] Add vector pair load/store instructions and vector pair register class X-Git-Tag: llvmorg-13-init~11436 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1372e23c7d4b25fd23689842246e66f70c949b46;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index ef19476..4a35a65 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -290,6 +290,11 @@ public: 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 @@ public: (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 @@ public: 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 362ddf7..ddb3727 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 325ede0..f7591d2 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 23b641f..00fd756 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 opcode, dag OOL, dag IOL, isPCRel; } +def PPCRegVSRpRCAsmOperand : AsmOperandClass { + let Name = "RegVSRpRC"; let PredicateMethod = "isVSRpEvenRegNumber"; +} + +def vsrprc : RegisterOperand { + let ParserMatchClass = PPCRegVSRpRCAsmOperand; +} + +class DQForm_XTp5_RA17_MEM opcode, bits<4> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list pattern> + : I { + 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 opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list pattern> + : I, 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 opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list 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 pref, bits<6> opcode, dag OOL, + dag IOL, dag PCRel_IOL, + string asmstr, InstrItinClass itin> { + def NAME : 8LS_DForm_R_XTp5_SI34_MEM; + def pc : 8LS_DForm_R_XTp5_SI34_MEM, + 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 a931967..50b2489 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -154,8 +154,11 @@ public: 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 e07b960..3a5df25 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 num, string n> : PPCReg { let HWEncoding{4-0} = num; } +// VSR Pairs - One of the 32 paired even-odd consecutive VSRs. +class VSRPair num, string n, list subregs> : PPCReg { + let HWEncoding{4-0} = num; + let SubRegs = subregs; +} + // General-purpose registers foreach Index = 0-31 in { def R#Index : GPR, DwarfRegNum<[-2, Index]>; @@ -143,6 +151,23 @@ foreach Index = 32-63 in { def VSX#Index : VSXReg; } +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("VSL"#Index), !cast("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("V"#Index), !cast("V"#!add(Index, 1))]>, + DwarfRegNum<[0, 0]>; + } +} + // The representation of r0 when treated as the constant 0. def ZERO : GPR<0, "0">, DwarfRegAlias; def ZERO8 : GP8, DwarfRegAlias; @@ -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 a9c70b7..18437d8 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 08cdcc7..7d1b1dc6 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 302d3e9..e55cf7f 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";