aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2010-11-16 01:16:36 +0000
committerBill Wendling <isanbard@gmail.com>2010-11-16 01:16:36 +0000
commit73fe34a3ee866867d5028f4a9afa2c3b8efebcba (patch)
tree38de70b817c48c84c6ab08ed78cf54b245b7d640
parent88af6b9217f9ff8b4592f38ac5175de697275f49 (diff)
Encode the multi-load/store instructions with their respective modes ('ia',
'db', 'ib', 'da') instead of having that mode as a separate field in the instruction. It's more convenient for the asm parser and much more readable for humans. <rdar://problem/8654088> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119310 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.cpp215
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp29
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td90
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td16
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td40
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td80
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td119
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp303
-rw-r--r--lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp32
-rw-r--r--lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h71
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp60
-rw-r--r--lib/Target/ARM/Thumb2SizeReduction.cpp43
-rw-r--r--utils/TableGen/ARMDecoderEmitter.cpp10
13 files changed, 567 insertions, 541 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 9bda8fd701..89b2102733 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -697,10 +697,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
.addReg(SrcReg, getKillRegState(isKill))
.addMemOperand(MMO));
} else {
- AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQ))
+ AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQIA))
.addReg(SrcReg, getKillRegState(isKill))
.addFrameIndex(FI)
- .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
.addMemOperand(MMO));
}
break;
@@ -715,9 +714,8 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
.addMemOperand(MMO));
} else {
MachineInstrBuilder MIB =
- AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMD))
- .addFrameIndex(FI)
- .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)))
+ AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA))
+ .addFrameIndex(FI))
.addMemOperand(MMO);
MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI);
MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI);
@@ -727,9 +725,8 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
break;
case ARM::QQQQPRRegClassID: {
MachineInstrBuilder MIB =
- AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMD))
- .addFrameIndex(FI)
- .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)))
+ AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA))
+ .addFrameIndex(FI))
.addMemOperand(MMO);
MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI);
MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI);
@@ -781,10 +778,8 @@ ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
return MI->getOperand(2).getReg();
}
break;
- case ARM::VSTMQ:
+ case ARM::VSTMQIA:
if (MI->getOperand(1).isFI() &&
- MI->getOperand(2).isImm() &&
- MI->getOperand(2).getImm() == ARM_AM::getAM4ModeImm(ARM_AM::ia) &&
MI->getOperand(0).getSubReg() == 0) {
FrameIndex = MI->getOperand(1).getIndex();
return MI->getOperand(0).getReg();
@@ -841,9 +836,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
.addFrameIndex(FI).addImm(16)
.addMemOperand(MMO));
} else {
- AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQ), DestReg)
+ AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQIA), DestReg)
.addFrameIndex(FI)
- .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
.addMemOperand(MMO));
}
break;
@@ -855,9 +849,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
.addMemOperand(MMO));
} else {
MachineInstrBuilder MIB =
- AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMD))
- .addFrameIndex(FI)
- .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)))
+ AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA))
+ .addFrameIndex(FI))
.addMemOperand(MMO);
MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI);
MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI);
@@ -867,9 +860,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
break;
case ARM::QQQQPRRegClassID: {
MachineInstrBuilder MIB =
- AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMD))
- .addFrameIndex(FI)
- .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)))
+ AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA))
+ .addFrameIndex(FI))
.addMemOperand(MMO);
MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI);
MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI);
@@ -921,10 +913,8 @@ ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
return MI->getOperand(0).getReg();
}
break;
- case ARM::VLDMQ:
+ case ARM::VLDMQIA:
if (MI->getOperand(1).isFI() &&
- MI->getOperand(2).isImm() &&
- MI->getOperand(2).getImm() == ARM_AM::getAM4ModeImm(ARM_AM::ia) &&
MI->getOperand(0).getSubReg() == 0) {
FrameIndex = MI->getOperand(1).getIndex();
return MI->getOperand(0).getReg();
@@ -1583,46 +1573,75 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData,
default:
llvm_unreachable("Unexpected multi-uops instruction!");
break;
- case ARM::VLDMQ:
- case ARM::VSTMQ:
+ case ARM::VLDMQIA:
+ case ARM::VLDMQDB:
+ case ARM::VSTMQIA:
+ case ARM::VSTMQDB:
return 2;
// The number of uOps for load / store multiple are determined by the number
// registers.
+ //
// On Cortex-A8, each pair of register loads / stores can be scheduled on the
// same cycle. The scheduling for the first load / store must be done
// separately by assuming the the address is not 64-bit aligned.
+ //
// On Cortex-A9, the formula is simply (#reg / 2) + (#reg % 2). If the address
- // is not 64-bit aligned, then AGU would take an extra cycle.
- // For VFP / NEON load / store multiple, the formula is
- // (#reg / 2) + (#reg % 2) + 1.
- case ARM::VLDMD:
- case ARM::VLDMS:
- case ARM::VLDMD_UPD:
- case ARM::VLDMS_UPD:
- case ARM::VSTMD:
- case ARM::VSTMS:
- case ARM::VSTMD_UPD:
- case ARM::VSTMS_UPD: {
+ // is not 64-bit aligned, then AGU would take an extra cycle. For VFP / NEON
+ // load / store multiple, the formula is (#reg / 2) + (#reg % 2) + 1.
+ case ARM::VLDMDIA:
+ case ARM::VLDMDDB:
+ case ARM::VLDMDIA_UPD:
+ case ARM::VLDMDDB_UPD:
+ case ARM::VLDMSIA:
+ case ARM::VLDMSDB:
+ case ARM::VLDMSIA_UPD:
+ case ARM::VLDMSDB_UPD:
+ case ARM::VSTMDIA:
+ case ARM::VSTMDDB:
+ case ARM::VSTMDIA_UPD:
+ case ARM::VSTMDDB_UPD:
+ case ARM::VSTMSIA:
+ case ARM::VSTMSDB:
+ case ARM::VSTMSIA_UPD:
+ case ARM::VSTMSDB_UPD: {
unsigned NumRegs = MI->getNumOperands() - Desc.getNumOperands();
return (NumRegs / 2) + (NumRegs % 2) + 1;
}
- case ARM::LDM_RET:
- case ARM::LDM:
- case ARM::LDM_UPD:
- case ARM::STM:
- case ARM::STM_UPD:
- case ARM::tLDM:
- case ARM::tLDM_UPD:
- case ARM::tSTM_UPD:
+
+ case ARM::LDMIA_RET:
+ case ARM::LDMIA:
+ case ARM::LDMDA:
+ case ARM::LDMDB:
+ case ARM::LDMIB:
+ case ARM::LDMIA_UPD:
+ case ARM::LDMDA_UPD:
+ case ARM::LDMDB_UPD:
+ case ARM::LDMIB_UPD:
+ case ARM::STMIA:
+ case ARM::STMDA:
+ case ARM::STMDB:
+ case ARM::STMIB:
+ case ARM::STMIA_UPD:
+ case ARM::STMDA_UPD:
+ case ARM::STMDB_UPD:
+ case ARM::STMIB_UPD:
+ case ARM::tLDMIA:
+ case ARM::tLDMIA_UPD:
+ case ARM::tSTMIA:
+ case ARM::tSTMIA_UPD:
case ARM::tPOP_RET:
case ARM::tPOP:
case ARM::tPUSH:
- case ARM::t2LDM_RET:
- case ARM::t2LDM:
- case ARM::t2LDM_UPD:
- case ARM::t2STM:
- case ARM::t2STM_UPD: {
+ case ARM::t2LDMIA_RET:
+ case ARM::t2LDMIA:
+ case ARM::t2LDMDB:
+ case ARM::t2LDMIA_UPD:
+ case ARM::t2LDMDB_UPD:
+ case ARM::t2STMIA:
+ case ARM::t2STMDB:
+ case ARM::t2STMIA_UPD:
+ case ARM::t2STMDB_UPD: {
unsigned NumRegs = MI->getNumOperands() - Desc.getNumOperands() + 1;
if (Subtarget.isCortexA8()) {
if (NumRegs < 4)
@@ -1669,13 +1688,17 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData,
} else if (Subtarget.isCortexA9()) {
DefCycle = RegNo;
bool isSLoad = false;
+
switch (DefTID.getOpcode()) {
default: break;
- case ARM::VLDMS:
- case ARM::VLDMS_UPD:
+ case ARM::VLDMSIA:
+ case ARM::VLDMSDB:
+ case ARM::VLDMSIA_UPD:
+ case ARM::VLDMSDB_UPD:
isSLoad = true;
break;
}
+
// If there are odd number of 'S' registers or if it's not 64-bit aligned,
// then it takes an extra cycle.
if ((isSLoad && (RegNo % 2)) || DefAlign < 8)
@@ -1741,13 +1764,17 @@ ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData,
} else if (Subtarget.isCortexA9()) {
UseCycle = RegNo;
bool isSStore = false;
+
switch (UseTID.getOpcode()) {
default: break;
- case ARM::VSTMS:
- case ARM::VSTMS_UPD:
+ case ARM::VSTMSIA:
+ case ARM::VSTMSDB:
+ case ARM::VSTMSIA_UPD:
+ case ARM::VSTMSDB_UPD:
isSStore = true;
break;
}
+
// If there are odd number of 'S' registers or if it's not 64-bit aligned,
// then it takes an extra cycle.
if ((isSStore && (RegNo % 2)) || UseAlign < 8)
@@ -1810,27 +1837,39 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
default:
DefCycle = ItinData->getOperandCycle(DefClass, DefIdx);
break;
- case ARM::VLDMD:
- case ARM::VLDMS:
- case ARM::VLDMD_UPD:
- case ARM::VLDMS_UPD: {
+
+ case ARM::VLDMDIA:
+ case ARM::VLDMDDB:
+ case ARM::VLDMDIA_UPD:
+ case ARM::VLDMDDB_UPD:
+ case ARM::VLDMSIA:
+ case ARM::VLDMSDB:
+ case ARM::VLDMSIA_UPD:
+ case ARM::VLDMSDB_UPD:
DefCycle = getVLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign);
break;
- }
- case ARM::LDM_RET:
- case ARM::LDM:
- case ARM::LDM_UPD:
- case ARM::tLDM:
- case ARM::tLDM_UPD:
+
+ case ARM::LDMIA_RET:
+ case ARM::LDMIA:
+ case ARM::LDMDA:
+ case ARM::LDMDB:
+ case ARM::LDMIB:
+ case ARM::LDMIA_UPD:
+ case ARM::LDMDA_UPD:
+ case ARM::LDMDB_UPD:
+ case ARM::LDMIB_UPD:
+ case ARM::tLDMIA:
+ case ARM::tLDMIA_UPD:
case ARM::tPUSH:
- case ARM::t2LDM_RET:
- case ARM::t2LDM:
- case ARM::t2LDM_UPD: {
+ case ARM::t2LDMIA_RET:
+ case ARM::t2LDMIA:
+ case ARM::t2LDMDB:
+ case ARM::t2LDMIA_UPD:
+ case ARM::t2LDMDB_UPD:
LdmBypass = 1;
DefCycle = getLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign);
break;
}
- }
if (DefCycle == -1)
// We can't seem to determine the result latency of the def, assume it's 2.
@@ -1841,24 +1880,37 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
default:
UseCycle = ItinData->getOperandCycle(UseClass, UseIdx);
break;
- case ARM::VSTMD:
- case ARM::VSTMS:
- case ARM::VSTMD_UPD:
- case ARM::VSTMS_UPD: {
+
+ case ARM::VSTMDIA:
+ case ARM::VSTMDDB:
+ case ARM::VSTMDIA_UPD:
+ case ARM::VSTMDDB_UPD:
+ case ARM::VSTMSIA:
+ case ARM::VSTMSDB:
+ case ARM::VSTMSIA_UPD:
+ case ARM::VSTMSDB_UPD:
UseCycle = getVSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign);
break;
- }
- case ARM::STM:
- case ARM::STM_UPD:
- case ARM::tSTM_UPD:
+
+ case ARM::STMIA:
+ case ARM::STMDA:
+ case ARM::STMDB:
+ case ARM::STMIB:
+ case ARM::STMIA_UPD:
+ case ARM::STMDA_UPD:
+ case ARM::STMDB_UPD:
+ case ARM::STMIB_UPD:
+ case ARM::tSTMIA:
+ case ARM::tSTMIA_UPD:
case ARM::tPOP_RET:
case ARM::tPOP:
- case ARM::t2STM:
- case ARM::t2STM_UPD: {
+ case ARM::t2STMIA:
+ case ARM::t2STMDB:
+ case ARM::t2STMIA_UPD:
+ case ARM::t2STMDB_UPD:
UseCycle = getSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign);
break;
}
- }
if (UseCycle == -1)
// Assume it's read in the first stage.
@@ -1873,8 +1925,9 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
UseClass, UseIdx))
--UseCycle;
} else if (ItinData->hasPipelineForwarding(DefClass, DefIdx,
- UseClass, UseIdx))
+ UseClass, UseIdx)) {
--UseCycle;
+ }
}
return UseCycle;
@@ -2040,8 +2093,10 @@ int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
switch (Opcode) {
default:
return ItinData->getStageLatency(get(Opcode).getSchedClass());
- case ARM::VLDMQ:
- case ARM::VSTMQ:
+ case ARM::VLDMQIA:
+ case ARM::VLDMQDB:
+ case ARM::VSTMQIA:
+ case ARM::VSTMQDB:
return 2;
}
}
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index f38c452fce..a6fbe72403 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -782,24 +782,30 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
break;
}
- case ARM::VLDMQ: {
+ case ARM::VLDMQIA:
+ case ARM::VLDMQDB: {
+ unsigned NewOpc = (Opcode == ARM::VLDMQIA) ? ARM::VLDMDIA : ARM::VLDMDDB;
MachineInstrBuilder MIB =
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::VLDMD));
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
unsigned OpIdx = 0;
+
// Grab the Q register destination.
bool DstIsDead = MI.getOperand(OpIdx).isDead();
unsigned DstReg = MI.getOperand(OpIdx++).getReg();
- // Copy the addrmode4 operands.
- MIB.addOperand(MI.getOperand(OpIdx++));
+
+ // Copy the source register.
MIB.addOperand(MI.getOperand(OpIdx++));
+
// Copy the predicate operands.
MIB.addOperand(MI.getOperand(OpIdx++));
MIB.addOperand(MI.getOperand(OpIdx++));
+
// Add the destination operands (D subregs).
unsigned D0 = TRI->getSubReg(DstReg, ARM::dsub_0);
unsigned D1 = TRI->getSubReg(DstReg, ARM::dsub_1);
MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))
.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
+
// Add an implicit def for the super-register.
MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
TransferImpOps(MI, MIB, MIB);
@@ -807,26 +813,33 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
break;
}
- case ARM::VSTMQ: {
+ case ARM::VSTMQIA:
+ case ARM::VSTMQDB: {
+ unsigned NewOpc = (Opcode == ARM::VSTMQIA) ? ARM::VSTMDIA : ARM::VSTMDDB;
MachineInstrBuilder MIB =
- BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::VSTMD));
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
unsigned OpIdx = 0;
+
// Grab the Q register source.
bool SrcIsKill = MI.getOperand(OpIdx).isKill();
unsigned SrcReg = MI.getOperand(OpIdx++).getReg();
- // Copy the addrmode4 operands.
- MIB.addOperand(MI.getOperand(OpIdx++));
+
+ // Copy the destination register.
MIB.addOperand(MI.getOperand(OpIdx++));
+
// Copy the predicate operands.
MIB.addOperand(MI.getOperand(OpIdx++));
MIB.addOperand(MI.getOperand(OpIdx++));
+
// Add the source operands (D subregs).
unsigned D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);
unsigned D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);
MIB.addReg(D0).addReg(D1);
+
if (SrcIsKill)
// Add an implicit kill for the Q register.
(*MIB).addRegisterKilled(SrcReg, TRI, true);
+
TransferImpOps(MI, MIB, MIB);
MI.eraseFromParent();
break;
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index 5a68c565bb..0c7c0b8aab 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -1194,18 +1194,6 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
}
}
-// FIXME: remove when we have a way to marking a MI with these properties.
-// FIXME: Should pc be an implicit operand like PICADD, etc?
-let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
- hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
- def LDM_RET : AXI4ld<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$mode, pred:$p,
- reglist:$dsts, variable_ops),
- IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr,
- "ldm${mode}${p}\t$Rn!, $dsts",
- "$Rn = $wb", []> {
- let Inst{21} = 1;
-}
-
// On non-Darwin platforms R9 is callee-saved.
let isCall = 1,
Defs = [R0, R1, R2, R3, R12, LR,
@@ -1797,23 +1785,23 @@ def STRHT: AI3sthpo<(outs GPR:$base_wb),
multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
InstrItinClass itin, InstrItinClass itin_upd> {
- def ia :
+ def IA :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeNone, f, itin,
- !strconcat(asm, "${p}\t$Rn, $regs"), "", []> {
+ !strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> {
let Inst{24-23} = 0b01; // Increment After
let Inst{21} = 0; // No writeback
let Inst{20} = L_bit;
}
- def ia_UPD :
+ def IA_UPD :
AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeUpd, f, itin_upd,
- !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+ !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b01; // Increment After
- let Inst{21} = 1; // No writeback
+ let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
}
- def da :
+ def DA :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeNone, f, itin,
!strconcat(asm, "da${p}\t$Rn, $regs"), "", []> {
@@ -1821,15 +1809,15 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
let Inst{21} = 0; // No writeback
let Inst{20} = L_bit;
}
- def da_UPD :
+ def DA_UPD :
AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeUpd, f, itin_upd,
!strconcat(asm, "da${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b00; // Decrement After
- let Inst{21} = 1; // No writeback
+ let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
}
- def db :
+ def DB :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeNone, f, itin,
!strconcat(asm, "db${p}\t$Rn, $regs"), "", []> {
@@ -1837,15 +1825,15 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
let Inst{21} = 0; // No writeback
let Inst{20} = L_bit;
}
- def db_UPD :
+ def DB_UPD :
AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeUpd, f, itin_upd,
!strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b10; // Decrement Before
- let Inst{21} = 1; // No writeback
+ let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
}
- def ib :
+ def IB :
AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeNone, f, itin,
!strconcat(asm, "ib${p}\t$Rn, $regs"), "", []> {
@@ -1853,17 +1841,16 @@ multiclass arm_ldst_mult<string asm, bit L_bit, Format f,
let Inst{21} = 0; // No writeback
let Inst{20} = L_bit;
}
- def ib_UPD :
+ def IB_UPD :
AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IndexModeUpd, f, itin_upd,
!strconcat(asm, "ib${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b11; // Increment Before
- let Inst{21} = 1; // No writeback
+ let Inst{21} = 1; // Writeback
let Inst{20} = L_bit;
}
}
-/* TODO:
let neverHasSideEffects = 1 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
@@ -1873,45 +1860,24 @@ let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
defm STM : arm_ldst_mult<"stm", 0, LdStMulFrm, IIC_iStore_m, IIC_iStore_mu>;
} // neverHasSideEffects
-*/
-let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1,
- isCodeGenOnly = 1 in {
-def LDM : AXI4ld<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$dsts, variable_ops),
- IndexModeNone, LdStMulFrm, IIC_iLoad_m,
- "ldm${amode}${p}\t$Rn, $dsts", "", []> {
- let Inst{21} = 0;
-}
+// Load / Store Multiple Mnemnoic Aliases
+def : MnemonicAlias<"ldm", "ldmia">;
+def : MnemonicAlias<"stm", "stmia">;
-def LDM_UPD : AXI4ld<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$dsts, variable_ops),
- IndexModeUpd, LdStMulFrm, IIC_iLoad_mu,
- "ldm${amode}${p}\t$Rn!, $dsts",
- "$Rn = $wb", []> {
- let Inst{21} = 1;
+// FIXME: remove when we have a way to marking a MI with these properties.
+// FIXME: Should pc be an implicit operand like PICADD, etc?
+let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
+ hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
+def LDMIA_RET : AXI4ld<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
+ reglist:$dsts, variable_ops),
+ IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr,
+ "ldmia${p}\t$Rn!, $dsts",
+ "$Rn = $wb", []> {
+ let Inst{24-23} = 0b01; // Increment After
+ let Inst{21} = 1; // Writeback
}
-} // mayLoad, neverHasSideEffects, hasExtraDefRegAllocReq
-let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1,
- isCodeGenOnly = 1 in {
-def STM : AXI4st<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$srcs, variable_ops),
- IndexModeNone, LdStMulFrm, IIC_iStore_m,
- "stm${amode}${p}\t$Rn, $srcs", "", []> {
- let Inst{21} = 0;
-}
-
-def STM_UPD : AXI4st<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$srcs, variable_ops),
- IndexModeUpd, LdStMulFrm, IIC_iStore_mu,
- "stm${amode}${p}\t$Rn!, $srcs",
- "$Rn = $wb", []> {
- bits<4> p;
- let Inst{31-28} = p;
- let Inst{21} = 1;
-}
-} // mayStore, neverHasSideEffects, hasExtraSrcRegAllocReq
//===----------------------------------------------------------------------===//
// Move Instructions.
diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td
index d3e83f42b1..f9a1d0dae6 100644
--- a/lib/Target/ARM/ARMInstrNEON.td
+++ b/lib/Target/ARM/ARMInstrNEON.td
@@ -142,15 +142,23 @@ def nModImm : Operand<i32> {
// Use VLDM to load a Q register as a D register pair.
// This is a pseudo instruction that is expanded to VLDMD after reg alloc.
-def VLDMQ
- : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn, ldstm_mode:$mode),
+def VLDMQIA
+ : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn),
+ IIC_fpLoad_m, "",
+ [(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>;
+def VLDMQDB
+ : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn),
IIC_fpLoad_m, "",
[(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>;
// Use VSTM to store a Q register as a D register pair.
// This is a pseudo instruction that is expanded to VSTMD after reg alloc.
-def VSTMQ
- : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn, ldstm_mode:$mode),
+def VSTMQIA
+ : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn),
+ IIC_fpStore_m, "",
+ [(store (v2f64 QPR:$src), GPR:$Rn)]>;
+def VSTMQDB
+ : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn),
IIC_fpStore_m, "",
[(store (v2f64 QPR:$src), GPR:$Rn)]>;
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 2d387bb394..d7a22a4842 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -539,17 +539,17 @@ def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i,
multiclass thumb_ldst_mult<string asm, InstrItinClass itin,
InstrItinClass itin_upd, bits<6> T1Enc,
bit L_bit> {
- def ia :
+ def IA :
T1I<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin, !strconcat(asm, "${p}\t$Rn, $regs"), []>,
+ itin, !strconcat(asm, "ia${p}\t$Rn, $regs"), []>,
T1Encoding<T1Enc>;
- def ia_UPD :
+ def IA_UPD :
T1It<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin_upd, !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []>,
+ itin_upd, !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []>,
T1Encoding<T1Enc>;
}
-/* TODO: Uncommented, this causes a decoding conflict.
+// These require base address to be written back or one of the loaded regs.
let neverHasSideEffects = 1 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
@@ -561,36 +561,6 @@ defm tSTM : thumb_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu,
{1,1,0,0,0,?}, 0>;
} // neverHasSideEffects
-*/
-
-// These require base address to be written back or one of the loaded regs.
-let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1,
- isCodeGenOnly = 1 in {
-def tLDM : T1I<(outs),
- (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, reglist:$dsts,
- variable_ops),
- IIC_iLoad_m,
- "ldm${amode}${p}\t$Rn, $dsts", []>,
- T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53
-
-def tLDM_UPD : T1It<(outs tGPR:$wb),
- (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, reglist:$dsts,
- variable_ops),
- IIC_iLoad_m,
- "ldm${amode}${p}\t$Rn!, $dsts",
- "$Rn = $wb", []>,
- T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53
-} // mayLoad, neverHasSideEffects = 1, hasExtraDefRegAllocReq
-
-let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1,
- isCodeGenOnly = 1 in
-def tSTM_UPD : T1It<(outs tGPR:$wb),
- (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, reglist:$srcs,
- variable_ops),
- IIC_iStore_mu,
- "stm${amode}${p}\t$Rn!, $srcs",
- "$Rn = $wb", []>,
- T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189
let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in
def tPOP : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops),
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 9d09019dba..e9d5212a46 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -1501,9 +1501,9 @@ defm t2PLI : T2Ipl<0, 1, "pli">, Requires<[IsThumb2,HasV7]>;
multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
InstrItinClass itin_upd, bit L_bit> {
- def ia :
+ def IA :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
+ itin, !strconcat(asm, "ia${p}.w\t$Rn, $regs"), []> {
bits<4> Rn;
bits<16> regs;
@@ -1516,9 +1516,9 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
let Inst{19-16} = Rn;
let Inst{15-0} = regs;
}
- def ia_UPD :
+ def IA_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
+ itin_upd, !strconcat(asm, "ia${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
bits<4> Rn;
bits<16> regs;
@@ -1531,7 +1531,7 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
let Inst{19-16} = Rn;
let Inst{15-0} = regs;
}
- def db :
+ def DB :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin, !strconcat(asm, "db${p}.w\t$Rn, $regs"), []> {
bits<4> Rn;
@@ -1546,7 +1546,7 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
let Inst{19-16} = Rn;
let Inst{15-0} = regs;
}
- def db_UPD :
+ def DB_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin_upd, !strconcat(asm, "db${p}.w\t$Rn, $regs"), "$Rn = $wb", []> {
bits<4> Rn;
@@ -1563,7 +1563,6 @@ multiclass thumb2_ldst_mult<string asm, InstrItinClass itin,
}
}
-/* TODO:
let neverHasSideEffects = 1 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in
@@ -1573,61 +1572,7 @@ let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
defm t2STM : thumb2_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu, 0>;
} // neverHasSideEffects
-*/
-let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1,
- isCodeGenOnly = 1 in {
-def t2LDM : T2XI<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$dsts, variable_ops), IIC_iLoad_m,
- "ldm${amode}${p}.w\t$Rn, $dsts", []> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b00;
- let Inst{24-23} = {?, ?}; // IA: '01', DB: '10'
- let Inst{22} = 0;
- let Inst{21} = 0; // The W bit.
- let Inst{20} = 1; // Load
-}
-
-def t2LDM_UPD : T2XIt<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$dsts, variable_ops),
- IIC_iLoad_mu,
- "ldm${amode}${p}.w\t$Rn!, $dsts",
- "$Rn = $wb", []> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b00;
- let Inst{24-23} = {?, ?}; // IA: '01', DB: '10'
- let Inst{22} = 0;
- let Inst{21} = 1; // The W bit.
- let Inst{20} = 1; // Load
-}
-} // mayLoad, neverHasSideEffects, hasExtraDefRegAllocReq
-
-let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1,
- isCodeGenOnly = 1 in {
-def t2STM : T2XI<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$srcs, variable_ops), IIC_iStore_m,
- "stm${amode}${p}.w\t$Rn, $srcs", []> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b00;
- let Inst{24-23} = {?, ?}; // IA: '01', DB: '10'
- let Inst{22} = 0;
- let Inst{21} = 0; // The W bit.
- let Inst{20} = 0; // Store
-}
-
-def t2STM_UPD : T2XIt<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
- reglist:$srcs, variable_ops),
- IIC_iStore_m,
- "stm${amode}${p}.w\t$Rn!, $srcs",
- "$Rn = $wb", []> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b00;
- let Inst{24-23} = {?, ?}; // IA: '01', DB: '10'
- let Inst{22} = 0;
- let Inst{21} = 1; // The W bit.
- let Inst{20} = 0; // Store
-}
-} // mayStore, neverHasSideEffects, hasExtraSrcRegAllocReq
//===----------------------------------------------------------------------===//
// Move Instructions.
@@ -2814,17 +2759,14 @@ let Defs =
// FIXME: Should pc be an implicit operand like PICADD, etc?
let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in
- def t2LDM_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p,
+def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
reglist:$dsts, variable_ops),
IIC_iLoad_mBr,
- "ldm${amode}${p}.w\t$Rn!, $dsts",
+ "ldmia${p}.w\t$Rn!, $dsts",
"$Rn = $wb", []> {
- let Inst{31-27} = 0b11101;
- let Inst{26-25} = 0b00;
- let Inst{24-23} = {?, ?}; // IA: '01', DB: '10'
- let Inst{22} = 0;
- let Inst{21} = 1; // The W bit.
- let Inst{20} = 1; // Load
+ let Inst{24-23} = 0b01; // IA: '01', DB: '10'
+ let Inst{21} = 1; // The W bit.
+ let Inst{20} = 1; // Load
}
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index e4048dd886..a9c99a191c 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -74,25 +74,26 @@ def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$Sd, addrmode5:$addr),
// Load / store multiple Instructions.
//
-multiclass vfp_ldst_d_mult<string asm, bit L_bit,
- InstrItinClass itin, InstrItinClass itin_upd> {
- def ia :
+multiclass vfp_ldst_mult<string asm, bit L_bit,
+ InstrItinCla