diff options
-rw-r--r-- | include/llvm/CodeGen/MachineOperand.h | 2 | ||||
-rw-r--r-- | include/llvm/CodeGen/MachineRegisterInfo.h | 23 | ||||
-rw-r--r-- | lib/CodeGen/MachineRegisterInfo.cpp | 92 | ||||
-rw-r--r-- | test/CodeGen/MSP430/Inst8rr.ll | 2 | ||||
-rw-r--r-- | test/CodeGen/X86/xor.ll | 2 |
5 files changed, 57 insertions, 64 deletions
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index adf2095..0cde75d 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -150,7 +150,7 @@ private: struct { // For MO_Register. // Register number is in SmallContents.RegNo. - MachineOperand *Prev; // Access list for register. See MRI. + MachineOperand **Prev; // Access list for register. MachineOperand *Next; } Reg; diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 42a8aa4..0fac1a8 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -468,6 +468,10 @@ public: const TargetRegisterInfo &TRI, const TargetInstrInfo &TII); +private: + void HandleVRegListReallocation(); + +public: /// defusechain_iterator - This class provides iterator support for machine /// operands in the function that use or define a specific register. If /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it @@ -513,20 +517,11 @@ public: assert(Op && "Cannot increment end iterator!"); Op = getNextOperandForReg(Op); - // All defs come before the uses, so stop def_iterator early. - if (!ReturnUses) { - if (Op) { - if (Op->isUse()) - Op = 0; - else - assert(!Op->isDebug() && "Can't have debug defs"); - } - } else { - // If this is an operand we don't care about, skip it. - while (Op && ((!ReturnDefs && Op->isDef()) || - (SkipDebug && Op->isDebug()))) - Op = getNextOperandForReg(Op); - } + // If this is an operand we don't care about, skip it. + while (Op && ((!ReturnUses && Op->isUse()) || + (!ReturnDefs && Op->isDef()) || + (SkipDebug && Op->isDebug()))) + Op = getNextOperandForReg(Op); return *this; } diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp index 5fb938f..6d05d35 100644 --- a/lib/CodeGen/MachineRegisterInfo.cpp +++ b/lib/CodeGen/MachineRegisterInfo.cpp @@ -102,9 +102,17 @@ MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){ // New virtual register number. unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs()); + + // Add a reg, but keep track of whether the vector reallocated or not. + const unsigned FirstVirtReg = TargetRegisterInfo::index2VirtReg(0); + void *ArrayBase = getNumVirtRegs() == 0 ? 0 : &VRegInfo[FirstVirtReg]; VRegInfo.grow(Reg); VRegInfo[Reg].first = RegClass; RegAllocHints.grow(Reg); + + if (ArrayBase && &VRegInfo[FirstVirtReg] != ArrayBase) + // The vector reallocated, handle this now. + HandleVRegListReallocation(); return Reg; } @@ -121,65 +129,55 @@ void MachineRegisterInfo::clearVirtRegs() { /// Add MO to the linked list of operands for its register. void MachineRegisterInfo::addRegOperandToUseList(MachineOperand *MO) { assert(!MO->isOnRegUseList() && "Already on list"); - MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg()); - MachineOperand *const Head = HeadRef; - - // Head points to the first list element. - // Next is NULL on the last list element. - // Prev pointers are circular, so Head->Prev == Last. - - // Head is NULL for an empty list. - if (!Head) { - MO->Contents.Reg.Prev = MO; - MO->Contents.Reg.Next = 0; - HeadRef = MO; - return; - } - assert(MO->getReg() == Head->getReg() && "Different regs on the same list!"); - - // Insert MO between Last and Head in the circular Prev chain. - MachineOperand *Last = Head->Contents.Reg.Prev; - assert(Last && "Inconsistent use list"); - assert(MO->getReg() == Last->getReg() && "Different regs on the same list!"); - Head->Contents.Reg.Prev = MO; - MO->Contents.Reg.Prev = Last; - - // Def operands always precede uses. This allows def_iterator to stop early. - // Insert def operands at the front, and use operands at the back. - if (MO->isDef()) { - // Insert def at the front. - MO->Contents.Reg.Next = Head; - HeadRef = MO; - } else { - // Insert use at the end. - MO->Contents.Reg.Next = 0; - Last->Contents.Reg.Next = MO; + MachineOperand **Head = &getRegUseDefListHead(MO->getReg()); + + // For SSA values, we prefer to keep the definition at the start of the list. + // we do this by skipping over the definition if it is at the head of the + // list. + if (*Head && (*Head)->isDef()) + Head = &(*Head)->Contents.Reg.Next; + + MO->Contents.Reg.Next = *Head; + if (MO->Contents.Reg.Next) { + assert(MO->getReg() == MO->Contents.Reg.Next->getReg() && + "Different regs on the same list!"); + MO->Contents.Reg.Next->Contents.Reg.Prev = &MO->Contents.Reg.Next; } + + MO->Contents.Reg.Prev = Head; + *Head = MO; } /// Remove MO from its use-def list. void MachineRegisterInfo::removeRegOperandFromUseList(MachineOperand *MO) { assert(MO->isOnRegUseList() && "Operand not on use list"); - MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg()); - MachineOperand *const Head = HeadRef; - assert(Head && "List already empty"); // Unlink this from the doubly linked list of operands. - MachineOperand *Next = MO->Contents.Reg.Next; - MachineOperand *Prev = MO->Contents.Reg.Prev; - - // Prev links are circular, next link is NULL instead of looping back to Head. - if (MO == Head) - HeadRef = Next; - else - Prev->Contents.Reg.Next = Next; - - (Next ? Next : Head)->Contents.Reg.Prev = Prev; - + MachineOperand *NextOp = MO->Contents.Reg.Next; + *MO->Contents.Reg.Prev = NextOp; + if (NextOp) { + assert(NextOp->getReg() == MO->getReg() && "Corrupt reg use/def chain!"); + NextOp->Contents.Reg.Prev = MO->Contents.Reg.Prev; + } MO->Contents.Reg.Prev = 0; MO->Contents.Reg.Next = 0; } +/// HandleVRegListReallocation - We just added a virtual register to the +/// VRegInfo info list and it reallocated. Update the use/def lists info +/// pointers. +void MachineRegisterInfo::HandleVRegListReallocation() { + // The back pointers for the vreg lists point into the previous vector. + // Update them to point to their correct slots. + for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + MachineOperand *List = VRegInfo[Reg].second; + if (!List) continue; + // Update the back-pointer to be accurate once more. + List->Contents.Reg.Prev = &VRegInfo[Reg].second; + } +} + /// replaceRegWith - Replace all instances of FromReg with ToReg in the /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), /// except that it also changes any definitions of the register as well. diff --git a/test/CodeGen/MSP430/Inst8rr.ll b/test/CodeGen/MSP430/Inst8rr.ll index b9c17d9..45342e2 100644 --- a/test/CodeGen/MSP430/Inst8rr.ll +++ b/test/CodeGen/MSP430/Inst8rr.ll @@ -4,7 +4,7 @@ target triple = "msp430-generic-generic" define i8 @mov(i8 %a, i8 %b) nounwind { ; CHECK: mov: -; CHECK: mov.{{[bw]}} r14, r15 +; CHECK: mov.b r14, r15 ret i8 %b } diff --git a/test/CodeGen/X86/xor.ll b/test/CodeGen/X86/xor.ll index 996bfc4..73416ef 100644 --- a/test/CodeGen/X86/xor.ll +++ b/test/CodeGen/X86/xor.ll @@ -31,7 +31,7 @@ entry: ; X64: test3: ; X64: notl ; X64: andl -; X64: shrl +; X64: shrl %eax ; X64: ret ; X32: test3: |