<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Thanks, added virtual destructor....</div><div><br></div>Author: david_goodwin<br>Date: Mon Oct 26 14:00:47 2009<br>New Revision: 85141<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=85141&view=rev">http://llvm.org/viewvc/llvm-project?rev=85141&view=rev</a><br>Log:<br>Add virtual destructor.<br><br>Modified:<br> llvm/trunk/include/llvm/CodeGen/AntiDepBreaker.h<br><div><div><br></div><div><br></div><div>On Oct 26, 2009, at 11:38 AM, Chandler Carruth wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>FYI, this change causes both llvm::AntiDepBreaker and<br>llvm::CriticalAntiDepBreaker to have virtual functions and an<br>accessible non-virtual destructor.<br><br>On Mon, Oct 26, 2009 at 9:59 AM, David Goodwin <<a href="mailto:david_goodwin@apple.com">david_goodwin@apple.com</a>> wrote:<br><blockquote type="cite">Author: david_goodwin<br></blockquote><blockquote type="cite">Date: Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">New Revision: 85127<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=85127&view=rev">http://llvm.org/viewvc/llvm-project?rev=85127&view=rev</a><br></blockquote><blockquote type="cite">Log:<br></blockquote><blockquote type="cite">Break anti-dependence breaking out into its own class.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Added:<br></blockquote><blockquote type="cite"> llvm/trunk/include/llvm/CodeGen/AntiDepBreaker.h<br></blockquote><blockquote type="cite"> llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.cpp<br></blockquote><blockquote type="cite"> llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.h<br></blockquote><blockquote type="cite">Modified:<br></blockquote><blockquote type="cite"> llvm/trunk/lib/CodeGen/CMakeLists.txt<br></blockquote><blockquote type="cite"> llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp<br></blockquote><blockquote type="cite"> llvm/trunk/lib/Target/ARM/ARMSubtarget.h<br></blockquote><blockquote type="cite"> llvm/trunk/test/CodeGen/X86/break-anti-dependencies.ll<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Added: llvm/trunk/include/llvm/CodeGen/AntiDepBreaker.h<br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AntiDepBreaker.h?rev=85127&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AntiDepBreaker.h?rev=85127&view=auto</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">==============================================================================<br></blockquote><blockquote type="cite">--- llvm/trunk/include/llvm/CodeGen/AntiDepBreaker.h (added)<br></blockquote><blockquote type="cite">+++ llvm/trunk/include/llvm/CodeGen/AntiDepBreaker.h Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">@@ -0,0 +1,56 @@<br></blockquote><blockquote type="cite">+//=- llvm/CodeGen/AntiDepBreaker.h - Anti-Dependence Breaking -*- C++ -*-=//<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// The LLVM Compiler Infrastructure<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// This file is distributed under the University of Illinois Open Source<br></blockquote><blockquote type="cite">+// License. See LICENSE.TXT for details.<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+//===----------------------------------------------------------------------===//<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// This file implements the AntiDepBreaker class, which implements<br></blockquote><blockquote type="cite">+// anti-dependence breaking heuristics for post-register-allocation scheduling.<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+//===----------------------------------------------------------------------===//<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#ifndef LLVM_CODEGEN_ANTIDEPBREAKER_H<br></blockquote><blockquote type="cite">+#define LLVM_CODEGEN_ANTIDEPBREAKER_H<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineBasicBlock.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineFrameInfo.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineFunction.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineRegisterInfo.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/ScheduleDAG.h"<br></blockquote><blockquote type="cite">+#include "llvm/Target/TargetRegisterInfo.h"<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+namespace llvm {<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+/// AntiDepBreaker - This class works into conjunction with the<br></blockquote><blockquote type="cite">+/// post-RA scheduler to rename registers to break register<br></blockquote><blockquote type="cite">+/// anti-dependencies.<br></blockquote><blockquote type="cite">+class AntiDepBreaker {<br></blockquote><blockquote type="cite">+public:<br></blockquote><blockquote type="cite">+ /// Start - Initialize anti-dep breaking for a new basic block.<br></blockquote><blockquote type="cite">+ virtual void StartBlock(MachineBasicBlock *BB) =0;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// BreakAntiDependencies - Identifiy anti-dependencies within a<br></blockquote><blockquote type="cite">+ /// basic-block region and break them by renaming registers. Return<br></blockquote><blockquote type="cite">+ /// the number of anti-dependencies broken.<br></blockquote><blockquote type="cite">+ ///<br></blockquote><blockquote type="cite">+ virtual unsigned BreakAntiDependencies(std::vector<SUnit>& SUnits,<br></blockquote><blockquote type="cite">+ MachineBasicBlock::iterator& Begin,<br></blockquote><blockquote type="cite">+ MachineBasicBlock::iterator& End,<br></blockquote><blockquote type="cite">+ unsigned InsertPosIndex) =0;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// Observe - Update liveness information to account for the current<br></blockquote><blockquote type="cite">+ /// instruction, which will not be scheduled.<br></blockquote><blockquote type="cite">+ ///<br></blockquote><blockquote type="cite">+ virtual void Observe(MachineInstr *MI, unsigned Count,<br></blockquote><blockquote type="cite">+ unsigned InsertPosIndex) =0;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// Finish - Finish anti-dep breaking for a basic block.<br></blockquote><blockquote type="cite">+ virtual void FinishBlock() =0;<br></blockquote><blockquote type="cite">+};<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#endif<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt<br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=85127&r1=85126&r2=85127&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=85127&r1=85126&r2=85127&view=diff</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">==============================================================================<br></blockquote><blockquote type="cite">--- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)<br></blockquote><blockquote type="cite">+++ llvm/trunk/lib/CodeGen/CMakeLists.txt Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">@@ -1,6 +1,7 @@<br></blockquote><blockquote type="cite"> add_llvm_library(LLVMCodeGen<br></blockquote><blockquote type="cite"> BranchFolding.cpp<br></blockquote><blockquote type="cite"> CodePlacementOpt.cpp<br></blockquote><blockquote type="cite">+ CriticalAntiDepBreaker.cpp<br></blockquote><blockquote type="cite"> DeadMachineInstructionElim.cpp<br></blockquote><blockquote type="cite"> DwarfEHPrepare.cpp<br></blockquote><blockquote type="cite"> ELFCodeEmitter.cpp<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Added: llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.cpp<br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.cpp?rev=85127&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.cpp?rev=85127&view=auto</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">==============================================================================<br></blockquote><blockquote type="cite">--- llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.cpp (added)<br></blockquote><blockquote type="cite">+++ llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.cpp Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">@@ -0,0 +1,539 @@<br></blockquote><blockquote type="cite">+//===----- CriticalAntiDepBreaker.cpp - Anti-dep breaker -------- ---------===//<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// The LLVM Compiler Infrastructure<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// This file is distributed under the University of Illinois Open Source<br></blockquote><blockquote type="cite">+// License. See LICENSE.TXT for details.<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+//===----------------------------------------------------------------------===//<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// This file implements the CriticalAntiDepBreaker class, which<br></blockquote><blockquote type="cite">+// implements register anti-dependence breaking along a blocks<br></blockquote><blockquote type="cite">+// critical path during post-RA scheduler.<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+//===----------------------------------------------------------------------===//<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#define DEBUG_TYPE "critical-antidep"<br></blockquote><blockquote type="cite">+#include "CriticalAntiDepBreaker.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineBasicBlock.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineFrameInfo.h"<br></blockquote><blockquote type="cite">+#include "llvm/Target/TargetMachine.h"<br></blockquote><blockquote type="cite">+#include "llvm/Target/TargetRegisterInfo.h"<br></blockquote><blockquote type="cite">+#include "llvm/Support/Debug.h"<br></blockquote><blockquote type="cite">+#include "llvm/Support/ErrorHandling.h"<br></blockquote><blockquote type="cite">+#include "llvm/Support/raw_ostream.h"<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+using namespace llvm;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+CriticalAntiDepBreaker::<br></blockquote><blockquote type="cite">+CriticalAntiDepBreaker(MachineFunction& MFi) :<br></blockquote><blockquote type="cite">+ AntiDepBreaker(), MF(MFi),<br></blockquote><blockquote type="cite">+ MRI(MF.getRegInfo()),<br></blockquote><blockquote type="cite">+ TRI(MF.getTarget().getRegisterInfo()),<br></blockquote><blockquote type="cite">+ AllocatableSet(TRI->getAllocatableSet(MF))<br></blockquote><blockquote type="cite">+{<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+CriticalAntiDepBreaker::~CriticalAntiDepBreaker() {<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {<br></blockquote><blockquote type="cite">+ // Clear out the register class data.<br></blockquote><blockquote type="cite">+ std::fill(Classes, array_endof(Classes),<br></blockquote><blockquote type="cite">+ static_cast<const TargetRegisterClass *>(0));<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Initialize the indices to indicate that no registers are live.<br></blockquote><blockquote type="cite">+ std::fill(KillIndices, array_endof(KillIndices), ~0u);<br></blockquote><blockquote type="cite">+ std::fill(DefIndices, array_endof(DefIndices), BB->size());<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Clear "do not change" set.<br></blockquote><blockquote type="cite">+ KeepRegs.clear();<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn());<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Determine the live-out physregs for this block.<br></blockquote><blockquote type="cite">+ if (IsReturnBlock) {<br></blockquote><blockquote type="cite">+ // In a return block, examine the function live-out regs.<br></blockquote><blockquote type="cite">+ for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(),<br></blockquote><blockquote type="cite">+ E = MRI.liveout_end(); I != E; ++I) {<br></blockquote><blockquote type="cite">+ unsigned Reg = *I;<br></blockquote><blockquote type="cite">+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ KillIndices[Reg] = BB->size();<br></blockquote><blockquote type="cite">+ DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">+ // Repeat, for all aliases.<br></blockquote><blockquote type="cite">+ for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">+ unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">+ Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ KillIndices[AliasReg] = BB->size();<br></blockquote><blockquote type="cite">+ DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ } else {<br></blockquote><blockquote type="cite">+ // In a non-return block, examine the live-in regs of all successors.<br></blockquote><blockquote type="cite">+ for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),<br></blockquote><blockquote type="cite">+ SE = BB->succ_end(); SI != SE; ++SI)<br></blockquote><blockquote type="cite">+ for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(),<br></blockquote><blockquote type="cite">+ E = (*SI)->livein_end(); I != E; ++I) {<br></blockquote><blockquote type="cite">+ unsigned Reg = *I;<br></blockquote><blockquote type="cite">+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ KillIndices[Reg] = BB->size();<br></blockquote><blockquote type="cite">+ DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">+ // Repeat, for all aliases.<br></blockquote><blockquote type="cite">+ for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">+ unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">+ Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ KillIndices[AliasReg] = BB->size();<br></blockquote><blockquote type="cite">+ DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Mark live-out callee-saved registers. In a return block this is<br></blockquote><blockquote type="cite">+ // all callee-saved registers. In non-return this is any<br></blockquote><blockquote type="cite">+ // callee-saved register that is not saved in the prolog.<br></blockquote><blockquote type="cite">+ const MachineFrameInfo *MFI = MF.getFrameInfo();<br></blockquote><blockquote type="cite">+ BitVector Pristine = MFI->getPristineRegs(BB);<br></blockquote><blockquote type="cite">+ for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) {<br></blockquote><blockquote type="cite">+ unsigned Reg = *I;<br></blockquote><blockquote type="cite">+ if (!IsReturnBlock && !Pristine.test(Reg)) continue;<br></blockquote><blockquote type="cite">+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ KillIndices[Reg] = BB->size();<br></blockquote><blockquote type="cite">+ DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">+ // Repeat, for all aliases.<br></blockquote><blockquote type="cite">+ for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">+ unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">+ Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ KillIndices[AliasReg] = BB->size();<br></blockquote><blockquote type="cite">+ DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+void CriticalAntiDepBreaker::FinishBlock() {<br></blockquote><blockquote type="cite">+ RegRefs.clear();<br></blockquote><blockquote type="cite">+ KeepRegs.clear();<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+void CriticalAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count,<br></blockquote><blockquote type="cite">+ unsigned InsertPosIndex) {<br></blockquote><blockquote type="cite">+ assert(Count < InsertPosIndex && "Instruction index out of expected range!");<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Any register which was defined within the previous scheduling region<br></blockquote><blockquote type="cite">+ // may have been rescheduled and its lifetime may overlap with registers<br></blockquote><blockquote type="cite">+ // in ways not reflected in our current liveness state. For each such<br></blockquote><blockquote type="cite">+ // register, adjust the liveness state to be conservatively correct.<br></blockquote><blockquote type="cite">+ for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg)<br></blockquote><blockquote type="cite">+ if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) {<br></blockquote><blockquote type="cite">+ assert(KillIndices[Reg] == ~0u && "Clobbered register is live!");<br></blockquote><blockquote type="cite">+ // Mark this register to be non-renamable.<br></blockquote><blockquote type="cite">+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ // Move the def index to the end of the previous region, to reflect<br></blockquote><blockquote type="cite">+ // that the def could theoretically have been scheduled at the end.<br></blockquote><blockquote type="cite">+ DefIndices[Reg] = InsertPosIndex;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ PrescanInstruction(MI);<br></blockquote><blockquote type="cite">+ ScanInstruction(MI, Count);<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+/// CriticalPathStep - Return the next SUnit after SU on the bottom-up<br></blockquote><blockquote type="cite">+/// critical path.<br></blockquote><blockquote type="cite">+static SDep *CriticalPathStep(SUnit *SU) {<br></blockquote><blockquote type="cite">+ SDep *Next = 0;<br></blockquote><blockquote type="cite">+ unsigned NextDepth = 0;<br></blockquote><blockquote type="cite">+ // Find the predecessor edge with the greatest depth.<br></blockquote><blockquote type="cite">+ for (SUnit::pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end();<br></blockquote><blockquote type="cite">+ P != PE; ++P) {<br></blockquote><blockquote type="cite">+ SUnit *PredSU = P->getSUnit();<br></blockquote><blockquote type="cite">+ unsigned PredLatency = P->getLatency();<br></blockquote><blockquote type="cite">+ unsigned PredTotalLatency = PredSU->getDepth() + PredLatency;<br></blockquote><blockquote type="cite">+ // In the case of a latency tie, prefer an anti-dependency edge over<br></blockquote><blockquote type="cite">+ // other types of edges.<br></blockquote><blockquote type="cite">+ if (NextDepth < PredTotalLatency ||<br></blockquote><blockquote type="cite">+ (NextDepth == PredTotalLatency && P->getKind() == SDep::Anti)) {<br></blockquote><blockquote type="cite">+ NextDepth = PredTotalLatency;<br></blockquote><blockquote type="cite">+ Next = &*P;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ return Next;<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr *MI) {<br></blockquote><blockquote type="cite">+ // Scan the register operands for this instruction and update<br></blockquote><blockquote type="cite">+ // Classes and RegRefs.<br></blockquote><blockquote type="cite">+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">+ MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">+ if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">+ unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">+ if (Reg == 0) continue;<br></blockquote><blockquote type="cite">+ const TargetRegisterClass *NewRC = 0;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ if (i < MI->getDesc().getNumOperands())<br></blockquote><blockquote type="cite">+ NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // For now, only allow the register to be changed if its register<br></blockquote><blockquote type="cite">+ // class is consistent across all uses.<br></blockquote><blockquote type="cite">+ if (!Classes[Reg] && NewRC)<br></blockquote><blockquote type="cite">+ Classes[Reg] = NewRC;<br></blockquote><blockquote type="cite">+ else if (!NewRC || Classes[Reg] != NewRC)<br></blockquote><blockquote type="cite">+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Now check for aliases.<br></blockquote><blockquote type="cite">+ for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">+ // If an alias of the reg is used during the live range, give up.<br></blockquote><blockquote type="cite">+ // Note that this allows us to skip checking if AntiDepReg<br></blockquote><blockquote type="cite">+ // overlaps with any of the aliases, among other things.<br></blockquote><blockquote type="cite">+ unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">+ if (Classes[AliasReg]) {<br></blockquote><blockquote type="cite">+ Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // If we're still willing to consider this register, note the reference.<br></blockquote><blockquote type="cite">+ if (Classes[Reg] != reinterpret_cast<TargetRegisterClass *>(-1))<br></blockquote><blockquote type="cite">+ RegRefs.insert(std::make_pair(Reg, &MO));<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // It's not safe to change register allocation for source operands of<br></blockquote><blockquote type="cite">+ // that have special allocation requirements.<br></blockquote><blockquote type="cite">+ if (MO.isUse() && MI->getDesc().hasExtraSrcRegAllocReq()) {<br></blockquote><blockquote type="cite">+ if (KeepRegs.insert(Reg)) {<br></blockquote><blockquote type="cite">+ for (const unsigned *Subreg = TRI->getSubRegisters(Reg);<br></blockquote><blockquote type="cite">+ *Subreg; ++Subreg)<br></blockquote><blockquote type="cite">+ KeepRegs.insert(*Subreg);<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+void CriticalAntiDepBreaker::ScanInstruction(MachineInstr *MI,<br></blockquote><blockquote type="cite">+ unsigned Count) {<br></blockquote><blockquote type="cite">+ // Update liveness.<br></blockquote><blockquote type="cite">+ // Proceding upwards, registers that are defed but not used in this<br></blockquote><blockquote type="cite">+ // instruction are now dead.<br></blockquote><blockquote type="cite">+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">+ MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">+ if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">+ unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">+ if (Reg == 0) continue;<br></blockquote><blockquote type="cite">+ if (!MO.isDef()) continue;<br></blockquote><blockquote type="cite">+ // Ignore two-addr defs.<br></blockquote><blockquote type="cite">+ if (MI->isRegTiedToUseOperand(i)) continue;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ DefIndices[Reg] = Count;<br></blockquote><blockquote type="cite">+ KillIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">+ assert(((KillIndices[Reg] == ~0u) !=<br></blockquote><blockquote type="cite">+ (DefIndices[Reg] == ~0u)) &&<br></blockquote><blockquote type="cite">+ "Kill and Def maps aren't consistent for Reg!");<br></blockquote><blockquote type="cite">+ KeepRegs.erase(Reg);<br></blockquote><blockquote type="cite">+ Classes[Reg] = 0;<br></blockquote><blockquote type="cite">+ RegRefs.erase(Reg);<br></blockquote><blockquote type="cite">+ // Repeat, for all subregs.<br></blockquote><blockquote type="cite">+ for (const unsigned *Subreg = TRI->getSubRegisters(Reg);<br></blockquote><blockquote type="cite">+ *Subreg; ++Subreg) {<br></blockquote><blockquote type="cite">+ unsigned SubregReg = *Subreg;<br></blockquote><blockquote type="cite">+ DefIndices[SubregReg] = Count;<br></blockquote><blockquote type="cite">+ KillIndices[SubregReg] = ~0u;<br></blockquote><blockquote type="cite">+ KeepRegs.erase(SubregReg);<br></blockquote><blockquote type="cite">+ Classes[SubregReg] = 0;<br></blockquote><blockquote type="cite">+ RegRefs.erase(SubregReg);<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ // Conservatively mark super-registers as unusable.<br></blockquote><blockquote type="cite">+ for (const unsigned *Super = TRI->getSuperRegisters(Reg);<br></blockquote><blockquote type="cite">+ *Super; ++Super) {<br></blockquote><blockquote type="cite">+ unsigned SuperReg = *Super;<br></blockquote><blockquote type="cite">+ Classes[SuperReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">+ MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">+ if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">+ unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">+ if (Reg == 0) continue;<br></blockquote><blockquote type="cite">+ if (!MO.isUse()) continue;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ const TargetRegisterClass *NewRC = 0;<br></blockquote><blockquote type="cite">+ if (i < MI->getDesc().getNumOperands())<br></blockquote><blockquote type="cite">+ NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // For now, only allow the register to be changed if its register<br></blockquote><blockquote type="cite">+ // class is consistent across all uses.<br></blockquote><blockquote type="cite">+ if (!Classes[Reg] && NewRC)<br></blockquote><blockquote type="cite">+ Classes[Reg] = NewRC;<br></blockquote><blockquote type="cite">+ else if (!NewRC || Classes[Reg] != NewRC)<br></blockquote><blockquote type="cite">+ Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ RegRefs.insert(std::make_pair(Reg, &MO));<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // It wasn't previously live but now it is, this is a kill.<br></blockquote><blockquote type="cite">+ if (KillIndices[Reg] == ~0u) {<br></blockquote><blockquote type="cite">+ KillIndices[Reg] = Count;<br></blockquote><blockquote type="cite">+ DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">+ assert(((KillIndices[Reg] == ~0u) !=<br></blockquote><blockquote type="cite">+ (DefIndices[Reg] == ~0u)) &&<br></blockquote><blockquote type="cite">+ "Kill and Def maps aren't consistent for Reg!");<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ // Repeat, for all aliases.<br></blockquote><blockquote type="cite">+ for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">+ unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">+ if (KillIndices[AliasReg] == ~0u) {<br></blockquote><blockquote type="cite">+ KillIndices[AliasReg] = Count;<br></blockquote><blockquote type="cite">+ DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+unsigned<br></blockquote><blockquote type="cite">+CriticalAntiDepBreaker::findSuitableFreeRegister(unsigned AntiDepReg,<br></blockquote><blockquote type="cite">+ unsigned LastNewReg,<br></blockquote><blockquote type="cite">+ const TargetRegisterClass *RC) {<br></blockquote><blockquote type="cite">+ for (TargetRegisterClass::iterator R = RC->allocation_order_begin(MF),<br></blockquote><blockquote type="cite">+ RE = RC->allocation_order_end(MF); R != RE; ++R) {<br></blockquote><blockquote type="cite">+ unsigned NewReg = *R;<br></blockquote><blockquote type="cite">+ // Don't replace a register with itself.<br></blockquote><blockquote type="cite">+ if (NewReg == AntiDepReg) continue;<br></blockquote><blockquote type="cite">+ // Don't replace a register with one that was recently used to repair<br></blockquote><blockquote type="cite">+ // an anti-dependence with this AntiDepReg, because that would<br></blockquote><blockquote type="cite">+ // re-introduce that anti-dependence.<br></blockquote><blockquote type="cite">+ if (NewReg == LastNewReg) continue;<br></blockquote><blockquote type="cite">+ // If NewReg is dead and NewReg's most recent def is not before<br></blockquote><blockquote type="cite">+ // AntiDepReg's kill, it's safe to replace AntiDepReg with NewReg.<br></blockquote><blockquote type="cite">+ assert(((KillIndices[AntiDepReg] == ~0u) != (DefIndices[AntiDepReg] == ~0u)) &&<br></blockquote><blockquote type="cite">+ "Kill and Def maps aren't consistent for AntiDepReg!");<br></blockquote><blockquote type="cite">+ assert(((KillIndices[NewReg] == ~0u) != (DefIndices[NewReg] == ~0u)) &&<br></blockquote><blockquote type="cite">+ "Kill and Def maps aren't consistent for NewReg!");<br></blockquote><blockquote type="cite">+ if (KillIndices[NewReg] != ~0u ||<br></blockquote><blockquote type="cite">+ Classes[NewReg] == reinterpret_cast<TargetRegisterClass *>(-1) ||<br></blockquote><blockquote type="cite">+ KillIndices[AntiDepReg] > DefIndices[NewReg])<br></blockquote><blockquote type="cite">+ continue;<br></blockquote><blockquote type="cite">+ return NewReg;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // No registers are free and available!<br></blockquote><blockquote type="cite">+ return 0;<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+unsigned CriticalAntiDepBreaker::<br></blockquote><blockquote type="cite">+BreakAntiDependencies(std::vector<SUnit>& SUnits,<br></blockquote><blockquote type="cite">+ MachineBasicBlock::iterator& Begin,<br></blockquote><blockquote type="cite">+ MachineBasicBlock::iterator& End,<br></blockquote><blockquote type="cite">+ unsigned InsertPosIndex) {<br></blockquote><blockquote type="cite">+ // The code below assumes that there is at least one instruction,<br></blockquote><blockquote type="cite">+ // so just duck out immediately if the block is empty.<br></blockquote><blockquote type="cite">+ if (SUnits.empty()) return 0;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Find the node at the bottom of the critical path.<br></blockquote><blockquote type="cite">+ SUnit *Max = 0;<br></blockquote><blockquote type="cite">+ for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {<br></blockquote><blockquote type="cite">+ SUnit *SU = &SUnits[i];<br></blockquote><blockquote type="cite">+ if (!Max || SU->getDepth() + SU->Latency > Max->getDepth() + Max->Latency)<br></blockquote><blockquote type="cite">+ Max = SU;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#ifndef NDEBUG<br></blockquote><blockquote type="cite">+ {<br></blockquote><blockquote type="cite">+ DEBUG(errs() << "Critical path has total latency "<br></blockquote><blockquote type="cite">+ << (Max->getDepth() + Max->Latency) << "\n");<br></blockquote><blockquote type="cite">+ DEBUG(errs() << "Available regs:");<br></blockquote><blockquote type="cite">+ for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) {<br></blockquote><blockquote type="cite">+ if (KillIndices[Reg] == ~0u)<br></blockquote><blockquote type="cite">+ DEBUG(errs() << " " << TRI->getName(Reg));<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ DEBUG(errs() << '\n');<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+#endif<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Track progress along the critical path through the SUnit graph as we walk<br></blockquote><blockquote type="cite">+ // the instructions.<br></blockquote><blockquote type="cite">+ SUnit *CriticalPathSU = Max;<br></blockquote><blockquote type="cite">+ MachineInstr *CriticalPathMI = CriticalPathSU->getInstr();<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Consider this pattern:<br></blockquote><blockquote type="cite">+ // A = ...<br></blockquote><blockquote type="cite">+ // ... = A<br></blockquote><blockquote type="cite">+ // A = ...<br></blockquote><blockquote type="cite">+ // ... = A<br></blockquote><blockquote type="cite">+ // A = ...<br></blockquote><blockquote type="cite">+ // ... = A<br></blockquote><blockquote type="cite">+ // A = ...<br></blockquote><blockquote type="cite">+ // ... = A<br></blockquote><blockquote type="cite">+ // There are three anti-dependencies here, and without special care,<br></blockquote><blockquote type="cite">+ // we'd break all of them using the same register:<br></blockquote><blockquote type="cite">+ // A = ...<br></blockquote><blockquote type="cite">+ // ... = A<br></blockquote><blockquote type="cite">+ // B = ...<br></blockquote><blockquote type="cite">+ // ... = B<br></blockquote><blockquote type="cite">+ // B = ...<br></blockquote><blockquote type="cite">+ // ... = B<br></blockquote><blockquote type="cite">+ // B = ...<br></blockquote><blockquote type="cite">+ // ... = B<br></blockquote><blockquote type="cite">+ // because at each anti-dependence, B is the first register that<br></blockquote><blockquote type="cite">+ // isn't A which is free. This re-introduces anti-dependencies<br></blockquote><blockquote type="cite">+ // at all but one of the original anti-dependencies that we were<br></blockquote><blockquote type="cite">+ // trying to break. To avoid this, keep track of the most recent<br></blockquote><blockquote type="cite">+ // register that each register was replaced with, avoid<br></blockquote><blockquote type="cite">+ // using it to repair an anti-dependence on the same register.<br></blockquote><blockquote type="cite">+ // This lets us produce this:<br></blockquote><blockquote type="cite">+ // A = ...<br></blockquote><blockquote type="cite">+ // ... = A<br></blockquote><blockquote type="cite">+ // B = ...<br></blockquote><blockquote type="cite">+ // ... = B<br></blockquote><blockquote type="cite">+ // C = ...<br></blockquote><blockquote type="cite">+ // ... = C<br></blockquote><blockquote type="cite">+ // B = ...<br></blockquote><blockquote type="cite">+ // ... = B<br></blockquote><blockquote type="cite">+ // This still has an anti-dependence on B, but at least it isn't on the<br></blockquote><blockquote type="cite">+ // original critical path.<br></blockquote><blockquote type="cite">+ //<br></blockquote><blockquote type="cite">+ // TODO: If we tracked more than one register here, we could potentially<br></blockquote><blockquote type="cite">+ // fix that remaining critical edge too. This is a little more involved,<br></blockquote><blockquote type="cite">+ // because unlike the most recent register, less recent registers should<br></blockquote><blockquote type="cite">+ // still be considered, though only if no other registers are available.<br></blockquote><blockquote type="cite">+ unsigned LastNewReg[TargetRegisterInfo::FirstVirtualRegister] = {};<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Attempt to break anti-dependence edges on the critical path. Walk the<br></blockquote><blockquote type="cite">+ // instructions from the bottom up, tracking information about liveness<br></blockquote><blockquote type="cite">+ // as we go to help determine which registers are available.<br></blockquote><blockquote type="cite">+ unsigned Broken = 0;<br></blockquote><blockquote type="cite">+ unsigned Count = InsertPosIndex - 1;<br></blockquote><blockquote type="cite">+ for (MachineBasicBlock::iterator I = End, E = Begin;<br></blockquote><blockquote type="cite">+ I != E; --Count) {<br></blockquote><blockquote type="cite">+ MachineInstr *MI = --I;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Check if this instruction has a dependence on the critical path that<br></blockquote><blockquote type="cite">+ // is an anti-dependence that we may be able to break. If it is, set<br></blockquote><blockquote type="cite">+ // AntiDepReg to the non-zero register associated with the anti-dependence.<br></blockquote><blockquote type="cite">+ //<br></blockquote><blockquote type="cite">+ // We limit our attention to the critical path as a heuristic to avoid<br></blockquote><blockquote type="cite">+ // breaking anti-dependence edges that aren't going to significantly<br></blockquote><blockquote type="cite">+ // impact the overall schedule. There are a limited number of registers<br></blockquote><blockquote type="cite">+ // and we want to save them for the important edges.<br></blockquote><blockquote type="cite">+ //<br></blockquote><blockquote type="cite">+ // TODO: Instructions with multiple defs could have multiple<br></blockquote><blockquote type="cite">+ // anti-dependencies. The current code here only knows how to break one<br></blockquote><blockquote type="cite">+ // edge per instruction. Note that we'd have to be able to break all of<br></blockquote><blockquote type="cite">+ // the anti-dependencies in an instruction in order to be effective.<br></blockquote><blockquote type="cite">+ unsigned AntiDepReg = 0;<br></blockquote><blockquote type="cite">+ if (MI == CriticalPathMI) {<br></blockquote><blockquote type="cite">+ if (SDep *Edge = CriticalPathStep(CriticalPathSU)) {<br></blockquote><blockquote type="cite">+ SUnit *NextSU = Edge->getSUnit();<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Only consider anti-dependence edges.<br></blockquote><blockquote type="cite">+ if (Edge->getKind() == SDep::Anti) {<br></blockquote><blockquote type="cite">+ AntiDepReg = Edge->getReg();<br></blockquote><blockquote type="cite">+ assert(AntiDepReg != 0 && "Anti-dependence on reg0?");<br></blockquote><blockquote type="cite">+ if (!AllocatableSet.test(AntiDepReg))<br></blockquote><blockquote type="cite">+ // Don't break anti-dependencies on non-allocatable registers.<br></blockquote><blockquote type="cite">+ AntiDepReg = 0;<br></blockquote><blockquote type="cite">+ else if (KeepRegs.count(AntiDepReg))<br></blockquote><blockquote type="cite">+ // Don't break anti-dependencies if an use down below requires<br></blockquote><blockquote type="cite">+ // this exact register.<br></blockquote><blockquote type="cite">+ AntiDepReg = 0;<br></blockquote><blockquote type="cite">+ else {<br></blockquote><blockquote type="cite">+ // If the SUnit has other dependencies on the SUnit that it<br></blockquote><blockquote type="cite">+ // anti-depends on, don't bother breaking the anti-dependency<br></blockquote><blockquote type="cite">+ // since those edges would prevent such units from being<br></blockquote><blockquote type="cite">+ // scheduled past each other regardless.<br></blockquote><blockquote type="cite">+ //<br></blockquote><blockquote type="cite">+ // Also, if there are dependencies on other SUnits with the<br></blockquote><blockquote type="cite">+ // same register as the anti-dependency, don't attempt to<br></blockquote><blockquote type="cite">+ // break it.<br></blockquote><blockquote type="cite">+ for (SUnit::pred_iterator P = CriticalPathSU->Preds.begin(),<br></blockquote><blockquote type="cite">+ PE = CriticalPathSU->Preds.end(); P != PE; ++P)<br></blockquote><blockquote type="cite">+ if (P->getSUnit() == NextSU ?<br></blockquote><blockquote type="cite">+ (P->getKind() != SDep::Anti || P->getReg() != AntiDepReg) :<br></blockquote><blockquote type="cite">+ (P->getKind() == SDep::Data && P->getReg() == AntiDepReg)) {<br></blockquote><blockquote type="cite">+ AntiDepReg = 0;<br></blockquote><blockquote type="cite">+ break;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ CriticalPathSU = NextSU;<br></blockquote><blockquote type="cite">+ CriticalPathMI = CriticalPathSU->getInstr();<br></blockquote><blockquote type="cite">+ } else {<br></blockquote><blockquote type="cite">+ // We've reached the end of the critical path.<br></blockquote><blockquote type="cite">+ CriticalPathSU = 0;<br></blockquote><blockquote type="cite">+ CriticalPathMI = 0;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ PrescanInstruction(MI);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ if (MI->getDesc().hasExtraDefRegAllocReq())<br></blockquote><blockquote type="cite">+ // If this instruction's defs have special allocation requirement, don't<br></blockquote><blockquote type="cite">+ // break this anti-dependency.<br></blockquote><blockquote type="cite">+ AntiDepReg = 0;<br></blockquote><blockquote type="cite">+ else if (AntiDepReg) {<br></blockquote><blockquote type="cite">+ // If this instruction has a use of AntiDepReg, breaking it<br></blockquote><blockquote type="cite">+ // is invalid.<br></blockquote><blockquote type="cite">+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">+ MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">+ if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">+ unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">+ if (Reg == 0) continue;<br></blockquote><blockquote type="cite">+ if (MO.isUse() && AntiDepReg == Reg) {<br></blockquote><blockquote type="cite">+ AntiDepReg = 0;<br></blockquote><blockquote type="cite">+ break;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Determine AntiDepReg's register class, if it is live and is<br></blockquote><blockquote type="cite">+ // consistently used within a single class.<br></blockquote><blockquote type="cite">+ const TargetRegisterClass *RC = AntiDepReg != 0 ? Classes[AntiDepReg] : 0;<br></blockquote><blockquote type="cite">+ assert((AntiDepReg == 0 || RC != NULL) &&<br></blockquote><blockquote type="cite">+ "Register should be live if it's causing an anti-dependence!");<br></blockquote><blockquote type="cite">+ if (RC == reinterpret_cast<TargetRegisterClass *>(-1))<br></blockquote><blockquote type="cite">+ AntiDepReg = 0;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Look for a suitable register to use to break the anti-depenence.<br></blockquote><blockquote type="cite">+ //<br></blockquote><blockquote type="cite">+ // TODO: Instead of picking the first free register, consider which might<br></blockquote><blockquote type="cite">+ // be the best.<br></blockquote><blockquote type="cite">+ if (AntiDepReg != 0) {<br></blockquote><blockquote type="cite">+ if (unsigned NewReg = findSuitableFreeRegister(AntiDepReg,<br></blockquote><blockquote type="cite">+ LastNewReg[AntiDepReg],<br></blockquote><blockquote type="cite">+ RC)) {<br></blockquote><blockquote type="cite">+ DEBUG(errs() << "Breaking anti-dependence edge on "<br></blockquote><blockquote type="cite">+ << TRI->getName(AntiDepReg)<br></blockquote><blockquote type="cite">+ << " with " << RegRefs.count(AntiDepReg) << " references"<br></blockquote><blockquote type="cite">+ << " using " << TRI->getName(NewReg) << "!\n");<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // Update the references to the old register to refer to the new<br></blockquote><blockquote type="cite">+ // register.<br></blockquote><blockquote type="cite">+ std::pair<std::multimap<unsigned, MachineOperand *>::iterator,<br></blockquote><blockquote type="cite">+ std::multimap<unsigned, MachineOperand *>::iterator><br></blockquote><blockquote type="cite">+ Range = RegRefs.equal_range(AntiDepReg);<br></blockquote><blockquote type="cite">+ for (std::multimap<unsigned, MachineOperand *>::iterator<br></blockquote><blockquote type="cite">+ Q = Range.first, QE = Range.second; Q != QE; ++Q)<br></blockquote><blockquote type="cite">+ Q->second->setReg(NewReg);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ // We just went back in time and modified history; the<br></blockquote><blockquote type="cite">+ // liveness information for the anti-depenence reg is now<br></blockquote><blockquote type="cite">+ // inconsistent. Set the state as if it were dead.<br></blockquote><blockquote type="cite">+ Classes[NewReg] = Classes[AntiDepReg];<br></blockquote><blockquote type="cite">+ DefIndices[NewReg] = DefIndices[AntiDepReg];<br></blockquote><blockquote type="cite">+ KillIndices[NewReg] = KillIndices[AntiDepReg];<br></blockquote><blockquote type="cite">+ assert(((KillIndices[NewReg] == ~0u) !=<br></blockquote><blockquote type="cite">+ (DefIndices[NewReg] == ~0u)) &&<br></blockquote><blockquote type="cite">+ "Kill and Def maps aren't consistent for NewReg!");<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ Classes[AntiDepReg] = 0;<br></blockquote><blockquote type="cite">+ DefIndices[AntiDepReg] = KillIndices[AntiDepReg];<br></blockquote><blockquote type="cite">+ KillIndices[AntiDepReg] = ~0u;<br></blockquote><blockquote type="cite">+ assert(((KillIndices[AntiDepReg] == ~0u) !=<br></blockquote><blockquote type="cite">+ (DefIndices[AntiDepReg] == ~0u)) &&<br></blockquote><blockquote type="cite">+ "Kill and Def maps aren't consistent for AntiDepReg!");<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ RegRefs.erase(AntiDepReg);<br></blockquote><blockquote type="cite">+ LastNewReg[AntiDepReg] = NewReg;<br></blockquote><blockquote type="cite">+ ++Broken;<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ ScanInstruction(MI, Count);<br></blockquote><blockquote type="cite">+ }<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ return Broken;<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Added: llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.h<br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.h?rev=85127&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.h?rev=85127&view=auto</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">==============================================================================<br></blockquote><blockquote type="cite">--- llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.h (added)<br></blockquote><blockquote type="cite">+++ llvm/trunk/lib/CodeGen/CriticalAntiDepBreaker.h Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">@@ -0,0 +1,95 @@<br></blockquote><blockquote type="cite">+//=- llvm/CodeGen/CriticalAntiDepBreaker.h - Anti-Dep Support -*- C++ -*-=//<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// The LLVM Compiler Infrastructure<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// This file is distributed under the University of Illinois Open Source<br></blockquote><blockquote type="cite">+// License. See LICENSE.TXT for details.<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+//===----------------------------------------------------------------------===//<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+// This file implements the CriticalAntiDepBreaker class, which<br></blockquote><blockquote type="cite">+// implements register anti-dependence breaking along a blocks<br></blockquote><blockquote type="cite">+// critical path during post-RA scheduler.<br></blockquote><blockquote type="cite">+//<br></blockquote><blockquote type="cite">+//===----------------------------------------------------------------------===//<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#ifndef LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H<br></blockquote><blockquote type="cite">+#define LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/AntiDepBreaker.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineBasicBlock.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineFrameInfo.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineFunction.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/MachineRegisterInfo.h"<br></blockquote><blockquote type="cite">+#include "llvm/CodeGen/ScheduleDAG.h"<br></blockquote><blockquote type="cite">+#include "llvm/Target/TargetRegisterInfo.h"<br></blockquote><blockquote type="cite">+#include "llvm/ADT/BitVector.h"<br></blockquote><blockquote type="cite">+#include "llvm/ADT/SmallSet.h"<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+namespace llvm {<br></blockquote><blockquote type="cite">+ class CriticalAntiDepBreaker : public AntiDepBreaker {<br></blockquote><blockquote type="cite">+ MachineFunction& MF;<br></blockquote><blockquote type="cite">+ MachineRegisterInfo &MRI;<br></blockquote><blockquote type="cite">+ const TargetRegisterInfo *TRI;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// AllocatableSet - The set of allocatable registers.<br></blockquote><blockquote type="cite">+ /// We'll be ignoring anti-dependencies on non-allocatable registers,<br></blockquote><blockquote type="cite">+ /// because they may not be safe to break.<br></blockquote><blockquote type="cite">+ const BitVector AllocatableSet;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// Classes - For live regs that are only used in one register class in a<br></blockquote><blockquote type="cite">+ /// live range, the register class. If the register is not live, the<br></blockquote><blockquote type="cite">+ /// corresponding value is null. If the register is live but used in<br></blockquote><blockquote type="cite">+ /// multiple register classes, the corresponding value is -1 casted to a<br></blockquote><blockquote type="cite">+ /// pointer.<br></blockquote><blockquote type="cite">+ const TargetRegisterClass *<br></blockquote><blockquote type="cite">+ Classes[TargetRegisterInfo::FirstVirtualRegister];<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// RegRegs - Map registers to all their references within a live range.<br></blockquote><blockquote type="cite">+ std::multimap<unsigned, MachineOperand *> RegRefs;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// KillIndices - The index of the most recent kill (proceding bottom-up),<br></blockquote><blockquote type="cite">+ /// or ~0u if the register is not live.<br></blockquote><blockquote type="cite">+ unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister];<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// DefIndices - The index of the most recent complete def (proceding bottom<br></blockquote><blockquote type="cite">+ /// up), or ~0u if the register is live.<br></blockquote><blockquote type="cite">+ unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister];<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// KeepRegs - A set of registers which are live and cannot be changed to<br></blockquote><blockquote type="cite">+ /// break anti-dependencies.<br></blockquote><blockquote type="cite">+ SmallSet<unsigned, 4> KeepRegs;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ public:<br></blockquote><blockquote type="cite">+ CriticalAntiDepBreaker(MachineFunction& MFi);<br></blockquote><blockquote type="cite">+ ~CriticalAntiDepBreaker();<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// Start - Initialize anti-dep breaking for a new basic block.<br></blockquote><blockquote type="cite">+ void StartBlock(MachineBasicBlock *BB);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// BreakAntiDependencies - Identifiy anti-dependencies along the critical path<br></blockquote><blockquote type="cite">+ /// of the ScheduleDAG and break them by renaming registers.<br></blockquote><blockquote type="cite">+ ///<br></blockquote><blockquote type="cite">+ unsigned BreakAntiDependencies(std::vector<SUnit>& SUnits,<br></blockquote><blockquote type="cite">+ MachineBasicBlock::iterator& Begin,<br></blockquote><blockquote type="cite">+ MachineBasicBlock::iterator& End,<br></blockquote><blockquote type="cite">+ unsigned InsertPosIndex);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// Observe - Update liveness information to account for the current<br></blockquote><blockquote type="cite">+ /// instruction, which will not be scheduled.<br></blockquote><blockquote type="cite">+ ///<br></blockquote><blockquote type="cite">+ void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ /// Finish - Finish anti-dep breaking for a basic block.<br></blockquote><blockquote type="cite">+ void FinishBlock();<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ private:<br></blockquote><blockquote type="cite">+ void PrescanInstruction(MachineInstr *MI);<br></blockquote><blockquote type="cite">+ void ScanInstruction(MachineInstr *MI, unsigned Count);<br></blockquote><blockquote type="cite">+ unsigned findSuitableFreeRegister(unsigned AntiDepReg,<br></blockquote><blockquote type="cite">+ unsigned LastNewReg,<br></blockquote><blockquote type="cite">+ const TargetRegisterClass *);<br></blockquote><blockquote type="cite">+ };<br></blockquote><blockquote type="cite">+}<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+#endif<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Modified: llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp<br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp?rev=85127&r1=85126&r2=85127&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp?rev=85127&r1=85126&r2=85127&view=diff</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">==============================================================================<br></blockquote><blockquote type="cite">--- llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp (original)<br></blockquote><blockquote type="cite">+++ llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">@@ -19,6 +19,7 @@<br></blockquote><blockquote type="cite"> //===----------------------------------------------------------------------===//<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> #define DEBUG_TYPE "post-RA-sched"<br></blockquote><blockquote type="cite">+#include "CriticalAntiDepBreaker.h"<br></blockquote><blockquote type="cite"> #include "ExactHazardRecognizer.h"<br></blockquote><blockquote type="cite"> #include "SimpleHazardRecognizer.h"<br></blockquote><blockquote type="cite"> #include "ScheduleDAGInstrs.h"<br></blockquote><blockquote type="cite">@@ -40,6 +41,7 @@<br></blockquote><blockquote type="cite"> #include "llvm/Support/Debug.h"<br></blockquote><blockquote type="cite"> #include "llvm/Support/ErrorHandling.h"<br></blockquote><blockquote type="cite"> #include "llvm/Support/raw_ostream.h"<br></blockquote><blockquote type="cite">+#include "llvm/ADT/BitVector.h"<br></blockquote><blockquote type="cite"> #include "llvm/ADT/Statistic.h"<br></blockquote><blockquote type="cite"> #include <map><br></blockquote><blockquote type="cite"> #include <set><br></blockquote><blockquote type="cite">@@ -47,6 +49,7 @@<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> STATISTIC(NumNoops, "Number of noops inserted");<br></blockquote><blockquote type="cite"> STATISTIC(NumStalls, "Number of pipeline stalls");<br></blockquote><blockquote type="cite">+STATISTIC(NumFixedAnti, "Number of fixed anti-dependencies");<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> // Post-RA scheduling is enabled with<br></blockquote><blockquote type="cite"> // TargetSubtarget.enablePostRAScheduler(). This flag can be used to<br></blockquote><blockquote type="cite">@@ -55,10 +58,11 @@<br></blockquote><blockquote type="cite"> EnablePostRAScheduler("post-RA-scheduler",<br></blockquote><blockquote type="cite"> cl::desc("Enable scheduling after register allocation"),<br></blockquote><blockquote type="cite"> cl::init(false), cl::Hidden);<br></blockquote><blockquote type="cite">-static cl::opt<bool><br></blockquote><blockquote type="cite">+static cl::opt<std::string><br></blockquote><blockquote type="cite"> EnableAntiDepBreaking("break-anti-dependencies",<br></blockquote><blockquote type="cite">- cl::desc("Break post-RA scheduling anti-dependencies"),<br></blockquote><blockquote type="cite">- cl::init(true), cl::Hidden);<br></blockquote><blockquote type="cite">+ cl::desc("Break post-RA scheduling anti-dependencies: "<br></blockquote><blockquote type="cite">+ "\"critical\", \"all\", or \"none\""),<br></blockquote><blockquote type="cite">+ cl::init("none"), cl::Hidden);<br></blockquote><blockquote type="cite"> static cl::opt<bool><br></blockquote><blockquote type="cite"> EnablePostRAHazardAvoidance("avoid-hazards",<br></blockquote><blockquote type="cite"> cl::desc("Enable exact hazard avoidance"),<br></blockquote><blockquote type="cite">@@ -116,56 +120,30 @@<br></blockquote><blockquote type="cite"> /// Topo - A topological ordering for SUnits.<br></blockquote><blockquote type="cite"> ScheduleDAGTopologicalSort Topo;<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- /// AllocatableSet - The set of allocatable registers.<br></blockquote><blockquote type="cite">- /// We'll be ignoring anti-dependencies on non-allocatable registers,<br></blockquote><blockquote type="cite">- /// because they may not be safe to break.<br></blockquote><blockquote type="cite">- const BitVector AllocatableSet;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite"> /// HazardRec - The hazard recognizer to use.<br></blockquote><blockquote type="cite"> ScheduleHazardRecognizer *HazardRec;<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">+ /// AntiDepBreak - Anti-dependence breaking object, or NULL if none<br></blockquote><blockquote type="cite">+ AntiDepBreaker *AntiDepBreak;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite"> /// AA - AliasAnalysis for making memory reference queries.<br></blockquote><blockquote type="cite"> AliasAnalysis *AA;<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- /// AntiDepMode - Anti-dependence breaking mode<br></blockquote><blockquote type="cite">- TargetSubtarget::AntiDepBreakMode AntiDepMode;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- /// Classes - For live regs that are only used in one register class in a<br></blockquote><blockquote type="cite">- /// live range, the register class. If the register is not live, the<br></blockquote><blockquote type="cite">- /// corresponding value is null. If the register is live but used in<br></blockquote><blockquote type="cite">- /// multiple register classes, the corresponding value is -1 casted to a<br></blockquote><blockquote type="cite">- /// pointer.<br></blockquote><blockquote type="cite">- const TargetRegisterClass *<br></blockquote><blockquote type="cite">- Classes[TargetRegisterInfo::FirstVirtualRegister];<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- /// RegRegs - Map registers to all their references within a live range.<br></blockquote><blockquote type="cite">- std::multimap<unsigned, MachineOperand *> RegRefs;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite"> /// KillIndices - The index of the most recent kill (proceding bottom-up),<br></blockquote><blockquote type="cite"> /// or ~0u if the register is not live.<br></blockquote><blockquote type="cite"> unsigned KillIndices[TargetRegisterInfo::FirstVirtualRegister];<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- /// DefIndices - The index of the most recent complete def (proceding bottom<br></blockquote><blockquote type="cite">- /// up), or ~0u if the register is live.<br></blockquote><blockquote type="cite">- unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister];<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- /// KeepRegs - A set of registers which are live and cannot be changed to<br></blockquote><blockquote type="cite">- /// break anti-dependencies.<br></blockquote><blockquote type="cite">- SmallSet<unsigned, 4> KeepRegs;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite"> public:<br></blockquote><blockquote type="cite"> SchedulePostRATDList(MachineFunction &MF,<br></blockquote><blockquote type="cite"> const MachineLoopInfo &MLI,<br></blockquote><blockquote type="cite"> const MachineDominatorTree &MDT,<br></blockquote><blockquote type="cite"> ScheduleHazardRecognizer *HR,<br></blockquote><blockquote type="cite">- AliasAnalysis *aa,<br></blockquote><blockquote type="cite">- TargetSubtarget::AntiDepBreakMode adm)<br></blockquote><blockquote type="cite">+ AntiDepBreaker *ADB,<br></blockquote><blockquote type="cite">+ AliasAnalysis *aa)<br></blockquote><blockquote type="cite"> : ScheduleDAGInstrs(MF, MLI, MDT), Topo(SUnits),<br></blockquote><blockquote type="cite">- AllocatableSet(TRI->getAllocatableSet(MF)),<br></blockquote><blockquote type="cite">- HazardRec(HR), AA(aa), AntiDepMode(adm) {}<br></blockquote><blockquote type="cite">+ HazardRec(HR), AntiDepBreak(ADB), AA(aa) {}<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> ~SchedulePostRATDList() {<br></blockquote><blockquote type="cite">- delete HazardRec;<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> /// StartBlock - Initialize register live-range state for scheduling in<br></blockquote><blockquote type="cite">@@ -177,11 +155,6 @@<br></blockquote><blockquote type="cite"> ///<br></blockquote><blockquote type="cite"> void Schedule();<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- /// FixupKills - Fix register kill flags that have been made<br></blockquote><blockquote type="cite">- /// invalid due to scheduling<br></blockquote><blockquote type="cite">- ///<br></blockquote><blockquote type="cite">- void FixupKills(MachineBasicBlock *MBB);<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite"> /// Observe - Update liveness information to account for the current<br></blockquote><blockquote type="cite"> /// instruction, which will not be scheduled.<br></blockquote><blockquote type="cite"> ///<br></blockquote><blockquote type="cite">@@ -191,17 +164,16 @@<br></blockquote><blockquote type="cite"> ///<br></blockquote><blockquote type="cite"> void FinishBlock();<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">+ /// FixupKills - Fix register kill flags that have been made<br></blockquote><blockquote type="cite">+ /// invalid due to scheduling<br></blockquote><blockquote type="cite">+ ///<br></blockquote><blockquote type="cite">+ void FixupKills(MachineBasicBlock *MBB);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite"> private:<br></blockquote><blockquote type="cite">- void PrescanInstruction(MachineInstr *MI);<br></blockquote><blockquote type="cite">- void ScanInstruction(MachineInstr *MI, unsigned Count);<br></blockquote><blockquote type="cite"> void ReleaseSucc(SUnit *SU, SDep *SuccEdge);<br></blockquote><blockquote type="cite"> void ReleaseSuccessors(SUnit *SU);<br></blockquote><blockquote type="cite"> void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle);<br></blockquote><blockquote type="cite"> void ListScheduleTopDown();<br></blockquote><blockquote type="cite">- bool BreakAntiDependencies();<br></blockquote><blockquote type="cite">- unsigned findSuitableFreeRegister(unsigned AntiDepReg,<br></blockquote><blockquote type="cite">- unsigned LastNewReg,<br></blockquote><blockquote type="cite">- const TargetRegisterClass *);<br></blockquote><blockquote type="cite"> void StartBlockForKills(MachineBasicBlock *BB);<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> // ToggleKillFlag - Toggle a register operand kill flag. Other<br></blockquote><blockquote type="cite">@@ -250,8 +222,9 @@<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> // Check for antidep breaking override...<br></blockquote><blockquote type="cite"> if (EnableAntiDepBreaking.getPosition() > 0) {<br></blockquote><blockquote type="cite">- AntiDepMode = (EnableAntiDepBreaking) ?<br></blockquote><blockquote type="cite">- TargetSubtarget::ANTIDEP_CRITICAL : TargetSubtarget::ANTIDEP_NONE;<br></blockquote><blockquote type="cite">+ AntiDepMode = (EnableAntiDepBreaking == "all") ? TargetSubtarget::ANTIDEP_ALL :<br></blockquote><blockquote type="cite">+ (EnableAntiDepBreaking == "critical") ? TargetSubtarget::ANTIDEP_CRITICAL :<br></blockquote><blockquote type="cite">+ TargetSubtarget::ANTIDEP_NONE;<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> DEBUG(errs() << "PostRAScheduler\n");<br></blockquote><blockquote type="cite">@@ -262,8 +235,12 @@<br></blockquote><blockquote type="cite"> ScheduleHazardRecognizer *HR = EnablePostRAHazardAvoidance ?<br></blockquote><blockquote type="cite"> (ScheduleHazardRecognizer *)new ExactHazardRecognizer(InstrItins) :<br></blockquote><blockquote type="cite"> (ScheduleHazardRecognizer *)new SimpleHazardRecognizer();<br></blockquote><blockquote type="cite">+ AntiDepBreaker *ADB =<br></blockquote><blockquote type="cite">+ (AntiDepMode == TargetSubtarget::ANTIDEP_ALL) ? NULL /* FIXME */ :<br></blockquote><blockquote type="cite">+ (AntiDepMode == TargetSubtarget::ANTIDEP_CRITICAL) ?<br></blockquote><blockquote type="cite">+ new CriticalAntiDepBreaker(Fn) : NULL;<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- SchedulePostRATDList Scheduler(Fn, MLI, MDT, HR, AA, AntiDepMode);<br></blockquote><blockquote type="cite">+ SchedulePostRATDList Scheduler(Fn, MLI, MDT, HR, ADB, AA);<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> // Loop over all of the basic blocks<br></blockquote><blockquote type="cite"> for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();<br></blockquote><blockquote type="cite">@@ -311,6 +288,9 @@<br></blockquote><blockquote type="cite"> Scheduler.FixupKills(MBB);<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">+ delete HR;<br></blockquote><blockquote type="cite">+ delete ADB;<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite"> return true;<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">@@ -321,78 +301,10 @@<br></blockquote><blockquote type="cite"> // Call the superclass.<br></blockquote><blockquote type="cite"> ScheduleDAGInstrs::StartBlock(BB);<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- // Reset the hazard recognizer.<br></blockquote><blockquote type="cite">+ // Reset the hazard recognizer and anti-dep breaker.<br></blockquote><blockquote type="cite"> HazardRec->Reset();<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Clear out the register class data.<br></blockquote><blockquote type="cite">- std::fill(Classes, array_endof(Classes),<br></blockquote><blockquote type="cite">- static_cast<const TargetRegisterClass *>(0));<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Initialize the indices to indicate that no registers are live.<br></blockquote><blockquote type="cite">- std::fill(KillIndices, array_endof(KillIndices), ~0u);<br></blockquote><blockquote type="cite">- std::fill(DefIndices, array_endof(DefIndices), BB->size());<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Clear "do not change" set.<br></blockquote><blockquote type="cite">- KeepRegs.clear();<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn());<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Determine the live-out physregs for this block.<br></blockquote><blockquote type="cite">- if (IsReturnBlock) {<br></blockquote><blockquote type="cite">- // In a return block, examine the function live-out regs.<br></blockquote><blockquote type="cite">- for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(),<br></blockquote><blockquote type="cite">- E = MRI.liveout_end(); I != E; ++I) {<br></blockquote><blockquote type="cite">- unsigned Reg = *I;<br></blockquote><blockquote type="cite">- Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- KillIndices[Reg] = BB->size();<br></blockquote><blockquote type="cite">- DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">- // Repeat, for all aliases.<br></blockquote><blockquote type="cite">- for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">- unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">- Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- KillIndices[AliasReg] = BB->size();<br></blockquote><blockquote type="cite">- DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- } else {<br></blockquote><blockquote type="cite">- // In a non-return block, examine the live-in regs of all successors.<br></blockquote><blockquote type="cite">- for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(),<br></blockquote><blockquote type="cite">- SE = BB->succ_end(); SI != SE; ++SI)<br></blockquote><blockquote type="cite">- for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(),<br></blockquote><blockquote type="cite">- E = (*SI)->livein_end(); I != E; ++I) {<br></blockquote><blockquote type="cite">- unsigned Reg = *I;<br></blockquote><blockquote type="cite">- Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- KillIndices[Reg] = BB->size();<br></blockquote><blockquote type="cite">- DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">- // Repeat, for all aliases.<br></blockquote><blockquote type="cite">- for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">- unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">- Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- KillIndices[AliasReg] = BB->size();<br></blockquote><blockquote type="cite">- DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Mark live-out callee-saved registers. In a return block this is<br></blockquote><blockquote type="cite">- // all callee-saved registers. In non-return this is any<br></blockquote><blockquote type="cite">- // callee-saved register that is not saved in the prolog.<br></blockquote><blockquote type="cite">- const MachineFrameInfo *MFI = MF.getFrameInfo();<br></blockquote><blockquote type="cite">- BitVector Pristine = MFI->getPristineRegs(BB);<br></blockquote><blockquote type="cite">- for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) {<br></blockquote><blockquote type="cite">- unsigned Reg = *I;<br></blockquote><blockquote type="cite">- if (!IsReturnBlock && !Pristine.test(Reg)) continue;<br></blockquote><blockquote type="cite">- Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- KillIndices[Reg] = BB->size();<br></blockquote><blockquote type="cite">- DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">- // Repeat, for all aliases.<br></blockquote><blockquote type="cite">- for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">- unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">- Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- KillIndices[AliasReg] = BB->size();<br></blockquote><blockquote type="cite">- DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">+ if (AntiDepBreak != NULL)<br></blockquote><blockquote type="cite">+ AntiDepBreak->StartBlock(BB);<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> /// Schedule - Schedule the instruction range using list scheduling.<br></blockquote><blockquote type="cite">@@ -403,8 +315,11 @@<br></blockquote><blockquote type="cite"> // Build the scheduling graph.<br></blockquote><blockquote type="cite"> BuildSchedGraph(AA);<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">- if (AntiDepMode != TargetSubtarget::ANTIDEP_NONE) {<br></blockquote><blockquote type="cite">- if (BreakAntiDependencies()) {<br></blockquote><blockquote type="cite">+ if (AntiDepBreak != NULL) {<br></blockquote><blockquote type="cite">+ unsigned Broken =<br></blockquote><blockquote type="cite">+ AntiDepBreak->BreakAntiDependencies(SUnits, Begin, InsertPos,<br></blockquote><blockquote type="cite">+ InsertPosIndex);<br></blockquote><blockquote type="cite">+ if (Broken > 0) {<br></blockquote><blockquote type="cite"> // We made changes. Update the dependency graph.<br></blockquote><blockquote type="cite"> // Theoretically we could update the graph in place:<br></blockquote><blockquote type="cite"> // When a live range is changed to use a different register, remove<br></blockquote><blockquote type="cite">@@ -415,6 +330,8 @@<br></blockquote><blockquote type="cite"> EntrySU = SUnit();<br></blockquote><blockquote type="cite"> ExitSU = SUnit();<br></blockquote><blockquote type="cite"> BuildSchedGraph(AA);<br></blockquote><blockquote type="cite">+<br></blockquote><blockquote type="cite">+ NumFixedAnti += Broken;<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">@@ -432,436 +349,20 @@<br></blockquote><blockquote type="cite"> /// instruction, which will not be scheduled.<br></blockquote><blockquote type="cite"> ///<br></blockquote><blockquote type="cite"> void SchedulePostRATDList::Observe(MachineInstr *MI, unsigned Count) {<br></blockquote><blockquote type="cite">- assert(Count < InsertPosIndex && "Instruction index out of expected range!");<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Any register which was defined within the previous scheduling region<br></blockquote><blockquote type="cite">- // may have been rescheduled and its lifetime may overlap with registers<br></blockquote><blockquote type="cite">- // in ways not reflected in our current liveness state. For each such<br></blockquote><blockquote type="cite">- // register, adjust the liveness state to be conservatively correct.<br></blockquote><blockquote type="cite">- for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg)<br></blockquote><blockquote type="cite">- if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) {<br></blockquote><blockquote type="cite">- assert(KillIndices[Reg] == ~0u && "Clobbered register is live!");<br></blockquote><blockquote type="cite">- // Mark this register to be non-renamable.<br></blockquote><blockquote type="cite">- Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- // Move the def index to the end of the previous region, to reflect<br></blockquote><blockquote type="cite">- // that the def could theoretically have been scheduled at the end.<br></blockquote><blockquote type="cite">- DefIndices[Reg] = InsertPosIndex;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- PrescanInstruction(MI);<br></blockquote><blockquote type="cite">- ScanInstruction(MI, Count);<br></blockquote><blockquote type="cite">+ if (AntiDepBreak != NULL)<br></blockquote><blockquote type="cite">+ AntiDepBreak->Observe(MI, Count, InsertPosIndex);<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> /// FinishBlock - Clean up register live-range state.<br></blockquote><blockquote type="cite"> ///<br></blockquote><blockquote type="cite"> void SchedulePostRATDList::FinishBlock() {<br></blockquote><blockquote type="cite">- RegRefs.clear();<br></blockquote><blockquote type="cite">+ if (AntiDepBreak != NULL)<br></blockquote><blockquote type="cite">+ AntiDepBreak->FinishBlock();<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"> // Call the superclass.<br></blockquote><blockquote type="cite"> ScheduleDAGInstrs::FinishBlock();<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">-/// CriticalPathStep - Return the next SUnit after SU on the bottom-up<br></blockquote><blockquote type="cite">-/// critical path.<br></blockquote><blockquote type="cite">-static SDep *CriticalPathStep(SUnit *SU) {<br></blockquote><blockquote type="cite">- SDep *Next = 0;<br></blockquote><blockquote type="cite">- unsigned NextDepth = 0;<br></blockquote><blockquote type="cite">- // Find the predecessor edge with the greatest depth.<br></blockquote><blockquote type="cite">- for (SUnit::pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end();<br></blockquote><blockquote type="cite">- P != PE; ++P) {<br></blockquote><blockquote type="cite">- SUnit *PredSU = P->getSUnit();<br></blockquote><blockquote type="cite">- unsigned PredLatency = P->getLatency();<br></blockquote><blockquote type="cite">- unsigned PredTotalLatency = PredSU->getDepth() + PredLatency;<br></blockquote><blockquote type="cite">- // In the case of a latency tie, prefer an anti-dependency edge over<br></blockquote><blockquote type="cite">- // other types of edges.<br></blockquote><blockquote type="cite">- if (NextDepth < PredTotalLatency ||<br></blockquote><blockquote type="cite">- (NextDepth == PredTotalLatency && P->getKind() == SDep::Anti)) {<br></blockquote><blockquote type="cite">- NextDepth = PredTotalLatency;<br></blockquote><blockquote type="cite">- Next = &*P;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- return Next;<br></blockquote><blockquote type="cite">-}<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">-void SchedulePostRATDList::PrescanInstruction(MachineInstr *MI) {<br></blockquote><blockquote type="cite">- // Scan the register operands for this instruction and update<br></blockquote><blockquote type="cite">- // Classes and RegRefs.<br></blockquote><blockquote type="cite">- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">- MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">- if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">- unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">- if (Reg == 0) continue;<br></blockquote><blockquote type="cite">- const TargetRegisterClass *NewRC = 0;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- if (i < MI->getDesc().getNumOperands())<br></blockquote><blockquote type="cite">- NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI);<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // For now, only allow the register to be changed if its register<br></blockquote><blockquote type="cite">- // class is consistent across all uses.<br></blockquote><blockquote type="cite">- if (!Classes[Reg] && NewRC)<br></blockquote><blockquote type="cite">- Classes[Reg] = NewRC;<br></blockquote><blockquote type="cite">- else if (!NewRC || Classes[Reg] != NewRC)<br></blockquote><blockquote type="cite">- Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Now check for aliases.<br></blockquote><blockquote type="cite">- for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">- // If an alias of the reg is used during the live range, give up.<br></blockquote><blockquote type="cite">- // Note that this allows us to skip checking if AntiDepReg<br></blockquote><blockquote type="cite">- // overlaps with any of the aliases, among other things.<br></blockquote><blockquote type="cite">- unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">- if (Classes[AliasReg]) {<br></blockquote><blockquote type="cite">- Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // If we're still willing to consider this register, note the reference.<br></blockquote><blockquote type="cite">- if (Classes[Reg] != reinterpret_cast<TargetRegisterClass *>(-1))<br></blockquote><blockquote type="cite">- RegRefs.insert(std::make_pair(Reg, &MO));<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // It's not safe to change register allocation for source operands of<br></blockquote><blockquote type="cite">- // that have special allocation requirements.<br></blockquote><blockquote type="cite">- if (MO.isUse() && MI->getDesc().hasExtraSrcRegAllocReq()) {<br></blockquote><blockquote type="cite">- if (KeepRegs.insert(Reg)) {<br></blockquote><blockquote type="cite">- for (const unsigned *Subreg = TRI->getSubRegisters(Reg);<br></blockquote><blockquote type="cite">- *Subreg; ++Subreg)<br></blockquote><blockquote type="cite">- KeepRegs.insert(*Subreg);<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-}<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">-void SchedulePostRATDList::ScanInstruction(MachineInstr *MI,<br></blockquote><blockquote type="cite">- unsigned Count) {<br></blockquote><blockquote type="cite">- // Update liveness.<br></blockquote><blockquote type="cite">- // Proceding upwards, registers that are defed but not used in this<br></blockquote><blockquote type="cite">- // instruction are now dead.<br></blockquote><blockquote type="cite">- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">- MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">- if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">- unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">- if (Reg == 0) continue;<br></blockquote><blockquote type="cite">- if (!MO.isDef()) continue;<br></blockquote><blockquote type="cite">- // Ignore two-addr defs.<br></blockquote><blockquote type="cite">- if (MI->isRegTiedToUseOperand(i)) continue;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- DefIndices[Reg] = Count;<br></blockquote><blockquote type="cite">- KillIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">- assert(((KillIndices[Reg] == ~0u) !=<br></blockquote><blockquote type="cite">- (DefIndices[Reg] == ~0u)) &&<br></blockquote><blockquote type="cite">- "Kill and Def maps aren't consistent for Reg!");<br></blockquote><blockquote type="cite">- KeepRegs.erase(Reg);<br></blockquote><blockquote type="cite">- Classes[Reg] = 0;<br></blockquote><blockquote type="cite">- RegRefs.erase(Reg);<br></blockquote><blockquote type="cite">- // Repeat, for all subregs.<br></blockquote><blockquote type="cite">- for (const unsigned *Subreg = TRI->getSubRegisters(Reg);<br></blockquote><blockquote type="cite">- *Subreg; ++Subreg) {<br></blockquote><blockquote type="cite">- unsigned SubregReg = *Subreg;<br></blockquote><blockquote type="cite">- DefIndices[SubregReg] = Count;<br></blockquote><blockquote type="cite">- KillIndices[SubregReg] = ~0u;<br></blockquote><blockquote type="cite">- KeepRegs.erase(SubregReg);<br></blockquote><blockquote type="cite">- Classes[SubregReg] = 0;<br></blockquote><blockquote type="cite">- RegRefs.erase(SubregReg);<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- // Conservatively mark super-registers as unusable.<br></blockquote><blockquote type="cite">- for (const unsigned *Super = TRI->getSuperRegisters(Reg);<br></blockquote><blockquote type="cite">- *Super; ++Super) {<br></blockquote><blockquote type="cite">- unsigned SuperReg = *Super;<br></blockquote><blockquote type="cite">- Classes[SuperReg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">- MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">- if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">- unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">- if (Reg == 0) continue;<br></blockquote><blockquote type="cite">- if (!MO.isUse()) continue;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- const TargetRegisterClass *NewRC = 0;<br></blockquote><blockquote type="cite">- if (i < MI->getDesc().getNumOperands())<br></blockquote><blockquote type="cite">- NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI);<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // For now, only allow the register to be changed if its register<br></blockquote><blockquote type="cite">- // class is consistent across all uses.<br></blockquote><blockquote type="cite">- if (!Classes[Reg] && NewRC)<br></blockquote><blockquote type="cite">- Classes[Reg] = NewRC;<br></blockquote><blockquote type="cite">- else if (!NewRC || Classes[Reg] != NewRC)<br></blockquote><blockquote type="cite">- Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- RegRefs.insert(std::make_pair(Reg, &MO));<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // It wasn't previously live but now it is, this is a kill.<br></blockquote><blockquote type="cite">- if (KillIndices[Reg] == ~0u) {<br></blockquote><blockquote type="cite">- KillIndices[Reg] = Count;<br></blockquote><blockquote type="cite">- DefIndices[Reg] = ~0u;<br></blockquote><blockquote type="cite">- assert(((KillIndices[Reg] == ~0u) !=<br></blockquote><blockquote type="cite">- (DefIndices[Reg] == ~0u)) &&<br></blockquote><blockquote type="cite">- "Kill and Def maps aren't consistent for Reg!");<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- // Repeat, for all aliases.<br></blockquote><blockquote type="cite">- for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {<br></blockquote><blockquote type="cite">- unsigned AliasReg = *Alias;<br></blockquote><blockquote type="cite">- if (KillIndices[AliasReg] == ~0u) {<br></blockquote><blockquote type="cite">- KillIndices[AliasReg] = Count;<br></blockquote><blockquote type="cite">- DefIndices[AliasReg] = ~0u;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-}<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">-unsigned<br></blockquote><blockquote type="cite">-SchedulePostRATDList::findSuitableFreeRegister(unsigned AntiDepReg,<br></blockquote><blockquote type="cite">- unsigned LastNewReg,<br></blockquote><blockquote type="cite">- const TargetRegisterClass *RC) {<br></blockquote><blockquote type="cite">- for (TargetRegisterClass::iterator R = RC->allocation_order_begin(MF),<br></blockquote><blockquote type="cite">- RE = RC->allocation_order_end(MF); R != RE; ++R) {<br></blockquote><blockquote type="cite">- unsigned NewReg = *R;<br></blockquote><blockquote type="cite">- // Don't replace a register with itself.<br></blockquote><blockquote type="cite">- if (NewReg == AntiDepReg) continue;<br></blockquote><blockquote type="cite">- // Don't replace a register with one that was recently used to repair<br></blockquote><blockquote type="cite">- // an anti-dependence with this AntiDepReg, because that would<br></blockquote><blockquote type="cite">- // re-introduce that anti-dependence.<br></blockquote><blockquote type="cite">- if (NewReg == LastNewReg) continue;<br></blockquote><blockquote type="cite">- // If NewReg is dead and NewReg's most recent def is not before<br></blockquote><blockquote type="cite">- // AntiDepReg's kill, it's safe to replace AntiDepReg with NewReg.<br></blockquote><blockquote type="cite">- assert(((KillIndices[AntiDepReg] == ~0u) != (DefIndices[AntiDepReg] == ~0u)) &&<br></blockquote><blockquote type="cite">- "Kill and Def maps aren't consistent for AntiDepReg!");<br></blockquote><blockquote type="cite">- assert(((KillIndices[NewReg] == ~0u) != (DefIndices[NewReg] == ~0u)) &&<br></blockquote><blockquote type="cite">- "Kill and Def maps aren't consistent for NewReg!");<br></blockquote><blockquote type="cite">- if (KillIndices[NewReg] != ~0u ||<br></blockquote><blockquote type="cite">- Classes[NewReg] == reinterpret_cast<TargetRegisterClass *>(-1) ||<br></blockquote><blockquote type="cite">- KillIndices[AntiDepReg] > DefIndices[NewReg])<br></blockquote><blockquote type="cite">- continue;<br></blockquote><blockquote type="cite">- return NewReg;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // No registers are free and available!<br></blockquote><blockquote type="cite">- return 0;<br></blockquote><blockquote type="cite">-}<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">-/// BreakAntiDependencies - Identifiy anti-dependencies along the critical path<br></blockquote><blockquote type="cite">-/// of the ScheduleDAG and break them by renaming registers.<br></blockquote><blockquote type="cite">-///<br></blockquote><blockquote type="cite">-bool SchedulePostRATDList::BreakAntiDependencies() {<br></blockquote><blockquote type="cite">- // The code below assumes that there is at least one instruction,<br></blockquote><blockquote type="cite">- // so just duck out immediately if the block is empty.<br></blockquote><blockquote type="cite">- if (SUnits.empty()) return false;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Find the node at the bottom of the critical path.<br></blockquote><blockquote type="cite">- SUnit *Max = 0;<br></blockquote><blockquote type="cite">- for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {<br></blockquote><blockquote type="cite">- SUnit *SU = &SUnits[i];<br></blockquote><blockquote type="cite">- if (!Max || SU->getDepth() + SU->Latency > Max->getDepth() + Max->Latency)<br></blockquote><blockquote type="cite">- Max = SU;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">-#ifndef NDEBUG<br></blockquote><blockquote type="cite">- {<br></blockquote><blockquote type="cite">- DEBUG(errs() << "Critical path has total latency "<br></blockquote><blockquote type="cite">- << (Max->getDepth() + Max->Latency) << "\n");<br></blockquote><blockquote type="cite">- DEBUG(errs() << "Available regs:");<br></blockquote><blockquote type="cite">- for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) {<br></blockquote><blockquote type="cite">- if (KillIndices[Reg] == ~0u)<br></blockquote><blockquote type="cite">- DEBUG(errs() << " " << TRI->getName(Reg));<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- DEBUG(errs() << '\n');<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-#endif<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Track progress along the critical path through the SUnit graph as we walk<br></blockquote><blockquote type="cite">- // the instructions.<br></blockquote><blockquote type="cite">- SUnit *CriticalPathSU = Max;<br></blockquote><blockquote type="cite">- MachineInstr *CriticalPathMI = CriticalPathSU->getInstr();<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Consider this pattern:<br></blockquote><blockquote type="cite">- // A = ...<br></blockquote><blockquote type="cite">- // ... = A<br></blockquote><blockquote type="cite">- // A = ...<br></blockquote><blockquote type="cite">- // ... = A<br></blockquote><blockquote type="cite">- // A = ...<br></blockquote><blockquote type="cite">- // ... = A<br></blockquote><blockquote type="cite">- // A = ...<br></blockquote><blockquote type="cite">- // ... = A<br></blockquote><blockquote type="cite">- // There are three anti-dependencies here, and without special care,<br></blockquote><blockquote type="cite">- // we'd break all of them using the same register:<br></blockquote><blockquote type="cite">- // A = ...<br></blockquote><blockquote type="cite">- // ... = A<br></blockquote><blockquote type="cite">- // B = ...<br></blockquote><blockquote type="cite">- // ... = B<br></blockquote><blockquote type="cite">- // B = ...<br></blockquote><blockquote type="cite">- // ... = B<br></blockquote><blockquote type="cite">- // B = ...<br></blockquote><blockquote type="cite">- // ... = B<br></blockquote><blockquote type="cite">- // because at each anti-dependence, B is the first register that<br></blockquote><blockquote type="cite">- // isn't A which is free. This re-introduces anti-dependencies<br></blockquote><blockquote type="cite">- // at all but one of the original anti-dependencies that we were<br></blockquote><blockquote type="cite">- // trying to break. To avoid this, keep track of the most recent<br></blockquote><blockquote type="cite">- // register that each register was replaced with, avoid<br></blockquote><blockquote type="cite">- // using it to repair an anti-dependence on the same register.<br></blockquote><blockquote type="cite">- // This lets us produce this:<br></blockquote><blockquote type="cite">- // A = ...<br></blockquote><blockquote type="cite">- // ... = A<br></blockquote><blockquote type="cite">- // B = ...<br></blockquote><blockquote type="cite">- // ... = B<br></blockquote><blockquote type="cite">- // C = ...<br></blockquote><blockquote type="cite">- // ... = C<br></blockquote><blockquote type="cite">- // B = ...<br></blockquote><blockquote type="cite">- // ... = B<br></blockquote><blockquote type="cite">- // This still has an anti-dependence on B, but at least it isn't on the<br></blockquote><blockquote type="cite">- // original critical path.<br></blockquote><blockquote type="cite">- //<br></blockquote><blockquote type="cite">- // TODO: If we tracked more than one register here, we could potentially<br></blockquote><blockquote type="cite">- // fix that remaining critical edge too. This is a little more involved,<br></blockquote><blockquote type="cite">- // because unlike the most recent register, less recent registers should<br></blockquote><blockquote type="cite">- // still be considered, though only if no other registers are available.<br></blockquote><blockquote type="cite">- unsigned LastNewReg[TargetRegisterInfo::FirstVirtualRegister] = {};<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Attempt to break anti-dependence edges on the critical path. Walk the<br></blockquote><blockquote type="cite">- // instructions from the bottom up, tracking information about liveness<br></blockquote><blockquote type="cite">- // as we go to help determine which registers are available.<br></blockquote><blockquote type="cite">- bool Changed = false;<br></blockquote><blockquote type="cite">- unsigned Count = InsertPosIndex - 1;<br></blockquote><blockquote type="cite">- for (MachineBasicBlock::iterator I = InsertPos, E = Begin;<br></blockquote><blockquote type="cite">- I != E; --Count) {<br></blockquote><blockquote type="cite">- MachineInstr *MI = --I;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Check if this instruction has a dependence on the critical path that<br></blockquote><blockquote type="cite">- // is an anti-dependence that we may be able to break. If it is, set<br></blockquote><blockquote type="cite">- // AntiDepReg to the non-zero register associated with the anti-dependence.<br></blockquote><blockquote type="cite">- //<br></blockquote><blockquote type="cite">- // We limit our attention to the critical path as a heuristic to avoid<br></blockquote><blockquote type="cite">- // breaking anti-dependence edges that aren't going to significantly<br></blockquote><blockquote type="cite">- // impact the overall schedule. There are a limited number of registers<br></blockquote><blockquote type="cite">- // and we want to save them for the important edges.<br></blockquote><blockquote type="cite">- //<br></blockquote><blockquote type="cite">- // TODO: Instructions with multiple defs could have multiple<br></blockquote><blockquote type="cite">- // anti-dependencies. The current code here only knows how to break one<br></blockquote><blockquote type="cite">- // edge per instruction. Note that we'd have to be able to break all of<br></blockquote><blockquote type="cite">- // the anti-dependencies in an instruction in order to be effective.<br></blockquote><blockquote type="cite">- unsigned AntiDepReg = 0;<br></blockquote><blockquote type="cite">- if (MI == CriticalPathMI) {<br></blockquote><blockquote type="cite">- if (SDep *Edge = CriticalPathStep(CriticalPathSU)) {<br></blockquote><blockquote type="cite">- SUnit *NextSU = Edge->getSUnit();<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Only consider anti-dependence edges.<br></blockquote><blockquote type="cite">- if (Edge->getKind() == SDep::Anti) {<br></blockquote><blockquote type="cite">- AntiDepReg = Edge->getReg();<br></blockquote><blockquote type="cite">- assert(AntiDepReg != 0 && "Anti-dependence on reg0?");<br></blockquote><blockquote type="cite">- if (!AllocatableSet.test(AntiDepReg))<br></blockquote><blockquote type="cite">- // Don't break anti-dependencies on non-allocatable registers.<br></blockquote><blockquote type="cite">- AntiDepReg = 0;<br></blockquote><blockquote type="cite">- else if (KeepRegs.count(AntiDepReg))<br></blockquote><blockquote type="cite">- // Don't break anti-dependencies if an use down below requires<br></blockquote><blockquote type="cite">- // this exact register.<br></blockquote><blockquote type="cite">- AntiDepReg = 0;<br></blockquote><blockquote type="cite">- else {<br></blockquote><blockquote type="cite">- // If the SUnit has other dependencies on the SUnit that it<br></blockquote><blockquote type="cite">- // anti-depends on, don't bother breaking the anti-dependency<br></blockquote><blockquote type="cite">- // since those edges would prevent such units from being<br></blockquote><blockquote type="cite">- // scheduled past each other regardless.<br></blockquote><blockquote type="cite">- //<br></blockquote><blockquote type="cite">- // Also, if there are dependencies on other SUnits with the<br></blockquote><blockquote type="cite">- // same register as the anti-dependency, don't attempt to<br></blockquote><blockquote type="cite">- // break it.<br></blockquote><blockquote type="cite">- for (SUnit::pred_iterator P = CriticalPathSU->Preds.begin(),<br></blockquote><blockquote type="cite">- PE = CriticalPathSU->Preds.end(); P != PE; ++P)<br></blockquote><blockquote type="cite">- if (P->getSUnit() == NextSU ?<br></blockquote><blockquote type="cite">- (P->getKind() != SDep::Anti || P->getReg() != AntiDepReg) :<br></blockquote><blockquote type="cite">- (P->getKind() == SDep::Data && P->getReg() == AntiDepReg)) {<br></blockquote><blockquote type="cite">- AntiDepReg = 0;<br></blockquote><blockquote type="cite">- break;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- CriticalPathSU = NextSU;<br></blockquote><blockquote type="cite">- CriticalPathMI = CriticalPathSU->getInstr();<br></blockquote><blockquote type="cite">- } else {<br></blockquote><blockquote type="cite">- // We've reached the end of the critical path.<br></blockquote><blockquote type="cite">- CriticalPathSU = 0;<br></blockquote><blockquote type="cite">- CriticalPathMI = 0;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- PrescanInstruction(MI);<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- if (MI->getDesc().hasExtraDefRegAllocReq())<br></blockquote><blockquote type="cite">- // If this instruction's defs have special allocation requirement, don't<br></blockquote><blockquote type="cite">- // break this anti-dependency.<br></blockquote><blockquote type="cite">- AntiDepReg = 0;<br></blockquote><blockquote type="cite">- else if (AntiDepReg) {<br></blockquote><blockquote type="cite">- // If this instruction has a use of AntiDepReg, breaking it<br></blockquote><blockquote type="cite">- // is invalid.<br></blockquote><blockquote type="cite">- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {<br></blockquote><blockquote type="cite">- MachineOperand &MO = MI->getOperand(i);<br></blockquote><blockquote type="cite">- if (!MO.isReg()) continue;<br></blockquote><blockquote type="cite">- unsigned Reg = MO.getReg();<br></blockquote><blockquote type="cite">- if (Reg == 0) continue;<br></blockquote><blockquote type="cite">- if (MO.isUse() && AntiDepReg == Reg) {<br></blockquote><blockquote type="cite">- AntiDepReg = 0;<br></blockquote><blockquote type="cite">- break;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Determine AntiDepReg's register class, if it is live and is<br></blockquote><blockquote type="cite">- // consistently used within a single class.<br></blockquote><blockquote type="cite">- const TargetRegisterClass *RC = AntiDepReg != 0 ? Classes[AntiDepReg] : 0;<br></blockquote><blockquote type="cite">- assert((AntiDepReg == 0 || RC != NULL) &&<br></blockquote><blockquote type="cite">- "Register should be live if it's causing an anti-dependence!");<br></blockquote><blockquote type="cite">- if (RC == reinterpret_cast<TargetRegisterClass *>(-1))<br></blockquote><blockquote type="cite">- AntiDepReg = 0;<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Look for a suitable register to use to break the anti-depenence.<br></blockquote><blockquote type="cite">- //<br></blockquote><blockquote type="cite">- // TODO: Instead of picking the first free register, consider which might<br></blockquote><blockquote type="cite">- // be the best.<br></blockquote><blockquote type="cite">- if (AntiDepReg != 0) {<br></blockquote><blockquote type="cite">- if (unsigned NewReg = findSuitableFreeRegister(AntiDepReg,<br></blockquote><blockquote type="cite">- LastNewReg[AntiDepReg],<br></blockquote><blockquote type="cite">- RC)) {<br></blockquote><blockquote type="cite">- DEBUG(errs() << "Breaking anti-dependence edge on "<br></blockquote><blockquote type="cite">- << TRI->getName(AntiDepReg)<br></blockquote><blockquote type="cite">- << " with " << RegRefs.count(AntiDepReg) << " references"<br></blockquote><blockquote type="cite">- << " using " << TRI->getName(NewReg) << "!\n");<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // Update the references to the old register to refer to the new<br></blockquote><blockquote type="cite">- // register.<br></blockquote><blockquote type="cite">- std::pair<std::multimap<unsigned, MachineOperand *>::iterator,<br></blockquote><blockquote type="cite">- std::multimap<unsigned, MachineOperand *>::iterator><br></blockquote><blockquote type="cite">- Range = RegRefs.equal_range(AntiDepReg);<br></blockquote><blockquote type="cite">- for (std::multimap<unsigned, MachineOperand *>::iterator<br></blockquote><blockquote type="cite">- Q = Range.first, QE = Range.second; Q != QE; ++Q)<br></blockquote><blockquote type="cite">- Q->second->setReg(NewReg);<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- // We just went back in time and modified history; the<br></blockquote><blockquote type="cite">- // liveness information for the anti-depenence reg is now<br></blockquote><blockquote type="cite">- // inconsistent. Set the state as if it were dead.<br></blockquote><blockquote type="cite">- Classes[NewReg] = Classes[AntiDepReg];<br></blockquote><blockquote type="cite">- DefIndices[NewReg] = DefIndices[AntiDepReg];<br></blockquote><blockquote type="cite">- KillIndices[NewReg] = KillIndices[AntiDepReg];<br></blockquote><blockquote type="cite">- assert(((KillIndices[NewReg] == ~0u) !=<br></blockquote><blockquote type="cite">- (DefIndices[NewReg] == ~0u)) &&<br></blockquote><blockquote type="cite">- "Kill and Def maps aren't consistent for NewReg!");<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- Classes[AntiDepReg] = 0;<br></blockquote><blockquote type="cite">- DefIndices[AntiDepReg] = KillIndices[AntiDepReg];<br></blockquote><blockquote type="cite">- KillIndices[AntiDepReg] = ~0u;<br></blockquote><blockquote type="cite">- assert(((KillIndices[AntiDepReg] == ~0u) !=<br></blockquote><blockquote type="cite">- (DefIndices[AntiDepReg] == ~0u)) &&<br></blockquote><blockquote type="cite">- "Kill and Def maps aren't consistent for AntiDepReg!");<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- RegRefs.erase(AntiDepReg);<br></blockquote><blockquote type="cite">- Changed = true;<br></blockquote><blockquote type="cite">- LastNewReg[AntiDepReg] = NewReg;<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- ScanInstruction(MI, Count);<br></blockquote><blockquote type="cite">- }<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite">- return Changed;<br></blockquote><blockquote type="cite">-}<br></blockquote><blockquote type="cite">-<br></blockquote><blockquote type="cite"> /// StartBlockForKills - Initialize register live-range state for updating kills<br></blockquote><blockquote type="cite"> ///<br></blockquote><blockquote type="cite"> void SchedulePostRATDList::StartBlockForKills(MachineBasicBlock *BB) {<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Modified: llvm/trunk/lib/Target/ARM/ARMSubtarget.h<br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.h?rev=85127&r1=85126&r2=85127&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.h?rev=85127&r1=85126&r2=85127&view=diff</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">==============================================================================<br></blockquote><blockquote type="cite">--- llvm/trunk/lib/Target/ARM/ARMSubtarget.h (original)<br></blockquote><blockquote type="cite">+++ llvm/trunk/lib/Target/ARM/ARMSubtarget.h Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">@@ -130,7 +130,7 @@<br></blockquote><blockquote type="cite"> /// for Thumb1.<br></blockquote><blockquote type="cite"> bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,<br></blockquote><blockquote type="cite"> TargetSubtarget::AntiDepBreakMode& mode) const {<br></blockquote><blockquote type="cite">- mode = TargetSubtarget::ANTIDEP_NONE;<br></blockquote><blockquote type="cite">+ mode = TargetSubtarget::ANTIDEP_CRITICAL;<br></blockquote><blockquote type="cite"> return PostRAScheduler && OptLevel >= CodeGenOpt::Default;<br></blockquote><blockquote type="cite"> }<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Modified: llvm/trunk/test/CodeGen/X86/break-anti-dependencies.ll<br></blockquote><blockquote type="cite">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/break-anti-dependencies.ll?rev=85127&r1=85126&r2=85127&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/break-anti-dependencies.ll?rev=85127&r1=85126&r2=85127&view=diff</a><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">==============================================================================<br></blockquote><blockquote type="cite">--- llvm/trunk/test/CodeGen/X86/break-anti-dependencies.ll (original)<br></blockquote><blockquote type="cite">+++ llvm/trunk/test/CodeGen/X86/break-anti-dependencies.ll Mon Oct 26 11:59:04 2009<br></blockquote><blockquote type="cite">@@ -1,7 +1,7 @@<br></blockquote><blockquote type="cite">-; RUN: llc < %s -march=x86-64 -post-RA-scheduler -break-anti-dependencies=false > %t<br></blockquote><blockquote type="cite">+; RUN: llc < %s -march=x86-64 -post-RA-scheduler -break-anti-dependencies=none > %t<br></blockquote><blockquote type="cite"> ; RUN: grep {%xmm0} %t | count 14<br></blockquote><blockquote type="cite"> ; RUN: not grep {%xmm1} %t<br></blockquote><blockquote type="cite">-; RUN: llc < %s -march=x86-64 -post-RA-scheduler -break-anti-dependencies > %t<br></blockquote><blockquote type="cite">+; RUN: llc < %s -march=x86-64 -post-RA-scheduler -break-anti-dependencies=critical > %t<br></blockquote><blockquote type="cite"> ; RUN: grep {%xmm0} %t | count 7<br></blockquote><blockquote type="cite"> ; RUN: grep {%xmm1} %t | count 7<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">_______________________________________________<br></blockquote><blockquote type="cite">llvm-commits mailing list<br></blockquote><blockquote type="cite"><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br></blockquote><blockquote type="cite"><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br></blockquote><blockquote type="cite"><br></blockquote></div></blockquote></div><br></body></html>