// 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; }
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; }
// 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; }