[llvm] 1c450c3 - [PowerPC] Export 16 byte load-store instructions

Kai Luo via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 14 18:56:19 PDT 2021


Author: Kai Luo
Date: 2021-06-15T01:56:10Z
New Revision: 1c450c3d7ec01d9daaf9f2651da93b01e7790ffd

URL: https://github.com/llvm/llvm-project/commit/1c450c3d7ec01d9daaf9f2651da93b01e7790ffd
DIFF: https://github.com/llvm/llvm-project/commit/1c450c3d7ec01d9daaf9f2651da93b01e7790ffd.diff

LOG: [PowerPC] Export 16 byte load-store instructions

Export `lq`, `stq`, `lqarx` and `stqcx.` in preparation for implementing 16-byte lock free atomic operations on AIX.
Add a new register class `g8prc` for these instructions, since these instructions require even-odd register pair.

Reviewed By: nemanjai, jsji, #powerpc

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

Added: 
    llvm/test/CodeGen/PowerPC/ldst-16-byte-asm.mir
    llvm/test/CodeGen/PowerPC/ldst-16-byte.mir

Modified: 
    llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
    llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
    llvm/lib/Target/PowerPC/PPCInstr64Bit.td
    llvm/lib/Target/PowerPC/PPCInstrFormats.td
    llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
    llvm/lib/Target/PowerPC/PPCInstrInfo.h
    llvm/lib/Target/PowerPC/PPCInstrInfo.td
    llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
    llvm/lib/Target/PowerPC/PPCRegisterInfo.h
    llvm/lib/Target/PowerPC/PPCRegisterInfo.td
    llvm/lib/Target/PowerPC/PPCSchedule.td
    llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt
    llvm/test/MC/Disassembler/PowerPC/ppc64-encoding.txt
    llvm/test/MC/PowerPC/ppc64-encoding-bookII.s
    llvm/test/MC/PowerPC/ppc64-encoding.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 54e73137ebd27..04c22cbaeac3e 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -294,6 +294,11 @@ struct PPCOperand : public MCParsedAsmOperand {
     return (unsigned) Imm.Val >> 1;
   }
 
+  unsigned getG8pReg() const {
+    assert(isEvenRegNumber() && "Invalid access!");
+    return (unsigned)Imm.Val;
+  }
+
   unsigned getCCReg() const {
     assert(isCCRegNumber() && "Invalid access!");
     return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal);
@@ -432,6 +437,9 @@ struct PPCOperand : public MCParsedAsmOperand {
                                        && isUInt<5>(getExprCRVal())) ||
                                       (Kind == Immediate
                                        && isUInt<5>(getImm())); }
+
+  bool isEvenRegNumber() const { return isRegNumber() && (getImm() & 1) == 0; }
+
   bool isCRBitMask() const { return Kind == Immediate && isUInt<8>(getImm()) &&
                                     isPowerOf2_32(getImm()); }
   bool isATBitsAsHint() const { return false; }
@@ -462,6 +470,11 @@ struct PPCOperand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createReg(XRegsNoX0[getReg()]));
   }
 
+  void addRegG8pRCOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::createReg(XRegs[getG8pReg()]));
+  }
+
   void addRegGxRCOperands(MCInst &Inst, unsigned N) const {
     if (isPPC64())
       addRegG8RCOperands(Inst, N);

diff  --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
index 44f9920d04ff0..94416fc584b56 100644
--- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
+++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
@@ -160,6 +160,12 @@ static DecodeStatus DecodeG8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
   return decodeRegisterClass(Inst, RegNo, XRegs);
 }
 
+static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                             uint64_t Address,
+                                             const void *Decoder) {
+  return decodeRegisterClass(Inst, RegNo, XRegs);
+}
+
 static DecodeStatus DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo,
                                             uint64_t Address,
                                             const void *Decoder) {

diff  --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 1ef6c1bfb9d73..2ea729ffdf4f7 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -271,11 +271,22 @@ let Defs = [CR0] in {
 let mayLoad = 1, hasSideEffects = 0 in {
 def LDARX : XForm_1_memOp<31,  84, (outs g8rc:$rD), (ins memrr:$ptr),
                           "ldarx $rD, $ptr", IIC_LdStLDARX, []>;
+// TODO: Add scheduling info.
+let hasNoSchedulingInfo = 1 in
+def LQARX : XForm_1_memOp<31, 276, (outs g8prc:$RTp), (ins memrr:$ptr),
+                          "lqarx $RTp, $ptr", IIC_LdStLQARX, []>, isPPC64;
 
 // Instruction to support lock versions of atomics
 // (EH=1 - see Power ISA 2.07 Book II 4.4.2)
 def LDARXL : XForm_1<31,  84, (outs g8rc:$rD), (ins memrr:$ptr),
                      "ldarx $rD, $ptr, 1", IIC_LdStLDARX, []>, isRecordForm;
+// TODO: Add scheduling info.
+let hasNoSchedulingInfo = 1 in
+// FIXME: We have to seek a way to remove isRecordForm since
+// LQARXL is not really altering CR0.
+def LQARXL : XForm_1<31, 276, (outs g8prc:$RTp), (ins memrr:$ptr),
+                     "lqarx $RTp, $ptr, 1", IIC_LdStLQARX, []>,
+                     isPPC64, isRecordForm;
 
 let hasExtraDefRegAllocReq = 1 in
 def LDAT : X_RD5_RS5_IM5<31, 614, (outs g8rc:$rD), (ins g8rc:$rA, u5imm:$FC),
@@ -283,9 +294,15 @@ def LDAT : X_RD5_RS5_IM5<31, 614, (outs g8rc:$rD), (ins g8rc:$rA, u5imm:$FC),
            Requires<[IsISA3_0]>;
 }
 
-let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
+let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
 def STDCX : XForm_1_memOp<31, 214, (outs), (ins g8rc:$rS, memrr:$dst),
                           "stdcx. $rS, $dst", IIC_LdStSTDCX, []>, isRecordForm;
+// TODO: Add scheduling info.
+let hasNoSchedulingInfo = 1 in
+def STQCX : XForm_1_memOp<31, 182, (outs), (ins g8prc:$RSp, memrr:$dst),
+                          "stqcx. $RSp, $dst", IIC_LdStSTQCX, []>,
+                          isPPC64, isRecordForm;
+}
 
 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
 def STDAT : X_RD5_RS5_IM5<31, 742, (outs), (ins g8rc:$rS, g8rc:$rA, u5imm:$FC),
@@ -1228,6 +1245,22 @@ def LDMX : XForm_1<31, 309, (outs g8rc:$rD), (ins memrr:$src),
                    "ldmx $rD, $src", IIC_LdStLD, []>, isPPC64,
                    Requires<[IsISA3_0]>;
 }
