diff options
-rw-r--r-- | lib/Target/ARM64/ARM64AsmPrinter.cpp | 93 | ||||
-rw-r--r-- | lib/Target/ARM64/ARM64FrameLowering.cpp | 32 | ||||
-rw-r--r-- | lib/Target/ARM64/ARM64ISelDAGToDAG.cpp | 48 | ||||
-rw-r--r-- | lib/Target/ARM64/ARM64InstrFormats.td | 113 | ||||
-rw-r--r-- | lib/Target/ARM64/ARM64InstrInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM64/ARM64InstrInfo.td | 162 | ||||
-rw-r--r-- | lib/Target/ARM64/ARM64LoadStoreOptimizer.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp | 40 | ||||
-rw-r--r-- | lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp | 85 |
9 files changed, 241 insertions, 336 deletions
diff --git a/lib/Target/ARM64/ARM64AsmPrinter.cpp b/lib/Target/ARM64/ARM64AsmPrinter.cpp index 5531101fe2..78f9ed12f5 100644 --- a/lib/Target/ARM64/ARM64AsmPrinter.cpp +++ b/lib/Target/ARM64/ARM64AsmPrinter.cpp @@ -423,45 +423,6 @@ void ARM64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, // instructions) auto-generated. #include "ARM64GenMCPseudoLowering.inc" -static unsigned getRealIndexedOpcode(unsigned Opc) { - switch (Opc) { - case ARM64::LDRXpre_isel: return ARM64::LDRXpre; - case ARM64::LDRWpre_isel: return ARM64::LDRWpre; - case ARM64::LDRQpre_isel: return ARM64::LDRQpre; - case ARM64::LDRDpre_isel: return ARM64::LDRDpre; - case ARM64::LDRSpre_isel: return ARM64::LDRSpre; - case ARM64::LDRBBpre_isel: return ARM64::LDRBBpre; - case ARM64::LDRHHpre_isel: return ARM64::LDRHHpre; - case ARM64::LDRSBWpre_isel: return ARM64::LDRSBWpre; - case ARM64::LDRSBXpre_isel: return ARM64::LDRSBXpre; - case ARM64::LDRSHWpre_isel: return ARM64::LDRSHWpre; - case ARM64::LDRSHXpre_isel: return ARM64::LDRSHXpre; - case ARM64::LDRSWpre_isel: return ARM64::LDRSWpre; - - case ARM64::LDRQpost_isel: return ARM64::LDRQpost; - case ARM64::LDRDpost_isel: return ARM64::LDRDpost; - case ARM64::LDRSpost_isel: return ARM64::LDRSpost; - case ARM64::LDRXpost_isel: return ARM64::LDRXpost; - case ARM64::LDRWpost_isel: return ARM64::LDRWpost; - case ARM64::LDRHHpost_isel: return ARM64::LDRHHpost; - case ARM64::LDRBBpost_isel: return ARM64::LDRBBpost; - case ARM64::LDRSWpost_isel: return ARM64::LDRSWpost; - case ARM64::LDRSHWpost_isel: return ARM64::LDRSHWpost; - case ARM64::LDRSHXpost_isel: return ARM64::LDRSHXpost; - case ARM64::LDRSBWpost_isel: return ARM64::LDRSBWpost; - case ARM64::LDRSBXpost_isel: return ARM64::LDRSBXpost; - - case ARM64::STRXpre_isel: return ARM64::STRXpre; - case ARM64::STRWpre_isel: return ARM64::STRWpre; - case ARM64::STRHHpre_isel: return ARM64::STRHHpre; - case ARM64::STRBBpre_isel: return ARM64::STRBBpre; - case ARM64::STRQpre_isel: return ARM64::STRQpre; - case ARM64::STRDpre_isel: return ARM64::STRDpre; - case ARM64::STRSpre_isel: return ARM64::STRSpre; - } - llvm_unreachable("Unexpected pre-indexed opcode!"); -} - void ARM64AsmPrinter::EmitInstruction(const MachineInstr *MI) { // Do any auto-generated pseudo lowerings. if (emitPseudoExpansionLowering(OutStreamer, MI)) @@ -488,60 +449,6 @@ void ARM64AsmPrinter::EmitInstruction(const MachineInstr *MI) { } return; } - // Indexed loads and stores use a pseudo to handle complex operand - // tricks and writeback to the base register. We strip off the writeback - // operand and switch the opcode here. Post-indexed stores were handled by the - // tablegen'erated pseudos above. (The complex operand <--> simple - // operand isel is beyond tablegen's ability, so we do these manually). - case ARM64::LDRHHpre_isel: - case ARM64::LDRBBpre_isel: - case ARM64::LDRXpre_isel: - case ARM64::LDRWpre_isel: - case ARM64::LDRQpre_isel: - case ARM64::LDRDpre_isel: - case ARM64::LDRSpre_isel: - case ARM64::LDRSBWpre_isel: - case ARM64::LDRSBXpre_isel: - case ARM64::LDRSHWpre_isel: - case ARM64::LDRSHXpre_isel: - case ARM64::LDRSWpre_isel: - case ARM64::LDRQpost_isel: - case ARM64::LDRDpost_isel: - case ARM64::LDRSpost_isel: - case ARM64::LDRXpost_isel: - case ARM64::LDRWpost_isel: - case ARM64::LDRHHpost_isel: - case ARM64::LDRBBpost_isel: - case ARM64::LDRSWpost_isel: - case ARM64::LDRSHWpost_isel: - case ARM64::LDRSHXpost_isel: - case ARM64::LDRSBWpost_isel: - case ARM64::LDRSBXpost_isel: { - MCInst TmpInst; - // For loads, the writeback operand to be skipped is the second. - TmpInst.setOpcode(getRealIndexedOpcode(MI->getOpcode())); - TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); - TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(2).getReg())); - TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm())); - EmitToStreamer(OutStreamer, TmpInst); - return; - } - case ARM64::STRXpre_isel: - case ARM64::STRWpre_isel: - case ARM64::STRHHpre_isel: - case ARM64::STRBBpre_isel: - case ARM64::STRQpre_isel: - case ARM64::STRDpre_isel: - case ARM64::STRSpre_isel: { - MCInst TmpInst; - // For loads, the writeback operand to be skipped is the first. - TmpInst.setOpcode(getRealIndexedOpcode(MI->getOpcode())); - TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); - TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(2).getReg())); - TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm())); - EmitToStreamer(OutStreamer, TmpInst); - return; - } // Tail calls use pseudo instructions so they have the proper code-gen // attributes (isCall, isReturn, etc.). We lower them to the real diff --git a/lib/Target/ARM64/ARM64FrameLowering.cpp b/lib/Target/ARM64/ARM64FrameLowering.cpp index 3b14649c48..9c17488ec5 100644 --- a/lib/Target/ARM64/ARM64FrameLowering.cpp +++ b/lib/Target/ARM64/ARM64FrameLowering.cpp @@ -246,14 +246,14 @@ void ARM64FrameLowering::emitPrologue(MachineFunction &MF) const { // that is a multiple of -2. assert((MBBI->getOpcode() == ARM64::STPXpre || MBBI->getOpcode() == ARM64::STPDpre) && - MBBI->getOperand(2).getReg() == ARM64::SP && - MBBI->getOperand(3).getImm() < 0 && - (MBBI->getOperand(3).getImm() & 1) == 0); + MBBI->getOperand(3).getReg() == ARM64::SP && + MBBI->getOperand(4).getImm() < 0 && + (MBBI->getOperand(4).getImm() & 1) == 0); // Frame pointer is fp = sp - 16. Since the STPXpre subtracts the space // required for the callee saved register area we get the frame pointer // by addding that offset - 16 = -getImm()*8 - 2*8 = -(getImm() + 2) * 8. - FPOffset = -(MBBI->getOperand(3).getImm() + 2) * 8; + FPOffset = -(MBBI->getOperand(4).getImm() + 2) * 8; assert(FPOffset >= 0 && "Bad Framepointer Offset"); } @@ -409,12 +409,16 @@ static bool isCalleeSavedRegister(unsigned Reg, const MCPhysReg *CSRegs) { } static bool isCSRestore(MachineInstr *MI, const MCPhysReg *CSRegs) { + unsigned RtIdx = 0; + if (MI->getOpcode() == ARM64::LDPXpost || MI->getOpcode() == ARM64::LDPDpost) + RtIdx = 1; + if (MI->getOpcode() == ARM64::LDPXpost || MI->getOpcode() == ARM64::LDPDpost || MI->getOpcode() == ARM64::LDPXi || MI->getOpcode() == ARM64::LDPDi) { - if (!isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs) || - !isCalleeSavedRegister(MI->getOperand(1).getReg(), CSRegs) || - MI->getOperand(2).getReg() != ARM64::SP) + if (!isCalleeSavedRegister(MI->getOperand(RtIdx).getReg(), CSRegs) || + !isCalleeSavedRegister(MI->getOperand(RtIdx + 1).getReg(), CSRegs) || + MI->getOperand(RtIdx + 2).getReg() != ARM64::SP) return false; return true; } @@ -667,8 +671,11 @@ bool ARM64FrameLowering::spillCalleeSavedRegisters( const int Offset = (i == 0) ? -Count : i; assert((Offset >= -64 && Offset <= 63) && "Offset out of bounds for STP immediate"); - BuildMI(MBB, MI, DL, TII.get(StrOpc)) - .addReg(Reg2, getPrologueDeath(MF, Reg2)) + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc)); + if (StrOpc == ARM64::STPDpre || StrOpc == ARM64::STPXpre) + MIB.addReg(ARM64::SP, RegState::Define); + + MIB.addReg(Reg2, getPrologueDeath(MF, Reg2)) .addReg(Reg1, getPrologueDeath(MF, Reg1)) .addReg(ARM64::SP) .addImm(Offset) // [sp, #offset * 8], where factor * 8 is implicit @@ -734,8 +741,11 @@ bool ARM64FrameLowering::restoreCalleeSavedRegisters( const int Offset = (i == Count - 2) ? Count : Count - i - 2; assert((Offset >= -64 && Offset <= 63) && "Offset out of bounds for LDP immediate"); - BuildMI(MBB, MI, DL, TII.get(LdrOpc)) - .addReg(Reg2, getDefRegState(true)) + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(LdrOpc)); + if (LdrOpc == ARM64::LDPXpost || LdrOpc == ARM64::LDPDpost) + MIB.addReg(ARM64::SP, RegState::Define); + + MIB.addReg(Reg2, getDefRegState(true)) .addReg(Reg1, getDefRegState(true)) .addReg(ARM64::SP) .addImm(Offset); // [sp], #offset * 8 or [sp, #offset * 8] diff --git a/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp b/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp index 8fec6f02b7..9b235db30a 100644 --- a/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp +++ b/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp @@ -901,14 +901,14 @@ SDNode *ARM64DAGToDAGISel::SelectIndexedLoad(SDNode *N, bool &Done) { ISD::LoadExtType ExtType = LD->getExtensionType(); bool InsertTo64 = false; if (VT == MVT::i64) - Opcode = IsPre ? ARM64::LDRXpre_isel : ARM64::LDRXpost_isel; + Opcode = IsPre ? ARM64::LDRXpre : ARM64::LDRXpost; else if (VT == MVT::i32) { if (ExtType == ISD::NON_EXTLOAD) - Opcode = IsPre ? ARM64::LDRWpre_isel : ARM64::LDRWpost_isel; + Opcode = IsPre ? ARM64::LDRWpre : ARM64::LDRWpost; else if (ExtType == ISD::SEXTLOAD) - Opcode = IsPre ? ARM64::LDRSWpre_isel : ARM64::LDRSWpost_isel; + Opcode = IsPre ? ARM64::LDRSWpre : ARM64::LDRSWpost; else { - Opcode = IsPre ? ARM64::LDRWpre_isel : ARM64::LDRWpost_isel; + Opcode = IsPre ? ARM64::LDRWpre : ARM64::LDRWpost; InsertTo64 = true; // The result of the load is only i32. It's the subreg_to_reg that makes // it into an i64. @@ -917,11 +917,11 @@ SDNode *ARM64DAGToDAGISel::SelectIndexedLoad(SDNode *N, bool &Done) { } else if (VT == MVT::i16) { if (ExtType == ISD::SEXTLOAD) { if (DstVT == MVT::i64) - Opcode = IsPre ? ARM64::LDRSHXpre_isel : ARM64::LDRSHXpost_isel; + Opcode = IsPre ? ARM64::LDRSHXpre : ARM64::LDRSHXpost; else - Opcode = IsPre ? ARM64::LDRSHWpre_isel : ARM64::LDRSHWpost_isel; + Opcode = IsPre ? ARM64::LDRSHWpre : ARM64::LDRSHWpost; } else { - Opcode = IsPre ? ARM64::LDRHHpre_isel : ARM64::LDRHHpost_isel; + Opcode = IsPre ? ARM64::LDRHHpre : ARM64::LDRHHpost; InsertTo64 = DstVT == MVT::i64; // The result of the load is only i32. It's the subreg_to_reg that makes // it into an i64. @@ -930,22 +930,22 @@ SDNode *ARM64DAGToDAGISel::SelectIndexedLoad(SDNode *N, bool &Done) { } else if (VT == MVT::i8) { if (ExtType == ISD::SEXTLOAD) { if (DstVT == MVT::i64) - Opcode = IsPre ? ARM64::LDRSBXpre_isel : ARM64::LDRSBXpost_isel; + Opcode = IsPre ? ARM64::LDRSBXpre : ARM64::LDRSBXpost; else - Opcode = IsPre ? ARM64::LDRSBWpre_isel : ARM64::LDRSBWpost_isel; + Opcode = IsPre ? ARM64::LDRSBWpre : ARM64::LDRSBWpost; } else { - Opcode = IsPre ? ARM64::LDRBBpre_isel : ARM64::LDRBBpost_isel; + Opcode = IsPre ? ARM64::LDRBBpre : ARM64::LDRBBpost; InsertTo64 = DstVT == MVT::i64; // The result of the load is only i32. It's the subreg_to_reg that makes // it into an i64. DstVT = MVT::i32; } } else if (VT == MVT::f32) { - Opcode = IsPre ? ARM64::LDRSpre_isel : ARM64::LDRSpost_isel; + Opcode = IsPre ? ARM64::LDRSpre : ARM64::LDRSpost; } else if (VT == MVT::f64 || VT.is64BitVector()) { - Opcode = IsPre ? ARM64::LDRDpre_isel : ARM64::LDRDpost_isel; + Opcode = IsPre ? ARM64::LDRDpre : ARM64::LDRDpost; } else if (VT.is128BitVector()) { - Opcode = IsPre ? ARM64::LDRQpre_isel : ARM64::LDRQpost_isel; + Opcode = IsPre ? ARM64::LDRQpre : ARM64::LDRQpost; } else return nullptr; SDValue Chain = LD->getChain(); @@ -954,21 +954,25 @@ SDNode *ARM64DAGToDAGISel::SelectIndexedLoad(SDNode *N, bool &Done) { int OffsetVal = (int)OffsetOp->getZExtValue(); SDValue Offset = CurDAG->getTargetConstant(OffsetVal, MVT::i64); SDValue Ops[] = { Base, Offset, Chain }; - SDNode *Res = CurDAG->getMachineNode(Opcode, SDLoc(N), DstVT, MVT::i64, + SDNode *Res = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i64, DstVT, MVT::Other, Ops); // Either way, we're replacing the node, so tell the caller that. Done = true; + SDValue LoadedVal = SDValue(Res, 1); if (InsertTo64) { SDValue SubReg = CurDAG->getTargetConstant(ARM64::sub_32, MVT::i32); - SDNode *Sub = CurDAG->getMachineNode( - ARM64::SUBREG_TO_REG, SDLoc(N), MVT::i64, - CurDAG->getTargetConstant(0, MVT::i64), SDValue(Res, 0), SubReg); - ReplaceUses(SDValue(N, 0), SDValue(Sub, 0)); - ReplaceUses(SDValue(N, 1), SDValue(Res, 1)); - ReplaceUses(SDValue(N, 2), SDValue(Res, 2)); - return nullptr; + LoadedVal = + SDValue(CurDAG->getMachineNode(ARM64::SUBREG_TO_REG, SDLoc(N), MVT::i64, + CurDAG->getTargetConstant(0, MVT::i64), + LoadedVal, SubReg), + 0); } - return Res; + + ReplaceUses(SDValue(N, 0), LoadedVal); + ReplaceUses(SDValue(N, 1), SDValue(Res, 0)); + ReplaceUses(SDValue(N, 2), SDValue(Res, 2)); + + return nullptr; } SDNode *ARM64DAGToDAGISel::SelectLoad(SDNode *N, unsigned NumVecs, unsigned Opc, diff --git a/lib/Target/ARM64/ARM64InstrFormats.td b/lib/Target/ARM64/ARM64InstrFormats.td index bf9fa2992b..ea45b3d4fb 100644 --- a/lib/Target/ARM64/ARM64InstrFormats.td +++ b/lib/Target/ARM64/ARM64InstrFormats.td @@ -2918,8 +2918,8 @@ multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, //--- class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, - string asm, string cstr> - : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, []> { + string asm, string cstr, list<dag> pat> + : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> { bits<5> Rt; bits<5> Rn; bits<9> offset; @@ -2939,74 +2939,34 @@ class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, let hasSideEffects = 0 in { let mayStore = 0, mayLoad = 1 in -// FIXME: Modeling the write-back of these instructions for isel used -// to be tricky. we need the complex addressing mode for the memory -// reference, but we also need the write-back specified as a tied -// operand to the base register. It should work now, but needs to be -// done as a separate patch. This would allow us to be rid of the -// codegenonly pseudoinstructions below too. class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, string asm> : BaseLoadStorePreIdx<sz, V, opc, - (outs regtype:$Rt/*, GPR64sp:$wback*/), + (outs GPR64sp:$wback, regtype:$Rt), (ins GPR64sp:$Rn, simm9:$offset), asm, - ""/*"$Rn = $wback"*/>, + "$Rn = $wback", []>, Sched<[WriteLD, WriteAdr]>; let mayStore = 1, mayLoad = 0 in class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, - string asm> + string asm, SDPatternOperator storeop, ValueType Ty> : BaseLoadStorePreIdx<sz, V, opc, - (outs/* GPR64sp:$wback*/), + (outs GPR64sp:$wback), (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset), - asm, ""/*"$Rn = $wback"*/>, + asm, "$Rn = $wback", + [(set GPR64sp:$wback, + (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>, Sched<[WriteAdr, WriteST]>; } // hasSideEffects = 0 -// ISel pseudo-instructions which have the tied operands. When the MC lowering -// logic finally gets smart enough to strip off tied operands that are just -// for isel convenience, we can get rid of these pseudos and just reference -// the real instructions directly. -// -// Ironically, also because of the writeback operands, we can't put the -// matcher pattern directly on the instruction, but need to define it -// separately. -// -// Loads aren't matched with patterns here at all, but rather in C++ -// custom lowering. -let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in { -class LoadPreIdxPseudo<RegisterClass regtype> - : Pseudo<(outs regtype:$Rt, GPR64sp:$wback), - (ins GPR64sp:$addr, simm9:$offset), [], - "$addr = $wback,@earlyclobber $wback">, - Sched<[WriteLD, WriteAdr]>; -class LoadPostIdxPseudo<RegisterClass regtype> - : Pseudo<(outs regtype:$Rt, GPR64sp:$wback), - (ins GPR64sp:$addr, simm9:$offset), [], - "$addr = $wback,@earlyclobber $wback">, - Sched<[WriteLD, WriteI]>; -} -multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty, - SDPatternOperator OpNode> { - let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in - def _isel: Pseudo<(outs GPR64sp:$wback), - (ins regtype:$Rt, GPR64sp:$addr, simm9:$offset), [], - "$addr = $wback,@earlyclobber $wback">, - Sched<[WriteAdr, WriteST]>; - - def : Pat<(OpNode (Ty regtype:$Rt), GPR64sp:$addr, simm9:$offset), - (!cast<Instruction>(NAME#_isel) regtype:$Rt, GPR64sp:$addr, - simm9:$offset)>; -} - //--- // Load/store post-indexed //--- // (pre-index) load/stores. class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, - string asm, string cstr> - : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, []> { + string asm, string cstr, list<dag> pat> + : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> { bits<5> Rt; bits<5> Rn; bits<9> offset; @@ -3026,51 +2986,26 @@ class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops, let hasSideEffects = 0 in { let mayStore = 0, mayLoad = 1 in -// FIXME: Modeling the write-back of these instructions for isel used -// to be tricky. we need the complex addressing mode for the memory -// reference, but we also need the write-back specified as a tied -// operand to the base register. It should work now, but needs to be -// done as a separate patch. This would allow us to be rid of the -// codegenonly pseudoinstructions below too. class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, string asm> : BaseLoadStorePostIdx<sz, V, opc, - (outs regtype:$Rt/*, GPR64sp:$wback*/), + (outs GPR64sp:$wback, regtype:$Rt), (ins GPR64sp:$Rn, simm9:$offset), - asm, ""/*"$addr.base = $wback"*/>, + asm, "$Rn = $wback", []>, Sched<[WriteLD, WriteI]>; let mayStore = 1, mayLoad = 0 in class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype, - string asm> + string asm, SDPatternOperator storeop, ValueType Ty> : BaseLoadStorePostIdx<sz, V, opc, - (outs/* GPR64sp:$wback*/), + (outs GPR64sp:$wback), (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset), - asm, ""/*"$addr.base = $wback"*/>, + asm, "$Rn = $wback", + [(set GPR64sp:$wback, + (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>, Sched<[WriteAdr, WriteST, ReadAdrBase]>; } // hasSideEffects = 0 -// ISel pseudo-instructions which have the tied operands. When the MC lowering -// logic finally gets smart enough to strip off tied operands that are just -// for isel convenience, we can get rid of these pseudos and just reference -// the real instructions directly. -// -// Ironically, also because of the writeback operands, we can't put the -// matcher pattern directly on the instruction, but need to define it -// separately. -multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty, - SDPatternOperator OpNode, Instruction Insn> { - let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in - def _isel: Pseudo<(outs GPR64sp:$wback), - (ins regtype:$Rt, GPR64sp:$Rn, simm9:$idx), [], - "$Rn = $wback,@earlyclobber $wback">, - PseudoInstExpansion<(Insn regtype:$Rt, GPR64sp:$Rn, simm9:$idx)>, - Sched<[WriteAdr, WriteST, ReadAdrBase]>; - - def : Pat<(OpNode (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$idx), - (!cast<Instruction>(NAME#_isel) regtype:$Rt, GPR64sp:$Rn, - simm9:$idx)>; -} //--- // Load/store pair @@ -3129,7 +3064,7 @@ multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype, // (pre-indexed) class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops, string asm> - : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "", []> { + : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback", []> { bits<5> Rt; bits<5> Rt2; bits<5> Rn; @@ -3152,14 +3087,14 @@ let mayStore = 0, mayLoad = 1 in class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype, Operand indextype, string asm> : BaseLoadStorePairPreIdx<opc, V, 1, - (outs regtype:$Rt, regtype:$Rt2), + (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2), (ins GPR64sp:$Rn, indextype:$offset), asm>, Sched<[WriteLD, WriteLDHi, WriteAdr]>; let mayStore = 1, mayLoad = 0 in class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype, Operand indextype, string asm> - : BaseLoadStorePairPreIdx<opc, V, 0, (outs), + : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback), (ins regtype:$Rt, regtype:$Rt2, GPR64sp:$Rn, indextype:$offset), asm>, @@ -3170,7 +3105,7 @@ class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype, class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops, string asm> - : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "", []> { + : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback", []> { bits<5> Rt; bits<5> Rt2; bits<5> Rn; @@ -3193,7 +3128,7 @@ let mayStore = 0, mayLoad = 1 in class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype, Operand idxtype, string asm> : BaseLoadStorePairPostIdx<opc, V, 1, - (outs regtype:$Rt, regtype:$Rt2), + (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2), (ins GPR64sp:$Rn, idxtype:$offset), asm>, Sched<[WriteLD, WriteLDHi, WriteAdr]>; @@ -3201,7 +3136,7 @@ let mayStore = 1, mayLoad = 0 in class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype, Operand idxtype, string asm> : BaseLoadStorePairPostIdx<opc, V, 0, (outs), - (ins regtype:$Rt, regtype:$Rt2, + (ins GPR64sp:$wback, regtype:$Rt, regtype:$Rt2, GPR64sp:$Rn, idxtype:$offset), asm>, Sched<[WriteAdr, WriteSTP]>; diff --git a/lib/Target/ARM64/ARM64InstrInfo.cpp b/lib/Target/ARM64/ARM64InstrInfo.cpp index e1f9667841..fbbddd5666 100644 --- a/lib/Target/ARM64/ARM64InstrInfo.cpp +++ b/lib/Target/ARM64/ARM64InstrInfo.cpp @@ -1389,10 +1389,12 @@ void ARM64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, SrcReg, getKillRegState(KillSrc)); } else { BuildMI(MBB, I, DL, get(ARM64::STRQpre)) + .addReg(ARM64::SP, RegState::Define) .addReg(SrcReg, getKillRegState(KillSrc)) .addReg(ARM64::SP) .addImm(-16); BuildMI(MBB, I, DL, get(ARM64::LDRQpre)) + .addReg(ARM64::SP, RegState::Define) .addReg(DestReg, RegState::Define) .addReg(ARM64::SP) .addImm(16); diff --git a/lib/Target/ARM64/ARM64InstrInfo.td b/lib/Target/ARM64/ARM64InstrInfo.td index 94a39c1112..9c39d72a8e 100644 --- a/lib/Target/ARM64/ARM64InstrInfo.td +++ b/lib/Target/ARM64/ARM64InstrInfo.td @@ -1699,21 +1699,6 @@ def LDRHHpre : LoadPreIdx<0b01, 0, 0b01, GPR32, "ldrh">; // load sign-extended word def LDRSWpre : LoadPreIdx<0b10, 0, 0b10, GPR64, "ldrsw">; -// ISel pseudos and patterns. See expanded comment on LoadPreIdxPseudo. -def LDRQpre_isel : LoadPreIdxPseudo<FPR128>; -def LDRDpre_isel : LoadPreIdxPseudo<FPR64>; -def LDRSpre_isel : LoadPreIdxPseudo<FPR32>; -def LDRXpre_isel : LoadPreIdxPseudo<GPR64>; -def LDRWpre_isel : LoadPreIdxPseudo<GPR32>; -def LDRHHpre_isel : LoadPreIdxPseudo<GPR32>; -def LDRBBpre_isel : LoadPreIdxPseudo<GPR32>; - -def LDRSWpre_isel : LoadPreIdxPseudo<GPR64>; -def LDRSHWpre_isel : LoadPreIdxPseudo<GPR32>; -def LDRSHXpre_isel : LoadPreIdxPseudo<GPR64>; -def LDRSBWpre_isel : LoadPreIdxPseudo<GPR32>; -def LDRSBXpre_isel : LoadPreIdxPseudo<GPR64>; - //--- // (immediate post-indexed) def LDRWpost : LoadPostIdx<0b10, 0, 0b01, GPR32, "ldr">; @@ -1739,21 +1724,6 @@ def LDRHHpost : LoadPostIdx<0b01, 0, 0b01, GPR32, "ldrh">; // load sign-extended word def LDRSWpost : LoadPostIdx<0b10, 0, 0b10, GPR64, "ldrsw">; -// ISel pseudos and patterns. See expanded comment on LoadPostIdxPseudo. -def LDRQpost_isel : LoadPostIdxPseudo<FPR128>; -def LDRDpost_isel : LoadPostIdxPseudo<FPR64>; -def LDRSpost_isel : LoadPostIdxPseudo<FPR32>; -def LDRXpost_isel : LoadPostIdxPseudo<GPR64>; -def LDRWpost_isel : LoadPostIdxPseudo<GPR32>; -def LDRHHpost_isel : LoadPostIdxPseudo<GPR32>; -def LDRBBpost_isel : LoadPostIdxPseudo<GPR32>; - -def LDRSWpost_isel : LoadPostIdxPseudo<GPR64>; -def LDRSHWpost_isel : LoadPostIdxPseudo<GPR32>; -def LDRSHXpost_isel : LoadPostIdxPseudo<GPR64>; -def LDRSBWpost_isel : LoadPostIdxPseudo<GPR32>; -def LDRSBXpost_isel : LoadPostIdxPseudo<GPR64>; - //===----------------------------------------------------------------------===// // Store instructions. //===----------------------------------------------------------------------===// @@ -2072,119 +2042,103 @@ defm STTRB : StoreUnprivileged<0b00, 0, 0b00, GPR32, "sttrb">; //--- // (immediate pre-indexed) -def STRWpre : StorePreIdx<0b10, 0, 0b00, GPR32, "str">; -def STRXpre : StorePreIdx<0b11, 0, 0b00, GPR64, "str">; -def STRBpre : StorePreIdx<0b00, 1, 0b00, FPR8, "str">; -def STRHpre : StorePreIdx<0b01, 1, 0b00, FPR16, "str">; -def STRSpre : StorePreIdx<0b10, 1, 0b00, FPR32, "str">; -def STRDpre : StorePreIdx<0b11, 1, 0b00, FPR64, "str">; -def STRQpre : StorePreIdx<0b00, 1, 0b10, FPR128, "str">; - -def STRBBpre : StorePreIdx<0b00, 0, 0b00, GPR32, "strb">; -def STRHHpre : StorePreIdx<0b01, 0, 0b00, GPR32, "strh">; - -// ISel pseudos and patterns. See expanded comment on StorePreIdxPseudo. -defm STRQpre : StorePreIdxPseudo<FPR128, f128, pre_store>; -defm STRDpre : StorePreIdxPseudo<FPR64, f64, pre_store>; -defm STRSpre : StorePreIdxPseudo<FPR32, f32, pre_store>; -defm STRXpre : StorePreIdxPseudo<GPR64, i64, pre_store>; -defm STRWpre : StorePreIdxPseudo<GPR32, i32, pre_store>; -defm STRHHpre : StorePreIdxPseudo<GPR32, i32, pre_truncsti16>; -defm STRBBpre : StorePreIdxPseudo<GPR32, i32, pre_truncsti8>; +def STRWpre : StorePreIdx<0b10, 0, 0b00, GPR32, "str", pre_store, i32>; +def STRXpre : StorePreIdx<0b11, 0, 0b00, GPR64, "str", pre_store, i64>; +def STRBpre : StorePreIdx<0b00, 1, 0b00, FPR8, "str", pre_store, untyped>; +def STRHpre : StorePreIdx<0b01, 1, 0b00, FPR16, "str", pre_store, f16>; +def STRSpre : StorePreIdx<0b10, 1, 0b00, FPR32, "str", pre_store, f32>; +def STRDpre : StorePreIdx<0b11, 1, 0b00, FPR64, "str", pre_store, f64>; +def STRQpre : StorePreIdx<0b00, 1, 0b10, FPR128, "str", pre_store, f128>; + +def STRBBpre : StorePreIdx<0b00, 0, 0b00, GPR32, "strb", pre_truncsti8, i32>; +def STRHHpre : StorePreIdx<0b01, 0, 0b00, GPR32, "strh", pre_truncsti16, i32>; + // truncstore i64 def : Pat<(pre_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off), - (STRWpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, - simm9:$off)>; + (STRWpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, + simm9:$off)>; def : Pat<(pre_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off), - (STRHHpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, - simm9:$off)>; + (STRHHpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, + simm9:$off)>; def : Pat<(pre_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off), - (STRBBpre_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, - simm9:$off)>; + (STRBBpre (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, + simm9:$off)>; def : Pat<(pre_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpre_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpre FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(pre_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpre_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpre FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; //--- // (immediate post-indexed) -def STRWpost : StorePostIdx<0b10, 0, 0b00, GPR32, "str">; -def STRXpost : StorePostIdx<0b11, 0, 0b00, GPR64, "str">; -def STRBpost : StorePostIdx<0b00, 1, 0b00, FPR8, "str">; -def STRHpost : StorePostIdx<0b01, 1, 0b00, FPR16, "str">; -def STRSpost : StorePostIdx<0b10, 1, 0b00, FPR32, "str">; -def STRDpost : StorePostIdx<0b11, 1, 0b00, FPR64, "str">; -def STRQpost : StorePostIdx<0b00, 1, 0b10, FPR128, "str">; - -def STRBBpost : StorePostIdx<0b00, 0, 0b00, GPR32, "strb">; -def STRHHpost : StorePostIdx<0b01, 0, 0b00, GPR32, "strh">; - -// ISel pseudos and patterns. See expanded comment on StorePostIdxPseudo. -defm STRQpost : StorePostIdxPseudo<FPR128, f128, post_store, STRQpost>; -defm STRDpost : StorePostIdxPseudo<FPR64, f64, post_store, STRDpost>; -defm STRSpost : StorePostIdxPseudo<FPR32, f32, post_store, STRSpost>; -defm STRXpost : StorePostIdxPseudo<GPR64, i64, post_store, STRXpost>; -defm STRWpost : StorePostIdxPseudo<GPR32, i32, post_store, STRWpost>; -defm STRHHpost : StorePostIdxPseudo<GPR32, i32, post_truncsti16, STRHHpost>; -defm STRBBpost : StorePostIdxPseudo<GPR32, i32, post_truncsti8, STRBBpost>; +def STRWpost : StorePostIdx<0b10, 0, 0b00, GPR32, "str", post_store, i32>; +def STRXpost : StorePostIdx<0b11, 0, 0b00, GPR64, "str", post_store, i64>; +def STRBpost : StorePostIdx<0b00, 1, 0b00, FPR8, "str", post_store, untyped>; +def STRHpost : StorePostIdx<0b01, 1, 0b00, FPR16, "str", post_store, f16>; +def STRSpost : StorePostIdx<0b10, 1, 0b00, FPR32, "str", post_store, f32>; +def STRDpost : StorePostIdx<0b11, 1, 0b00, FPR64, "str", post_store, f64>; +def STRQpost : StorePostIdx<0b00, 1, 0b10, FPR128, "str", post_store, f128>; + +def STRBBpost : StorePostIdx<0b00, 0, 0b00, GPR32, "strb", post_truncsti8, i32>; +def STRHHpost : StorePostIdx<0b01, 0, 0b00, GPR32, "strh", post_truncsti16, i32>; + // truncstore i64 def : Pat<(post_truncsti32 GPR64:$Rt, GPR64sp:$addr, simm9:$off), - (STRWpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, - simm9:$off)>; + (STRWpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, + simm9:$off)>; def : Pat<(post_truncsti16 GPR64:$Rt, GPR64sp:$addr, simm9:$off), - (STRHHpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, - simm9:$off)>; + (STRHHpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, + simm9:$off)>; def : Pat<(post_truncsti8 GPR64:$Rt, GPR64sp:$addr, simm9:$off), - (STRBBpost_isel (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, - simm9:$off)>; + (STRBBpost (EXTRACT_SUBREG GPR64:$Rt, sub_32), GPR64sp:$addr, + simm9:$off)>; def : Pat<(post_store (v8i8 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v4i16 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v2i32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v2f32 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v1i64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v1f64 FPR64:$Rt), GPR64sp:$addr, simm9:$off), - (STRDpost_isel FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRDpost FPR64:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v16i8 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v8i16 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v4i32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v4f32 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v2i64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; def : Pat<(post_store (v2f64 FPR128:$Rt), GPR64sp:$addr, simm9:$off), - (STRQpost_isel FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; + (STRQpost FPR128:$Rt, GPR64sp:$addr, simm9:$off)>; //===----------------------------------------------------------------------===// // Load/store exclusive instructions. diff --git a/lib/Target/ARM64/ARM64LoadStoreOptimizer.cpp b/lib/Target/ARM64/ARM64LoadStoreOptimizer.cpp index 9a8e1c3d91..e2c4b13f03 100644 --- a/lib/Target/ARM64/ARM64LoadStoreOptimizer.cpp +++ b/lib/Target/ARM64/ARM64LoadStoreOptimizer.cpp @@ -528,6 +528,7 @@ ARM64LoadStoreOpt::mergePreIdxUpdateInsn(MachineBasicBlock::iterator I, unsigned NewOpc = getPreIndexedOpcode(I->getOpcode()); MachineInstrBuilder MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), TII->get(NewOpc)) + .addOperand(Update->getOperand(0)) .addOperand(I->getOperand(0)) .addOperand(I->getOperand(1)) .addImm(Value); @@ -571,6 +572,7 @@ ARM64LoadStoreOpt::mergePostIdxUpdateInsn(MachineBasicBlock::iterator I, unsigned NewOpc = getPostIndexedOpcode(I->getOpcode()); MachineInstrBuilder MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), TII->get(NewOpc)) + .addOperand(Update->getOperand(0)) .addOperand(I->getOperand(0)) .addOperand(I->getOperand(1)) .addImm(Value); diff --git a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp index 982690fe86..0c422c5cec 100644 --- a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -3146,9 +3146,9 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, case ARM64::LDPWpre: case ARM64::LDPXpost: case ARM64::LDPXpre: { - unsigned Rt = Inst.getOperand(0).getReg(); - unsigned Rt2 = Inst.getOperand(1).getReg(); - unsigned Rn = Inst.getOperand(2).getReg(); + unsigned Rt = Inst.getOperand(1).getReg(); + unsigned Rt2 = Inst.getOperand(2).getReg(); + unsigned Rn = Inst.getOperand(3).getReg(); if (RI->isSubRegisterEq(Rn, Rt)) return Error(Loc[0], "unpredictable LDP instruction, writeback base " "is also a destination"); @@ -3157,13 +3157,6 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, "is also a destination"); // FALLTHROUGH } - case ARM64::LDPDpost: - case ARM64::LDPDpre: - case ARM64::LDPQpost: - case ARM64::LDPQpre: - case ARM64::LDPSpost: - case ARM64::LDPSpre: - case ARM64::LDPSWpost: case ARM64::LDPDi: case ARM64::LDPQi: case ARM64::LDPSi: @@ -3176,6 +3169,19 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt"); break; } + case ARM64::LDPDpost: + case ARM64::LDPDpre: + case ARM64::LDPQpost: + case ARM64::LDPQpre: + case ARM64::LDPSpost: + case ARM64::LDPSpre: + case ARM64::LDPSWpost: { + unsigned Rt = Inst.getOperand(1).getReg(); + unsigned Rt2 = Inst.getOperand(2).getReg(); + if (Rt == Rt2) + return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt"); + break; + } case ARM64::STPDpost: case ARM64::STPDpre: case ARM64::STPQpost: @@ -3186,9 +3192,9 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, case ARM64::STPWpre: case ARM64::STPXpost: case ARM64::STPXpre: { - unsigned Rt = Inst.getOperand(0).getReg(); - unsigned Rt2 = Inst.getOperand(1).getReg(); - unsigned Rn = Inst.getOperand(2).getReg(); + unsigned Rt = Inst.getOperand(1).getReg(); + unsigned Rt2 = Inst.getOperand(2).getReg(); + unsigned Rn = Inst.getOperand(3).getReg(); if (RI->isSubRegisterEq(Rn, Rt)) return Error(Loc[0], "unpredictable STP instruction, writeback base " "is also a source"); @@ -3219,8 +3225,8 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, case ARM64::LDRSWpost: case ARM64::LDRWpost: case ARM64::LDRXpost: { - unsigned Rt = Inst.getOperand(0).getReg(); - unsigned Rn = Inst.getOperand(1).getReg(); + unsigned Rt = Inst.getOperand(1).getReg(); + unsigned Rn = Inst.getOperand(2).getReg(); if (RI->isSubRegisterEq(Rn, Rt)) return Error(Loc[0], "unpredictable LDR instruction, writeback base " "is also a source"); @@ -3238,8 +3244,8 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, case ARM64::STRHpre: case ARM64::STRWpre: case ARM64::STRXpre: { - unsigned Rt = Inst.getOperand(0).getReg(); - unsigned Rn = Inst.getOperand(1).getReg(); + unsigned Rt = Inst.getOperand(1).getReg(); + unsigned Rn = Inst.getOperand(2).getReg(); if (RI->isSubRegisterEq(Rn, Rt)) return Error(Loc[0], "unpredictable STR instruction, writeback base " "is also a source"); diff --git a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp index 20bcb366bf..4fa9339d2b 100644 --- a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp +++ b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp @@ -902,6 +902,60 @@ static DecodeStatus DecodeSignedLdStInstruction(llvm::MCInst &Inst, if (offset & (1 << (9 - 1))) offset |= ~((1LL << 9) - 1); + // First operand is always the writeback to the address register, if needed. + switch (Inst.getOpcode()) { + default: + break; + case ARM64::LDRSBWpre: + case ARM64::LDRSHWpre: + case ARM64::STRBBpre: + case ARM64::LDRBBpre: + case ARM64::STRHHpre: + case ARM64::LDRHHpre: + case ARM64::STRWpre: + case ARM64::LDRWpre: + case ARM64::LDRSBWpost: + case ARM64::LDRSHWpost: + case ARM64::STRBBpost: + case ARM64::LDRBBpost: + case ARM64::STRHHpost: + case ARM64::LDRHHpost: + case ARM64::STRWpost: + case ARM64::LDRWpost: + case ARM64::LDRSBXpre: + case ARM64::LDRSHXpre: + case ARM64::STRXpre: + case ARM64::LDRSWpre: + case ARM64::LDRXpre: + case ARM64::LDRSBXpost: + case ARM64::LDRSHXpost: + case ARM64::STRXpost: + case ARM64::LDRSWpost: + case ARM64::LDRXpost: + case ARM64::LDRQpre: + case ARM64::STRQpre: + case ARM64::LDRQpost: + case ARM64::STRQpost: + case ARM64::LDRDpre: + case ARM64::STRDpre: + case ARM64::LDRDpost: + case ARM64::STRDpost: + case ARM64::LDRSpre: + case ARM64::STRSpre: + case ARM64::LDRSpost: + case ARM64::STRSpost: + case ARM64::LDRHpre: + case ARM64::STRHpre: + case ARM64::LDRHpost: + case ARM64::STRHpost: + case ARM64::LDRBpre: + case ARM64::STRBpre: + case ARM64::LDRBpost: + case ARM64::STRBpost: + DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); + break; + } + switch (Inst.getOpcode()) { default: return Fail; @@ -1112,6 +1166,37 @@ static DecodeStatus DecodePairLdStInstruction(llvm::MCInst &Inst, uint32_t insn, unsigned Opcode = Inst.getOpcode(); bool NeedsDisjointWritebackTransfer = false; + + // First operand is always writeback of base register. + switch (Opcode) { + default: + break; + case ARM64::LDPXpost: + case ARM64::STPXpost: + case ARM64::LDPSWpost: + case ARM64::LDPXpre: + case ARM64::STPXpre: + case ARM64::LDPSWpre: + case ARM64::LDPWpost: + case ARM64::STPWpost: + case ARM64::LDPWpre: + case ARM64::STPWpre: + case ARM64::LDPQpost: + case ARM64::STPQpost: + case ARM64::LDPQpre: + case ARM64::STPQpre: + case ARM64::LDPDpost: + case ARM64::STPDpost: + case ARM64::LDPDpre: + case ARM64::STPDpre: + case ARM64::LDPSpost: + case ARM64::STPSpost: + case ARM64::LDPSpre: + case ARM64::STPSpre: + DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); + break; + } + switch (Opcode) { default: return Fail; |