Example #1
0
// Process all comparison instructions in MBB.  Return true if something
// changed.
bool SystemZElimCompare::processBlock(MachineBasicBlock &MBB) {
  bool Changed = false;

  // Walk backwards through the block looking for comparisons, recording
  // all CC users as we go.  The subroutines can delete Compare and
  // instructions before it.
  bool CompleteCCUsers = !isCCLiveOut(MBB);
  SmallVector<MachineInstr *, 4> CCUsers;
  MachineBasicBlock::iterator MBBI = MBB.end();
  while (MBBI != MBB.begin()) {
    MachineInstr *MI = --MBBI;
    if (CompleteCCUsers &&
        (MI->isCompare() || isLoadAndTestAsCmp(MI)) &&
        (optimizeCompareZero(MI, CCUsers) ||
         fuseCompareAndBranch(MI, CCUsers))) {
      ++MBBI;
      MI->eraseFromParent();
      Changed = true;
      CCUsers.clear();
      continue;
    }

    if (MI->definesRegister(SystemZ::CC)) {
      CCUsers.clear();
      CompleteCCUsers = true;
    }
    if (MI->readsRegister(SystemZ::CC) && CompleteCCUsers)
      CCUsers.push_back(MI);
  }
  return Changed;
}
Example #2
0
void RegDefsUses::setCallerSaved(const MachineInstr &MI) {
  assert(MI.isCall());

  // Add RA/RA_64 to Defs to prevent users of RA/RA_64 from going into
  // the delay slot. The reason is that RA/RA_64 must not be changed
  // in the delay slot so that the callee can return to the caller.
  if (MI.definesRegister(Mips::RA) || MI.definesRegister(Mips::RA_64)) {
    Defs.set(Mips::RA);
    Defs.set(Mips::RA_64);
  }

  // If MI is a call, add all caller-saved registers to Defs.
  BitVector CallerSavedRegs(TRI.getNumRegs(), true);

  CallerSavedRegs.reset(Mips::ZERO);
  CallerSavedRegs.reset(Mips::ZERO_64);

  for (const MCPhysReg *R = TRI.getCalleeSavedRegs(MI.getParent()->getParent());
       *R; ++R)
    for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI)
      CallerSavedRegs.reset(*AI);

  Defs |= CallerSavedRegs;
}
Example #3
0
// isLegalToPacketizeTogether: packetize SUSucc to SU (SU is already in current packet)
// SUSucc is the current instruction that is out side of the current packet.
// SU is the current instruction inside the current packet against which
// SUSucc will be packetized. Yangyy: it seems this function only checks schedule dependence.
bool
MSPUPacketizerList::isLegalToPacketizeTogether(SUnit *SUSucc, SUnit *SU)
{
	MachineInstr *I = SUSucc->getInstr();
	MachineInstr *J = SU->getInstr();
	assert(I && J && "Unable to packetize null instruction!");

	const MCInstrDesc &MCIDI = I->getDesc();
	const MCInstrDesc &MCIDJ = J->getDesc();

	MachineBasicBlock::iterator InstrItor = I;

	const unsigned FrameSize = MF.getFrameInfo()->getStackSize();
	const MSPURegisterInfo* RegInfo =(const MSPURegisterInfo *) TM.getRegisterInfo();
	const MSPUInstrInfo *InstrInfo = (const MSPUInstrInfo *) TII;

	// Inline asm cannot go in the packet.
	/*if(I->getOpcode() == MSPU::INLINEASM)
		llvm_unreachable("Should not meet inline asm here!");*/

	if(isSoloInstruction(I))
		llvm_unreachable("Should not meet solo instr here!");

	if(SU->isSucc(SUSucc)) { // test whether SUSucc is a successor of SU
		// scan and find the right successor to obtain scheduling dependence type
		for(unsigned i = 0; (i < SU->Succs.size()) && !FoundSequentialDependence; ++i) {

			if(SU->Succs[i].getSUnit() != SUSucc) {
				continue;
			}

			// obtain scheduling dependence
			SDep::Kind DepType = SU->Succs[i].getKind();

			// For direct calls:
			// Ignore register dependences for call instructions for
			// packetization purposes except for those due to r31 and
			// predicate registers.
			//
			// For indirect calls:
			// Same as direct calls + check for true dependences to the register
			// used in the indirect call.
			//
			// We completely ignore Order dependences for call instructions
			//
			// For returns:
			// Ignore register dependences for return instructions like jumpr,
			// dealloc return unless we have dependencies on the explicit uses
			// of the registers used by jumpr (like r31) or dealloc return
			// (like r29 or r30).
			//
			// TODO: Currently, jumpr is handling only return of r31. So, the
			// following logic (specificaly IsCallDependent) is working fine.
			// We need to enable jumpr for register other than r31 and then,
			// we need to rework the last part, where it handles indirect call
			// of that (IsCallDependent) function. Bug 6216 is opened for this.

			unsigned DepReg = 0;
			const TargetRegisterClass* RC = NULL;
			if(DepType == SDep::Data) {
				DepReg = SU->Succs[i].getReg();
				RC = RegInfo->getMinimalPhysRegClass(DepReg);
			}

			else if(MCIDI.isConditionalBranch() && (DepType != SDep::Data) &&
					(DepType != SDep::Output)) {
				// Ignore all dependences for jumps except for true and output
				// dependences
				/* do nothing */
			}

			// Ignore output dependences due to superregs. We can
			// write to two different subregisters of R1:0 for instance
			// in the same cycle

			// Let the
			// If neither I nor J defines DepReg, then this is a
			// superfluous output dependence. The dependence must be of the
			// form:
			//  R0 = ...
			//  R1 = ...
			// and there is an output dependence between the two instructions
			// with
			// DepReg = D0
			// We want to ignore these dependences.
			// Ideally, the dependence constructor should annotate such
			// dependences. We can then avoid this relatively expensive check.
			//
			else if(DepType == SDep::Output) {
				// DepReg is the register that's responsible for the dependence.
				unsigned DepReg = SU->Succs[i].getReg();

				// Check if I and J really defines DepReg.
				if(I->definesRegister(DepReg) ||
						J->definesRegister(DepReg)) {
					FoundSequentialDependence = true;
					break;
				}
			}

			// We ignore Order dependences for
			// 1. Two loads unless they are volatile.
			// 2. Two stores in V4 unless they are volatile.
			else if((DepType == SDep::Order) &&
					!I->hasOrderedMemoryRef() &&
					!J->hasOrderedMemoryRef()) {
				FoundSequentialDependence = true;
				break;
			}

			// Skip over anti-dependences. Two instructions that are
			// anti-dependent can share a packet
			else if(DepType != SDep::Anti) {
				FoundSequentialDependence = true;
				break;
			}
		}

		if(FoundSequentialDependence) {
			Dependence = true;
			return false;
		}
	}

	return true;
}