diff options
author | Jim Grosbach <grosbach@apple.com> | 2010-10-26 22:37:02 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2010-10-26 22:37:02 +0000 |
commit | 3e5561247202bae994dd259a2d8dc4eff8f799f3 (patch) | |
tree | 4a3d53fc109ee222ad3a4dae98373aca68dcff1f /lib | |
parent | 3a0e0715a5691e26ca70bc853d6d3d116e5949b8 (diff) | |
download | external_llvm-3e5561247202bae994dd259a2d8dc4eff8f799f3.zip external_llvm-3e5561247202bae994dd259a2d8dc4eff8f799f3.tar.gz external_llvm-3e5561247202bae994dd259a2d8dc4eff8f799f3.tar.bz2 |
First part of refactoring ARM addrmode2 (load/store) instructions to be more
explicit about the operands. Split out the different variants into separate
instructions. This gives us the ability to, among other things, assign
different scheduling itineraries to the variants. rdar://8477752.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117409 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM/ARMAsmPrinter.cpp | 11 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 21 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.h | 1 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseRegisterInfo.cpp | 10 | ||||
-rw-r--r-- | lib/Target/ARM/ARMCodeEmitter.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMConstantIslandPass.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMFastISel.cpp | 15 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 139 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 33 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 70 | ||||
-rw-r--r-- | lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 45 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 23 | ||||
-rw-r--r-- | lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 5 |
14 files changed, 314 insertions, 65 deletions
diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 01ad2f5..e334307 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -873,7 +873,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { case ARM::PICSTR: Opcode = ARM::STR; break; case ARM::PICSTRB: Opcode = ARM::STRB; break; case ARM::PICSTRH: Opcode = ARM::STRH; break; - case ARM::PICLDR: Opcode = ARM::LDR; break; + case ARM::PICLDR: Opcode = ARM::LDRrs; break; case ARM::PICLDRB: Opcode = ARM::LDRB; break; case ARM::PICLDRH: Opcode = ARM::LDRH; break; case ARM::PICLDRSB: Opcode = ARM::LDRSB; break; @@ -1220,10 +1220,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { unsigned ScratchReg = MI->getOperand(1).getReg(); { MCInst TmpInst; - TmpInst.setOpcode(ARM::LDR); + TmpInst.setOpcode(ARM::LDRi12); TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); - TmpInst.addOperand(MCOperand::CreateReg(0)); TmpInst.addOperand(MCOperand::CreateImm(8)); // Predicate. TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); @@ -1232,10 +1231,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } { MCInst TmpInst; - TmpInst.setOpcode(ARM::LDR); + TmpInst.setOpcode(ARM::LDRi12); TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); - TmpInst.addOperand(MCOperand::CreateReg(0)); TmpInst.addOperand(MCOperand::CreateImm(4)); // Predicate. TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); @@ -1244,10 +1242,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { } { MCInst TmpInst; - TmpInst.setOpcode(ARM::LDR); + TmpInst.setOpcode(ARM::LDRi12); TmpInst.addOperand(MCOperand::CreateReg(ARM::R7)); TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); - TmpInst.addOperand(MCOperand::CreateReg(0)); TmpInst.addOperand(MCOperand::CreateImm(0)); // Predicate. TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 8834ff3..98876bb 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -144,7 +144,7 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, if (isLoad) MemMI = BuildMI(MF, MI->getDebugLoc(), get(MemOpc), MI->getOperand(0).getReg()) - .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); + .addReg(WBReg).addImm(0).addImm(Pred); else MemMI = BuildMI(MF, MI->getDebugLoc(), get(MemOpc)).addReg(MI->getOperand(1).getReg()) @@ -155,7 +155,7 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, if (isLoad) MemMI = BuildMI(MF, MI->getDebugLoc(), get(MemOpc), MI->getOperand(0).getReg()) - .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); + .addReg(BaseReg).addImm(0).addImm(Pred); else MemMI = BuildMI(MF, MI->getDebugLoc(), get(MemOpc)).addReg(MI->getOperand(1).getReg()) @@ -823,8 +823,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, switch (RC->getID()) { case ARM::GPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg) - .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO)); + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDRi12), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); break; case ARM::SPRRegClassID: AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) @@ -894,7 +894,7 @@ ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { switch (MI->getOpcode()) { default: break; - case ARM::LDR: + case ARM::LDRrs: case ARM::t2LDRs: // FIXME: don't use t2LDRs to access frame. if (MI->getOperand(1).isFI() && MI->getOperand(2).isReg() && @@ -905,6 +905,7 @@ ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, return MI->getOperand(0).getReg(); } break; + case ARM::LDRi12: case ARM::t2LDRi12: case ARM::tRestore: case ARM::VLDRD: @@ -1078,7 +1079,7 @@ bool ARMBaseInstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, switch (Load1->getMachineOpcode()) { default: return false; - case ARM::LDR: + case ARM::LDRi12: case ARM::LDRB: case ARM::LDRD: case ARM::LDRH: @@ -1097,7 +1098,7 @@ bool ARMBaseInstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, switch (Load2->getMachineOpcode()) { default: return false; - case ARM::LDR: + case ARM::LDRi12: case ARM::LDRB: case ARM::LDRD: case ARM::LDRH: @@ -1362,6 +1363,12 @@ bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned NumBits = 0; unsigned Scale = 1; switch (AddrMode) { + case ARMII::AddrMode_i12: { + ImmIdx = FrameRegIdx + 1; + InstrOffs = MI.getOperand(ImmIdx).getImm(); + NumBits = 12; + break; + } case ARMII::AddrMode2: { ImmIdx = FrameRegIdx+2; InstrOffs = ARM_AM::getAM2Offset(MI.getOperand(ImmIdx).getImm()); diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index f607f26..e19bd9c 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -50,6 +50,7 @@ namespace ARMII { AddrModeT2_so = 13, AddrModeT2_pc = 14, // +/- i12 for pc relative data AddrModeT2_i8s4 = 15, // i8 * 4 + AddrMode_i12 = 16, // Size* - Flags to keep track of the size of an instruction. SizeShift = 5, diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index 736ba6d..e6e7892 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -1201,7 +1201,7 @@ emitLoadConstPool(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, dl, TII.get(ARM::LDRcp)) .addReg(DestReg, getDefRegState(true), SubIdx) .addConstantPoolIndex(Idx) - .addReg(0).addImm(0).addImm(Pred).addReg(PredReg); + .addImm(0).addImm(Pred).addReg(PredReg); } bool ARMBaseRegisterInfo:: @@ -1314,6 +1314,7 @@ getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const { switch (AddrMode) { case ARMII::AddrModeT2_i8: case ARMII::AddrModeT2_i12: + case ARMII::AddrMode_i12: InstrOffs = MI->getOperand(Idx+1).getImm(); Scale = 1; break; @@ -1375,7 +1376,7 @@ needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const { // return false for everything else. unsigned Opc = MI->getOpcode(); switch (Opc) { - case ARM::LDR: case ARM::LDRH: case ARM::LDRB: + case ARM::LDRi12: case ARM::LDRH: case ARM::LDRB: case ARM::STR: case ARM::STRH: case ARM::STRB: case ARM::t2LDRi12: case ARM::t2LDRi8: case ARM::t2STRi12: case ARM::t2STRi8: @@ -1519,6 +1520,7 @@ bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, NumBits = 8; Scale = 4; break; + case ARMII::AddrMode_i12: case ARMII::AddrMode2: NumBits = 12; break; @@ -1813,7 +1815,7 @@ static bool isCSRestore(MachineInstr *MI, const ARMBaseInstrInfo &TII, const unsigned *CSRegs) { return ((MI->getOpcode() == (int)ARM::VLDRD || - MI->getOpcode() == (int)ARM::LDR || + MI->getOpcode() == (int)ARM::LDRi12 || MI->getOpcode() == (int)ARM::t2LDRi12) && MI->getOperand(1).isFI() && isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)); @@ -1881,7 +1883,7 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getDPRCalleeSavedAreaSize()); // Move SP to SP upon entry to the function. - movePastCSLoadStoreOps(MBB, MBBI, ARM::LDR, ARM::t2LDRi12, 1, STI); + movePastCSLoadStoreOps(MBB, MBBI, ARM::LDRi12, ARM::t2LDRi12, 1, STI); emitSPUpdate(isARM, MBB, MBBI, dl, TII, AFI->getGPRCalleeSavedAreaSize()); } diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 78a73e2..edb9c90 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -174,6 +174,8 @@ namespace { const { return 0; } unsigned getBitfieldInvertedMaskOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getAddrModeImm12OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } /// getMovi32Value - Return binary encoding of operand for movw/movt. If the /// machine operand requires relocation, record the relocation and return diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 60e923b..6f01846 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -603,7 +603,7 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &MF, Scale = 4; break; - case ARM::LDR: + case ARM::LDRi12: case ARM::LDRcp: case ARM::t2LDRpci: Bits = 12; // +-offset_12 diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index bbaa308..7cf7ec0 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -449,7 +449,7 @@ unsigned ARMFastISel::ARMMaterializeInt(const Constant *C, EVT VT) { AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(ARM::LDRcp), DestReg) .addConstantPoolIndex(Idx) - .addReg(0).addImm(0)); + .addImm(0)); return DestReg; } @@ -750,7 +750,7 @@ bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg, RC = ARM::GPRRegisterClass; break; case MVT::i32: - Opc = isThumb ? ARM::t2LDRi12 : ARM::LDR; + Opc = isThumb ? ARM::t2LDRi12 : ARM::LDRi12; RC = ARM::GPRRegisterClass; break; case MVT::f32: @@ -776,14 +776,9 @@ bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg, // The thumb and floating point instructions both take 2 operands, ARM takes // another register. - if (isFloat || isThumb) - AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, - TII.get(Opc), ResultReg) - .addReg(Base).addImm(Offset)); - else - AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, - TII.get(Opc), ResultReg) - .addReg(Base).addReg(0).addImm(Offset)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(Opc), ResultReg) + .addReg(Base).addImm(Offset)); return true; } diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index bde1967..5285a43 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -80,6 +80,9 @@ public: bool SelectShifterOperandReg(SDValue N, SDValue &A, SDValue &B, SDValue &C); + bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); + bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); + AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset, @@ -95,6 +98,7 @@ public: bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc) { SelectAddrMode2Worker(N, Base, Offset, Opc); +// return SelectAddrMode2ShOp(N, Base, Offset, Opc); // This always matches one way or another. return true; } @@ -268,6 +272,138 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, return true; } +bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, + SDValue &Base, + SDValue &OffImm) { + // Match simple R + imm12 operands. + + // Base only. + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { + if (N.getOpcode() == ISD::FrameIndex) { + // Match frame index... + int FI = cast<FrameIndexSDNode>(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } else if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } else + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (N.getOpcode() == ISD::SUB) + RHSC = -RHSC; + + if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast<FrameIndexSDNode>(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + + // Base only. + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + + + +bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, + SDValue &Opc) { + if (N.getOpcode() == ISD::MUL) { + if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { + // X * [3,5,9] -> X + X * [2,4,8] etc. + int RHSC = (int)RHS->getZExtValue(); + if (RHSC & 1) { + RHSC = RHSC & ~1; + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + if (isPowerOf2_32(RHSC)) { + unsigned ShAmt = Log2_32(RHSC); + Base = Offset = N.getOperand(0); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, + ARM_AM::lsl), + MVT::i32); + return true; + } + } + } + } + + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) + return false; + + // Leave simple R +/- imm12 operands for LDRi12 + if (N.getOpcode() == ISD::ADD) { + if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if ((RHSC >= 0 && RHSC < 0x1000) || + (RHSC < 0 && RHSC > -0x1000)) // 12 bits. + return false; + } + } + + // Otherwise this is R +/- [possibly shifted] R. + ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + unsigned ShAmt = 0; + + Base = N.getOperand(0); + Offset = N.getOperand(1); + + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = + dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + Offset = N.getOperand(1).getOperand(0); + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + // Try matching (R shl C) + (R). + if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't + // fold it. + if (ConstantSDNode *Sh = + dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + Offset = N.getOperand(0).getOperand(0); + Base = N.getOperand(1); + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + } + + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), + MVT::i32); + return true; +} + + + + +//----- + AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, SDValue &Base, SDValue &Offset, @@ -1701,14 +1837,13 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { } else { SDValue Ops[] = { CPIdx, - CurDAG->getRegister(0, MVT::i32), CurDAG->getTargetConstant(0, MVT::i32), getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), CurDAG->getEntryNode() }; ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, - Ops, 6); + Ops, 5); } ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); return NULL; diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 7069e91..2350e40 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -104,6 +104,7 @@ def AddrModeT2_i8 : AddrMode<12>; def AddrModeT2_so : AddrMode<13>; def AddrModeT2_pc : AddrMode<14>; def AddrModeT2_i8s4 : AddrMode<15>; +def AddrMode_i12 : AddrMode<16>; // Instruction size. class SizeFlagVal<bits<3> val> { @@ -399,6 +400,38 @@ class AI2<dag oops, dag iops, Format f, InstrItinClass itin, } // loads + +// LDR/LDRB +class AIldr1<bits<3> op, bit opc22, dag oops, dag iops, AddrMode am, Format f, + InstrItinClass itin, string opc, string asm, list<dag> pattern> + : I<oops, iops, am, Size4Bytes, IndexModeNone, f, itin, opc, asm, + "", pattern> { + let Inst{27-25} = op; + let Inst{24} = 1; // 24 == P + // 23 == U + let Inst{22} = opc22; + let Inst{21} = 0; // 21 == W + let Inst{20} = 1; +} +// LDRH/LDRSB/LDRSH/LDRD +class AIldr2<bits<4> op, bit opc22, bit opc20, dag oops, dag iops, AddrMode am, + Format f, InstrItinClass itin, string opc, string asm, + list<dag> pattern> + : I<oops, iops, am, Size4Bytes, IndexModeNone, f, itin, opc, asm, + "", pattern> { + let Inst{27-25} = 0b000; + let Inst{24} = 1; // 24 == P + // 23 == U + let Inst{22} = opc22; + let Inst{21} = 0; // 21 == W + let Inst{20} = opc20; + + let Inst{7-4} = op; +} + + + + class AI2ldw<dag oops, dag iops, Format f, InstrItinClass itin, string opc, string asm, list<dag> pattern> : I<oops, iops, AddrMode2, Size4Bytes, IndexModeNone, f, itin, diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index ba228ff..671b8e0 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -33,7 +33,7 @@ unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { default: break; case ARM::LDR_PRE: case ARM::LDR_POST: - return ARM::LDR; + return ARM::LDRi12; case ARM::LDRH_PRE: case ARM::LDRH_POST: return ARM::LDRH; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index d82ff25..e447a4a 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -382,22 +382,27 @@ def imm0_31_m1 : Operand<i32>, PatLeaf<(imm), [{ // Define ARM specific addressing modes. -// addrmode2base := reg +/- imm12 + +// addrmode_imm12 := reg +/- imm12 // -def addrmode2base : Operand<i32>, - ComplexPattern<i32, 3, "SelectAddrMode2Base", []> { - let PrintMethod = "printAddrMode2Operand"; - let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +def addrmode_imm12 : Operand<i32>, + ComplexPattern<i32, 2, "SelectAddrModeImm12", []> { + + string EncoderMethod = "getAddrModeImm12OpValue"; + let PrintMethod = "printAddrModeImm12Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } -// addrmode2shop := reg +/- reg shop imm +// ldst_so_reg := reg +/- reg shop imm // -def addrmode2shop : Operand<i32>, - ComplexPattern<i32, 3, "SelectAddrMode2ShOp", []> { +def ldst_so_reg : Operand<i32>, + ComplexPattern<i32, 3, "SelectLdStSOReg", []> { + // FIXME: Simplify the printer let PrintMethod = "printAddrMode2Operand"; let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); } -// addrmode2 := (addrmode2base || addrmode2shop) +// addrmode2 := reg +/- imm12 +// := reg +/- reg shop imm // def addrmode2 : Operand<i32>, ComplexPattern<i32, 3, "SelectAddrMode2", []> { @@ -797,6 +802,34 @@ multiclass AI1_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode, } } +let canFoldAsLoad = 1, isReMaterializable = 1 in { +multiclass AI_ldr1<bit opc22, string opc, InstrItinClass iii, + InstrItinClass iir, PatFrag opnode> { + // Note: We use the complex addrmode_imm12 rather than just an input + // GPR and a constrained immediate so that we can use this to match + // frame index references and avoid matching constant pool references. + def i12 : AIldr1<0b010, 0, (outs GPR:$Rt), (ins addrmode_imm12:$addr), + AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr", + [(set GPR:$Rt, (opnode addrmode_imm12:$addr))]> { + bits<4> Rt; + bits<17> addr; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = addr{11-0}; // imm12 + } + def rs : AIldr1<0b011, 0, (outs GPR:$Rt), (ins ldst_so_reg:$shift), + AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift", + [(set GPR:$Rt, (opnode ldst_so_reg:$shift))]> { + bits<4> Rt; + bits<17> shift; + let Inst{23} = shift{12}; // U (add = ('U' == 1)) + let Inst{19-16} = shift{16-13}; // Rn + let Inst{11-0} = shift{11-0}; + } +} +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -1365,16 +1398,23 @@ def RFE : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, GPR:$base), // // Load -let canFoldAsLoad = 1, isReMaterializable = 1 in -def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoad_r, - "ldr", "\t$dst, $addr", - [(set GPR:$dst, (load addrmode2:$addr))]>; + + +defm LDR : AI_ldr1<0, "ldr", IIC_iLoad_i, IIC_iLoad_r, + UnOpFrag<(load node:$Src)>>; // Special LDR for loads from non-pc-relative constpools. let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1, isReMaterializable = 1 in -def LDRcp : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoad_r, - "ldr", "\t$dst, $addr", []>; +def LDRcp : AIldr1<0b010, 0, (outs GPR:$Rt), (ins addrmode_imm12:$addr), + AddrMode_i12, LdFrm, IIC_iLoad_r, "ldr", "\t$Rt, $addr", []> { + bits<4> Rt; + bits<17> addr; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rt; + let Inst{11-0} = addr{11-0}; // imm12 +} // Loads with zero extension def LDRH : AI3ldh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index 44c6821..85a0981 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -130,7 +130,7 @@ namespace { static int getLoadStoreMultipleOpcode(int Opcode) { switch (Opcode) { - case ARM::LDR: + case ARM::LDRi12: ++NumLDMGened; return ARM::LDM; case ARM::STR: @@ -166,7 +166,7 @@ static bool isT2i32Load(unsigned Opc) { } static bool isi32Load(unsigned Opc) { - return Opc == ARM::LDR || isT2i32Load(Opc); + return Opc == ARM::LDRi12 || isT2i32Load(Opc); } static bool isT2i32Store(unsigned Opc) { @@ -440,7 +440,7 @@ static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base, static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) { switch (MI->getOpcode()) { default: return 0; - case ARM::LDR: + case ARM::LDRi12: case ARM::STR: case ARM::t2LDRi8: case ARM::t2LDRi12: @@ -578,7 +578,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) { switch (Opc) { - case ARM::LDR: return ARM::LDR_PRE; + case ARM::LDRi12: return ARM::LDR_PRE; case ARM::STR: return ARM::STR_PRE; case ARM::VLDRS: return ARM::VLDMS_UPD; case ARM::VLDRD: return ARM::VLDMD_UPD; @@ -597,7 +597,7 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) { static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) { switch (Opc) { - case ARM::LDR: return ARM::LDR_POST; + case ARM::LDRi12: return ARM::LDR_POST; case ARM::STR: return ARM::STR_POST; case ARM::VLDRS: return ARM::VLDMS_UPD; case ARM::VLDRD: return ARM::VLDMD_UPD; @@ -629,14 +629,18 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, DebugLoc dl = MI->getDebugLoc(); bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS || Opcode == ARM::VSTRD || Opcode == ARM::VSTRS); - bool isAM2 = (Opcode == ARM::LDR || Opcode == ARM::STR); - if (isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) + bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STR); + // FIXME: This special handling of LDRi12 is hackery until all of the ARM + // LDR/STR insns are moved away from the addrmode2 mega-instruction to + // the split (LDRi12/LDRrs) style instructions. + if (Opcode == ARM::LDRi12 || isT2i32Load(Opcode) || isT2i32Store(Opcode)) + if (MI->getOperand(2).getImm() != 0) + return false; + if (isAM2 && Opcode != ARM::LDRi12 + && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) return false; if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0) return false; - if (isT2i32Load(Opcode) || isT2i32Store(Opcode)) - if (MI->getOperand(2).getImm() != 0) - return false; bool isLd = isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD; // Can't do the merge if the destination register is the same as the would-be @@ -782,7 +786,6 @@ static bool isMemoryOp(const MachineInstr *MI) { int Opcode = MI->getOpcode(); switch (Opcode) { default: break; - case ARM::LDR: case ARM::STR: return MI->getOperand(1).isReg() && MI->getOperand(2).getReg() == 0; case ARM::VLDRS: @@ -791,6 +794,7 @@ static bool isMemoryOp(const MachineInstr *MI) { case ARM::VLDRD: case ARM::VSTRD: return MI->getOperand(1).isReg(); + case ARM::LDRi12: case ARM::t2LDRi8: case ARM::t2LDRi12: case ARM::t2STRi8: @@ -818,14 +822,15 @@ void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) { static int getMemoryOpOffset(const MachineInstr *MI) { int Opcode = MI->getOpcode(); - bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR; + bool isAM2 = Opcode == ARM::STR; bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD; unsigned NumOperands = MI->getDesc().getNumOperands(); unsigned OffField = MI->getOperand(NumOperands-3).getImm(); if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 || Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 || - Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) + Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 || + Opcode == ARM::LDRi12) return OffField; int Offset = isAM2 @@ -944,7 +949,7 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, assert((!isT2 || !OffReg) && "Thumb2 ldrd / strd does not encode offset register!"); unsigned NewOpc = (isLd) - ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDR) + ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12) : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STR); DebugLoc dl = MBBI->getDebugLoc(); // If this is a load and base register is killed, it may have been @@ -1342,7 +1347,7 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, // FIXME: VLDRS / VSTRS -> VLDRD / VSTRD unsigned Scale = 1; unsigned Opcode = Op0->getOpcode(); - if (Opcode == ARM::LDR) + if (Opcode == ARM::LDRi12) NewOpc = ARM::LDRD; else if (Opcode == ARM::STR) NewOpc = ARM::STRD; @@ -1358,7 +1363,7 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, return false; // Make sure the offset registers match. - if (!isT2 && + if (!isT2 && Opcode != ARM::LDRi12 && (Op0->getOperand(2).getReg() != Op1->getOperand(2).getReg())) return false; @@ -1405,7 +1410,7 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, if (EvenReg == OddReg) return false; BaseReg = Op0->getOperand(1).getReg(); - if (!isT2) + if (!isT2 && Opcode != ARM::LDRi12) OffReg = Op0->getOperand(2).getReg(); Pred = llvm::getInstrPredicate(Op0, PredReg); dl = Op0->getDebugLoc(); @@ -1513,8 +1518,12 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, .addReg(EvenReg, RegState::Define) .addReg(OddReg, RegState::Define) .addReg(BaseReg); + // For now, we're converting from LDRi12 to an insn that still + // uses addrmode2, so we need an explicit offset reg. It should + // always by reg0 since we're transforming LDRi12s. The old + // was just being paranoid in allowing for anything else. if (!isT2) - MIB.addReg(OffReg); + MIB.addReg(0); MIB.addImm(Offset).addImm(Pred).addReg(PredReg); ++NumLDRDFormed; } else { diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index f0680e8..13a80bd 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -49,6 +49,10 @@ public: /// operand requires relocation, record the relocation and return zero. unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const; + /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' + /// operand. + unsigned getAddrModeImm12OpValue(const MCInst &MI, unsigned Op) const; + /// getCCOutOpValue - Return encoding of the 's' bit. unsigned getCCOutOpValue(const MCInst &MI, unsigned Op) const { // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or @@ -171,6 +175,25 @@ unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI, return 0; } +/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' +/// operand. +unsigned ARMMCCodeEmitter::getAddrModeImm12OpValue(const MCInst &MI, + unsigned OpIdx) const { + // {17-13} = reg + // {12} = (U)nsigned (add == '1', sub == '0') + // {11-0} = imm12 + const MCOperand &MO = MI.getOperand(OpIdx); + const MCOperand &MO1 = MI.getOperand(OpIdx + 1); + unsigned Reg = getARMRegisterNumbering(MO.getReg()); + int32_t Imm12 = MO1.getImm(); + uint32_t Binary; + Binary = Imm12 & 0xfff; + if (Imm12 >= 0) + Binary |= (1 << 12); + Binary |= (Reg << 13); + return Binary; +} + unsigned ARMMCCodeEmitter::getSORegOpValue(const MCInst &MI, unsigned OpIdx) const { // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index fd1bdc3..5df5aa1 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -605,6 +605,11 @@ void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum, const MCOperand &MO1 = MI->getOperand(OpNum); const MCOperand &MO2 = MI->getOperand(OpNum+1); + if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, OpNum, O); + return; + } + O << "[" << getRegisterName(MO1.getReg()); unsigned OffImm = MO2.getImm(); |