diff options
author | Bill Wendling <isanbard@gmail.com> | 2010-11-16 01:16:36 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2010-11-16 01:16:36 +0000 |
commit | 73fe34a3ee866867d5028f4a9afa2c3b8efebcba (patch) | |
tree | 38de70b817c48c84c6ab08ed78cf54b245b7d640 | |
parent | 88af6b9217f9ff8b4592f38ac5175de697275f49 (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.cpp | 215 | ||||
-rw-r--r-- | lib/Target/ARM/ARMExpandPseudoInsts.cpp | 29 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 90 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrNEON.td | 16 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb.td | 40 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 80 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrVFP.td | 119 | ||||
-rw-r--r-- | lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 303 | ||||
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp | 32 | ||||
-rw-r--r-- | lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h | 71 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 60 | ||||
-rw-r--r-- | lib/Target/ARM/Thumb2SizeReduction.cpp | 43 | ||||
-rw-r--r-- | utils/TableGen/ARMDecoderEmitter.cpp | 10 |
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 |