From 50ea01ed5ba23c8988af9fed0b91178e69140a80 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 9 Sep 2005 20:29:51 +0000 Subject: [PATCH] Use continue in the use-processing loop to make it clear what the early exits are, simplify logic, and cause things to not be nested as deeply. This also uses MRI->areAliases instead of an explicit loop. No functionality change, just code cleanup. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23296 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/VirtRegMap.cpp | 228 +++++++++++++++++++------------------ 1 file changed, 118 insertions(+), 110 deletions(-) diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index ff23d54c276..b68f36b6646 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -314,129 +314,137 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, const VirtRegMap &VRM) { // Process all of the spilled uses and all non spilled reg references. for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); - if (MO.isRegister() && MO.getReg() && - MRegisterInfo::isPhysicalRegister(MO.getReg())) + if (!MO.isRegister() || MO.getReg() == 0) + continue; // Ignore non-register operands. + + if (MRegisterInfo::isPhysicalRegister(MO.getReg())) { + // Ignore physregs for spilling, but remember that it is used by this + // function. PhysRegsUsed[MO.getReg()] = true; - else if (MO.isRegister() && MO.getReg() && - MRegisterInfo::isVirtualRegister(MO.getReg())) { - unsigned VirtReg = MO.getReg(); + continue; + } + + assert(MRegisterInfo::isVirtualRegister(MO.getReg()) && + "Not a virtual or a physical register?"); + + unsigned VirtReg = MO.getReg(); + if (!VRM.hasStackSlot(VirtReg)) { + // This virtual register was assigned a physreg! + unsigned Phys = VRM.getPhys(VirtReg); + PhysRegsUsed[Phys] = true; + MI.SetMachineOperandReg(i, Phys); + continue; + } + + // This virtual register is now known to be a spilled value. + if (!MO.isUse()) + continue; // Handle defs in the loop below (handle use&def here though) - if (!VRM.hasStackSlot(VirtReg)) { - // This virtual register was assigned a physreg! - unsigned Phys = VRM.getPhys(VirtReg); - PhysRegsUsed[Phys] = true; - MI.SetMachineOperandReg(i, Phys); - } else { - // Is this virtual register a spilled value? - if (MO.isUse()) { - int StackSlot = VRM.getStackSlot(VirtReg); - unsigned PhysReg; + // If this is both a def and a use, we need to emit a store to the + // stack slot after the instruction. Keep track of D&U operands + // because we are about to change it to a physreg here. + if (MO.isDef()) { + // Remember that this was a def-and-use operand, and that the + // stack slot is live after this instruction executes. + DefAndUseVReg.push_back(std::make_pair(i, VirtReg)); + } + + int StackSlot = VRM.getStackSlot(VirtReg); + unsigned PhysReg; - // Check to see if this stack slot is available. - std::map::iterator SSI = - SpillSlotsAvailable.find(StackSlot); - if (SSI != SpillSlotsAvailable.end()) { - DEBUG(std::cerr << "Reusing SS#" << StackSlot << " from physreg " - << MRI->getName(SSI->second) << " for vreg" - << VirtReg <<" instead of reloading into physreg " - << MRI->getName(VRM.getPhys(VirtReg)) << "\n"); - // If this stack slot value is already available, reuse it! - PhysReg = SSI->second; - MI.SetMachineOperandReg(i, PhysReg); + // Check to see if this stack slot is available. + std::map::iterator SSI = + SpillSlotsAvailable.find(StackSlot); + if (SSI != SpillSlotsAvailable.end()) { + DEBUG(std::cerr << "Reusing SS#" << StackSlot << " from physreg " + << MRI->getName(SSI->second) << " for vreg" + << VirtReg <<" instead of reloading into physreg " + << MRI->getName(VRM.getPhys(VirtReg)) << "\n"); + // If this stack slot value is already available, reuse it! + PhysReg = SSI->second; + MI.SetMachineOperandReg(i, PhysReg); - // The only technical detail we have is that we don't know that - // PhysReg won't be clobbered by a reloaded stack slot that occurs - // later in the instruction. In particular, consider 'op V1, V2'. - // If V1 is available in physreg R0, we would choose to reuse it - // here, instead of reloading it into the register the allocator - // indicated (say R1). However, V2 might have to be reloaded - // later, and it might indicate that it needs to live in R0. When - // this occurs, we need to have information available that - // indicates it is safe to use R1 for the reload instead of R0. - // - // To further complicate matters, we might conflict with an alias, - // or R0 and R1 might not be compatible with each other. In this - // case, we actually insert a reload for V1 in R1, ensuring that - // we can get at R0 or its alias. - ReusedOperands.push_back(ReusedOp(i, StackSlot, PhysReg, - VRM.getPhys(VirtReg))); - ++NumReused; - } else { - // Otherwise, reload it and remember that we have it. - PhysReg = VRM.getPhys(VirtReg); + // The only technical detail we have is that we don't know that + // PhysReg won't be clobbered by a reloaded stack slot that occurs + // later in the instruction. In particular, consider 'op V1, V2'. + // If V1 is available in physreg R0, we would choose to reuse it + // here, instead of reloading it into the register the allocator + // indicated (say R1). However, V2 might have to be reloaded + // later, and it might indicate that it needs to live in R0. When + // this occurs, we need to have information available that + // indicates it is safe to use R1 for the reload instead of R0. + // + // To further complicate matters, we might conflict with an alias, + // or R0 and R1 might not be compatible with each other. In this + // case, we actually insert a reload for V1 in R1, ensuring that + // we can get at R0 or its alias. + ReusedOperands.push_back(ReusedOp(i, StackSlot, PhysReg, + VRM.getPhys(VirtReg))); + ++NumReused; + continue; + } + + // Otherwise, reload it and remember that we have it. + PhysReg = VRM.getPhys(VirtReg); - RecheckRegister: - // Note that, if we reused a register for a previous operand, the - // register we want to reload into might not actually be - // available. If this occurs, use the register indicated by the - // reuser. - if (!ReusedOperands.empty()) // This is most often empty. - for (unsigned ro = 0, e = ReusedOperands.size(); ro != e; ++ro) - if (ReusedOperands[ro].PhysRegReused == PhysReg) { - // Yup, use the reload register that we didn't use before. - PhysReg = ReusedOperands[ro].AssignedPhysReg; - goto RecheckRegister; - } else { - ReusedOp &Op = ReusedOperands[ro]; - unsigned PRRU = Op.PhysRegReused; - for (const unsigned *AS = MRI->getAliasSet(PRRU); *AS; ++AS) - if (*AS == PhysReg) { - // Okay, we found out that an alias of a reused register - // was used. This isn't good because it means we have - // to undo a previous reuse. - MRI->loadRegFromStackSlot(MBB, &MI, Op.AssignedPhysReg, - Op.StackSlot); - ClobberPhysReg(Op.AssignedPhysReg, SpillSlotsAvailable, - PhysRegsAvailable); - - // Any stores to this stack slot are not dead anymore. - MaybeDeadStores.erase(Op.StackSlot); - - MI.SetMachineOperandReg(Op.Operand, Op.AssignedPhysReg); - PhysRegsAvailable[Op.AssignedPhysReg] = Op.StackSlot; - SpillSlotsAvailable[Op.StackSlot] = Op.AssignedPhysReg; - PhysRegsAvailable.erase(Op.PhysRegReused); - DEBUG(std::cerr << "Remembering SS#" << Op.StackSlot - << " in physreg " - << MRI->getName(Op.AssignedPhysReg) << "\n"); - ++NumLoads; - DEBUG(std::cerr << '\t' << *prior(MII)); - - DEBUG(std::cerr << "Reuse undone!\n"); - ReusedOperands.erase(ReusedOperands.begin()+ro); - --NumReused; - goto ContinueReload; - } - } - ContinueReload: - PhysRegsUsed[PhysReg] = true; - MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot); - // This invalidates PhysReg. - ClobberPhysReg(PhysReg, SpillSlotsAvailable, PhysRegsAvailable); + RecheckRegister: + // Note that, if we reused a register for a previous operand, the + // register we want to reload into might not actually be + // available. If this occurs, use the register indicated by the + // reuser. + if (!ReusedOperands.empty()) // This is most often empty. + for (unsigned ro = 0, e = ReusedOperands.size(); ro != e; ++ro) + if (ReusedOperands[ro].PhysRegReused == PhysReg) { + // Yup, use the reload register that we didn't use before. + PhysReg = ReusedOperands[ro].AssignedPhysReg; + goto RecheckRegister; + } else { + ReusedOp &Op = ReusedOperands[ro]; + unsigned PRRU = Op.PhysRegReused; + if (MRI->areAliases(PRRU, PhysReg)) { + // Okay, we found out that an alias of a reused register + // was used. This isn't good because it means we have + // to undo a previous reuse. + MRI->loadRegFromStackSlot(MBB, &MI, Op.AssignedPhysReg, + Op.StackSlot); + ClobberPhysReg(Op.AssignedPhysReg, SpillSlotsAvailable, + PhysRegsAvailable); // Any stores to this stack slot are not dead anymore. - MaybeDeadStores.erase(StackSlot); + MaybeDeadStores.erase(Op.StackSlot); - MI.SetMachineOperandReg(i, PhysReg); - PhysRegsAvailable[PhysReg] = StackSlot; - SpillSlotsAvailable[StackSlot] = PhysReg; - DEBUG(std::cerr << "Remembering SS#" << StackSlot <<" in physreg " - << MRI->getName(PhysReg) << "\n"); + MI.SetMachineOperandReg(Op.Operand, Op.AssignedPhysReg); + PhysRegsAvailable[Op.AssignedPhysReg] = Op.StackSlot; + SpillSlotsAvailable[Op.StackSlot] = Op.AssignedPhysReg; + PhysRegsAvailable.erase(Op.PhysRegReused); + DEBUG(std::cerr << "Remembering SS#" << Op.StackSlot + << " in physreg " + << MRI->getName(Op.AssignedPhysReg) << "\n"); ++NumLoads; DEBUG(std::cerr << '\t' << *prior(MII)); - } - // If this is both a def and a use, we need to emit a store to the - // stack slot after the instruction. Keep track of D&U operands - // because we already changed it to a physreg here. - if (MO.isDef()) { - // Remember that this was a def-and-use operand, and that the - // stack slot is live after this instruction executes. - DefAndUseVReg.push_back(std::make_pair(i, VirtReg)); + DEBUG(std::cerr << "Reuse undone!\n"); + ReusedOperands.erase(ReusedOperands.begin()+ro); + --NumReused; + goto ContinueReload; } } - } - } + ContinueReload: + PhysRegsUsed[PhysReg] = true; + MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot); + // This invalidates PhysReg. + ClobberPhysReg(PhysReg, SpillSlotsAvailable, PhysRegsAvailable); + + // Any stores to this stack slot are not dead anymore. + MaybeDeadStores.erase(StackSlot); + + MI.SetMachineOperandReg(i, PhysReg); + PhysRegsAvailable[PhysReg] = StackSlot; + SpillSlotsAvailable[StackSlot] = PhysReg; + DEBUG(std::cerr << "Remembering SS#" << StackSlot <<" in physreg " + << MRI->getName(PhysReg) << "\n"); + ++NumLoads; + DEBUG(std::cerr << '\t' << *prior(MII)); } // Loop over all of the implicit defs, clearing them from our available