int AArch64A57FPLoadBalancing::scavengeRegister(Chain *G, Color C, MachineBasicBlock &MBB) { RegScavenger RS; RS.enterBasicBlock(&MBB); RS.forward(MachineBasicBlock::iterator(G->getStart())); // Can we find an appropriate register that is available throughout the life // of the chain? unsigned RegClassID = G->getStart()->getDesc().OpInfo[0].RegClass; BitVector AvailableRegs = RS.getRegsAvailable(TRI->getRegClass(RegClassID)); for (MachineBasicBlock::iterator I = G->getStart(), E = G->getEnd(); I != E; ++I) { RS.forward(I); AvailableRegs &= RS.getRegsAvailable(TRI->getRegClass(RegClassID)); // Remove any registers clobbered by a regmask. for (auto J : I->operands()) { if (J.isRegMask()) AvailableRegs.clearBitsNotInMask(J.getRegMask()); } } // Make sure we allocate in-order, to get the cheapest registers first. auto Ord = RCI.getOrder(TRI->getRegClass(RegClassID)); for (auto Reg : Ord) { if (!AvailableRegs[Reg]) continue; if ((C == Color::Even && (Reg % 2) == 0) || (C == Color::Odd && (Reg % 2) == 1)) return Reg; } return -1; }
int AArch64A57FPLoadBalancing::scavengeRegister(Chain *G, Color C, MachineBasicBlock &MBB) { RegScavenger RS; RS.enterBasicBlock(&MBB); RS.forward(MachineBasicBlock::iterator(G->getStart())); // Can we find an appropriate register that is available throughout the life // of the chain? unsigned RegClassID = G->getStart()->getDesc().OpInfo[0].RegClass; BitVector AvailableRegs = RS.getRegsAvailable(TRI->getRegClass(RegClassID)); for (MachineBasicBlock::iterator I = G->getStart(), E = G->getEnd(); I != E; ++I) { RS.forward(I); AvailableRegs &= RS.getRegsAvailable(TRI->getRegClass(RegClassID)); // Remove any registers clobbered by a regmask or any def register that is // immediately dead. for (auto J : I->operands()) { if (J.isRegMask()) AvailableRegs.clearBitsNotInMask(J.getRegMask()); if (J.isReg() && J.isDef()) { MCRegAliasIterator AI(J.getReg(), TRI, /*IncludeSelf=*/true); if (J.isDead()) for (; AI.isValid(); ++AI) AvailableRegs.reset(*AI); #ifndef NDEBUG else for (; AI.isValid(); ++AI) assert(!AvailableRegs[*AI] && "Non-dead def should have been removed by now!"); #endif } } } // Make sure we allocate in-order, to get the cheapest registers first. auto Ord = RCI.getOrder(TRI->getRegClass(RegClassID)); for (auto Reg : Ord) { if (!AvailableRegs[Reg]) continue; if ((C == Color::Even && (Reg % 2) == 0) || (C == Color::Odd && (Reg % 2) == 1)) return Reg; } return -1; }
/// fixupLoopInsts - For Hexagon, if the loop label is to far from the /// loop instruction then we need to set the LC0 and SA0 registers /// explicitly instead of using LOOP(start,count). This function /// checks the distance, and generates register assignments if needed. /// /// This function makes two passes over the basic blocks. The first /// pass computes the offset of the basic block from the start. /// The second pass checks all the loop instructions. bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { // Offset of the current instruction from the start. unsigned InstOffset = 0; // Map for each basic block to it's first instruction. DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset; // First pass - compute the offset of each basic block. for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); MBB != MBBe; ++MBB) { BlockToInstOffset[MBB] = InstOffset; InstOffset += (MBB->size() * 4); } // Second pass - check each loop instruction to see if it needs to // be converted. InstOffset = 0; bool Changed = false; RegScavenger RS; // Loop over all the basic blocks. for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); MBB != MBBe; ++MBB) { InstOffset = BlockToInstOffset[MBB]; RS.enterBasicBlock(MBB); // Loop over all the instructions. MachineBasicBlock::iterator MIE = MBB->end(); MachineBasicBlock::iterator MII = MBB->begin(); while (MII != MIE) { if (isHardwareLoop(MII)) { RS.forward(MII); assert(MII->getOperand(0).isMBB() && "Expect a basic block as loop operand"); int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()]; diff = (diff > 0 ? diff : -diff); if ((unsigned)diff > MAX_LOOP_DISTANCE) { // Convert to explicity setting LC0 and SA0. convertLoopInstr(MF, MII, RS); MII = MBB->erase(MII); Changed = true; } else { ++MII; } } else { ++MII; } InstOffset += 4; } } return Changed; }
/// This function generates the sequence of instructions needed to get the /// result of adding register REG and immediate IMM. unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, unsigned &NewImm) const { // // given original instruction is: // Instr rx, T[offset] where offset is too big. // // lo = offset & 0xFFFF // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF; // // let T = temporary register // li T, hi // shl T, 16 // add T, Rx, T // RegScavenger rs; int32_t lo = Imm & 0xFFFF; NewImm = lo; int Reg =0; int SpReg = 0; rs.enterBasicBlock(MBB); rs.forward(II); // // We need to know which registers can be used, in the case where there // are not enough free registers. We exclude all registers that // are used in the instruction that we are helping. // // Consider all allocatable registers in the register class initially BitVector Candidates = RI.getAllocatableSet (*II->getParent()->getParent(), &Mips::CPU16RegsRegClass); // Exclude all the registers being used by the instruction. for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { MachineOperand &MO = II->getOperand(i); if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() && !TargetRegisterInfo::isVirtualRegister(MO.getReg())) Candidates.reset(MO.getReg()); } // If the same register was used and defined in an instruction, then // it will not be in the list of candidates. // // we need to analyze the instruction that we are helping. // we need to know if it defines register x but register x is not // present as an operand of the instruction. this tells // whether the register is live before the instruction. if it's not // then we don't need to save it in case there are no free registers. int DefReg = 0; for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { MachineOperand &MO = II->getOperand(i); if (MO.isReg() && MO.isDef()) { DefReg = MO.getReg(); break; } } BitVector Available = rs.getRegsAvailable(&Mips::CPU16RegsRegClass); Available &= Candidates; // // we use T0 for the first register, if we need to save something away. // we use T1 for the second register, if we need to save something away. // unsigned FirstRegSaved =0, SecondRegSaved=0; unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0; Reg = Available.find_first(); if (Reg == -1) { Reg = Candidates.find_first(); Candidates.reset(Reg); if (DefReg != Reg) { FirstRegSaved = Reg; FirstRegSavedTo = Mips::T0; copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true); } } else Available.reset(Reg); BuildMI(MBB, II, DL, get(Mips::LwConstant32), Reg).addImm(Imm).addImm(-1); NewImm = 0; if (FrameReg == Mips::SP) { SpReg = Available.find_first(); if (SpReg == -1) { SpReg = Candidates.find_first(); // Candidates.reset(SpReg); // not really needed if (DefReg!= SpReg) { SecondRegSaved = SpReg; SecondRegSavedTo = Mips::T1; } if (SecondRegSaved) copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true); } else Available.reset(SpReg); copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false); BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(SpReg, RegState::Kill) .addReg(Reg); } else BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(FrameReg) .addReg(Reg, RegState::Kill); if (FirstRegSaved || SecondRegSaved) { II = std::next(II); if (FirstRegSaved) copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true); if (SecondRegSaved) copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true); } return Reg; }