Skip to content
VirtRegMap.cpp 52 KiB
Newer Older
        MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, SSorRMId, RC);

      // Any stores to this stack slot are not dead anymore.
      Spills.addAvailable(SSorRMId, &MI, PhysReg);
      // Assumes this is the last use. IsKill will be unset if reg is reused
      // unless it's a two-address operand.
      if (TID->getOperandConstraint(i, TOI::TIED_TO) == -1)
        MI.getOperand(i).setIsKill();
      unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
      MI.getOperand(i).setReg(RReg);
      UpdateKills(*prior(MII), RegKills, KillOps);

    // If we have folded references to memory operands, make sure we clear all
    // physical registers that may contain the value of the spilled virtual
    // register
    for (tie(I, End) = VRM.getFoldedVirts(&MI); I != End; ++I) {
      DOUT << "Folded vreg: " << I->second.first << "  MR: "
           << I->second.second;
      unsigned VirtReg = I->second.first;
      VirtRegMap::ModRef MR = I->second.second;
      DOUT << " - StackSlot: " << SS << "\n";
      
      // If this folded instruction is just a use, check to see if it's a
      // straight load from the virt reg slot.
      if ((MR & VirtRegMap::isRef) && !(MR & VirtRegMap::isMod)) {
        int FrameIdx;
        unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx);
        if (DestReg && FrameIdx == SS) {
          // If this spill slot is available, turn it into a copy (or nothing)
          // instead of leaving it as a load!
          if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) {
            DOUT << "Promoted Load To Copy: " << MI;
            if (DestReg != InReg) {
              const TargetRegisterClass *RC = RegMap->getRegClass(VirtReg);
              MRI->copyRegToReg(MBB, &MI, DestReg, InReg, RC, RC);
              // Revisit the copy so we make sure to notice the effects of the
              // operation on the destreg (either needing to RA it if it's 
              // virtual or needing to clobber any values if it's physical).
              NextMII = &MI;
              --NextMII;  // backtrack to the copy.
              BackTracked = true;
            } else
              DOUT << "Removing now-noop copy: " << MI;

            VRM.RemoveFromFoldedVirtMap(&MI);
            MBB.erase(&MI);
            Erased = true;
            goto ProcessNextInst;
        } else {
          unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS);
          SmallVector<MachineInstr*, 4> NewMIs;
          if (PhysReg &&
              MRI->unfoldMemoryOperand(MF, &MI, PhysReg, false, false, NewMIs)) {
            MBB.insert(MII, NewMIs[0]);
            VRM.RemoveFromFoldedVirtMap(&MI);
            MBB.erase(&MI);
            Erased = true;
            --NextMII;  // backtrack to the unfolded instruction.
            BackTracked = true;
            goto ProcessNextInst;
          }
      // If this reference is not a use, any previous store is now dead.
      // Otherwise, the store to this stack slot is not dead anymore.
      MachineInstr* DeadStore = MaybeDeadStores[SS];
      if (DeadStore) {
        bool isDead = true;
        MachineInstr *NewStore = NULL;
        if (MR & VirtRegMap::isRef) {
          unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS);
          SmallVector<MachineInstr*, 4> NewMIs;
          if (PhysReg &&
              DeadStore->findRegisterUseOperandIdx(PhysReg, true) != -1 &&
              MRI->unfoldMemoryOperand(MF, &MI, PhysReg, false, true, NewMIs)) {
            MBB.insert(MII, NewMIs[0]);
            NewStore = NewMIs[1];
            MBB.insert(MII, NewStore);
            VRM.RemoveFromFoldedVirtMap(&MI);
            MBB.erase(&MI);
            Erased = true;
            --NextMII;
            --NextMII;  // backtrack to the unfolded instruction.
            BackTracked = true;
          } else
            isDead = false;
        }

        if (isDead) {  // Previous store is dead.
          // If we get here, the store is dead, nuke it now.
          DOUT << "Removed dead store:\t" << *DeadStore;
          InvalidateKills(*DeadStore, RegKills, KillOps);
          VRM.RemoveFromFoldedVirtMap(DeadStore);
          MBB.erase(DeadStore);
          if (!NewStore)
            ++NumDSE;
        if (NewStore) {
          // Treat this store as a spill merged into a copy. That makes the
          // stack slot value available.
          VRM.virtFolded(VirtReg, NewStore, VirtRegMap::isMod);
          goto ProcessNextInst;
        }
      }

      // If the spill slot value is available, and this is a new definition of
      // the value, the value is not available anymore.
      if (MR & VirtRegMap::isMod) {
        // Notice that the value in this stack slot has been modified.
        Spills.ModifyStackSlotOrReMat(SS);
        
        // If this is *just* a mod of the value, check to see if this is just a
        // store to the spill slot (i.e. the spill got merged into the copy). If
        // so, realize that the vreg is available now, and add the store to the
        // MaybeDeadStore info.
        int StackSlot;
        if (!(MR & VirtRegMap::isRef)) {
          if (unsigned SrcReg = TII->isStoreToStackSlot(&MI, StackSlot)) {
            assert(MRegisterInfo::isPhysicalRegister(SrcReg) &&
                   "Src hasn't been allocated yet?");
            // Okay, this is certainly a store of SrcReg to [StackSlot].  Mark
            // this as a potentially dead store in case there is a subsequent
            // store into the stack slot without a read from it.
            MaybeDeadStores[StackSlot] = &MI;

            // If the stack slot value was previously available in some other
            // register, change it now.  Otherwise, make the register available,
            // in PhysReg.
            Spills.addAvailable(StackSlot, &MI, SrcReg, false/*don't clobber*/);
    // Process all of the spilled defs.
    for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
      MachineOperand &MO = MI.getOperand(i);
      if (MO.isRegister() && MO.getReg() && MO.isDef()) {
        unsigned VirtReg = MO.getReg();

        if (!MRegisterInfo::isVirtualRegister(VirtReg)) {
          // Check to see if this is a noop copy.  If so, eliminate the
          // instruction before considering the dest reg to be changed.
          unsigned Src, Dst;
          if (TII->isMoveInstr(MI, Src, Dst) && Src == Dst) {
            ++NumDCE;
            DOUT << "Removing now-noop copy: " << MI;
            Spills.disallowClobberPhysReg(VirtReg);
          
          // If it's not a no-op copy, it clobbers the value in the destreg.
          ReusedOperands.markClobbered(VirtReg);
 
          // Check to see if this instruction is a load from a stack slot into
          // a register.  If so, this provides the stack slot value in the reg.
          int FrameIdx;
          if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) {
            assert(DestReg == VirtReg && "Unknown load situation!");

            // If it is a folded reference, then it's not safe to clobber.
            bool Folded = FoldedSS.count(FrameIdx);
            // Otherwise, if it wasn't available, remember that it is now!
            Spills.addAvailable(FrameIdx, &MI, DestReg, !Folded);
        bool DoReMat = VRM.isReMaterialized(VirtReg);
        if (DoReMat)
          ReMatDefs.insert(&MI);

Chris Lattner's avatar
Chris Lattner committed
        // The only vregs left are stack slot definitions.
        int StackSlot = VRM.getStackSlot(VirtReg);
        const TargetRegisterClass *RC = RegMap->getRegClass(VirtReg);
Chris Lattner's avatar
Chris Lattner committed

        // If this def is part of a two-address operand, make sure to execute
        // the store from the correct physical register.
        unsigned PhysReg;
        int TiedOp = MI.getInstrDescriptor()->findTiedToSrcOperand(i);
        if (TiedOp != -1)
          PhysReg = MI.getOperand(TiedOp).getReg();
          if (ReusedOperands.isClobbered(PhysReg)) {
            // Another def has taken the assigned physreg. It must have been a
            // use&def which got it due to reuse. Undo the reuse!
            PhysReg = ReusedOperands.GetRegForReload(PhysReg, &MI, 
                               Spills, MaybeDeadStores, RegKills, KillOps, VRM);
Chris Lattner's avatar
Chris Lattner committed

        MF.setPhysRegUsed(PhysReg);
        ReusedOperands.markClobbered(PhysReg);
        MI.getOperand(i).setReg(PhysReg);
        if (!MO.isDead()) {
          MRI->storeRegToStackSlot(MBB, next(MII), PhysReg, StackSlot, RC);
          DOUT << "Store:\t" << *next(MII);

          // If there is a dead store to this stack slot, nuke it now.
          MachineInstr *&LastStore = MaybeDeadStores[StackSlot];
          if (LastStore) {
            DOUT << "Removed dead store:\t" << *LastStore;
            ++NumDSE;
            SmallVector<unsigned, 1> KillRegs;
            InvalidateKills(*LastStore, RegKills, KillOps, &KillRegs);
            MachineBasicBlock::iterator PrevMII = LastStore;
            bool CheckDef = PrevMII != MBB.begin();
            if (CheckDef)
              --PrevMII;
            MBB.erase(LastStore);
            VRM.RemoveFromFoldedVirtMap(LastStore);
            if (CheckDef) {
              // Look at defs of killed registers on the store. Mark the defs
              // as dead since the store has been deleted and they aren't
              // being reused.
              for (unsigned j = 0, ee = KillRegs.size(); j != ee; ++j) {
                bool HasOtherDef = false;
                if (InvalidateRegDef(PrevMII, MI, KillRegs[j], HasOtherDef)) {
                  MachineInstr *DeadDef = PrevMII;
                  if (ReMatDefs.count(DeadDef) && !HasOtherDef) {
                    // FIXME: This assumes a remat def does not have side
                    // effects.
                    MBB.erase(DeadDef);
                    VRM.RemoveFromFoldedVirtMap(DeadDef);
                    ++NumDRM;
                  }
                }
              }
            }
          }
          LastStore = next(MII);
Chris Lattner's avatar
Chris Lattner committed

          // If the stack slot value was previously available in some other
          // register, change it now.  Otherwise, make the register available,
          // in PhysReg.
          Spills.ModifyStackSlotOrReMat(StackSlot);
          Spills.ClobberPhysReg(PhysReg);
          Spills.addAvailable(StackSlot, LastStore, PhysReg);
          ++NumStores;

          // Check to see if this is a noop copy.  If so, eliminate the
          // instruction before considering the dest reg to be changed.
          {
            unsigned Src, Dst;
            if (TII->isMoveInstr(MI, Src, Dst) && Src == Dst) {
              ++NumDCE;
              DOUT << "Removing now-noop copy: " << MI;
              MBB.erase(&MI);
              Erased = true;
              VRM.RemoveFromFoldedVirtMap(&MI);
              UpdateKills(*LastStore, RegKills, KillOps);
              goto ProcessNextInst;
            }
    if (!Erased && !BackTracked)
      for (MachineBasicBlock::iterator II = MI; II != NextMII; ++II)
        UpdateKills(*II, RegKills, KillOps);
llvm::Spiller* llvm::createSpiller() {
  switch (SpillerOpt) {
  default: assert(0 && "Unreachable!");
  case local:
    return new LocalSpiller();
  case simple:
    return new SimpleSpiller();
  }