Skip to content
MachineLICM.cpp 41.5 KiB
Newer Older
void MachineLICM::InitCSEMap(MachineBasicBlock *BB) {
  for (MachineBasicBlock::iterator I = BB->begin(),E = BB->end(); I != E; ++I) {
    const MachineInstr *MI = &*I;
    // FIXME: For now, only hoist re-materilizable instructions. LICM will
    // increase register pressure. We want to make sure it doesn't increase
    // spilling.
    if (TII->isTriviallyReMaterializable(MI, AA)) {
      unsigned Opcode = MI->getOpcode();
      DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator
        CI = CSEMap.find(Opcode);
      if (CI != CSEMap.end())
        CI->second.push_back(MI);
      else {
        std::vector<const MachineInstr*> CSEMIs;
        CSEMIs.push_back(MI);
        CSEMap.insert(std::make_pair(Opcode, CSEMIs));
      }
    }
  }
}

const MachineInstr*
MachineLICM::LookForDuplicate(const MachineInstr *MI,
                              std::vector<const MachineInstr*> &PrevMIs) {
Evan Cheng's avatar
Evan Cheng committed
  for (unsigned i = 0, e = PrevMIs.size(); i != e; ++i) {
    const MachineInstr *PrevMI = PrevMIs[i];
    if (TII->produceSameValue(MI, PrevMI))
Evan Cheng's avatar
Evan Cheng committed
      return PrevMI;
  }
  return 0;
}

bool MachineLICM::EliminateCSE(MachineInstr *MI,
          DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator &CI) {
  // Do not CSE implicit_def so ProcessImplicitDefs can properly propagate
  // the undef property onto uses.
  if (CI == CSEMap.end() || MI->isImplicitDef())
    return false;

  if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) {
David Greene's avatar
 
David Greene committed
    DEBUG(dbgs() << "CSEing " << *MI << " with " << *Dup);

    // Replace virtual registers defined by MI by their counterparts defined
    // by Dup.
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      const MachineOperand &MO = MI->getOperand(i);

      // Physical registers may not differ here.
      assert((!MO.isReg() || MO.getReg() == 0 ||
              !TargetRegisterInfo::isPhysicalRegister(MO.getReg()) ||
              MO.getReg() == Dup->getOperand(i).getReg()) &&
             "Instructions with different phys regs are not identical!");

      if (MO.isReg() && MO.isDef() &&
          !TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
        MRI->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg());
        MRI->clearKillFlags(Dup->getOperand(i).getReg());
Evan Cheng's avatar
Evan Cheng committed
    }
Evan Cheng's avatar
Evan Cheng committed
  }
  return false;
}

/// Hoist - When an instruction is found to use only loop invariant operands
/// that are safe to hoist, this instruction is called to do the dirty work.
void MachineLICM::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader) {
  // First check whether we should hoist this instruction.
  if (!IsLoopInvariantInst(*MI) || !IsProfitableToHoist(*MI)) {
    // If not, try unfolding a hoistable load.
    MI = ExtractHoistableLoad(MI);
    if (!MI) return;
  // Now move the instructions to the predecessor, inserting it before any
  // terminator instructions.
  DEBUG({
David Greene's avatar
 
David Greene committed
      dbgs() << "Hoisting " << *MI;
      if (Preheader->getBasicBlock())
David Greene's avatar
 
David Greene committed
        dbgs() << " to MachineBasicBlock "
      if (MI->getParent()->getBasicBlock())
David Greene's avatar
 
David Greene committed
        dbgs() << " from MachineBasicBlock "
David Greene's avatar
 
David Greene committed
      dbgs() << "\n";
  // If this is the first instruction being hoisted to the preheader,
  // initialize the CSE map with potential common expressions.
  // Look for opportunity to CSE the hoisted instruction.
  unsigned Opcode = MI->getOpcode();
  DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator
    CI = CSEMap.find(Opcode);
Evan Cheng's avatar
Evan Cheng committed
  if (!EliminateCSE(MI, CI)) {
    // Otherwise, splice the instruction to the preheader.
    Preheader->splice(Preheader->getFirstTerminator(),MI->getParent(),MI);
    // Clear the kill flags of any register this instruction defines,
    // since they may need to be live throughout the entire loop
    // rather than just live for part of it.
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      MachineOperand &MO = MI->getOperand(i);
      if (MO.isReg() && MO.isDef() && !MO.isDead())
    // Add to the CSE map.
    if (CI != CSEMap.end())
      CI->second.push_back(MI);
    else {
      std::vector<const MachineInstr*> CSEMIs;
      CSEMap.insert(std::make_pair(Opcode, CSEMIs));

MachineBasicBlock *MachineLICM::getCurPreheader() {
  // Determine the block to which to hoist instructions. If we can't find a
  // suitable loop predecessor, we can't do any hoisting.

  // If we've tried to get a preheader and failed, don't try again.
  if (CurPreheader == reinterpret_cast<MachineBasicBlock *>(-1))
    return 0;

  if (!CurPreheader) {
    CurPreheader = CurLoop->getLoopPreheader();
    if (!CurPreheader) {
      MachineBasicBlock *Pred = CurLoop->getLoopPredecessor();
      if (!Pred) {
        CurPreheader = reinterpret_cast<MachineBasicBlock *>(-1);
        return 0;
      }

      CurPreheader = Pred->SplitCriticalEdge(CurLoop->getHeader(), this);
      if (!CurPreheader) {
        CurPreheader = reinterpret_cast<MachineBasicBlock *>(-1);
        return 0;
      }
    }
  }
  return CurPreheader;
}