/// EmitLiveInCopies - Emit copies to initialize livein virtual registers /// into the given entry block. void MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB, const TargetRegisterInfo &TRI, const TargetInstrInfo &TII) { // Emit the copies into the top of the block. for (unsigned i = 0, e = LiveIns.size(); i != e; ++i) if (LiveIns[i].second) { if (use_empty(LiveIns[i].second)) { // The livein has no uses. Drop it. // // It would be preferable to have isel avoid creating live-in // records for unused arguments in the first place, but it's // complicated by the debug info code for arguments. LiveIns.erase(LiveIns.begin() + i); --i; --e; } else { // Emit a copy. BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(), TII.get(TargetOpcode::COPY), LiveIns[i].second) .addReg(LiveIns[i].first); // Add the register to the entry block live-in set. EntryMBB->addLiveIn(LiveIns[i].first); } } else { // Add the register to the entry block live-in set. EntryMBB->addLiveIn(LiveIns[i].first); } }
/// emitSPUpdate - Emit a series of instructions to increment / decrement the /// stack pointer by a constant value. static void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int64_t NumBytes, const TargetInstrInfo &TII) { unsigned Opc; uint64_t Chunk; bool isSub = NumBytes < 0; uint64_t Offset = isSub ? -NumBytes : NumBytes; if (Offset >= (1LL << 15) - 1) { Opc = SystemZ::ADD64ri32; Chunk = (1LL << 31) - 1; } else { Opc = SystemZ::ADD64ri16; Chunk = (1LL << 15) - 1; } DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); while (Offset) { uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset; MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D) .addReg(SystemZ::R15D).addImm(isSub ? -ThisVal : ThisVal); // The PSW implicit def is dead. MI->getOperand(3).setIsDead(); Offset -= ThisVal; } }
static void EmitDefCfaOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc dl, const TargetInstrInfo &TII, MachineModuleInfo *MMI, int Offset) { MCSymbol *Label = MMI->getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(Label); MMI->addFrameInst(MCCFIInstruction::createDefCfaOffset(Label, -Offset)); }
static void EmitCfiOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc dl, const TargetInstrInfo &TII, MachineModuleInfo *MMI, unsigned DRegNum, int Offset) { unsigned CFIIndex = MMI->addFrameInst( MCCFIInstruction::createOffset(nullptr, DRegNum, Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); }
static void EmitCfiOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc dl, const TargetInstrInfo &TII, MachineModuleInfo *MMI, unsigned DRegNum, int Offset, MCSymbol *Label) { if (!Label) { Label = MMI->getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(Label); } MMI->addFrameInst(MCCFIInstruction::createOffset(Label, DRegNum, Offset)); }
unsigned llvm::Mips::loadImmediate(int64_t Imm, bool IsN64, const TargetInstrInfo &TII, MachineBasicBlock& MBB, MachineBasicBlock::iterator II, DebugLoc DL, bool LastInstrIsADDiu, MipsAnalyzeImmediate::Inst *LastInst) { MipsAnalyzeImmediate AnalyzeImm; unsigned Size = IsN64 ? 64 : 32; unsigned LUi = IsN64 ? Mips::LUi64 : Mips::LUi; unsigned ZEROReg = IsN64 ? Mips::ZERO_64 : Mips::ZERO; unsigned ATReg = IsN64 ? Mips::AT_64 : Mips::AT; const MipsAnalyzeImmediate::InstSeq &Seq = AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu); MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); if (LastInst && (Seq.size() == 1)) { *LastInst = *Inst; return 0; } // The first instruction can be a LUi, which is different from other // instructions (ADDiu, ORI and SLL) in that it does not have a register // operand. if (Inst->Opc == LUi) BuildMI(MBB, II, DL, TII.get(LUi), ATReg) .addImm(SignExtend64<16>(Inst->ImmOpnd)); else BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) .addImm(SignExtend64<16>(Inst->ImmOpnd)); // Build the remaining instructions in Seq. Skip the last instruction if // LastInst is not 0. for (++Inst; Inst != Seq.end() - !!LastInst; ++Inst) BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) .addImm(SignExtend64<16>(Inst->ImmOpnd)); if (LastInst) *LastInst = *Inst; return Seq.size() - !!LastInst; }
/// The SP register is moved in steps of 'MaxImmU16' towards the top of the /// frame. During these steps, it may be necessary to re-load registers. /// IfNeededLDAWSP emits the necessary LDAWSP instructions to move the SP only /// as far as to make 'OffsetFromTop' reachable using an LDAWSP_lru6. /// \param OffsetFromTop the spill offset from the top of the frame. /// \param [in,out] RemainingAdj the current SP offset from the top of the /// frame. static void IfNeededLDAWSP(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc dl, const TargetInstrInfo &TII, int OffsetFromTop, int &RemainingAdj) { while (OffsetFromTop < RemainingAdj - MaxImmU16) { assert(RemainingAdj && "OffsetFromTop is beyond FrameSize"); int OpImm = (RemainingAdj > MaxImmU16) ? MaxImmU16 : RemainingAdj; int Opcode = isImmU6(OpImm) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6; BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(OpImm); RemainingAdj -= OpImm; } }
static void loadFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DstReg, int Offset, DebugLoc dl, const TargetInstrInfo &TII) { assert(Offset%4 == 0 && "Misaligned stack offset"); Offset/=4; bool isU6 = isImmU6(Offset); if (!isU6 && !isImmU16(Offset)) report_fatal_error("loadFromStack offset too big " + Twine(Offset)); int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; BuildMI(MBB, I, dl, TII.get(Opcode), DstReg) .addImm(Offset); }
/// emitThumbConstant - Emit a series of instructions to materialize a /// constant. static void emitThumbConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, unsigned DestReg, int Imm, const TargetInstrInfo &TII, const Thumb1RegisterInfo& MRI, DebugLoc dl) { bool isSub = Imm < 0; if (isSub) Imm = -Imm; int Chunk = (1 << 8) - 1; int ThisVal = (Imm > Chunk) ? Chunk : Imm; Imm -= ThisVal; AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), DestReg)) .addImm(ThisVal)); if (Imm > 0) emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); if (isSub) { const MCInstrDesc &MCID = TII.get(ARM::tRSB); AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) .addReg(DestReg, RegState::Kill)); } }
unsigned llvm::constrainRegToClass(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, unsigned Reg, const TargetRegisterClass &RegClass) { if (!RBI.constrainGenericRegister(Reg, RegClass, MRI)) { unsigned NewReg = MRI.createVirtualRegister(&RegClass); BuildMI(*InsertPt.getParent(), InsertPt, InsertPt.getDebugLoc(), TII.get(TargetOpcode::COPY), NewReg) .addReg(Reg); return NewReg; } return Reg; }
/// The SP register is moved in steps of 'MaxImmU16' towards the bottom of the /// frame. During these steps, it may be necessary to spill registers. /// IfNeededExtSP emits the necessary EXTSP instructions to move the SP only /// as far as to make 'OffsetFromBottom' reachable using an STWSP_lru6. /// \param OffsetFromTop the spill offset from the top of the frame. /// \param [in,out] Adjusted the current SP offset from the top of the frame. static void IfNeededExtSP(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc dl, const TargetInstrInfo &TII, MachineModuleInfo *MMI, int OffsetFromTop, int &Adjusted, int FrameSize, bool emitFrameMoves) { while (OffsetFromTop > Adjusted) { assert(Adjusted < FrameSize && "OffsetFromTop is beyond FrameSize"); int remaining = FrameSize - Adjusted; int OpImm = (remaining > MaxImmU16) ? MaxImmU16 : remaining; int Opcode = isImmU6(OpImm) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6; BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(OpImm); Adjusted += OpImm; if (emitFrameMoves) EmitDefCfaOffset(MBB, MBBI, dl, TII, MMI, Adjusted*4); } }
/// Restore clobbered registers with their spill slot value. /// The SP will be adjusted at the same time, thus the SpillList must be ordered /// with the largest (negative) offsets first. static void RestoreSpillList(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc dl, const TargetInstrInfo &TII, int &RemainingAdj, SmallVectorImpl<StackSlotInfo> &SpillList) { for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { assert(SpillList[i].Offset % 4 == 0 && "Misaligned stack offset"); assert(SpillList[i].Offset <= 0 && "Unexpected positive stack offset"); int OffsetFromTop = - SpillList[i].Offset/4; IfNeededLDAWSP(MBB, MBBI, dl, TII, OffsetFromTop, RemainingAdj); int Offset = RemainingAdj - OffsetFromTop; int Opcode = isImmU6(Offset) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6; BuildMI(MBB, MBBI, dl, TII.get(Opcode), SpillList[i].Reg) .addImm(Offset) .addMemOperand(getFrameIndexMMO(MBB, SpillList[i].FI, MachineMemOperand::MOLoad)); } }
void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo, LiveIntervals &LIS, const TargetInstrInfo &TII) { DebugLoc DL; MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, DL, LIS); MachineOperand &Loc = locations[LocNo]; // Frame index locations may require a target callback. if (Loc.isFI()) { MachineInstr *MI = TII.emitFrameIndexDebugValue(*MBB->getParent(), Loc.getIndex(), offset, variable, DL); if (MI) { MBB->insert(I, MI); return; } } // This is not a frame index, or the target is happy with a standard FI. BuildMI(*MBB, I, DL, TII.get(TargetOpcode::DBG_VALUE)) .addOperand(Loc).addImm(offset).addMetadata(variable); }
/// emitSPUpdate - Emit a series of instructions to increment / decrement the /// stack pointer by a constant value. static void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, unsigned StackPtr, int64_t NumBytes, bool Is64Bit, const TargetInstrInfo &TII) { bool isSub = NumBytes < 0; uint64_t Offset = isSub ? -NumBytes : NumBytes; unsigned Opc = isSub ? getSUBriOpcode(Is64Bit, Offset) : getADDriOpcode(Is64Bit, Offset); uint64_t Chunk = (1LL << 31) - 1; DebugLoc DL = MBB.findDebugLoc(MBBI); while (Offset) { uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset; MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr) .addReg(StackPtr) .addImm(ThisVal); MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. Offset -= ThisVal; } }
/// emitSPUpdate - Emit a series of instructions to increment / decrement the /// stack pointer by a constant value. static void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, unsigned StackPtr, int64_t NumBytes, bool Is64Bit, const TargetInstrInfo &TII) { bool isSub = NumBytes < 0; uint64_t Offset = isSub ? -NumBytes : NumBytes; unsigned Opc = isSub ? ((Offset < 128) ? (Is64Bit ? X86::SUB64ri8 : X86::SUB32ri8) : (Is64Bit ? X86::SUB64ri32 : X86::SUB32ri)) : ((Offset < 128) ? (Is64Bit ? X86::ADD64ri8 : X86::ADD32ri8) : (Is64Bit ? X86::ADD64ri32 : X86::ADD32ri)); uint64_t Chunk = (1LL << 31) - 1; while (Offset) { uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset; MachineInstr *MI = BuildMI(MBB, MBBI, TII.get(Opc), StackPtr).addReg(StackPtr).addImm(ThisVal); // The EFLAGS implicit def is dead. MI->getOperand(3).setIsDead(); Offset -= ThisVal; } }
/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize /// a destreg = basereg + immediate in Thumb code. void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo& MRI, unsigned MIFlags) { bool isSub = NumBytes < 0; unsigned Bytes = (unsigned)NumBytes; if (isSub) Bytes = -NumBytes; bool isMul4 = (Bytes & 3) == 0; bool isTwoAddr = false; bool DstNotEqBase = false; unsigned NumBits = 1; unsigned Scale = 1; int Opc = 0; int ExtraOpc = 0; bool NeedCC = false; if (DestReg == BaseReg && BaseReg == ARM::SP) { assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); NumBits = 7; Scale = 4; Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; isTwoAddr = true; } else if (!isSub && BaseReg == ARM::SP) { // r1 = add sp, 403 // => // r1 = add sp, 100 * 4 // r1 = add r1, 3 if (!isMul4) { Bytes &= ~3; ExtraOpc = ARM::tADDi3; } DstNotEqBase = true; NumBits = 8; Scale = 4; Opc = ARM::tADDrSPi; } else { // sp = sub sp, c // r1 = sub sp, c // r8 = sub sp, c if (DestReg != BaseReg) DstNotEqBase = true; if (DestReg == ARM::SP) { Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!"); NumBits = 7; Scale = 4; } else { Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; NumBits = 8; NeedCC = true; } isTwoAddr = true; } unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; if (NumMIs > Threshold) { // This will expand into too many instructions. Load the immediate from a // constpool entry. emitThumbRegPlusImmInReg(MBB, MBBI, dl, DestReg, BaseReg, NumBytes, true, TII, MRI, MIFlags); return; } if (DstNotEqBase) { if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) unsigned Chunk = (1 << 3) - 1; unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; Bytes -= ThisVal; const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); const MachineInstrBuilder MIB = AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg) .setMIFlags(MIFlags)); AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); } else if (isARMLowRegister(DestReg) && BaseReg == ARM::SP && Bytes > 0) { unsigned ThisVal = std::min(1020U, Bytes / 4 * 4); Bytes -= ThisVal; AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), DestReg) .addReg(BaseReg, RegState::Kill).addImm(ThisVal / 4)) .setMIFlags(MIFlags); } else { AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) .addReg(BaseReg, RegState::Kill)) .setMIFlags(MIFlags); } BaseReg = DestReg; } unsigned Chunk = ((1 << NumBits) - 1) * Scale; while (Bytes) { unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; Bytes -= ThisVal; ThisVal /= Scale; // Build the new tADD / tSUB. if (isTwoAddr) { MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); if (NeedCC) MIB = AddDefaultT1CC(MIB); MIB.addReg(DestReg).addImm(ThisVal); MIB = AddDefaultPred(MIB); MIB.setMIFlags(MIFlags); } else { bool isKill = BaseReg != ARM::SP; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); if (NeedCC) MIB = AddDefaultT1CC(MIB); MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); MIB = AddDefaultPred(MIB); MIB.setMIFlags(MIFlags); BaseReg = DestReg; if (Opc == ARM::tADDrSPi) { // r4 = add sp, imm // r4 = add r4, imm // ... NumBits = 8; Scale = 1; Chunk = ((1 << NumBits) - 1) * Scale; Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; NeedCC = isTwoAddr = true; } } } if (ExtraOpc) { const MCInstrDesc &MCID = TII.get(ExtraOpc); AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) .addReg(DestReg, RegState::Kill) .addImm(((unsigned)NumBytes) & 3) .setMIFlags(MIFlags)); } }
/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize /// a destreg = basereg + immediate in Thumb code. Tries a series of ADDs or /// SUBs first, and uses a constant pool value if the instruction sequence would /// be too long. This is allowed to modify the condition flags. void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo &MRI, unsigned MIFlags) { bool isSub = NumBytes < 0; unsigned Bytes = (unsigned)NumBytes; if (isSub) Bytes = -NumBytes; int CopyOpc = 0; unsigned CopyBits = 0; unsigned CopyScale = 1; bool CopyNeedsCC = false; int ExtraOpc = 0; unsigned ExtraBits = 0; unsigned ExtraScale = 1; bool ExtraNeedsCC = false; // Strategy: // We need to select two types of instruction, maximizing the available // immediate range of each. The instructions we use will depend on whether // DestReg and BaseReg are low, high or the stack pointer. // * CopyOpc - DestReg = BaseReg + imm // This will be emitted once if DestReg != BaseReg, and never if // DestReg == BaseReg. // * ExtraOpc - DestReg = DestReg + imm // This will be emitted as many times as necessary to add the // full immediate. // If the immediate ranges of these instructions are not large enough to cover // NumBytes with a reasonable number of instructions, we fall back to using a // value loaded from a constant pool. if (DestReg == ARM::SP) { if (BaseReg == ARM::SP) { // sp -> sp // Already in right reg, no copy needed } else { // low -> sp or high -> sp CopyOpc = ARM::tMOVr; CopyBits = 0; } ExtraOpc = isSub ? ARM::tSUBspi : ARM::tADDspi; ExtraBits = 7; ExtraScale = 4; } else if (isARMLowRegister(DestReg)) { if (BaseReg == ARM::SP) { // sp -> low assert(!isSub && "Thumb1 does not have tSUBrSPi"); CopyOpc = ARM::tADDrSPi; CopyBits = 8; CopyScale = 4; } else if (DestReg == BaseReg) { // low -> same low // Already in right reg, no copy needed } else if (isARMLowRegister(BaseReg)) { // low -> different low CopyOpc = isSub ? ARM::tSUBi3 : ARM::tADDi3; CopyBits = 3; CopyNeedsCC = true; } else { // high -> low CopyOpc = ARM::tMOVr; CopyBits = 0; } ExtraOpc = isSub ? ARM::tSUBi8 : ARM::tADDi8; ExtraBits = 8; ExtraNeedsCC = true; } else /* DestReg is high */ { if (DestReg == BaseReg) { // high -> same high // Already in right reg, no copy needed } else { // {low,high,sp} -> high CopyOpc = ARM::tMOVr; CopyBits = 0; } ExtraOpc = 0; } // We could handle an unaligned immediate with an unaligned copy instruction // and an aligned extra instruction, but this case is not currently needed. assert(((Bytes & 3) == 0 || ExtraScale == 1) && "Unaligned offset, but all instructions require alignment"); unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale; // If we would emit the copy with an immediate of 0, just use tMOVr. if (CopyOpc && Bytes < CopyScale) { CopyOpc = ARM::tMOVr; CopyScale = 1; CopyNeedsCC = false; CopyRange = 0; } unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale; // per instruction unsigned RequiredCopyInstrs = CopyOpc ? 1 : 0; unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0 : (Bytes - CopyRange); // We could handle this case when the copy instruction does not require an // aligned immediate, but we do not currently do this. assert(RangeAfterCopy % ExtraScale == 0 && "Extra instruction requires immediate to be aligned"); unsigned RequiredExtraInstrs; if (ExtraRange) RequiredExtraInstrs = alignTo(RangeAfterCopy, ExtraRange) / ExtraRange; else if (RangeAfterCopy > 0) // We need an extra instruction but none is available RequiredExtraInstrs = 1000000; else RequiredExtraInstrs = 0; unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs; unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; // Use a constant pool, if the sequence of ADDs/SUBs is too expensive. if (RequiredInstrs > Threshold) { emitThumbRegPlusImmInReg(MBB, MBBI, dl, DestReg, BaseReg, NumBytes, true, TII, MRI, MIFlags); return; } // Emit zero or one copy instructions if (CopyOpc) { unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale; Bytes -= CopyImm * CopyScale; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(CopyOpc), DestReg); if (CopyNeedsCC) MIB = MIB.add(t1CondCodeOp()); MIB.addReg(BaseReg, RegState::Kill); if (CopyOpc != ARM::tMOVr) { MIB.addImm(CopyImm); } MIB.setMIFlags(MIFlags).add(predOps(ARMCC::AL)); BaseReg = DestReg; } // Emit zero or more in-place add/sub instructions while (Bytes) { unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale; Bytes -= ExtraImm * ExtraScale; MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg); if (ExtraNeedsCC) MIB = MIB.add(t1CondCodeOp()); MIB.addReg(BaseReg) .addImm(ExtraImm) .add(predOps(ARMCC::AL)) .setMIFlags(MIFlags); } }