+
+let mayLoad = 1, hasNoSchedulingInfo = 1 in {
+// Full 16-byte load.
+// Early clobber $RTp to avoid assigned to the same register as RA.
+// TODO: Add scheduling info.
+def LQ   : DQForm_RTp5_RA17_MEM<56, 0,
+                                (outs g8prc:$RTp),
+                                (ins memrix16:$src),
+                                "lq $RTp, $src", IIC_LdStLQ,
+                                []>,
+                                RegConstraint<"@earlyclobber $RTp">,
+                                isPPC64;
+def RESTORE_QUADWORD : PPCEmitTimePseudo<(outs g8prc:$RTp), (ins memrix:$src),
+                                         "#RESTORE_QUADWORD", []>;
+}
+
 }
 
 // Support for medium and large code model.
@@ -1411,6 +1444,17 @@ def STDBRX: XForm_8_memOp<31, 660, (outs), (ins g8rc:$rS, memrr:$dst),
                           "stdbrx $rS, $dst", IIC_LdStStore,
                           [(PPCstbrx i64:$rS, ForceXForm:$dst, i64)]>, isPPC64,
                           PPC970_DGroup_Cracked;
+
+let mayStore = 1, hasNoSchedulingInfo = 1 in {
+// Normal 16-byte stores.
+// TODO: Add scheduling info.
+def STQ : DSForm_1<62, 2, (outs), (ins g8prc:$RSp, memrix:$dst),
+                   "stq $RSp, $dst", IIC_LdStSTQ,
+                   []>, isPPC64;
+def SPILL_QUADWORD : PPCEmitTimePseudo<(outs), (ins g8prc:$RSp, memrix:$dst),
+                                       "#SPILL_QUADWORD", []>;
+}
+
 }
 
 // Stores with Update (pre-inc).

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index bb25e42c4648b..cab5774244016 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -422,6 +422,20 @@ class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
   let Inst{29-31} = xo;
 }
 
+class DQForm_RTp5_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> RTp;
+  bits<17> DQ_RA;
+  let Pattern = pattern;
+
+  let Inst{6-10} =  RTp{4-0};
+  let Inst{11-15} = DQ_RA{16-12};  // Register #
+  let Inst{16-27} = DQ_RA{11-0};   // Displacement.
+  let Inst{28-31} = xo;
+}
+
 // 1.7.6 X-Form
 class XForm_base_r3xo<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, 
                       InstrItinClass itin, list<dag> pattern>

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index d9ed506c8e608..625730eec8213 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -1834,6 +1834,22 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
     if (SrcPrimed && !KillSrc)
       BuildMI(MBB, I, DL, get(PPC::XXMTACC), SrcReg).addReg(SrcReg);
     return;
+  } else if (PPC::G8pRCRegClass.contains(DestReg) &&
+             PPC::G8pRCRegClass.contains(SrcReg)) {
+    // TODO: Handle G8RC to G8pRC (and vice versa) copy.
+    unsigned DestRegIdx = DestReg - PPC::G8p0;
+    MCRegister DestRegSub0 = PPC::X0 + 2 * DestRegIdx;
+    MCRegister DestRegSub1 = PPC::X0 + 2 * DestRegIdx + 1;
+    unsigned SrcRegIdx = SrcReg - PPC::G8p0;
+    MCRegister SrcRegSub0 = PPC::X0 + 2 * SrcRegIdx;
+    MCRegister SrcRegSub1 = PPC::X0 + 2 * SrcRegIdx + 1;
+    BuildMI(MBB, I, DL, get(PPC::OR8), DestRegSub0)
+        .addReg(SrcRegSub0)
+        .addReg(SrcRegSub0, getKillRegState(KillSrc));
+    BuildMI(MBB, I, DL, get(PPC::OR8), DestRegSub1)
+        .addReg(SrcRegSub1)
+        .addReg(SrcRegSub1, getKillRegState(KillSrc));
+    return;
   } else
     llvm_unreachable("Impossible reg-to-reg copy");
 
@@ -1886,6 +1902,8 @@ unsigned PPCInstrInfo::getSpillIndex(const TargetRegisterClass *RC) const {
     assert(Subtarget.pairedVectorMemops() &&
            "Register unexpected when paired memops are disabled.");
     OpcodeIndex = SOK_PairedVecSpill;
+  } else if (PPC::G8pRCRegClass.hasSubClassEq(RC)) {
+    OpcodeIndex = SOK_PairedG8Spill;
   } else {
     llvm_unreachable("Unknown regclass!");
   }

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
index cbd5e4308fc3c..404156de232f5 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -127,6 +127,7 @@ enum SpillOpcodeKey {
   SOK_AccumulatorSpill,
   SOK_UAccumulatorSpill,
   SOK_SPESpill,
+  SOK_PairedG8Spill,
   SOK_LastOpcodeSpill // This must be last on the enum.
 };
 
