diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-01-05 04:38:12 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-01-05 04:38:12 +0000 |
commit | fe445cd6468822b84e322f7cf4839b4c7ee832d5 (patch) | |
tree | f4c8c8551454367d442394f2ec2190329975f008 /llvm/lib/CodeGen/MachineRegisterInfo.cpp | |
parent | c4048062e5ddfae5bbc1b1146da5a7469709450a (diff) | |
download | bcm5719-llvm-fe445cd6468822b84e322f7cf4839b4c7ee832d5.tar.gz bcm5719-llvm-fe445cd6468822b84e322f7cf4839b4c7ee832d5.zip |
Add MachineRegisterInfo::moveOperands().
This function works like memmove() for MachineOperands, except it also
updates any use-def chains containing the moved operands.
The use-def chains are updated without affecting the order of operands
in the list. That isn't possible when using the
removeRegOperandFromUseList() and addRegOperandToUseList() functions.
Callers to follow soon.
llvm-svn: 171597
Diffstat (limited to 'llvm/lib/CodeGen/MachineRegisterInfo.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineRegisterInfo.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp index 95d7a7dd689..9858b4999e0 100644 --- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -180,6 +180,55 @@ void MachineRegisterInfo::removeRegOperandFromUseList(MachineOperand *MO) { MO->Contents.Reg.Next = 0; } +/// Move NumOps operands from Src to Dst, updating use-def lists as needed. +/// +/// The Dst range is assumed to be uninitialized memory. (Or it may contain +/// operands that won't be destroyed, which is OK because the MO destructor is +/// trivial anyway). +/// +/// The Src and Dst ranges may overlap. +void MachineRegisterInfo::moveOperands(MachineOperand *Dst, + MachineOperand *Src, + unsigned NumOps) { + assert(Src != Dst && NumOps && "Noop moveOperands"); + + // Copy backwards if Dst is within the Src range. + int Stride = 1; + if (Dst >= Src && Dst < Src + NumOps) { + Stride = -1; + Dst += NumOps - 1; + Src += NumOps - 1; + } + + // Copy one operand at a time. + do { + new (Dst) MachineOperand(*Src); + + // Dst takes Src's place in the use-def chain. + if (Src->isReg()) { + MachineOperand *&Head = getRegUseDefListHead(Src->getReg()); + MachineOperand *Prev = Src->Contents.Reg.Prev; + MachineOperand *Next = Src->Contents.Reg.Next; + assert(Head && "List empty, but operand is chained"); + assert(Prev && "Operand was not on use-def list"); + + // Prev links are circular, next link is NULL instead of looping back to + // Head. + if (Src == Head) + Head = Dst; + else + Prev->Contents.Reg.Next = Dst; + + // Update Prev pointer. This also works when Src was pointing to itself + // in a 1-element list. In that case Head == Dst. + (Next ? Next : Head)->Contents.Reg.Prev = Dst; + } + + Dst += Stride; + Src += Stride; + } while (--NumOps); +} + /// 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. |