bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
                            bool &sawLoad,
                            bool &sawStore,
                            SmallSet<unsigned, 32> &RegDefs,
                            SmallSet<unsigned, 32> &RegUses)
{

  if (candidate->isImplicitDef() || candidate->isKill())
    return true;

  if (candidate->mayLoad()) {
    sawLoad = true;
    if (sawStore)
      return true;
  }

  if (candidate->mayStore()) {
    if (sawStore)
      return true;
    sawStore = true;
    if (sawLoad)
      return true;
  }

  for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
    const MachineOperand &MO = candidate->getOperand(i);
    if (!MO.isReg())
      continue; // skip

    unsigned Reg = MO.getReg();

    if (MO.isDef()) {
      // check whether Reg is defined or used before delay slot.
      if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))
        return true;
    }
    if (MO.isUse()) {
      // check whether Reg is defined before delay slot.
      if (IsRegInSet(RegDefs, Reg))
        return true;
    }
  }

  unsigned Opcode = candidate->getOpcode();
  // LD and LDD may have NOPs inserted afterwards in the case of some LEON
  // processors, so we can't use the delay slot if this feature is switched-on.
  if (Subtarget->insertNOPLoad()
      &&
      Opcode >=  SP::LDDArr && Opcode <= SP::LDrr)
    return true;

  // Same as above for FDIV and FSQRT on some LEON processors.
  if (Subtarget->fixAllFDIVSQRT()
      &&
      Opcode >=  SP::FDIVD && Opcode <= SP::FSQRTD)
    return true;


  return false;
}
Example #2
0
bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
                            bool &sawLoad,
                            bool &sawStore,
                            SmallSet<unsigned, 32> &RegDefs,
                            SmallSet<unsigned, 32> &RegUses) {
  if (candidate->isImplicitDef() || candidate->isKill())
    return true;

  // Loads or stores cannot be moved past a store to the delay slot
  // and stores cannot be moved past a load. 
  if (candidate->mayLoad()) {
    if (sawStore)
      return true;
    sawLoad = true;
  }

  if (candidate->mayStore()) {
    if (sawStore)
      return true;
    sawStore = true;
    if (sawLoad)
      return true;
  }

  assert((!candidate->isCall() && !candidate->isReturn()) &&
         "Cannot put calls or returns in delay slot.");

  for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
    const MachineOperand &MO = candidate->getOperand(i);
    unsigned Reg;

    if (!MO.isReg() || !(Reg = MO.getReg()))
      continue; // skip

    if (MO.isDef()) {
      // check whether Reg is defined or used before delay slot.
      if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))
        return true;
    }
    if (MO.isUse()) {
      // check whether Reg is defined before delay slot.
      if (IsRegInSet(RegDefs, Reg))
        return true;
    }
  }
  return false;
}
Example #3
0
bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate,
                            bool &sawLoad,
                            bool &sawStore,
                            SmallSet<unsigned, 32> &RegDefs,
                            SmallSet<unsigned, 32> &RegUses)
{

  if (candidate->isImplicitDef() || candidate->isKill())
    return true;

  if (candidate->mayLoad()) {
    sawLoad = true;
    if (sawStore)
      return true;
  }

  if (candidate->mayStore()) {
    if (sawStore)
      return true;
    sawStore = true;
    if (sawLoad)
      return true;
  }

  for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) {
    const MachineOperand &MO = candidate->getOperand(i);
    if (!MO.isReg())
      continue; // skip

    unsigned Reg = MO.getReg();

    if (MO.isDef()) {
      //check whether Reg is defined or used before delay slot.
      if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))
        return true;
    }
    if (MO.isUse()) {
      //check whether Reg is defined before delay slot.
      if (IsRegInSet(RegDefs, Reg))
        return true;
    }
  }
  return false;
}
Example #4
0
bool
MSPUPacketizer::runOnMachineFunction(MachineFunction &Fn)
{
	const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
	MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
	MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();

	// Instantiate the packetizer.
	MSPUPacketizerList Packetizer(Fn, MLI, MDT);

	// DFA state table should not be empty.
	assert(Packetizer.getResourceTracker() && "Empty DFA table!");

	//
	// Loop over all basic blocks and remove KILL pseudo-instructions
	// These instructions confuse the dependence analysis. Consider:
	// D0 = ... 		(Insn 0)
	// R0 = KILL R0, D0 (Insn 1)
	// R0 = ... 		(Insn 2)
	// Here, Insn 1 will result in the dependence graph not emitting an output
	// dependence between Insn 0 and Insn 2. This can lead to incorrect
	// packetization
	//
	for(MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
			MBB != MBBe; ++MBB) {
		MachineBasicBlock::iterator End = MBB->end();
		MachineBasicBlock::iterator MI = MBB->begin();
		while(MI != End) {
			if(MI->isKill()) {
				MachineBasicBlock::iterator DeleteMI = MI;
				++MI;
				MBB->erase(DeleteMI);
				End = MBB->end();
				continue;
			}
			++MI;
		}
	}

	// Loop over all of the basic blocks.
	for(MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
			MBB != MBBe; ++MBB) {
		// Find scheduling regions and schedule / packetize each region.
		unsigned RemainingCount = MBB->size();
		for(MachineBasicBlock::iterator RegionEnd = MBB->end();
				RegionEnd != MBB->begin();) {
			// The next region starts above the previous region. Look backward in the
			// instruction stream until we find the nearest boundary.
			MachineBasicBlock::iterator I = RegionEnd;
			for(; I != MBB->begin(); --I, --RemainingCount) {
				if(TII->isSchedulingBoundary(llvm::prior(I), MBB, Fn))
					break;
			}
			I = MBB->begin();

			// Skip empty scheduling regions.
			if(I == RegionEnd) {
				RegionEnd = llvm::prior(RegionEnd);
				--RemainingCount;
				continue;
			}
			// Skip regions with one instruction.
			if(I == llvm::prior(RegionEnd)) {
				RegionEnd = llvm::prior(RegionEnd);
				continue;
			}

			// PacketizeMIs() does a VLIW scheduling on MachineInstr list and packetizing.
			Packetizer.PacketizeMIs(MBB, I, RegionEnd);
			RegionEnd = I;
		}
	}

	return true;
}