@@ -136,14 +137,16 @@ enum SpillOpcodeKey {
   {                                                                            \
     PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR,                    \
         PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXVD2X, PPC::LXSDX, PPC::LXSSPX,    \
-        PPC::SPILLTOVSR_LD, NoInstr, NoInstr, NoInstr, PPC::EVLDD              \
+        PPC::SPILLTOVSR_LD, NoInstr, NoInstr, NoInstr, PPC::EVLDD,             \
+        PPC::RESTORE_QUADWORD                                                  \
   }
 
 #define Pwr9LoadOpcodes                                                        \
   {                                                                            \
     PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR,                    \
         PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXV, PPC::DFLOADf64,                \
-        PPC::DFLOADf32, PPC::SPILLTOVSR_LD, NoInstr, NoInstr, NoInstr, NoInstr \
+        PPC::DFLOADf32, PPC::SPILLTOVSR_LD, NoInstr, NoInstr, NoInstr,         \
+        NoInstr, PPC::RESTORE_QUADWORD                                         \
   }
 
 #define Pwr10LoadOpcodes                                                       \
@@ -151,21 +154,23 @@ enum SpillOpcodeKey {
     PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR,                    \
         PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXV, PPC::DFLOADf64,                \
         PPC::DFLOADf32, PPC::SPILLTOVSR_LD, PPC::LXVP, PPC::RESTORE_ACC,       \
-        PPC::RESTORE_UACC, NoInstr                                             \
+        PPC::RESTORE_UACC, NoInstr, PPC::RESTORE_QUADWORD                      \
   }
 
 #define Pwr8StoreOpcodes                                                       \
   {                                                                            \
     PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, \
         PPC::STVX, PPC::STXVD2X, PPC::STXSDX, PPC::STXSSPX,                    \
-        PPC::SPILLTOVSR_ST, NoInstr, NoInstr, NoInstr, PPC::EVSTDD             \
+        PPC::SPILLTOVSR_ST, NoInstr, NoInstr, NoInstr, PPC::EVSTDD,            \
+        PPC::SPILL_QUADWORD                                                    \
   }
 
 #define Pwr9StoreOpcodes                                                       \
   {                                                                            \
     PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, \
         PPC::STVX, PPC::STXV, PPC::DFSTOREf64, PPC::DFSTOREf32,                \
-        PPC::SPILLTOVSR_ST, NoInstr, NoInstr, NoInstr, NoInstr                 \
+        PPC::SPILLTOVSR_ST, NoInstr, NoInstr, NoInstr, NoInstr,                \
+        PPC::SPILL_QUADWORD                                                    \
   }
 
 #define Pwr10StoreOpcodes                                                      \
@@ -173,7 +178,7 @@ enum SpillOpcodeKey {
     PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, \
         PPC::STVX, PPC::STXV, PPC::DFSTOREf64, PPC::DFSTOREf32,                \
         PPC::SPILLTOVSR_ST, PPC::STXVP, PPC::SPILL_ACC, PPC::SPILL_UACC,       \
-        NoInstr                                                                \
+        NoInstr, PPC::SPILL_QUADWORD                                           \
   }
 
 // Initialize arrays for load and store spill opcodes on supported subtargets.

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 1e52fa82802c9..c4bf8af943d3b 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -635,6 +635,12 @@ def PPCRegG8RCAsmOperand : AsmOperandClass {
 def g8rc : RegisterOperand<G8RC> {
   let ParserMatchClass = PPCRegG8RCAsmOperand;
 }
+def PPCRegG8pRCAsmOperand : AsmOperandClass {
+  let Name = "RegG8pRC"; let PredicateMethod = "isEvenRegNumber";
+}
+def g8prc : RegisterOperand<G8pRC> {
+  let ParserMatchClass = PPCRegG8pRCAsmOperand;
+}
 def PPCRegGPRCNoR0AsmOperand : AsmOperandClass {
   let Name = "RegGPRCNoR0"; let PredicateMethod = "isRegNumber";
 }

diff  --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 260c5f3897c01..8adef376149d3 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -1146,6 +1146,59 @@ void PPCRegisterInfo::lowerACCRestore(MachineBasicBlock::iterator II,
   MBB.erase(II);
 }
 
+/// lowerQuadwordSpilling - Generate code to spill paired general register.
+void PPCRegisterInfo::lowerQuadwordSpilling(MachineBasicBlock::iterator II,
+                                            unsigned FrameIndex) const {
+  MachineInstr &MI = *II;
+  MachineBasicBlock &MBB = *MI.getParent();
+  MachineFunction &MF = *MBB.getParent();
+  const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
+  const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
+  DebugLoc DL = MI.getDebugLoc();
+
+  Register SrcReg = MI.getOperand(0).getReg();
+  bool IsKilled = MI.getOperand(0).isKill();
+
+  Register Reg = PPC::X0 + (SrcReg - PPC::G8p0) * 2;
+  bool IsLittleEndian = Subtarget.isLittleEndian();
+
+  addFrameReference(BuildMI(MBB, II, DL, TII.get(PPC::STD))
+                        .addReg(Reg, getKillRegState(IsKilled)),
+                    FrameIndex, IsLittleEndian ? 8 : 0);
+  addFrameReference(BuildMI(MBB, II, DL, TII.get(PPC::STD))
+                        .addReg(Reg + 1, getKillRegState(IsKilled)),
+                    FrameIndex, IsLittleEndian ? 0 : 8);
+
+  // Discard the pseudo instruction.
+  MBB.erase(II);
+}
+
+/// lowerQuadwordRestore - Generate code to restore paired general register.
+void PPCRegisterInfo::lowerQuadwordRestore(MachineBasicBlock::iterator II,
+                                           unsigned FrameIndex) const {
+  MachineInstr &MI = *II;
+  MachineBasicBlock &MBB = *MI.getParent();
+  MachineFunction &MF = *MBB.getParent();
+  const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
+  const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
+  DebugLoc DL = MI.getDebugLoc();
+
+  Register DestReg = MI.getOperand(0).getReg();
+  assert(MI.definesRegister(DestReg) &&
+         "RESTORE_QUADWORD does not define its destination");
+
+  Register Reg = PPC::X0 + (DestReg - PPC::G8p0) * 2;
+  bool IsLittleEndian = Subtarget.isLittleEndian();
+
+  addFrameReference(BuildMI(MBB, II, DL, TII.get(PPC::LD), Reg), FrameIndex,
+                    IsLittleEndian ? 8 : 0);
+  addFrameReference(BuildMI(MBB, II, DL, TII.get(PPC::LD), Reg + 1), FrameIndex,
+                    IsLittleEndian ? 0 : 8);
+
+  // Discard the pseudo instruction.
+  MBB.erase(II);
+}
+
 bool PPCRegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
                                            Register Reg, int &FrameIdx) const {
   // For the nonvolatile condition registers (CR2, CR3, CR4) return true to
@@ -1182,12 +1235,14 @@ static unsigned offsetMinAlignForOpcode(unsigned OpC) {
   case PPC::LXSSP:
   case PPC::STXSD:
   case PPC::STXSSP:
+  case PPC::STQ:
     return 4;
   case PPC::EVLDD:
   case PPC::EVSTDD:
     return 8;
   case PPC::LXV:
   case PPC::STXV:
+  case PPC::LQ:
     return 16;
   }
 }
@@ -1283,6 +1338,12 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   } else if (OpC == PPC::RESTORE_ACC || OpC == PPC::RESTORE_UACC) {
     lowerACCRestore(II, FrameIndex);
     return;
+  } else if (OpC == PPC::SPILL_QUADWORD) {
+    lowerQuadwordSpilling(II, FrameIndex);
+    return;
+  } else if (OpC == PPC::RESTORE_QUADWORD) {
+    lowerQuadwordRestore(II, FrameIndex);
+    return;
   }
 
   // Replace the FrameIndex with base register with GPR1 (SP) or GPR31 (FP).

