diff options
Diffstat (limited to 'lib/Target')
-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(); |