- /// runOnMachineFunction - register allocate the whole function
- bool runOnMachineFunction(MachineFunction&);
-
- void releaseMemory();
-
- private:
- /// linearScan - the linear scan algorithm
- void linearScan();
-
- /// initIntervalSets - initializa the four interval sets:
- /// unhandled, fixed, active and inactive
- void initIntervalSets();
-
- /// processActiveIntervals - expire old intervals and move
- /// non-overlapping ones to the incative list
- void processActiveIntervals(LiveInterval* cur);
-
- /// processInactiveIntervals - expire old intervals and move
- /// overlapping ones to the active list
- void processInactiveIntervals(LiveInterval* cur);
-
- /// updateSpillWeights - updates the spill weights of the
- /// specifed physical register and its weight
- void updateSpillWeights(unsigned reg, SpillWeights::value_type weight);
-
- /// assignRegOrStackSlotAtInterval - assign a register if one
- /// is available, or spill.
- void assignRegOrStackSlotAtInterval(LiveInterval* cur);
-
- ///
- /// register handling helpers
- ///
-
- /// getFreePhysReg - return a free physical register for this
- /// virtual register interval if we have one, otherwise return
- /// 0
- unsigned getFreePhysReg(LiveInterval* cur);
-
- /// assignVirt2StackSlot - assigns this virtual register to a
- /// stack slot. returns the stack slot
- int assignVirt2StackSlot(unsigned virtReg);
-
- template <typename ItTy>
- void printIntervals(const char* const str, ItTy i, ItTy e) const {
- if (str) std::cerr << str << " intervals:\n";
- for (; i != e; ++i) {
- std::cerr << "\t" << **i << " -> ";
- unsigned reg = (*i)->reg;
- if (MRegisterInfo::isVirtualRegister(reg)) {
- reg = vrm_->getPhys(reg);
- }
- std::cerr << mri_->getName(reg) << '\n';
- }
- }
- };
+void RALinScan::ComputeRelatedRegClasses() {
+ const TargetRegisterInfo &TRI = *tri_;
+
+ // First pass, add all reg classes to the union, and determine at least one
+ // reg class that each register is in.
+ bool HasAliases = false;
+ for (TargetRegisterInfo::regclass_iterator RCI = TRI.regclass_begin(),
+ E = TRI.regclass_end(); RCI != E; ++RCI) {
+ RelatedRegClasses.insert(*RCI);
+ for (TargetRegisterClass::iterator I = (*RCI)->begin(), E = (*RCI)->end();
+ I != E; ++I) {
+ HasAliases = HasAliases || *TRI.getAliasSet(*I) != 0;
+
+ const TargetRegisterClass *&PRC = OneClassForEachPhysReg[*I];
+ if (PRC) {
+ // Already processed this register. Just make sure we know that
+ // multiple register classes share a register.
+ RelatedRegClasses.unionSets(PRC, *RCI);
+ } else {
+ PRC = *RCI;
+ }
+ }
+ }
+
+ // Second pass, now that we know conservatively what register classes each reg
+ // belongs to, add info about aliases. We don't need to do this for targets
+ // without register aliases.
+ if (HasAliases)
+ for (std::map<unsigned, const TargetRegisterClass*>::iterator
+ I = OneClassForEachPhysReg.begin(), E = OneClassForEachPhysReg.end();
+ I != E; ++I)
+ for (const unsigned *AS = TRI.getAliasSet(I->first); *AS; ++AS)
+ RelatedRegClasses.unionSets(I->second, OneClassForEachPhysReg[*AS]);
+}
+
+/// attemptTrivialCoalescing - If a simple interval is defined by a copy,
+/// try allocate the definition the same register as the source register
+/// if the register is not defined during live time of the interval. This
+/// eliminate a copy. This is used to coalesce copies which were not
+/// coalesced away before allocation either due to dest and src being in
+/// different register classes or because the coalescer was overly
+/// conservative.
+unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
+ if ((cur.preference && cur.preference == Reg) || !cur.containsOneValue())
+ return Reg;
+
+ VNInfo *vni = cur.getValNumInfo(0);
+ if (!vni->def || vni->def == ~1U || vni->def == ~0U)
+ return Reg;
+ MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
+ unsigned SrcReg, DstReg;
+ if (!CopyMI || !tii_->isMoveInstr(*CopyMI, SrcReg, DstReg))
+ return Reg;
+ if (TargetRegisterInfo::isVirtualRegister(SrcReg))
+ if (!vrm_->isAssignedReg(SrcReg))
+ return Reg;
+ else
+ SrcReg = vrm_->getPhys(SrcReg);
+ if (Reg == SrcReg)
+ return Reg;
+
+ const TargetRegisterClass *RC = reginfo_->getRegClass(cur.reg);
+ if (!RC->contains(SrcReg))
+ return Reg;
+
+ // Try to coalesce.
+ if (!li_->conflictsWithPhysRegDef(cur, *vrm_, SrcReg)) {
+ DOUT << "Coalescing: " << cur << " -> " << tri_->getName(SrcReg) << '\n';
+ vrm_->clearVirt(cur.reg);
+ vrm_->assignVirt2Phys(cur.reg, SrcReg);
+ ++NumCoalesce;
+ return SrcReg;
+ }
+
+ return Reg;
+}
+
+bool RALinScan::runOnMachineFunction(MachineFunction &fn) {
+ mf_ = &fn;
+ tm_ = &fn.getTarget();
+ tri_ = tm_->getRegisterInfo();
+ tii_ = tm_->getInstrInfo();
+ reginfo_ = &mf_->getRegInfo();
+ allocatableRegs_ = tri_->getAllocatableSet(fn);
+ li_ = &getAnalysis<LiveIntervals>();
+ loopInfo = &getAnalysis<MachineLoopInfo>();
+
+ // We don't run the coalescer here because we have no reason to
+ // interact with it. If the coalescer requires interaction, it
+ // won't do anything. If it doesn't require interaction, we assume
+ // it was run as a separate pass.
+
+ // If this is the first function compiled, compute the related reg classes.
+ if (RelatedRegClasses.empty())
+ ComputeRelatedRegClasses();
+
+ if (!prt_.get()) prt_.reset(new PhysRegTracker(*tri_));
+ vrm_.reset(new VirtRegMap(*mf_));
+ if (!spiller_.get()) spiller_.reset(createSpiller());
+
+ initIntervalSets();
+
+ linearScan();
+
+ // Rewrite spill code and update the PhysRegsUsed set.
+ spiller_->runOnMachineFunction(*mf_, *vrm_);
+ vrm_.reset(); // Free the VirtRegMap
+
+ while (!unhandled_.empty()) unhandled_.pop();
+ fixed_.clear();
+ active_.clear();
+ inactive_.clear();
+ handled_.clear();
+
+ return true;