mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	Allow the aggressive anti-dep breaker to process the same region multiple times. This is necessary because new anti-dependencies are exposed when "current" ones are broken.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85166 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -31,6 +31,10 @@ class AntiDepBreaker { | |||||||
| public: | public: | ||||||
|   virtual ~AntiDepBreaker(); |   virtual ~AntiDepBreaker(); | ||||||
|  |  | ||||||
|  |   /// GetMaxTrials - Return the maximum number of anti-dependence | ||||||
|  |   /// breaking attempts that will be made for a block. | ||||||
|  |   virtual unsigned GetMaxTrials() =0; | ||||||
|  |  | ||||||
|   /// Start - Initialize anti-dep breaking for a new basic block. |   /// Start - Initialize anti-dep breaking for a new basic block. | ||||||
|   virtual void StartBlock(MachineBasicBlock *BB) =0; |   virtual void StartBlock(MachineBasicBlock *BB) =0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,26 +22,19 @@ | |||||||
| #include "llvm/Target/TargetInstrInfo.h" | #include "llvm/Target/TargetInstrInfo.h" | ||||||
| #include "llvm/Target/TargetMachine.h" | #include "llvm/Target/TargetMachine.h" | ||||||
| #include "llvm/Target/TargetRegisterInfo.h" | #include "llvm/Target/TargetRegisterInfo.h" | ||||||
|  | #include "llvm/Support/CommandLine.h" | ||||||
| #include "llvm/Support/Debug.h" | #include "llvm/Support/Debug.h" | ||||||
| #include "llvm/Support/ErrorHandling.h" | #include "llvm/Support/ErrorHandling.h" | ||||||
| #include "llvm/Support/raw_ostream.h" | #include "llvm/Support/raw_ostream.h" | ||||||
|  |  | ||||||
| using namespace llvm; | using namespace llvm; | ||||||
|  |  | ||||||
| AggressiveAntiDepBreaker:: | static cl::opt<int> | ||||||
| AggressiveAntiDepBreaker(MachineFunction& MFi) :  | AntiDepTrials("agg-antidep-trials", | ||||||
|   AntiDepBreaker(), MF(MFi), |               cl::desc("Maximum number of anti-dependency breaking passes"), | ||||||
|   MRI(MF.getRegInfo()), |               cl::init(2), cl::Hidden); | ||||||
|   TRI(MF.getTarget().getRegisterInfo()), |  | ||||||
|   AllocatableSet(TRI->getAllocatableSet(MF)), |  | ||||||
|   GroupNodes(TargetRegisterInfo::FirstVirtualRegister, 0) |  | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() { | AggressiveAntiDepState::AggressiveAntiDepState(MachineBasicBlock *BB) : | ||||||
| } |   GroupNodes(TargetRegisterInfo::FirstVirtualRegister, 0) { | ||||||
|  |  | ||||||
| void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { |  | ||||||
|   // Initialize all registers to be in their own group. Initially we |   // Initialize all registers to be in their own group. Initially we | ||||||
|   // assign the register to the same-indexed GroupNode. |   // assign the register to the same-indexed GroupNode. | ||||||
|   for (unsigned i = 0; i < TargetRegisterInfo::FirstVirtualRegister; ++i) |   for (unsigned i = 0; i < TargetRegisterInfo::FirstVirtualRegister; ++i) | ||||||
| @@ -50,102 +43,9 @@ void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { | |||||||
|   // Initialize the indices to indicate that no registers are live. |   // Initialize the indices to indicate that no registers are live. | ||||||
|   std::fill(KillIndices, array_endof(KillIndices), ~0u); |   std::fill(KillIndices, array_endof(KillIndices), ~0u); | ||||||
|   std::fill(DefIndices, array_endof(DefIndices), BB->size()); |   std::fill(DefIndices, array_endof(DefIndices), BB->size()); | ||||||
|  |  | ||||||
|   bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn()); |  | ||||||
|  |  | ||||||
|   // Determine the live-out physregs for this block. |  | ||||||
|   if (IsReturnBlock) { |  | ||||||
|     // In a return block, examine the function live-out regs. |  | ||||||
|     for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), |  | ||||||
|          E = MRI.liveout_end(); I != E; ++I) { |  | ||||||
|       unsigned Reg = *I; |  | ||||||
|       UnionGroups(Reg, 0); |  | ||||||
|       KillIndices[Reg] = BB->size(); |  | ||||||
|       DefIndices[Reg] = ~0u; |  | ||||||
|       // Repeat, for all aliases. |  | ||||||
|       for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { |  | ||||||
|         unsigned AliasReg = *Alias; |  | ||||||
|         UnionGroups(AliasReg, 0); |  | ||||||
|         KillIndices[AliasReg] = BB->size(); |  | ||||||
|         DefIndices[AliasReg] = ~0u; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     // In a non-return block, examine the live-in regs of all successors. |  | ||||||
|     for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), |  | ||||||
|          SE = BB->succ_end(); SI != SE; ++SI) |  | ||||||
|       for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), |  | ||||||
|            E = (*SI)->livein_end(); I != E; ++I) { |  | ||||||
|         unsigned Reg = *I; |  | ||||||
|         UnionGroups(Reg, 0); |  | ||||||
|         KillIndices[Reg] = BB->size(); |  | ||||||
|         DefIndices[Reg] = ~0u; |  | ||||||
|         // Repeat, for all aliases. |  | ||||||
|         for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { |  | ||||||
|           unsigned AliasReg = *Alias; |  | ||||||
|           UnionGroups(AliasReg, 0); |  | ||||||
|           KillIndices[AliasReg] = BB->size(); |  | ||||||
|           DefIndices[AliasReg] = ~0u; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Mark live-out callee-saved registers. In a return block this is |  | ||||||
|   // all callee-saved registers. In non-return this is any |  | ||||||
|   // callee-saved register that is not saved in the prolog. |  | ||||||
|   const MachineFrameInfo *MFI = MF.getFrameInfo(); |  | ||||||
|   BitVector Pristine = MFI->getPristineRegs(BB); |  | ||||||
|   for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) { |  | ||||||
|     unsigned Reg = *I; |  | ||||||
|     if (!IsReturnBlock && !Pristine.test(Reg)) continue; |  | ||||||
|     UnionGroups(Reg, 0); |  | ||||||
|     KillIndices[Reg] = BB->size(); |  | ||||||
|     DefIndices[Reg] = ~0u; |  | ||||||
|     // Repeat, for all aliases. |  | ||||||
|     for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { |  | ||||||
|       unsigned AliasReg = *Alias; |  | ||||||
|       UnionGroups(AliasReg, 0); |  | ||||||
|       KillIndices[AliasReg] = BB->size(); |  | ||||||
|       DefIndices[AliasReg] = ~0u; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void AggressiveAntiDepBreaker::FinishBlock() { | unsigned AggressiveAntiDepState::GetGroup(unsigned Reg) | ||||||
|   RegRefs.clear(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AggressiveAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count, |  | ||||||
|                                      unsigned InsertPosIndex) { |  | ||||||
|   assert(Count < InsertPosIndex && "Instruction index out of expected range!"); |  | ||||||
|  |  | ||||||
|   DEBUG(errs() << "Observe: "); |  | ||||||
|   DEBUG(MI->dump()); |  | ||||||
|  |  | ||||||
|   for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { |  | ||||||
|     // If Reg is current live, then mark that it can't be renamed as |  | ||||||
|     // we don't know the extent of its live-range anymore (now that it |  | ||||||
|     // has been scheduled). If it is not live but was defined in the |  | ||||||
|     // previous schedule region, then set its def index to the most |  | ||||||
|     // conservative location (i.e. the beginning of the previous |  | ||||||
|     // schedule region). |  | ||||||
|     if (IsLive(Reg)) { |  | ||||||
|       DEBUG(if (GetGroup(Reg) != 0) |  | ||||||
|               errs() << " " << TRI->getName(Reg) << "=g" <<  |  | ||||||
|                 GetGroup(Reg) << "->g0(region live-out)"); |  | ||||||
|       UnionGroups(Reg, 0); |  | ||||||
|     } else if ((DefIndices[Reg] < InsertPosIndex) && (DefIndices[Reg] >= Count)) { |  | ||||||
|       DefIndices[Reg] = Count; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   std::set<unsigned> PassthruRegs; |  | ||||||
|   GetPassthruRegs(MI, PassthruRegs); |  | ||||||
|   PrescanInstruction(MI, Count, PassthruRegs); |  | ||||||
|   ScanInstruction(MI, Count); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| unsigned AggressiveAntiDepBreaker::GetGroup(unsigned Reg) |  | ||||||
| { | { | ||||||
|   unsigned Node = GroupNodeIndices[Reg]; |   unsigned Node = GroupNodeIndices[Reg]; | ||||||
|   while (GroupNodes[Node] != Node) |   while (GroupNodes[Node] != Node) | ||||||
| @@ -154,7 +54,7 @@ unsigned AggressiveAntiDepBreaker::GetGroup(unsigned Reg) | |||||||
|   return Node; |   return Node; | ||||||
| } | } | ||||||
|  |  | ||||||
| void AggressiveAntiDepBreaker::GetGroupRegs(unsigned Group, std::vector<unsigned> &Regs) | void AggressiveAntiDepState::GetGroupRegs(unsigned Group, std::vector<unsigned> &Regs) | ||||||
| { | { | ||||||
|   for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { |   for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { | ||||||
|     if (GetGroup(Reg) == Group) |     if (GetGroup(Reg) == Group) | ||||||
| @@ -162,7 +62,7 @@ void AggressiveAntiDepBreaker::GetGroupRegs(unsigned Group, std::vector<unsigned | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| unsigned AggressiveAntiDepBreaker::UnionGroups(unsigned Reg1, unsigned Reg2) | unsigned AggressiveAntiDepState::UnionGroups(unsigned Reg1, unsigned Reg2) | ||||||
| { | { | ||||||
|   assert(GroupNodes[0] == 0 && "GroupNode 0 not parent!"); |   assert(GroupNodes[0] == 0 && "GroupNode 0 not parent!"); | ||||||
|   assert(GroupNodeIndices[0] == 0 && "Reg 0 not in Group 0!"); |   assert(GroupNodeIndices[0] == 0 && "Reg 0 not in Group 0!"); | ||||||
| @@ -178,7 +78,7 @@ unsigned AggressiveAntiDepBreaker::UnionGroups(unsigned Reg1, unsigned Reg2) | |||||||
|   return Parent; |   return Parent; | ||||||
| } | } | ||||||
|    |    | ||||||
| unsigned AggressiveAntiDepBreaker::LeaveGroup(unsigned Reg) | unsigned AggressiveAntiDepState::LeaveGroup(unsigned Reg) | ||||||
| { | { | ||||||
|   // Create a new GroupNode for Reg. Reg's existing GroupNode must |   // Create a new GroupNode for Reg. Reg's existing GroupNode must | ||||||
|   // stay as is because there could be other GroupNodes referring to |   // stay as is because there could be other GroupNodes referring to | ||||||
| @@ -189,13 +89,143 @@ unsigned AggressiveAntiDepBreaker::LeaveGroup(unsigned Reg) | |||||||
|   return idx; |   return idx; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool AggressiveAntiDepBreaker::IsLive(unsigned Reg) | bool AggressiveAntiDepState::IsLive(unsigned Reg) | ||||||
| { | { | ||||||
|   // KillIndex must be defined and DefIndex not defined for a register |   // KillIndex must be defined and DefIndex not defined for a register | ||||||
|   // to be live. |   // to be live. | ||||||
|   return((KillIndices[Reg] != ~0u) && (DefIndices[Reg] == ~0u)); |   return((KillIndices[Reg] != ~0u) && (DefIndices[Reg] == ~0u)); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | AggressiveAntiDepBreaker:: | ||||||
|  | AggressiveAntiDepBreaker(MachineFunction& MFi) :  | ||||||
|  |   AntiDepBreaker(), MF(MFi), | ||||||
|  |   MRI(MF.getRegInfo()), | ||||||
|  |   TRI(MF.getTarget().getRegisterInfo()), | ||||||
|  |   AllocatableSet(TRI->getAllocatableSet(MF)), | ||||||
|  |   State(NULL), SavedState(NULL) { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() { | ||||||
|  |   delete State; | ||||||
|  |   delete SavedState; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | unsigned AggressiveAntiDepBreaker::GetMaxTrials() { | ||||||
|  |   if (AntiDepTrials <= 0) | ||||||
|  |     return 1; | ||||||
|  |   return AntiDepTrials; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { | ||||||
|  |   assert(State == NULL); | ||||||
|  |   State = new AggressiveAntiDepState(BB); | ||||||
|  |  | ||||||
|  |   bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn()); | ||||||
|  |   unsigned *KillIndices = State->GetKillIndices(); | ||||||
|  |   unsigned *DefIndices = State->GetDefIndices(); | ||||||
|  |  | ||||||
|  |   // Determine the live-out physregs for this block. | ||||||
|  |   if (IsReturnBlock) { | ||||||
|  |     // In a return block, examine the function live-out regs. | ||||||
|  |     for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), | ||||||
|  |          E = MRI.liveout_end(); I != E; ++I) { | ||||||
|  |       unsigned Reg = *I; | ||||||
|  |       State->UnionGroups(Reg, 0); | ||||||
|  |       KillIndices[Reg] = BB->size(); | ||||||
|  |       DefIndices[Reg] = ~0u; | ||||||
|  |       // Repeat, for all aliases. | ||||||
|  |       for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { | ||||||
|  |         unsigned AliasReg = *Alias; | ||||||
|  |         State->UnionGroups(AliasReg, 0); | ||||||
|  |         KillIndices[AliasReg] = BB->size(); | ||||||
|  |         DefIndices[AliasReg] = ~0u; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     // In a non-return block, examine the live-in regs of all successors. | ||||||
|  |     for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), | ||||||
|  |          SE = BB->succ_end(); SI != SE; ++SI) | ||||||
|  |       for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), | ||||||
|  |            E = (*SI)->livein_end(); I != E; ++I) { | ||||||
|  |         unsigned Reg = *I; | ||||||
|  |         State->UnionGroups(Reg, 0); | ||||||
|  |         KillIndices[Reg] = BB->size(); | ||||||
|  |         DefIndices[Reg] = ~0u; | ||||||
|  |         // Repeat, for all aliases. | ||||||
|  |         for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { | ||||||
|  |           unsigned AliasReg = *Alias; | ||||||
|  |           State->UnionGroups(AliasReg, 0); | ||||||
|  |           KillIndices[AliasReg] = BB->size(); | ||||||
|  |           DefIndices[AliasReg] = ~0u; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Mark live-out callee-saved registers. In a return block this is | ||||||
|  |   // all callee-saved registers. In non-return this is any | ||||||
|  |   // callee-saved register that is not saved in the prolog. | ||||||
|  |   const MachineFrameInfo *MFI = MF.getFrameInfo(); | ||||||
|  |   BitVector Pristine = MFI->getPristineRegs(BB); | ||||||
|  |   for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) { | ||||||
|  |     unsigned Reg = *I; | ||||||
|  |     if (!IsReturnBlock && !Pristine.test(Reg)) continue; | ||||||
|  |     State->UnionGroups(Reg, 0); | ||||||
|  |     KillIndices[Reg] = BB->size(); | ||||||
|  |     DefIndices[Reg] = ~0u; | ||||||
|  |     // Repeat, for all aliases. | ||||||
|  |     for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { | ||||||
|  |       unsigned AliasReg = *Alias; | ||||||
|  |       State->UnionGroups(AliasReg, 0); | ||||||
|  |       KillIndices[AliasReg] = BB->size(); | ||||||
|  |       DefIndices[AliasReg] = ~0u; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AggressiveAntiDepBreaker::FinishBlock() { | ||||||
|  |   delete State; | ||||||
|  |   State = NULL; | ||||||
|  |   delete SavedState; | ||||||
|  |   SavedState = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AggressiveAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count, | ||||||
|  |                                      unsigned InsertPosIndex) { | ||||||
|  |   assert(Count < InsertPosIndex && "Instruction index out of expected range!"); | ||||||
|  |  | ||||||
|  |   DEBUG(errs() << "Observe: "); | ||||||
|  |   DEBUG(MI->dump()); | ||||||
|  |  | ||||||
|  |   unsigned *DefIndices = State->GetDefIndices(); | ||||||
|  |   for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { | ||||||
|  |     // If Reg is current live, then mark that it can't be renamed as | ||||||
|  |     // we don't know the extent of its live-range anymore (now that it | ||||||
|  |     // has been scheduled). If it is not live but was defined in the | ||||||
|  |     // previous schedule region, then set its def index to the most | ||||||
|  |     // conservative location (i.e. the beginning of the previous | ||||||
|  |     // schedule region). | ||||||
|  |     if (State->IsLive(Reg)) { | ||||||
|  |       DEBUG(if (State->GetGroup(Reg) != 0) | ||||||
|  |               errs() << " " << TRI->getName(Reg) << "=g" <<  | ||||||
|  |                 State->GetGroup(Reg) << "->g0(region live-out)"); | ||||||
|  |       State->UnionGroups(Reg, 0); | ||||||
|  |     } else if ((DefIndices[Reg] < InsertPosIndex) && (DefIndices[Reg] >= Count)) { | ||||||
|  |       DefIndices[Reg] = Count; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   std::set<unsigned> PassthruRegs; | ||||||
|  |   GetPassthruRegs(MI, PassthruRegs); | ||||||
|  |   PrescanInstruction(MI, Count, PassthruRegs); | ||||||
|  |   ScanInstruction(MI, Count); | ||||||
|  |  | ||||||
|  |   // We're starting a new schedule region so forget any saved state. | ||||||
|  |   delete SavedState; | ||||||
|  |   SavedState = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
| bool AggressiveAntiDepBreaker::IsImplicitDefUse(MachineInstr *MI, | bool AggressiveAntiDepBreaker::IsImplicitDefUse(MachineInstr *MI, | ||||||
|                                             MachineOperand& MO) |                                             MachineOperand& MO) | ||||||
| { | { | ||||||
| @@ -249,6 +279,10 @@ static void AntiDepPathStep(SUnit *SU, std::vector<SDep*>& Edges) { | |||||||
|  |  | ||||||
| void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Count, | void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Count, | ||||||
|                                               std::set<unsigned>& PassthruRegs) { |                                               std::set<unsigned>& PassthruRegs) { | ||||||
|  |   unsigned *DefIndices = State->GetDefIndices(); | ||||||
|  |   std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&  | ||||||
|  |     RegRefs = State->GetRegRefs(); | ||||||
|  |  | ||||||
|   // Scan the register defs for this instruction and update |   // Scan the register defs for this instruction and update | ||||||
|   // live-ranges, groups and RegRefs. |   // live-ranges, groups and RegRefs. | ||||||
|   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { |   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { | ||||||
| @@ -275,23 +309,23 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Cou | |||||||
|     unsigned Reg = MO.getReg(); |     unsigned Reg = MO.getReg(); | ||||||
|     if (Reg == 0) continue; |     if (Reg == 0) continue; | ||||||
|  |  | ||||||
|     DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << GetGroup(Reg));  |     DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << State->GetGroup(Reg));  | ||||||
|  |  | ||||||
|     // If MI's defs have special allocation requirement, don't allow |     // If MI's defs have special allocation requirement, don't allow | ||||||
|     // any def registers to be changed. Also assume all registers |     // any def registers to be changed. Also assume all registers | ||||||
|     // defined in a call must not be changed (ABI). |     // defined in a call must not be changed (ABI). | ||||||
|     if (MI->getDesc().isCall() || MI->getDesc().hasExtraDefRegAllocReq()) { |     if (MI->getDesc().isCall() || MI->getDesc().hasExtraDefRegAllocReq()) { | ||||||
|       DEBUG(if (GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); |       DEBUG(if (State->GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); | ||||||
|       UnionGroups(Reg, 0); |       State->UnionGroups(Reg, 0); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Any aliased that are live at this point are completely or |     // Any aliased that are live at this point are completely or | ||||||
|     // partially defined here, so group those subregisters with Reg. |     // partially defined here, so group those subregisters with Reg. | ||||||
|     for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { |     for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { | ||||||
|       unsigned AliasReg = *Alias; |       unsigned AliasReg = *Alias; | ||||||
|       if (IsLive(AliasReg)) { |       if (State->IsLive(AliasReg)) { | ||||||
|         UnionGroups(Reg, AliasReg); |         State->UnionGroups(Reg, AliasReg); | ||||||
|         DEBUG(errs() << "->g" << GetGroup(Reg) << "(via " <<  |         DEBUG(errs() << "->g" << State->GetGroup(Reg) << "(via " <<  | ||||||
|               TRI->getName(AliasReg) << ")"); |               TRI->getName(AliasReg) << ")"); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -300,7 +334,7 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Cou | |||||||
|     const TargetRegisterClass *RC = NULL; |     const TargetRegisterClass *RC = NULL; | ||||||
|     if (i < MI->getDesc().getNumOperands()) |     if (i < MI->getDesc().getNumOperands()) | ||||||
|       RC = MI->getDesc().OpInfo[i].getRegClass(TRI); |       RC = MI->getDesc().OpInfo[i].getRegClass(TRI); | ||||||
|     RegisterReference RR = { &MO, RC }; |     AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; | ||||||
|     RegRefs.insert(std::make_pair(Reg, RR)); |     RegRefs.insert(std::make_pair(Reg, RR)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -310,6 +344,10 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Cou | |||||||
| void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, | void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, | ||||||
|                                            unsigned Count) { |                                            unsigned Count) { | ||||||
|   DEBUG(errs() << "\tUse Groups:"); |   DEBUG(errs() << "\tUse Groups:"); | ||||||
|  |   unsigned *KillIndices = State->GetKillIndices(); | ||||||
|  |   unsigned *DefIndices = State->GetDefIndices(); | ||||||
|  |   std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&  | ||||||
|  |     RegRefs = State->GetRegRefs(); | ||||||
|  |  | ||||||
|   // Scan the register uses for this instruction and update |   // Scan the register uses for this instruction and update | ||||||
|   // live-ranges, groups and RegRefs. |   // live-ranges, groups and RegRefs. | ||||||
| @@ -319,29 +357,30 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, | |||||||
|     unsigned Reg = MO.getReg(); |     unsigned Reg = MO.getReg(); | ||||||
|     if (Reg == 0) continue; |     if (Reg == 0) continue; | ||||||
|      |      | ||||||
|     DEBUG(errs() << " " << TRI->getName(Reg) << "=g" << GetGroup(Reg));  |     DEBUG(errs() << " " << TRI->getName(Reg) << "=g" <<  | ||||||
|  |           State->GetGroup(Reg));  | ||||||
|  |  | ||||||
|     // It wasn't previously live but now it is, this is a kill. Forget |     // It wasn't previously live but now it is, this is a kill. Forget | ||||||
|     // the previous live-range information and start a new live-range |     // the previous live-range information and start a new live-range | ||||||
|     // for the register. |     // for the register. | ||||||
|     if (!IsLive(Reg)) { |     if (!State->IsLive(Reg)) { | ||||||
|       KillIndices[Reg] = Count; |       KillIndices[Reg] = Count; | ||||||
|       DefIndices[Reg] = ~0u; |       DefIndices[Reg] = ~0u; | ||||||
|       RegRefs.erase(Reg); |       RegRefs.erase(Reg); | ||||||
|       LeaveGroup(Reg); |       State->LeaveGroup(Reg); | ||||||
|       DEBUG(errs() << "->g" << GetGroup(Reg) << "(last-use)"); |       DEBUG(errs() << "->g" << State->GetGroup(Reg) << "(last-use)"); | ||||||
|     } |     } | ||||||
|     // Repeat, for subregisters. |     // Repeat, for subregisters. | ||||||
|     for (const unsigned *Subreg = TRI->getSubRegisters(Reg); |     for (const unsigned *Subreg = TRI->getSubRegisters(Reg); | ||||||
|          *Subreg; ++Subreg) { |          *Subreg; ++Subreg) { | ||||||
|       unsigned SubregReg = *Subreg; |       unsigned SubregReg = *Subreg; | ||||||
|       if (!IsLive(SubregReg)) { |       if (!State->IsLive(SubregReg)) { | ||||||
|         KillIndices[SubregReg] = Count; |         KillIndices[SubregReg] = Count; | ||||||
|         DefIndices[SubregReg] = ~0u; |         DefIndices[SubregReg] = ~0u; | ||||||
|         RegRefs.erase(SubregReg); |         RegRefs.erase(SubregReg); | ||||||
|         LeaveGroup(SubregReg); |         State->LeaveGroup(SubregReg); | ||||||
|         DEBUG(errs() << " " << TRI->getName(SubregReg) << "->g" << |         DEBUG(errs() << " " << TRI->getName(SubregReg) << "->g" << | ||||||
|               GetGroup(SubregReg) << "(last-use)"); |               State->GetGroup(SubregReg) << "(last-use)"); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -349,15 +388,15 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, | |||||||
|     // any use registers to be changed. Also assume all registers |     // any use registers to be changed. Also assume all registers | ||||||
|     // used in a call must not be changed (ABI). |     // used in a call must not be changed (ABI). | ||||||
|     if (MI->getDesc().isCall() || MI->getDesc().hasExtraSrcRegAllocReq()) { |     if (MI->getDesc().isCall() || MI->getDesc().hasExtraSrcRegAllocReq()) { | ||||||
|       DEBUG(if (GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); |       DEBUG(if (State->GetGroup(Reg) != 0) errs() << "->g0(alloc-req)"); | ||||||
|       UnionGroups(Reg, 0); |       State->UnionGroups(Reg, 0); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Note register reference... |     // Note register reference... | ||||||
|     const TargetRegisterClass *RC = NULL; |     const TargetRegisterClass *RC = NULL; | ||||||
|     if (i < MI->getDesc().getNumOperands()) |     if (i < MI->getDesc().getNumOperands()) | ||||||
|       RC = MI->getDesc().OpInfo[i].getRegClass(TRI); |       RC = MI->getDesc().OpInfo[i].getRegClass(TRI); | ||||||
|     RegisterReference RR = { &MO, RC }; |     AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; | ||||||
|     RegRefs.insert(std::make_pair(Reg, RR)); |     RegRefs.insert(std::make_pair(Reg, RR)); | ||||||
|   } |   } | ||||||
|    |    | ||||||
| @@ -377,14 +416,14 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, | |||||||
|        |        | ||||||
|       if (FirstReg != 0) { |       if (FirstReg != 0) { | ||||||
|         DEBUG(errs() << "=" << TRI->getName(Reg)); |         DEBUG(errs() << "=" << TRI->getName(Reg)); | ||||||
|         UnionGroups(FirstReg, Reg); |         State->UnionGroups(FirstReg, Reg); | ||||||
|       } else { |       } else { | ||||||
|         DEBUG(errs() << " " << TRI->getName(Reg)); |         DEBUG(errs() << " " << TRI->getName(Reg)); | ||||||
|         FirstReg = Reg; |         FirstReg = Reg; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|    |    | ||||||
|     DEBUG(errs() << "->g" << GetGroup(FirstReg) << '\n'); |     DEBUG(errs() << "->g" << State->GetGroup(FirstReg) << '\n'); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -395,10 +434,12 @@ BitVector AggressiveAntiDepBreaker::GetRenameRegisters(unsigned Reg) { | |||||||
|   // Check all references that need rewriting for Reg. For each, use |   // Check all references that need rewriting for Reg. For each, use | ||||||
|   // the corresponding register class to narrow the set of registers |   // the corresponding register class to narrow the set of registers | ||||||
|   // that are appropriate for renaming. |   // that are appropriate for renaming. | ||||||
|   std::pair<std::multimap<unsigned, RegisterReference>::iterator, |   std::pair<std::multimap<unsigned,  | ||||||
|             std::multimap<unsigned, RegisterReference>::iterator> |                      AggressiveAntiDepState::RegisterReference>::iterator, | ||||||
|     Range = RegRefs.equal_range(Reg); |             std::multimap<unsigned, | ||||||
|   for (std::multimap<unsigned, RegisterReference>::iterator |                      AggressiveAntiDepState::RegisterReference>::iterator> | ||||||
|  |     Range = State->GetRegRefs().equal_range(Reg); | ||||||
|  |   for (std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>::iterator | ||||||
|          Q = Range.first, QE = Range.second; Q != QE; ++Q) { |          Q = Range.first, QE = Range.second; Q != QE; ++Q) { | ||||||
|     const TargetRegisterClass *RC = Q->second.RC; |     const TargetRegisterClass *RC = Q->second.RC; | ||||||
|     if (RC == NULL) continue; |     if (RC == NULL) continue; | ||||||
| @@ -420,11 +461,16 @@ BitVector AggressiveAntiDepBreaker::GetRenameRegisters(unsigned Reg) { | |||||||
| bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( | bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( | ||||||
|                           unsigned AntiDepGroupIndex, |                           unsigned AntiDepGroupIndex, | ||||||
|                           std::map<unsigned, unsigned> &RenameMap) { |                           std::map<unsigned, unsigned> &RenameMap) { | ||||||
|  |   unsigned *KillIndices = State->GetKillIndices(); | ||||||
|  |   unsigned *DefIndices = State->GetDefIndices(); | ||||||
|  |   std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&  | ||||||
|  |     RegRefs = State->GetRegRefs(); | ||||||
|  |  | ||||||
|   // Collect all registers in the same group as AntiDepReg. These all |   // Collect all registers in the same group as AntiDepReg. These all | ||||||
|   // need to be renamed together if we are to break the |   // need to be renamed together if we are to break the | ||||||
|   // anti-dependence. |   // anti-dependence. | ||||||
|   std::vector<unsigned> Regs; |   std::vector<unsigned> Regs; | ||||||
|   GetGroupRegs(AntiDepGroupIndex, Regs); |   State->GetGroupRegs(AntiDepGroupIndex, Regs); | ||||||
|   assert(Regs.size() > 0 && "Empty register group!"); |   assert(Regs.size() > 0 && "Empty register group!"); | ||||||
|   if (Regs.size() == 0) |   if (Regs.size() == 0) | ||||||
|     return false; |     return false; | ||||||
| @@ -484,7 +530,7 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( | |||||||
|     // If Reg is dead and Reg's most recent def is not before |     // If Reg is dead and Reg's most recent def is not before | ||||||
|     // SuperRegs's kill, it's safe to replace SuperReg with |     // SuperRegs's kill, it's safe to replace SuperReg with | ||||||
|     // Reg. We must also check all subregisters of Reg. |     // Reg. We must also check all subregisters of Reg. | ||||||
|     if (IsLive(Reg) || (KillIndices[SuperReg] > DefIndices[Reg])) { |     if (State->IsLive(Reg) || (KillIndices[SuperReg] > DefIndices[Reg])) { | ||||||
|       DEBUG(errs() << "(live)"); |       DEBUG(errs() << "(live)"); | ||||||
|       continue; |       continue; | ||||||
|     } else { |     } else { | ||||||
| @@ -492,7 +538,7 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( | |||||||
|       for (const unsigned *Subreg = TRI->getSubRegisters(Reg); |       for (const unsigned *Subreg = TRI->getSubRegisters(Reg); | ||||||
|            *Subreg; ++Subreg) { |            *Subreg; ++Subreg) { | ||||||
|         unsigned SubregReg = *Subreg; |         unsigned SubregReg = *Subreg; | ||||||
|         if (IsLive(SubregReg) || (KillIndices[SuperReg] > DefIndices[SubregReg])) { |         if (State->IsLive(SubregReg) || (KillIndices[SuperReg] > DefIndices[SubregReg])) { | ||||||
|           DEBUG(errs() << "(subreg " << TRI->getName(SubregReg) << " live)"); |           DEBUG(errs() << "(subreg " << TRI->getName(SubregReg) << " live)"); | ||||||
|           found = true; |           found = true; | ||||||
|           break; |           break; | ||||||
| @@ -518,13 +564,29 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( | |||||||
| /// BreakAntiDependencies - Identifiy anti-dependencies within the | /// BreakAntiDependencies - Identifiy anti-dependencies within the | ||||||
| /// ScheduleDAG and break them by renaming registers. | /// ScheduleDAG and break them by renaming registers. | ||||||
| /// | /// | ||||||
| unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUnits, | unsigned AggressiveAntiDepBreaker::BreakAntiDependencies( | ||||||
|                                    MachineBasicBlock::iterator& Begin, |                               std::vector<SUnit>& SUnits, | ||||||
|                                    MachineBasicBlock::iterator& End, |                               MachineBasicBlock::iterator& Begin, | ||||||
|                                    unsigned InsertPosIndex) { |                               MachineBasicBlock::iterator& End, | ||||||
|  |                               unsigned InsertPosIndex) { | ||||||
|  |   unsigned *KillIndices = State->GetKillIndices(); | ||||||
|  |   unsigned *DefIndices = State->GetDefIndices(); | ||||||
|  |   std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&  | ||||||
|  |     RegRefs = State->GetRegRefs(); | ||||||
|  |  | ||||||
|   // The code below assumes that there is at least one instruction, |   // The code below assumes that there is at least one instruction, | ||||||
|   // so just duck out immediately if the block is empty. |   // so just duck out immediately if the block is empty. | ||||||
|   if (SUnits.empty()) return false; |   if (SUnits.empty()) return false; | ||||||
|  |    | ||||||
|  |   // Manage saved state to enable multiple passes... | ||||||
|  |   if (AntiDepTrials > 1) { | ||||||
|  |     if (SavedState == NULL) { | ||||||
|  |       SavedState = new AggressiveAntiDepState(*State); | ||||||
|  |     } else { | ||||||
|  |       delete State; | ||||||
|  |       State = new AggressiveAntiDepState(*SavedState); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // ...need a map from MI to SUnit. |   // ...need a map from MI to SUnit. | ||||||
|   std::map<MachineInstr *, SUnit *> MISUnitMap; |   std::map<MachineInstr *, SUnit *> MISUnitMap; | ||||||
| @@ -539,7 +601,7 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn | |||||||
|   { |   { | ||||||
|     DEBUG(errs() << "Available regs:"); |     DEBUG(errs() << "Available regs:"); | ||||||
|     for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { |     for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { | ||||||
|       if (!IsLive(Reg)) |       if (!State->IsLive(Reg)) | ||||||
|         DEBUG(errs() << " " << TRI->getName(Reg)); |         DEBUG(errs() << " " << TRI->getName(Reg)); | ||||||
|     } |     } | ||||||
|     DEBUG(errs() << '\n'); |     DEBUG(errs() << '\n'); | ||||||
| @@ -623,7 +685,7 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn | |||||||
|         if (AntiDepReg == 0) continue; |         if (AntiDepReg == 0) continue; | ||||||
|          |          | ||||||
|         // Determine AntiDepReg's register group. |         // Determine AntiDepReg's register group. | ||||||
|         const unsigned GroupIndex = GetGroup(AntiDepReg); |         const unsigned GroupIndex = State->GetGroup(AntiDepReg); | ||||||
|         if (GroupIndex == 0) { |         if (GroupIndex == 0) { | ||||||
|           DEBUG(errs() << " (zero group)\n"); |           DEBUG(errs() << " (zero group)\n"); | ||||||
|           continue; |           continue; | ||||||
| @@ -649,10 +711,12 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn | |||||||
|              |              | ||||||
|             // Update the references to the old register CurrReg to |             // Update the references to the old register CurrReg to | ||||||
|             // refer to the new register NewReg. |             // refer to the new register NewReg. | ||||||
|             std::pair<std::multimap<unsigned, RegisterReference>::iterator, |             std::pair<std::multimap<unsigned,  | ||||||
|               std::multimap<unsigned, RegisterReference>::iterator> |                               AggressiveAntiDepState::RegisterReference>::iterator, | ||||||
|  |                       std::multimap<unsigned, | ||||||
|  |                               AggressiveAntiDepState::RegisterReference>::iterator> | ||||||
|               Range = RegRefs.equal_range(CurrReg); |               Range = RegRefs.equal_range(CurrReg); | ||||||
|             for (std::multimap<unsigned, RegisterReference>::iterator |             for (std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>::iterator | ||||||
|                    Q = Range.first, QE = Range.second; Q != QE; ++Q) { |                    Q = Range.first, QE = Range.second; Q != QE; ++Q) { | ||||||
|               Q->second.Operand->setReg(NewReg); |               Q->second.Operand->setReg(NewReg); | ||||||
|             } |             } | ||||||
| @@ -660,12 +724,12 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(std::vector<SUnit>& SUn | |||||||
|             // We just went back in time and modified history; the |             // We just went back in time and modified history; the | ||||||
|             // liveness information for CurrReg is now inconsistent. Set |             // liveness information for CurrReg is now inconsistent. Set | ||||||
|             // the state as if it were dead. |             // the state as if it were dead. | ||||||
|             UnionGroups(NewReg, 0); |             State->UnionGroups(NewReg, 0); | ||||||
|             RegRefs.erase(NewReg); |             RegRefs.erase(NewReg); | ||||||
|             DefIndices[NewReg] = DefIndices[CurrReg]; |             DefIndices[NewReg] = DefIndices[CurrReg]; | ||||||
|             KillIndices[NewReg] = KillIndices[CurrReg]; |             KillIndices[NewReg] = KillIndices[CurrReg]; | ||||||
|              |              | ||||||
|             UnionGroups(CurrReg, 0); |             State->UnionGroups(CurrReg, 0); | ||||||
|             RegRefs.erase(CurrReg); |             RegRefs.erase(CurrReg); | ||||||
|             DefIndices[CurrReg] = KillIndices[CurrReg]; |             DefIndices[CurrReg] = KillIndices[CurrReg]; | ||||||
|             KillIndices[CurrReg] = ~0u; |             KillIndices[CurrReg] = ~0u; | ||||||
|   | |||||||
| @@ -28,11 +28,12 @@ | |||||||
| #include "llvm/ADT/SmallSet.h" | #include "llvm/ADT/SmallSet.h" | ||||||
|  |  | ||||||
| namespace llvm { | namespace llvm { | ||||||
|   class AggressiveAntiDepBreaker : public AntiDepBreaker { |   /// Class AggressiveAntiDepState  | ||||||
|     MachineFunction& MF; |   /// Contains all the state necessary for anti-dep breaking. We place | ||||||
|     MachineRegisterInfo &MRI; |   /// into a separate class so be can conveniently save/restore it to | ||||||
|     const TargetRegisterInfo *TRI; |   /// enable multi-pass anti-dep breaking. | ||||||
|  |   class AggressiveAntiDepState { | ||||||
|  |   public: | ||||||
|     /// RegisterReference - Information about a register reference |     /// RegisterReference - Information about a register reference | ||||||
|     /// within a liverange |     /// within a liverange | ||||||
|     typedef struct { |     typedef struct { | ||||||
| @@ -42,59 +43,43 @@ namespace llvm { | |||||||
|       const TargetRegisterClass *RC; |       const TargetRegisterClass *RC; | ||||||
|     } RegisterReference; |     } RegisterReference; | ||||||
|  |  | ||||||
|     /// AllocatableSet - The set of allocatable registers. |   private: | ||||||
|     /// We'll be ignoring anti-dependencies on non-allocatable registers, |  | ||||||
|     /// because they may not be safe to break. |  | ||||||
|     const BitVector AllocatableSet; |  | ||||||
|  |  | ||||||
|     /// GroupNodes - Implements a disjoint-union data structure to |     /// GroupNodes - Implements a disjoint-union data structure to | ||||||
|     /// form register groups. A node is represented by an index into |     /// form register groups. A node is represented by an index into | ||||||
|     /// the vector. A node can "point to" itself to indicate that it |     /// the vector. A node can "point to" itself to indicate that it | ||||||
|     /// is the parent of a group, or point to another node to indicate |     /// is the parent of a group, or point to another node to indicate | ||||||
|     /// that it is a member of the same group as that node. |     /// that it is a member of the same group as that node. | ||||||
|     std::vector<unsigned> GroupNodes; |     std::vector<unsigned> GroupNodes; | ||||||
|  |    | ||||||
|     /// GroupNodeIndices - For each register, the index of the GroupNode |     /// GroupNodeIndices - For each register, the index of the GroupNode | ||||||
|     /// currently representing the group that the register belongs to. |     /// currently representing the group that the register belongs to. | ||||||
|     /// Register 0 is always represented by the 0 group, a group |     /// Register 0 is always represented by the 0 group, a group | ||||||
|     /// composed of registers that are not eligible for anti-aliasing. |     /// composed of registers that are not eligible for anti-aliasing. | ||||||
|     unsigned GroupNodeIndices[TargetRegisterInfo::FirstVirtualRegister]; |     unsigned GroupNodeIndices[TargetRegisterInfo::FirstVirtualRegister]; | ||||||
|  |    | ||||||
|     /// RegRegs - Map registers to all their references within a live range. |     /// RegRefs - Map registers to all their references within a live range. | ||||||
|     std::multimap<unsigned, RegisterReference> RegRefs; |     std::multimap<unsigned, RegisterReference> RegRefs; | ||||||
|  |    | ||||||
|     /// KillIndices - The index of the most recent kill (proceding bottom-up), |     /// KillIndices - The index of the most recent kill (proceding bottom-up), | ||||||
|     /// or ~0u if the register is not live. |     /// or ~0u if the register is not live. | ||||||
|     unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister]; |     unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister]; | ||||||
|  |    | ||||||
|     /// DefIndices - The index of the most recent complete def (proceding bottom |     /// DefIndices - The index of the most recent complete def (proceding bottom | ||||||
|     /// up), or ~0u if the register is live. |     /// up), or ~0u if the register is live. | ||||||
|     unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister]; |     unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister]; | ||||||
|  |  | ||||||
|   public: |   public: | ||||||
|     AggressiveAntiDepBreaker(MachineFunction& MFi); |     AggressiveAntiDepState(MachineBasicBlock *BB); | ||||||
|     ~AggressiveAntiDepBreaker(); |  | ||||||
|      |      | ||||||
|     /// Start - Initialize anti-dep breaking for a new basic block. |     /// GetKillIndices - Return the kill indices. | ||||||
|     void StartBlock(MachineBasicBlock *BB); |     unsigned *GetKillIndices() { return KillIndices; } | ||||||
|  |  | ||||||
|     /// BreakAntiDependencies - Identifiy anti-dependencies along the critical path |     /// GetDefIndices - Return the define indices. | ||||||
|     /// of the ScheduleDAG and break them by renaming registers. |     unsigned *GetDefIndices() { return DefIndices; } | ||||||
|     /// |  | ||||||
|     unsigned BreakAntiDependencies(std::vector<SUnit>& SUnits, |  | ||||||
|                                    MachineBasicBlock::iterator& Begin, |  | ||||||
|                                    MachineBasicBlock::iterator& End, |  | ||||||
|                                    unsigned InsertPosIndex); |  | ||||||
|  |  | ||||||
|     /// Observe - Update liveness information to account for the current |     /// GetRegRefs - Return the RegRefs map. | ||||||
|     /// instruction, which will not be scheduled. |     std::multimap<unsigned, RegisterReference>& GetRegRefs() { return RegRefs; } | ||||||
|     /// |  | ||||||
|     void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex); |  | ||||||
|  |  | ||||||
|     /// Finish - Finish anti-dep breaking for a basic block. |  | ||||||
|     void FinishBlock(); |  | ||||||
|  |  | ||||||
|   private: |  | ||||||
|     // GetGroup - Get the group for a register. The returned value is |     // GetGroup - Get the group for a register. The returned value is | ||||||
|     // the index of the GroupNode representing the group. |     // the index of the GroupNode representing the group. | ||||||
|     unsigned GetGroup(unsigned Reg); |     unsigned GetGroup(unsigned Reg); | ||||||
| @@ -115,7 +100,57 @@ namespace llvm { | |||||||
|  |  | ||||||
|     /// IsLive - Return true if Reg is live |     /// IsLive - Return true if Reg is live | ||||||
|     bool IsLive(unsigned Reg); |     bool IsLive(unsigned Reg); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /// Class AggressiveAntiDepBreaker  | ||||||
|  |   class AggressiveAntiDepBreaker : public AntiDepBreaker { | ||||||
|  |     MachineFunction& MF; | ||||||
|  |     MachineRegisterInfo &MRI; | ||||||
|  |     const TargetRegisterInfo *TRI; | ||||||
|  |  | ||||||
|  |     /// AllocatableSet - The set of allocatable registers. | ||||||
|  |     /// We'll be ignoring anti-dependencies on non-allocatable registers, | ||||||
|  |     /// because they may not be safe to break. | ||||||
|  |     const BitVector AllocatableSet; | ||||||
|  |  | ||||||
|  |     /// State - The state used to identify and rename anti-dependence | ||||||
|  |     /// registers. | ||||||
|  |     AggressiveAntiDepState *State; | ||||||
|  |  | ||||||
|  |     /// SavedState - The state for the start of an anti-dep | ||||||
|  |     /// region. Used to restore the state at the beginning of each | ||||||
|  |     /// pass | ||||||
|  |     AggressiveAntiDepState *SavedState; | ||||||
|  |  | ||||||
|  |   public: | ||||||
|  |     AggressiveAntiDepBreaker(MachineFunction& MFi); | ||||||
|  |     ~AggressiveAntiDepBreaker(); | ||||||
|      |      | ||||||
|  |     /// GetMaxTrials - As anti-dependencies are broken, additional | ||||||
|  |     /// dependencies may be exposed, so multiple passes are required. | ||||||
|  |     unsigned GetMaxTrials(); | ||||||
|  |  | ||||||
|  |     /// Start - Initialize anti-dep breaking for a new basic block. | ||||||
|  |     void StartBlock(MachineBasicBlock *BB); | ||||||
|  |  | ||||||
|  |     /// BreakAntiDependencies - Identifiy anti-dependencies along the critical path | ||||||
|  |     /// of the ScheduleDAG and break them by renaming registers. | ||||||
|  |     /// | ||||||
|  |     unsigned BreakAntiDependencies(std::vector<SUnit>& SUnits, | ||||||
|  |                                    MachineBasicBlock::iterator& Begin, | ||||||
|  |                                    MachineBasicBlock::iterator& End, | ||||||
|  |                                    unsigned InsertPosIndex); | ||||||
|  |  | ||||||
|  |     /// Observe - Update liveness information to account for the current | ||||||
|  |     /// instruction, which will not be scheduled. | ||||||
|  |     /// | ||||||
|  |     void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex); | ||||||
|  |  | ||||||
|  |     /// Finish - Finish anti-dep breaking for a basic block. | ||||||
|  |     void FinishBlock(); | ||||||
|  |  | ||||||
|  |   private: | ||||||
|     /// IsImplicitDefUse - Return true if MO represents a register |     /// IsImplicitDefUse - Return true if MO represents a register | ||||||
|     /// that is both implicitly used and defined in MI |     /// that is both implicitly used and defined in MI | ||||||
|     bool IsImplicitDefUse(MachineInstr *MI, MachineOperand& MO); |     bool IsImplicitDefUse(MachineInstr *MI, MachineOperand& MO); | ||||||
|   | |||||||
| @@ -64,6 +64,10 @@ namespace llvm { | |||||||
|     CriticalAntiDepBreaker(MachineFunction& MFi); |     CriticalAntiDepBreaker(MachineFunction& MFi); | ||||||
|     ~CriticalAntiDepBreaker(); |     ~CriticalAntiDepBreaker(); | ||||||
|      |      | ||||||
|  |     /// GetMaxTrials - Critical path anti-dependence breaking requires | ||||||
|  |     /// only a single pass | ||||||
|  |     unsigned GetMaxTrials() { return 1; } | ||||||
|  |  | ||||||
|     /// Start - Initialize anti-dep breaking for a new basic block. |     /// Start - Initialize anti-dep breaking for a new basic block. | ||||||
|     void StartBlock(MachineBasicBlock *BB); |     void StartBlock(MachineBasicBlock *BB); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,6 +40,7 @@ | |||||||
| #include "llvm/Target/TargetInstrInfo.h" | #include "llvm/Target/TargetInstrInfo.h" | ||||||
| #include "llvm/Target/TargetRegisterInfo.h" | #include "llvm/Target/TargetRegisterInfo.h" | ||||||
| #include "llvm/Target/TargetSubtarget.h" | #include "llvm/Target/TargetSubtarget.h" | ||||||
|  | #include "llvm/Support/CommandLine.h" | ||||||
| #include "llvm/Support/Debug.h" | #include "llvm/Support/Debug.h" | ||||||
| #include "llvm/Support/ErrorHandling.h" | #include "llvm/Support/ErrorHandling.h" | ||||||
| #include "llvm/Support/raw_ostream.h" | #include "llvm/Support/raw_ostream.h" | ||||||
| @@ -315,16 +316,20 @@ void SchedulePostRATDList::StartBlock(MachineBasicBlock *BB) { | |||||||
| /// Schedule - Schedule the instruction range using list scheduling. | /// Schedule - Schedule the instruction range using list scheduling. | ||||||
| /// | /// | ||||||
| void SchedulePostRATDList::Schedule() { | void SchedulePostRATDList::Schedule() { | ||||||
|   DEBUG(errs() << "********** List Scheduling **********\n"); |  | ||||||
|    |  | ||||||
|   // Build the scheduling graph. |   // Build the scheduling graph. | ||||||
|   BuildSchedGraph(AA); |   BuildSchedGraph(AA); | ||||||
|  |  | ||||||
|   if (AntiDepBreak != NULL) { |   if (AntiDepBreak != NULL) { | ||||||
|     unsigned Broken =  |     for (unsigned i = 0, Trials = AntiDepBreak->GetMaxTrials(); | ||||||
|       AntiDepBreak->BreakAntiDependencies(SUnits, Begin, InsertPos, |          i < Trials; ++i) { | ||||||
|                                           InsertPosIndex); |       DEBUG(errs() << "********** Break Anti-Deps, Trial " <<  | ||||||
|     if (Broken > 0) { |             i << " **********\n"); | ||||||
|  |       unsigned Broken =  | ||||||
|  |         AntiDepBreak->BreakAntiDependencies(SUnits, Begin, InsertPos, | ||||||
|  |                                             InsertPosIndex); | ||||||
|  |       if (Broken == 0) | ||||||
|  |         break; | ||||||
|  |  | ||||||
|       // We made changes. Update the dependency graph. |       // We made changes. Update the dependency graph. | ||||||
|       // Theoretically we could update the graph in place: |       // Theoretically we could update the graph in place: | ||||||
|       // When a live range is changed to use a different register, remove |       // When a live range is changed to use a different register, remove | ||||||
| @@ -340,6 +345,8 @@ void SchedulePostRATDList::Schedule() { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   DEBUG(errs() << "********** List Scheduling **********\n"); | ||||||
|  |    | ||||||
|   DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) |   DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) | ||||||
|           SUnits[su].dumpAll(this)); |           SUnits[su].dumpAll(this)); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user