+/// Iterate over all the MachineBasicBlocks in the current function and set
+/// the allocated registers for each instruction (using updateInstruction()),
+/// after register allocation is complete. Then move code out of delay slots.
+///
+void PhyRegAlloc::updateMachineCode()
+{
+ // Insert any instructions needed at method entry
+ MachineBasicBlock::iterator MII = MF->front().begin();
+ PrependInstructions(AddedInstrAtEntry.InstrnsBefore, MF->front(), MII,
+ "At function entry: \n");
+ assert(AddedInstrAtEntry.InstrnsAfter.empty() &&
+ "InstrsAfter should be unnecessary since we are just inserting at "
+ "the function entry point here.");
+
+ for (MachineFunction::iterator BBI = MF->begin(), BBE = MF->end();
+ BBI != BBE; ++BBI) {
+ MachineBasicBlock &MBB = *BBI;
+
+ // Iterate over all machine instructions in BB and mark operands with
+ // their assigned registers or insert spill code, as appropriate.
+ // Also, fix operands of call/return instructions.
+ for (MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII)
+ if (! TM.getInstrInfo().isDummyPhiInstr((*MII)->getOpCode()))
+ updateInstruction(MII, MBB);
+
+ // Now, move code out of delay slots of branches and returns if needed.
+ // (Also, move "after" code from calls to the last delay slot instruction.)
+ // Moving code out of delay slots is needed in 2 situations:
+ // (1) If this is a branch and it needs instructions inserted after it,
+ // move any existing instructions out of the delay slot so that the
+ // instructions can go into the delay slot. This only supports the
+ // case that #instrsAfter <= #delay slots.
+ //
+ // (2) If any instruction in the delay slot needs
+ // instructions inserted, move it out of the delay slot and before the
+ // branch because putting code before or after it would be VERY BAD!
+ //
+ // If the annul bit of the branch is set, neither of these is legal!
+ // If so, we need to handle spill differently but annulling is not yet used.
+ for (MachineBasicBlock::iterator MII = MBB.begin();
+ MII != MBB.end(); ++MII)
+ if (unsigned delaySlots =
+ TM.getInstrInfo().getNumDelaySlots((*MII)->getOpCode())) {
+ MachineInstr *MInst = *MII, *DelaySlotMI = *(MII+1);
+
+ // Check the 2 conditions above:
+ // (1) Does a branch need instructions added after it?
+ // (2) O/w does delay slot instr. need instrns before or after?
+ bool isBranch = (TM.getInstrInfo().isBranch(MInst->getOpCode()) ||
+ TM.getInstrInfo().isReturn(MInst->getOpCode()));
+ bool cond1 = (isBranch &&
+ AddedInstrMap.count(MInst) &&
+ AddedInstrMap[MInst].InstrnsAfter.size() > 0);
+ bool cond2 = (AddedInstrMap.count(DelaySlotMI) &&
+ (AddedInstrMap[DelaySlotMI].InstrnsBefore.size() > 0 ||
+ AddedInstrMap[DelaySlotMI].InstrnsAfter.size() > 0));
+
+ if (cond1 || cond2) {
+ assert((MInst->getOpCodeFlags() & AnnulFlag) == 0 &&
+ "FIXME: Moving an annulled delay slot instruction!");
+ assert(delaySlots==1 &&
+ "InsertBefore does not yet handle >1 delay slots!");
+ InsertBefore(DelaySlotMI, MBB, MII); // MII pts back to branch
+
+ // In case (1), delete it and don't replace with anything!
+ // Otherwise (i.e., case (2) only) replace it with a NOP.
+ if (cond1) {
+ DeleteInstruction(MBB, ++MII); // MII now points to next inst.
+ --MII; // reset MII for ++MII of loop
+ }
+ else
+ SubstituteInPlace(BuildMI(TM.getInstrInfo().getNOPOpCode(),1),
+ MBB, MII+1); // replace with NOP
+
+ if (DEBUG_RA) {
+ std::cerr << "\nRegAlloc: Moved instr. with added code: "
+ << *DelaySlotMI
+ << " out of delay slots of instr: " << *MInst;
+ }
+ }
+ else
+ // For non-branch instr with delay slots (probably a call), move
+ // InstrAfter to the instr. in the last delay slot.
+ move2DelayedInstr(*MII, *(MII+delaySlots));
+ }