diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -294,6 +294,16 @@ return (unsigned) Imm.Val >> 1; } + unsigned getG8pEvenReg() const { + assert(isG8pEvenRegNumber() && "Invalid access!"); + return (unsigned)Imm.Val >> 1; + } + + unsigned getG8pReg() const { + assert(isG8pEvenRegNumber() && "Invalid access!"); + return (unsigned)Imm.Val; + } + unsigned getCCReg() const { assert(isCCRegNumber() && "Invalid access!"); return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); @@ -432,6 +442,10 @@ && isUInt<5>(getExprCRVal())) || (Kind == Immediate && isUInt<5>(getImm())); } + bool isG8pEvenRegNumber() const { + return Kind == Immediate && isUInt<4>(getImm()) && ((getImm() & 1) == 0); + } + bool isCRBitMask() const { return Kind == Immediate && isUInt<8>(getImm()) && isPowerOf2_32(getImm()); } bool isATBitsAsHint() const { return false; } @@ -462,6 +476,11 @@ Inst.addOperand(MCOperand::createReg(XRegsNoX0[getReg()])); } + void addRegG8pRCOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(G8pRegs[getG8pEvenReg()])); + } + 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 --- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -160,6 +160,12 @@ return decodeRegisterClass(Inst, RegNo, XRegs); } +static DecodeStatus DecodeG8pRCRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, G8pRegs); +} + static DecodeStatus DecodeG8RC_NOX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -129,6 +129,12 @@ X##0, X##1, X##2, X##3, X##4, X##5, X##6, X##7 \ } +#define PPC_REGS0_15(X) \ + { \ + X##0, X##1, X##2, X##3, X##4, X##5, X##6, X##7, X##8, X##9, X##10, X##11, \ + X##12, X##13, X##14, X##15 \ + } + #define PPC_REGS0_31(X) \ { \ X##0, X##1, X##2, X##3, X##4, X##5, X##6, X##7, X##8, X##9, X##10, X##11, \ @@ -160,6 +166,7 @@ #define DEFINE_PPC_REGCLASSES \ static const MCPhysReg RRegs[32] = PPC_REGS0_31(PPC::R); \ static const MCPhysReg XRegs[32] = PPC_REGS0_31(PPC::X); \ + static const MCPhysReg G8pRegs[16] = PPC_REGS0_15(PPC::G8p); \ 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); \ diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -271,6 +271,10 @@ 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, []>; // Instruction to support lock versions of atomics // (EH=1 - see Power ISA 2.07 Book II 4.4.2) @@ -283,9 +287,14 @@ 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, []>, 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 +1237,13 @@ "ldmx $rD, $src", IIC_LdStLD, []>, isPPC64, Requires<[IsISA3_0]>; } + +// Full 16-byte load. +// TODO: Add scheduling info. +let mayLoad = 1, hasNoSchedulingInfo = 1 in +def LQ : DQForm_RTp5_RA17_MEM<56, 0, (outs g8prc:$RTp), (ins memrix16:$src), + "lq $RTp, $src", IIC_LdStLQ, + [(set i128:$RTp, (load DQForm:$src))]>, isPPC64; } // Support for medium and large code model. @@ -1411,6 +1427,12 @@ "stdbrx $rS, $dst", IIC_LdStStore, [(PPCstbrx i64:$rS, ForceXForm:$dst, i64)]>, isPPC64, PPC970_DGroup_Cracked; +// Normal 16-byte stores. +// TODO: Add scheduling info. +let mayStore = 1, hasNoSchedulingInfo = 1 in +def STQ : DSForm_1<62, 2, (outs), (ins g8prc:$RSp, memrix:$dst), + "stq $RSp, $dst", IIC_LdStSTQ, + [(store i128:$RSp, DSForm:$dst)]>, isPPC64; } // Stores with Update (pre-inc). diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td --- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td +++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td @@ -422,6 +422,19 @@ let Inst{29-31} = xo; } +class DQForm_RTp5_RA17_MEM opcode, bits<4> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list pattern> + : I { + 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 opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list pattern> diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h @@ -127,6 +127,7 @@ SOK_AccumulatorSpill, SOK_UAccumulatorSpill, SOK_SPESpill, + SOK_PairedG8Spill, SOK_LastOpcodeSpill // This must be last on the enum. }; @@ -136,14 +137,15 @@ { \ 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::LQ \ } #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::LQ \ } #define Pwr10LoadOpcodes \ @@ -151,21 +153,21 @@ 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::LQ \ } #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::STQ \ } #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::STQ \ } #define Pwr10StoreOpcodes \ @@ -173,7 +175,7 @@ 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::STQ \ } // Initialize arrays for load and store spill opcodes on supported subtargets. diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1834,6 +1834,22 @@ 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 @@ 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.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -635,6 +635,12 @@ def g8rc : RegisterOperand { let ParserMatchClass = PPCRegG8RCAsmOperand; } +def PPCRegG8pRCAsmOperand : AsmOperandClass { + let Name = "RegG8pRC"; let PredicateMethod = "isG8pEvenRegNumber"; +} +def g8prc : RegisterOperand { + 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 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -114,6 +114,10 @@ ImmToIdxMap[PPC::STW8] = PPC::STWX8; ImmToIdxMap[PPC::STDU] = PPC::STDUX; ImmToIdxMap[PPC::ADDI8] = PPC::ADD8; + // Quadword load and store. + ImmToIdxMap[PPC::LQ] = PPC::LQ; + ImmToIdxMap[PPC::STQ] = PPC::STQ; + // VSX ImmToIdxMap[PPC::DFLOADf32] = PPC::LXSSPX; ImmToIdxMap[PPC::DFLOADf64] = PPC::LXSDX; @@ -1174,6 +1178,8 @@ return 8; case PPC::LXV: case PPC::STXV: + case PPC::STQ: + case PPC::LQ: return 16; } } diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td @@ -20,6 +20,8 @@ def sub_vsx1 : SubRegIndex<128, 128>; def sub_pair0 : SubRegIndex<256>; def sub_pair1 : SubRegIndex<256, 256>; +def sub_gp8_pair0 : SubRegIndex<64>; +def sub_gp8_pair1 : SubRegIndex<64, 64>; } @@ -119,6 +121,12 @@ let SubRegs = subregs; } +// GP8Pair - One of the 16 paired even-odd consecutinve GP8s. +class GP8Pair num, string n, list subregs> : PPCReg { + let HWEncoding{3-0} = num; + let SubRegs = subregs; +} + // General-purpose registers foreach Index = 0-31 in { def R#Index : GPR, DwarfRegNum<[-2, Index]>; @@ -185,6 +193,15 @@ } } +let SubRegIndices = [sub_gp8_pair0, sub_gp8_pair1] in { + 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("X"#Index), !cast("X"#!add(Index, 1))]>, + DwarfRegNum<[Index, -2]>; + } +} + // The representation of r0 when treated as the constant 0. def ZERO : GPR<0, "0">, DwarfRegAlias; def ZERO8 : GP8, DwarfRegAlias; @@ -462,3 +479,15 @@ VSRp27, VSRp26)> { let Size = 256; } + +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().is64BitELFABI(); + }]; + let Size = 128; +} diff --git a/llvm/lib/Target/PowerPC/PPCSchedule.td b/llvm/lib/Target/PowerPC/PPCSchedule.td --- a/llvm/lib/Target/PowerPC/PPCSchedule.td +++ b/llvm/lib/Target/PowerPC/PPCSchedule.td @@ -43,6 +43,8 @@ def IIC_LdStStore : InstrItinClass; def IIC_LdStDSS : InstrItinClass; def IIC_LdStICBI : InstrItinClass; +def IIC_LdStLQ : InstrItinClass; +def IIC_LdStLQARX : InstrItinClass; def IIC_LdStLD : InstrItinClass; def IIC_LdStLDU : InstrItinClass; def IIC_LdStLDUX : InstrItinClass; @@ -59,6 +61,8 @@ def IIC_LdStLWARX : InstrItinClass; def IIC_LdStSLBIA : InstrItinClass; def IIC_LdStSLBIE : InstrItinClass; +def IIC_LdStSTQ : InstrItinClass; +def IIC_LdStSTQCX : InstrItinClass; def IIC_LdStSTD : InstrItinClass; def IIC_LdStSTDCX : InstrItinClass; def IIC_LdStSTU : InstrItinClass; diff --git a/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir b/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir @@ -0,0 +1,189 @@ +# 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: 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_pair1: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: renamable $g8p2 = LQ 128, $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:g8prc = LQ 128, $x3 + STQ %0:g8prc, 160, $x3 + $x3 = COPY %0.sub_gp8_pair0:g8prc + BLR8 implicit $lr8, implicit undef $rm, implicit $x3 +... + +--- +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: STQ killed renamable $g8p4, -160, $x1 :: (store 16 into %stack.0) + ; CHECK: renamable $g8p5 = LQARX $x3, renamable $x4 + ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4 + ; CHECK: STQ killed renamable $g8p4, -176, $x1 :: (store 16 into %stack.1) + ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4 + ; CHECK: STQ killed renamable $g8p4, -192, $x1 :: (store 16 into %stack.2) + ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4 + ; CHECK: STQ killed renamable $g8p4, -208, $x1 :: (store 16 into %stack.3) + ; CHECK: renamable $g8p4 = LQARX $x3, renamable $x4 + ; CHECK: STQ killed renamable $g8p4, -224, $x1 :: (store 16 into %stack.4) + ; 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: renamable $g8p4 = LQ -224, $x1 :: (load 16 from %stack.4) + ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0 + ; CHECK: renamable $g8p4 = LQ -208, $x1 :: (load 16 from %stack.3) + ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0 + ; CHECK: renamable $g8p4 = LQ -192, $x1 :: (load 16 from %stack.2) + ; CHECK: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0 + ; CHECK: renamable $g8p4 = LQ -176, $x1 :: (load 16 from %stack.1) + ; 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: renamable $g8p4 = LQ -160, $x1 :: (load 16 from %stack.0) + ; 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_pair1: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_pair1:g8prc + $x4 = COPY %0.sub_gp8_pair0:g8prc + BLR8 implicit $lr8, implicit undef $rm, implicit $x3, implicit $x4 +...