summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM64/ARM64AsmPrinter.cpp93
-rw-r--r--lib/Target/ARM64/ARM64FrameLowering.cpp32
-rw-r--r--lib/Target/ARM64/ARM64ISelDAGToDAG.cpp48
-rw-r--r--lib/Target/ARM64/ARM64InstrFormats.td113
-rw-r--r--lib/Target/ARM64/ARM64InstrInfo.cpp2
-rw-r--r--lib/Target/ARM64/ARM64InstrInfo.td162
-rw-r--r--lib/Target/ARM64/ARM64LoadStoreOptimizer.cpp2
-rw-r--r--lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp40
-rw-r--r--lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp85
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;