diff  --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
index dc29dd71e4a90..27fc01c163da7 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -123,6 +123,11 @@ class PPCRegisterInfo : public PPCGenRegisterInfo {
   void lowerACCRestore(MachineBasicBlock::iterator II,
                        unsigned FrameIndex) const;
 
+  void lowerQuadwordSpilling(MachineBasicBlock::iterator II,
+                             unsigned FrameIndex) const;
+  void lowerQuadwordRestore(MachineBasicBlock::iterator II,
+                            unsigned FrameIndex) const;
+
   static void emitAccCopyInfo(MachineBasicBlock &MBB, MCRegister DestReg,
                               MCRegister SrcReg);
 

diff  --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 551735c85b514..6bc8f75f38641 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -20,6 +20,8 @@ def sub_vsx0 : SubRegIndex<128>;
 def sub_vsx1 : SubRegIndex<128, 128>;
 def sub_pair0 : SubRegIndex<256>;
 def sub_pair1 : SubRegIndex<256, 256>;
+def sub_gp8_x0 : SubRegIndex<64>;
+def sub_gp8_x1 : SubRegIndex<64, 64>;
 }
 
 
@@ -119,6 +121,15 @@ class VSRPair<bits<5> num, string n, list<Register> subregs> : PPCReg<n> {
   let SubRegs = subregs;
 }
 
