llvm.org GIT mirror llvm / 46f4c35
Don't use pointer-pointers for the register use lists. Use a more conventional doubly linked list where the Prev pointers form a cycle. This means it is no longer necessary to adjust the Prev pointers when reallocating the VRegInfo array. The test changes are required because the register allocation hint is using the use-list order to break ties. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161633 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 7 years ago
5 changed file(s) with 43 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
149149
150150 struct { // For MO_Register.
151151 // Register number is in SmallContents.RegNo.
152 MachineOperand **Prev; // Access list for register.
152 MachineOperand *Prev; // Access list for register. See MRI.
153153 MachineOperand *Next;
154154 } Reg;
155155
467467 const TargetRegisterInfo &TRI,
468468 const TargetInstrInfo &TII);
469469
470 private:
471 void HandleVRegListReallocation();
472
473 public:
474470 /// defusechain_iterator - This class provides iterator support for machine
475471 /// operands in the function that use or define a specific register. If
476472 /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it
101101
102102 // New virtual register number.
103103 unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs());
104
105 // Add a reg, but keep track of whether the vector reallocated or not.
106 const unsigned FirstVirtReg = TargetRegisterInfo::index2VirtReg(0);
107 void *ArrayBase = getNumVirtRegs() == 0 ? 0 : &VRegInfo[FirstVirtReg];
108104 VRegInfo.grow(Reg);
109105 VRegInfo[Reg].first = RegClass;
110106 RegAllocHints.grow(Reg);
111
112 if (ArrayBase && &VRegInfo[FirstVirtReg] != ArrayBase)
113 // The vector reallocated, handle this now.
114 HandleVRegListReallocation();
115107 return Reg;
116108 }
117109
128120 /// Add MO to the linked list of operands for its register.
129121 void MachineRegisterInfo::addRegOperandToUseList(MachineOperand *MO) {
130122 assert(!MO->isOnRegUseList() && "Already on list");
131 MachineOperand **Head = &getRegUseDefListHead(MO->getReg());
132
133 // For SSA values, we prefer to keep the definition at the start of the list.
134 // we do this by skipping over the definition if it is at the head of the
135 // list.
136 if (*Head && (*Head)->isDef())
137 Head = &(*Head)->Contents.Reg.Next;
138
139 MO->Contents.Reg.Next = *Head;
140 if (MO->Contents.Reg.Next) {
141 assert(MO->getReg() == MO->Contents.Reg.Next->getReg() &&
142 "Different regs on the same list!");
143 MO->Contents.Reg.Next->Contents.Reg.Prev = &MO->Contents.Reg.Next;
123 MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
124 MachineOperand *const Head = HeadRef;
125
126 // Head points to the first list element.
127 // Next is NULL on the last list element.
128 // Prev pointers are circular, so Head->Prev == Last.
129
130 // Head is NULL for an empty list.
131 if (!Head) {
132 MO->Contents.Reg.Prev = MO;
133 MO->Contents.Reg.Next = 0;
134 HeadRef = MO;
135 return;
144136 }
145
146 MO->Contents.Reg.Prev = Head;
147 *Head = MO;
137 assert(MO->getReg() == Head->getReg() && "Different regs on the same list!");
138
139 // Insert MO between Last and Head in the circular Prev chain.
140 MachineOperand *Last = Head->Contents.Reg.Prev;
141 assert(Last && "Inconsistent use list");
142 assert(MO->getReg() == Last->getReg() && "Different regs on the same list!");
143 Head->Contents.Reg.Prev = MO;
144 MO->Contents.Reg.Prev = Last;
145
146 // Insert at the front.
147 MO->Contents.Reg.Next = Head;
148 HeadRef = MO;
148149 }
149150
150151 /// Remove MO from its use-def list.
151152 void MachineRegisterInfo::removeRegOperandFromUseList(MachineOperand *MO) {
152153 assert(MO->isOnRegUseList() && "Operand not on use list");
154 MachineOperand *&HeadRef = getRegUseDefListHead(MO->getReg());
155 MachineOperand *const Head = HeadRef;
156 assert(Head && "List already empty");
153157
154158 // Unlink this from the doubly linked list of operands.
155 MachineOperand *NextOp = MO->Contents.Reg.Next;
156 *MO->Contents.Reg.Prev = NextOp;
157 if (NextOp) {
158 assert(NextOp->getReg() == MO->getReg() && "Corrupt reg use/def chain!");
159 NextOp->Contents.Reg.Prev = MO->Contents.Reg.Prev;
160 }
159 MachineOperand *Next = MO->Contents.Reg.Next;
160 MachineOperand *Prev = MO->Contents.Reg.Prev;
161
162 // Prev links are circular, next link is NULL instead of looping back to Head.
163 if (MO == Head)
164 HeadRef = Next;
165 else
166 Prev->Contents.Reg.Next = Next;
167
168 (Next ? Next : Head)->Contents.Reg.Prev = Prev;
169
161170 MO->Contents.Reg.Prev = 0;
162171 MO->Contents.Reg.Next = 0;
163 }
164
165 /// HandleVRegListReallocation - We just added a virtual register to the
166 /// VRegInfo info list and it reallocated. Update the use/def lists info
167 /// pointers.
168 void MachineRegisterInfo::HandleVRegListReallocation() {
169 // The back pointers for the vreg lists point into the previous vector.
170 // Update them to point to their correct slots.
171 for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i) {
172 unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
173 MachineOperand *List = VRegInfo[Reg].second;
174 if (!List) continue;
175 // Update the back-pointer to be accurate once more.
176 List->Contents.Reg.Prev = &VRegInfo[Reg].second;
177 }
178172 }
179173
180174 /// replaceRegWith - Replace all instances of FromReg with ToReg in the
33
44 define i8 @mov(i8 %a, i8 %b) nounwind {
55 ; CHECK: mov:
6 ; CHECK: mov.b r14, r15
6 ; CHECK: mov.{{[bw]}} r14, r15
77 ret i8 %b
88 }
99
22 ; PR8573
33
44 ; CHECK: foo:
5 ; CHECK: leaq (%rdi), %rax
6 ; CHECK-NEXT: movl %esi, %ecx
5 ; CHECK: movl %esi, %ecx
6 ; CHECK-NEXT: leaq (%rdi), %rax
77 ; CHECK-NEXT: monitor
88 ; WIN64: foo:
99 ; WIN64: leaq (%rcx), %rax