+// GP8Pair - Consecutive even-odd paired GP8.
+class GP8Pair<string n, bits<5> EvenIndex> : PPCReg<n> {
+  assert !eq(EvenIndex{0}, 0), "Index should be even.";
+  let HWEncoding{4-0} = EvenIndex;
+  let SubRegs = [!cast<GP8>("X"#EvenIndex), !cast<GP8>("X"#!add(EvenIndex, 1))];
+  let DwarfNumbers = [-1, -1];
+  let SubRegIndices = [sub_gp8_x0, sub_gp8_x1];
+}
+
 // General-purpose registers
 foreach Index = 0-31 in {
   def R#Index : GPR<Index, "r"#Index>, DwarfRegNum<[-2, Index]>;
@@ -185,6 +196,11 @@ let SubRegIndices = [sub_vsx0, sub_vsx1] in {
   }
 }
 
+// 16 paired even-odd consecutive GP8s.
+foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in {
+  def G8p#!srl(Index, 1) : GP8Pair<"r"#Index, Index>;
+}
+
 // The representation of r0 when treated as the constant 0.
 def ZERO  : GPR<0, "0">,    DwarfRegAlias<R0>;
 def ZERO8 : GP8<ZERO, "0">, DwarfRegAlias<X0>;
@@ -462,3 +478,18 @@ def VSRpRC :
                      VSRp27, VSRp26)> {
   let Size = 256;
 }
+
+// Make AllocationOrder as similar as G8RC's to avoid potential spilling.
+// Similarly, we have an AltOrder for 64-bit ELF ABI which r2 is allocated
+// at last.
+def G8pRC :
+  RegisterClass<"PPC", [i128], 128,
+                (add (sequence "G8p%u", 1, 5),
+                     (sequence "G8p%u", 14, 7),
+                     G8p15, G8p6, G8p0)> {
+  let AltOrders = [(add (sub G8pRC, G8p1), G8p1)];
+  let AltOrderSelect = [{
+    return MF.getSubtarget<PPCSubtarget>().is64BitELFABI();
+  }];
+  let Size = 128;
+}

diff  --git a/llvm/lib/Target/PowerPC/PPCSchedule.td b/llvm/lib/Target/PowerPC/PPCSchedule.td
index 4fa29d96ca14d..e378d57d325e5 100644
--- a/llvm/lib/Target/PowerPC/PPCSchedule.td
+++ b/llvm/lib/Target/PowerPC/PPCSchedule.td
@@ -54,6 +54,8 @@ def IIC_LdStLHA      : InstrItinClass;
 def IIC_LdStLHAU     : InstrItinClass;
 def IIC_LdStLHAUX    : InstrItinClass;
 def IIC_LdStLMW      : InstrItinClass;
+def IIC_LdStLQ       : InstrItinClass;
+def IIC_LdStLQARX    : InstrItinClass;
 def IIC_LdStLVecX    : InstrItinClass;
 def IIC_LdStLWA      : InstrItinClass;
 def IIC_LdStLWARX    : InstrItinClass;
@@ -61,6 +63,8 @@ def IIC_LdStSLBIA    : InstrItinClass;
 def IIC_LdStSLBIE    : InstrItinClass;
 def IIC_LdStSTD      : InstrItinClass;
 def IIC_LdStSTDCX    : InstrItinClass;
+def IIC_LdStSTQ      : InstrItinClass;
+def IIC_LdStSTQCX    : InstrItinClass;
 def IIC_LdStSTU      : InstrItinClass;
 def IIC_LdStSTUX     : InstrItinClass;
 def IIC_LdStSTFD     : InstrItinClass;

diff  --git a/llvm/test/CodeGen/PowerPC/ldst-16-byte-asm.mir b/llvm/test/CodeGen/PowerPC/ldst-16-byte-asm.mir
new file mode 100644
index 0000000000000..f82d794a1ede8
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/ldst-16-byte-asm.mir
@@ -0,0 +1,23 @@
+# RUN: llc -simplify-mir -verify-machineinstrs -mtriple=powerpc64-ibm-aix-xcoff \
+# RUN:   %s -o - | FileCheck %s
+
+---
+name: foo
+alignment: 8
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+  liveins: $x3, $x4, $x30, $x31
+    ; CHECK-LABEL: .foo
+    ; CHECK: lq 2, 128(4)
+    ; CHECK: lqarx 28, 30, 31
+    ; CHECK: stqcx. 28, 30, 31
+    ; CHECK: stq 2, 128(4)
+  $g8p1 = LQ 128, $x4
+  $g8p14 = LQARX $x30, $x31
+  STQCX $g8p14, $x30, $x31, implicit-def $cr0
+  STQ $g8p1, 128, $x4
+  $x3 = COPY $x31
+  BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+...
+

diff  --git a/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir b/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir
new file mode 100644
index 0000000000000..d6efa5bcd3f5a
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir
@@ -0,0 +1,221 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -simplify-mir -verify-machineinstrs -mtriple=powerpc64-ibm-aix-xcoff \
+# RUN:   -stop-after=postrapseudos %s -o - | FileCheck %s
+
+---
+name: foo
+alignment: 8
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+  liveins: $x3, $x4
+    ; CHECK-LABEL: name: foo
+    ; CHECK: liveins: $x3, $x4
+    ; CHECK: early-clobber renamable $g8p3 = LQ 128, $x4
+    ; CHECK: $x3 = OR8 $x7, $x7
+    ; CHECK: STQ killed renamable $g8p3, 160, $x3
+    ; CHECK: BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+  %0:g8prc = LQ 128, $x4
+  $x3 = COPY %0.sub_gp8_x1:g8prc
+  STQ %0, 160, $x3
+  BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+...
+
+---
+name: foobar
+alignment: 8
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+  liveins: $x3, $x4
+    ; CHECK-LABEL: name: foobar
+    ; CHECK: liveins: $x3, $x4
+    ; CHECK: renamable $g8p3 = LQARX $x3, $x4
+    ; CHECK: STQCX renamable $g8p3, $x3, $x4, implicit-def dead $cr0
+    ; CHECK: $x3 = OR8 $x7, $x7, implicit killed $g8p3
+    ; CHECK: BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+  %0:g8prc = LQARX $x3, $x4
+  STQCX %0:g8prc, $x3, $x4, implicit-def $cr0
+  $x3 = COPY %0.sub_gp8_x1:g8prc
+  BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+...
+
+---
+name: bar
+alignment: 8
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+  liveins: $x3, $x4
+    ; CHECK-LABEL: name: bar
+    ; CHECK: liveins: $x3, $x4
+    ; CHECK: early-clobber renamable $g8p2 = LQ 128, renamable $x3
+    ; CHECK: STQ renamable $g8p2, 160, $x3
+    ; CHECK: $x3 = OR8 $x4, $x4, implicit killed $g8p2
+    ; CHECK: BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+  %0:g8rc_nox0 = COPY $x3
+  %1:g8prc = LQ 128, %0
+  STQ %1, 160, $x3
+  $x3 = COPY %1.sub_gp8_x0:g8prc
+  BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+...
+
+# `spill_g8prc`'s code contains undefined behaviors. This code is only to
+# demonstrate correctness of spiller.
+---
+name: spill_g8prc
+alignment: 8
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+  liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12
+    ; CHECK-LABEL: name: spill_g8prc
+    ; CHECK: liveins: $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x14, $x15, $x16, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $x29, $x30, $x31
+    ; CHECK: STD killed $x14, -144, $x1 :: (store 8 into %fixed-stack.17, align 16)
+    ; CHECK: STD killed $x15, -136, $x1 :: (store 8 into %fixed-stack.16)
+    ; CHECK: STD killed $x16, -128, $x1 :: (store 8 into %fixed-stack.15, align 16)
+    ; CHECK: STD killed $x17, -120, $x1 :: (store 8 into %fixed-stack.14)
+    ; CHECK: STD killed $x18, -112, $x1 :: (store 8 into %fixed-stack.13, align 16)
+    ; CHECK: STD killed $x19, -104, $x1 :: (store 8 into %fixed-stack.12)
+    ; CHECK: STD killed $x20, -96, $x1 :: (store 8 into %fixed-stack.11, align 16)
+    ; CHECK: STD killed $x21, -88, $x1 :: (store 8 into %fixed-stack.10)
+    ; CHECK: STD killed $x22, -80, $x1 :: (store 8 into %fixed-stack.9, align 16)
+    ; CHECK: STD killed $x23, -72, $x1 :: (store 8 into %fixed-stack.8)
+    ; CHECK: STD killed $x24, -64, $x1 :: (store 8 into %fixed-stack.7, align 16)
+    ; CHECK: STD killed $x25, -56, $x1 :: (store 8 into %fixed-stack.6)
+    ; CHECK: STD killed $x26, -48, $x1 :: (store 8 into %fixed-stack.5, align 16)
+    ; CHECK: STD killed $x27, -40, $x1 :: (store 8 into %fixed-stack.4)
+    ; CHECK: STD killed $x28, -32, $x1 :: (store 8 into %fixed-stack.3, align 16)
+    ; CHECK: STD killed $x29, -24, $x1 :: (store 8 into %fixed-stack.2)
+    ; CHECK: STD killed $x30, -16, $x1 :: (store 8 into %fixed-stack.1, align 16)
+    ; CHECK: STD killed $x31, -8, $x1 :: (store 8 into %fixed-stack.0)
+    ; CHECK: $x7 = OR8 $x3, $x3
+    ; CHECK: renamable $g8p4 = LQARX $x5, $x6
+    ; CHECK: STD killed $x8, -160, $x1
+    ; CHECK: STD killed $x9, -152, $x1
+    ; CHECK: renamable $g8p5 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4
+    ; CHECK: STD killed $x8, -176, $x1
+    ; CHECK: STD killed $x9, -168, $x1
+    ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4
+    ; CHECK: STD killed $x8, -192, $x1
+    ; CHECK: STD killed $x9, -184, $x1
+    ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4
+    ; CHECK: STD killed $x8, -208, $x1
+    ; CHECK: STD killed $x9, -200, $x1
+    ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4
+    ; CHECK: STD killed $x8, -224, $x1
+    ; CHECK: STD killed $x9, -216, $x1
+    ; CHECK: renamable $g8p10 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p9 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p8 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p7 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p15 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p11 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p12 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p13 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p14 = LQARX $x3, renamable $x4
+    ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4
+    ; CHECK: $x3 = OR8 $x11, $x11
+    ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p14, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p13, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p12, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p11, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p15, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p7, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p8, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p9, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p10, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: $x8 = LD -224, $x1
+    ; CHECK: $x9 = LD -216, $x1
+    ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: $x8 = LD -208, $x1
+    ; CHECK: $x9 = LD -200, $x1
+    ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: $x8 = LD -192, $x1
+    ; CHECK: $x9 = LD -184, $x1
+    ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: $x8 = LD -176, $x1
+    ; CHECK: $x9 = LD -168, $x1
+    ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0
+    ; CHECK: STQCX killed renamable $g8p5, killed renamable $x7, killed renamable $x4, implicit-def dead $cr0
+    ; CHECK: $x8 = LD -160, $x1
+    ; CHECK: $x9 = LD -152, $x1
+    ; CHECK: STQCX killed renamable $g8p4, $x5, $x6, implicit-def dead $cr0
+    ; CHECK: $x31 = LD -8, $x1 :: (load 8 from %fixed-stack.0)
+    ; CHECK: $x30 = LD -16, $x1 :: (load 8 from %fixed-stack.1, align 16)
+    ; CHECK: $x29 = LD -24, $x1 :: (load 8 from %fixed-stack.2)
+    ; CHECK: $x28 = LD -32, $x1 :: (load 8 from %fixed-stack.3, align 16)
+    ; CHECK: $x27 = LD -40, $x1 :: (load 8 from %fixed-stack.4)
+    ; CHECK: $x26 = LD -48, $x1 :: (load 8 from %fixed-stack.5, align 16)
+    ; CHECK: $x25 = LD -56, $x1 :: (load 8 from %fixed-stack.6)
+    ; CHECK: $x24 = LD -64, $x1 :: (load 8 from %fixed-stack.7, align 16)
+    ; CHECK: $x23 = LD -72, $x1 :: (load 8 from %fixed-stack.8)
+    ; CHECK: $x22 = LD -80, $x1 :: (load 8 from %fixed-stack.9, align 16)
+    ; CHECK: $x21 = LD -88, $x1 :: (load 8 from %fixed-stack.10)
+    ; CHECK: $x20 = LD -96, $x1 :: (load 8 from %fixed-stack.11, align 16)
+    ; CHECK: $x19 = LD -104, $x1 :: (load 8 from %fixed-stack.12)
+    ; CHECK: $x18 = LD -112, $x1 :: (load 8 from %fixed-stack.13, align 16)
+    ; CHECK: $x17 = LD -120, $x1 :: (load 8 from %fixed-stack.14)
+    ; CHECK: $x16 = LD -128, $x1 :: (load 8 from %fixed-stack.15, align 16)
+    ; CHECK: $x15 = LD -136, $x1 :: (load 8 from %fixed-stack.16)
+    ; CHECK: $x14 = LD -144, $x1 :: (load 8 from %fixed-stack.17, align 16)
+    ; CHECK: BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+  %addr0:g8rc_nox0 = COPY $x3
+  %addr1:g8rc = COPY $x4
+  %0:g8prc = LQARX $x5, $x6
+  %1:g8prc = LQARX %addr0, %addr1
+  %2:g8prc = LQARX %addr0, %addr1
+  %3:g8prc = LQARX %addr0, %addr1
+  %4:g8prc = LQARX %addr0, %addr1
+  %5:g8prc = LQARX %addr0, %addr1
+  %6:g8prc = LQARX %addr0, %addr1
+  %7:g8prc = LQARX %addr0, %addr1
+  %8:g8prc = LQARX %addr0, %addr1
+  %9:g8prc = LQARX %addr0, %addr1
+  %10:g8prc = LQARX %addr0, %addr1
+  %11:g8prc = LQARX %addr0, %addr1
+  %12:g8prc = LQARX %addr0, %addr1
+  %13:g8prc = LQARX %addr0, %addr1
+  %14:g8prc = LQARX %addr0, %addr1
+  %15:g8prc = LQARX %addr0, %addr1
+  STQCX %15:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %14:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %13:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %12:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %11:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %10:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %9:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %8:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %7:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %6:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %5:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %4:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %3:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %2:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %1:g8prc, %addr0, %addr1, implicit-def $cr0
+  STQCX %0:g8prc, $x5, $x6, implicit-def $cr0
+  $x3 = COPY %1.sub_gp8_x1:g8prc
+  BLR8 implicit $lr8, implicit undef $rm, implicit $x3
+...
+
+---
+name: copy_g8prc
+alignment: 8
+tracksRegLiveness: true
+body: |
+  bb.0.entry:
+  liveins: $g8p8
+    ; CHECK-LABEL: name: copy_g8prc
+    ; CHECK: liveins: $g8p8
+    ; CHECK: $x4 = OR8 $x16, $x16
+    ; CHECK: $x5 = OR8 $x17, $x17
+    ; CHECK: $x3 = OR8 $x5, $x5
+    ; CHECK: $x4 = KILL renamable $x4, implicit killed $g8p2
+    ; CHECK: BLR8 implicit $lr8, implicit undef $rm, implicit killed $x3, implicit $x4
+  %0:g8prc = COPY $g8p8
+  $x3 = COPY %0.sub_gp8_x1:g8prc
+  $x4 = COPY %0.sub_gp8_x0:g8prc
+  BLR8 implicit $lr8, implicit undef $rm, implicit $x3, implicit $x4
+...

diff  --git a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt
index 08ac70e41c8d8..52069def36da1 100644
--- a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt
+++ b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-bookII.txt
@@ -33,6 +33,12 @@
 # CHECK: stdcx. 2, 3, 4                  
 0x7c 0x43 0x21 0xad
 
+# CHECK: stqcx. 2, 3, 4
+0x7c 0x43 0x21 0x6d
+
+# CHECK: stqcx. 28, 30, 31
+0x7f 0x9e 0xf9 0x6d
+
 # CHECK: stwat 2, 3, 28
 0x7c 0x43 0xe5 0x8c
 
@@ -72,6 +78,12 @@
 # CHECK: ldarx 2, 3, 4
 0x7c 0x43 0x20 0xa8
 
+# CHECK: lqarx 2, 3, 4
+0x7c 0x43 0x22 0x28
+
+# CHECK: lqarx 28, 30, 31
+0x7f 0x9e 0xfa 0x28
+
 # CHECK: lbarx 2, 3, 4, 1
 0x7c 0x43 0x20 0x69
 
@@ -84,6 +96,12 @@
 # CHECK: ldarx 2, 3, 4, 1
 0x7c 0x43 0x20 0xa9
 
+# CHECK: lqarx 2, 3, 4, 1
+0x7c 0x43 0x22 0x29
+
+# CHECK: lqarx 28, 30, 31, 1
+0x7f 0x9e 0xfa 0x29
+
 # CHECK: lwat 2, 3, 28
 0x7c 0x43 0xe4 0x8c
 

diff  --git a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding.txt b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding.txt
index e145b2c03db2b..7242f05e0febf 100644
--- a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding.txt
+++ b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding.txt
@@ -154,6 +154,12 @@
 # CHECK: ldmx 2, 3, 4
 0x7c 0x43 0x22 0x6a
 
+# CHECK: lq 2, 128(4)
+0xe0 0x44 0x00 0x80
+
+# CHECK: lq 28, 128(30)
+0xe3 0x9e 0x00 0x80
+
 # CHECK: stb 2, 128(4)                   
 0x98 0x44 0x00 0x80
 
@@ -202,6 +208,12 @@
 # CHECK: stdux 2, 3, 4                   
 0x7c 0x43 0x21 0x6a
 
+# CHECK: stq 2, 128(4)
+0xf8 0x44 0x00 0x82
+
+# CHECK: stq 28, 128(30)
+0xfb 0x9e 0x00 0x82
+
 # CHECK: lhbrx 2, 3, 4                   
 0x7c 0x43 0x26 0x2c
 

diff  --git a/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s b/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s
index 70b635ed2c2b5..447542fba672e 100644
--- a/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s
+++ b/llvm/test/MC/PowerPC/ppc64-encoding-bookII.s
@@ -83,6 +83,14 @@
 # CHECK-LE: stdcx. 2, 3, 4                  # encoding: [0xad,0x21,0x43,0x7c]
             stdcx. 2, 3, 4
 
+# CHECK-BE: stqcx. 2, 3, 4                  # encoding: [0x7c,0x43,0x21,0x6d]
+# CHECK-LE: stqcx. 2, 3, 4                  # encoding: [0x6d,0x21,0x43,0x7c]
+            stqcx. 2, 3, 4
+
+# CHECK-BE: stqcx. 28, 30, 31               # encoding: [0x7f,0x9e,0xf9,0x6d]
+# CHECK-LE: stqcx. 28, 30, 31               # encoding: [0x6d,0xf9,0x9e,0x7f]
+            stqcx. 28, 30, 31
+
 # CHECK-BE: stwat 2, 3, 28                  # encoding: [0x7c,0x43,0xe5,0x8c]
 # CHECK-LE: stwat 2, 3, 28                  # encoding: [0x8c,0xe5,0x43,0x7c]
             stwat 2, 3, 28
@@ -134,6 +142,14 @@
 # CHECK-LE: ldarx 2, 3, 4                   # encoding: [0xa8,0x20,0x43,0x7c]
             ldarx 2, 3, 4
 
+# CHECK-BE: lqarx 2, 3, 4                   # encoding: [0x7c,0x43,0x22,0x28]
+# CHECK-LE: lqarx 2, 3, 4                   # encoding: [0x28,0x22,0x43,0x7c]
+            lqarx 2, 3, 4
+
+# CHECK-BE: lqarx 28, 30, 31                # encoding: [0x7f,0x9e,0xfa,0x28]
+# CHECK-LE: lqarx 28, 30, 31                # encoding: [0x28,0xfa,0x9e,0x7f]
+            lqarx 28, 30, 31
+
 # CHECK-BE: lbarx 2, 3, 4, 1                # encoding: [0x7c,0x43,0x20,0x69]
 # CHECK-LE: lbarx 2, 3, 4, 1                # encoding: [0x69,0x20,0x43,0x7c]
             lbarx 2, 3, 4, 1
@@ -150,6 +166,14 @@
 # CHECK-LE: ldarx 2, 3, 4, 1                # encoding: [0xa9,0x20,0x43,0x7c]
             ldarx 2, 3, 4, 1
 
+# CHECK-BE: lqarx 2, 3, 4, 1                # encoding: [0x7c,0x43,0x22,0x29]
+# CHECK-LE: lqarx 2, 3, 4, 1                # encoding: [0x29,0x22,0x43,0x7c]
+            lqarx 2, 3, 4, 1
+
+# CHECK-BE: lqarx 28, 30, 31, 1             # encoding: [0x7f,0x9e,0xfa,0x29]
+# CHECK-LE: lqarx 28, 30, 31, 1             # encoding: [0x29,0xfa,0x9e,0x7f]
+            lqarx 28, 30, 31, 1
+
 # CHECK-BE: lwat 2, 3, 28                   # encoding: [0x7c,0x43,0xe4,0x8c]
 # CHECK-LE: lwat 2, 3, 28                   # encoding: [0x8c,0xe4,0x43,0x7c]
             lwat 2, 3, 28

diff  --git a/llvm/test/MC/PowerPC/ppc64-encoding.s b/llvm/test/MC/PowerPC/ppc64-encoding.s
index 7dd1981fe2176..48972c1787adb 100644
--- a/llvm/test/MC/PowerPC/ppc64-encoding.s
+++ b/llvm/test/MC/PowerPC/ppc64-encoding.s
@@ -241,6 +241,12 @@
 # CHECK-BE: ldmx 2, 3, 4                    # encoding: [0x7c,0x43,0x22,0x6a]
 # CHECK-LE: ldmx 2, 3, 4                    # encoding: [0x6a,0x22,0x43,0x7c]
             ldmx 2, 3, 4
+# CHECK-BE: lq 2, 128(4)                    # encoding: [0xe0,0x44,0x00,0x80]
+# CHECK-LE: lq 2, 128(4)                    # encoding: [0x80,0x00,0x44,0xe0]
+            lq 2, 128(4)
+# CHECK-BE: lq 28, 128(30)                  # encoding: [0xe3,0x9e,0x00,0x80]
+# CHECK-LE: lq 28, 128(30)                  # encoding: [0x80,0x00,0x9e,0xe3]
+            lq 28, 128(30)
 
 # Fixed-point store instructions
 
@@ -292,6 +298,12 @@
 # CHECK-BE: stdux 2, 3, 4                   # encoding: [0x7c,0x43,0x21,0x6a]
 # CHECK-LE: stdux 2, 3, 4                   # encoding: [0x6a,0x21,0x43,0x7c]
             stdux 2, 3, 4
+# CHECK-BE: stq 2, 128(4)                   # encoding: [0xf8,0x44,0x00,0x82]
+# CHECK-LE: stq 2, 128(4)                   # encoding: [0x82,0x00,0x44,0xf8]
+            stq 2, 128(4)
+# CHECK-BE: stq 28, 128(30)                 # encoding: [0xfb,0x9e,0x00,0x82]
+# CHECK-LE: stq 28, 128(30)                 # encoding: [0x82,0x00,0x9e,0xfb]
+            stq 28, 128(30)
 
 # Fixed-point load and store with byte reversal instructions
 


        


More information about the llvm-commits mailing list