1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

Simplify REG_SEQUENCE lowering.

The TwoAddressInstructionPass takes the machine code out of SSA form by
expanding REG_SEQUENCE instructions into copies. It is no longer
necessary to rewrite the registers used by a REG_SEQUENCE instruction
because the new coalescer algorithm can do it now.

REG_SEQUENCE is just converted to a sequence of sub-register copies now.

llvm-svn: 169067
This commit is contained in:
Jakob Stoklund Olesen 2012-12-01 01:06:44 +00:00
parent 5f2988f933
commit 4aa22e2c8d
2 changed files with 78 additions and 196 deletions

View File

@ -92,10 +92,6 @@ class TwoAddressInstructionPass : public MachineFunctionPass {
// virtual registers. e.g. r1 = move v1024. // virtual registers. e.g. r1 = move v1024.
DenseMap<unsigned, unsigned> DstRegMap; DenseMap<unsigned, unsigned> DstRegMap;
/// RegSequences - Keep track the list of REG_SEQUENCE instructions seen
/// during the initial walk of the machine function.
SmallVector<MachineInstr*, 16> RegSequences;
bool sink3AddrInstruction(MachineInstr *MI, unsigned Reg, bool sink3AddrInstruction(MachineInstr *MI, unsigned Reg,
MachineBasicBlock::iterator OldPos); MachineBasicBlock::iterator OldPos);
@ -135,11 +131,7 @@ class TwoAddressInstructionPass : public MachineFunctionPass {
typedef SmallDenseMap<unsigned, TiedPairList> TiedOperandMap; typedef SmallDenseMap<unsigned, TiedPairList> TiedOperandMap;
bool collectTiedOperands(MachineInstr *MI, TiedOperandMap&); bool collectTiedOperands(MachineInstr *MI, TiedOperandMap&);
void processTiedPairs(MachineInstr *MI, TiedPairList&, unsigned &Dist); void processTiedPairs(MachineInstr *MI, TiedPairList&, unsigned &Dist);
void eliminateRegSequence(MachineBasicBlock::iterator&);
/// eliminateRegSequences - Eliminate REG_SEQUENCE instructions as part of
/// the de-ssa process. This replaces sources of REG_SEQUENCE as sub-register
/// references of the register defined by REG_SEQUENCE.
bool eliminateRegSequences();
public: public:
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
@ -1375,9 +1367,10 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) {
continue; continue;
} }
// Remember REG_SEQUENCE instructions, we'll deal with them later. // Expand REG_SEQUENCE instructions. This will position mi at the first
// expanded instruction.
if (mi->isRegSequence()) if (mi->isRegSequence())
RegSequences.push_back(&*mi); eliminateRegSequence(mi);
DistanceMap.insert(std::make_pair(mi, ++Dist)); DistanceMap.insert(std::make_pair(mi, ++Dist));
@ -1444,192 +1437,81 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) {
} }
} }
// Eliminate REG_SEQUENCE instructions. Their whole purpose was to preseve
// SSA form. It's now safe to de-SSA.
MadeChange |= eliminateRegSequences();
return MadeChange; return MadeChange;
} }
static void UpdateRegSequenceSrcs(unsigned SrcReg, /// Eliminate a REG_SEQUENCE instruction as part of the de-ssa process.
unsigned DstReg, unsigned SubIdx,
MachineRegisterInfo *MRI,
const TargetRegisterInfo &TRI) {
for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg),
RE = MRI->reg_end(); RI != RE; ) {
MachineOperand &MO = RI.getOperand();
++RI;
MO.substVirtReg(DstReg, SubIdx, TRI);
}
}
// Find the first def of Reg, assuming they are all in the same basic block.
static MachineInstr *findFirstDef(unsigned Reg, MachineRegisterInfo *MRI) {
SmallPtrSet<MachineInstr*, 8> Defs;
MachineInstr *First = 0;
for (MachineRegisterInfo::def_iterator RI = MRI->def_begin(Reg);
MachineInstr *MI = RI.skipInstruction(); Defs.insert(MI))
First = MI;
if (!First)
return 0;
MachineBasicBlock *MBB = First->getParent();
MachineBasicBlock::iterator A = First, B = First;
bool Moving;
do {
Moving = false;
if (A != MBB->begin()) {
Moving = true;
--A;
if (Defs.erase(A)) First = A;
}
if (B != MBB->end()) {
Defs.erase(B);
++B;
Moving = true;
}
} while (Moving && !Defs.empty());
assert(Defs.empty() && "Instructions outside basic block!");
return First;
}
static bool HasOtherRegSequenceUses(unsigned Reg, MachineInstr *RegSeq,
MachineRegisterInfo *MRI) {
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg),
UE = MRI->use_end(); UI != UE; ++UI) {
MachineInstr *UseMI = &*UI;
if (UseMI != RegSeq && UseMI->isRegSequence())
return true;
}
return false;
}
/// eliminateRegSequences - Eliminate REG_SEQUENCE instructions as part
/// of the de-ssa process. This replaces sources of REG_SEQUENCE as
/// sub-register references of the register defined by REG_SEQUENCE. e.g.
/// ///
/// %reg1029<def>, %reg1030<def> = VLD1q16 %reg1024<kill>, ... /// The instruction is turned into a sequence of sub-register copies:
/// %reg1031<def> = REG_SEQUENCE %reg1029<kill>, 5, %reg1030<kill>, 6 ///
/// => /// %dst = REG_SEQUENCE %v1, ssub0, %v2, ssub1
/// %reg1031:5<def>, %reg1031:6<def> = VLD1q16 %reg1024<kill>, ... ///
bool TwoAddressInstructionPass::eliminateRegSequences() { /// Becomes:
if (RegSequences.empty()) ///
return false; /// %dst:ssub0<def,undef> = COPY %v1
/// %dst:ssub1<def> = COPY %v2
for (unsigned i = 0, e = RegSequences.size(); i != e; ++i) { ///
MachineInstr *MI = RegSequences[i]; void TwoAddressInstructionPass::
unsigned DstReg = MI->getOperand(0).getReg(); eliminateRegSequence(MachineBasicBlock::iterator &MBBI) {
if (MI->getOperand(0).getSubReg() || MachineInstr *MI = MBBI;
TargetRegisterInfo::isPhysicalRegister(DstReg) || unsigned DstReg = MI->getOperand(0).getReg();
!(MI->getNumOperands() & 1)) { if (MI->getOperand(0).getSubReg() ||
DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << *MI); TargetRegisterInfo::isPhysicalRegister(DstReg) ||
llvm_unreachable(0); !(MI->getNumOperands() & 1)) {
} DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << *MI);
llvm_unreachable(0);
bool IsImpDef = true;
SmallVector<unsigned, 4> RealSrcs;
SmallSet<unsigned, 4> Seen;
for (unsigned i = 1, e = MI->getNumOperands(); i < e; i += 2) {
// Nothing needs to be inserted for <undef> operands.
if (MI->getOperand(i).isUndef()) {
MI->getOperand(i).setReg(0);
continue;
}
unsigned SrcReg = MI->getOperand(i).getReg();
unsigned SrcSubIdx = MI->getOperand(i).getSubReg();
unsigned SubIdx = MI->getOperand(i+1).getImm();
// DefMI of NULL means the value does not have a vreg in this block
// i.e., its a physical register or a subreg.
// In either case we force a copy to be generated.
MachineInstr *DefMI = NULL;
if (!MI->getOperand(i).getSubReg() &&
!TargetRegisterInfo::isPhysicalRegister(SrcReg)) {
DefMI = MRI->getUniqueVRegDef(SrcReg);
}
if (DefMI && DefMI->isImplicitDef()) {
DefMI->eraseFromParent();
continue;
}
IsImpDef = false;
// Remember COPY sources. These might be candidate for coalescing.
if (DefMI && DefMI->isCopy() && DefMI->getOperand(1).getSubReg())
RealSrcs.push_back(DefMI->getOperand(1).getReg());
bool isKill = MI->getOperand(i).isKill();
if (!DefMI || !Seen.insert(SrcReg) ||
MI->getParent() != DefMI->getParent() ||
!isKill || HasOtherRegSequenceUses(SrcReg, MI, MRI) ||
!TRI->getMatchingSuperRegClass(MRI->getRegClass(DstReg),
MRI->getRegClass(SrcReg), SubIdx)) {
// REG_SEQUENCE cannot have duplicated operands, add a copy.
// Also add an copy if the source is live-in the block. We don't want
// to end up with a partial-redef of a livein, e.g.
// BB0:
// reg1051:10<def> =
// ...
// BB1:
// ... = reg1051:10
// BB2:
// reg1051:9<def> =
// LiveIntervalAnalysis won't like it.
//
// If the REG_SEQUENCE doesn't kill its source, keeping live variables
// correctly up to date becomes very difficult. Insert a copy.
// Defer any kill flag to the last operand using SrcReg. Otherwise, we
// might insert a COPY that uses SrcReg after is was killed.
if (isKill)
for (unsigned j = i + 2; j < e; j += 2)
if (MI->getOperand(j).getReg() == SrcReg) {
MI->getOperand(j).setIsKill();
isKill = false;
break;
}
MachineBasicBlock::iterator InsertLoc = MI;
MachineInstr *CopyMI = BuildMI(*MI->getParent(), InsertLoc,
MI->getDebugLoc(), TII->get(TargetOpcode::COPY))
.addReg(DstReg, RegState::Define, SubIdx)
.addReg(SrcReg, getKillRegState(isKill), SrcSubIdx);
MI->getOperand(i).setReg(0);
if (LV && isKill && !TargetRegisterInfo::isPhysicalRegister(SrcReg))
LV->replaceKillInstruction(SrcReg, MI, CopyMI);
DEBUG(dbgs() << "Inserted: " << *CopyMI);
}
}
for (unsigned i = 1, e = MI->getNumOperands(); i < e; i += 2) {
unsigned SrcReg = MI->getOperand(i).getReg();
if (!SrcReg) continue;
unsigned SubIdx = MI->getOperand(i+1).getImm();
UpdateRegSequenceSrcs(SrcReg, DstReg, SubIdx, MRI, *TRI);
}
// Set <def,undef> flags on the first DstReg def in the basic block.
// It marks the beginning of the live range. All the other defs are
// read-modify-write.
if (MachineInstr *Def = findFirstDef(DstReg, MRI)) {
for (unsigned i = 0, e = Def->getNumOperands(); i != e; ++i) {
MachineOperand &MO = Def->getOperand(i);
if (MO.isReg() && MO.isDef() && MO.getReg() == DstReg)
MO.setIsUndef();
}
DEBUG(dbgs() << "First def: " << *Def);
}
if (IsImpDef) {
DEBUG(dbgs() << "Turned: " << *MI << " into an IMPLICIT_DEF");
MI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF));
for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j)
MI->RemoveOperand(j);
} else {
DEBUG(dbgs() << "Eliminated: " << *MI);
MI->eraseFromParent();
}
} }
RegSequences.clear(); bool DefEmitted = false;
return true; for (unsigned i = 1, e = MI->getNumOperands(); i < e; i += 2) {
MachineOperand &UseMO = MI->getOperand(i);
unsigned SrcReg = UseMO.getReg();
unsigned SubIdx = MI->getOperand(i+1).getImm();
// Nothing needs to be inserted for <undef> operands.
if (UseMO.isUndef())
continue;
// Defer any kill flag to the last operand using SrcReg. Otherwise, we
// might insert a COPY that uses SrcReg after is was killed.
bool isKill = UseMO.isKill();
if (isKill)
for (unsigned j = i + 2; j < e; j += 2)
if (MI->getOperand(j).getReg() == SrcReg) {
MI->getOperand(j).setIsKill();
UseMO.setIsKill(false);
isKill = false;
break;
}
// Insert the sub-register copy.
MachineInstr *CopyMI = BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
TII->get(TargetOpcode::COPY))
.addReg(DstReg, RegState::Define, SubIdx)
.addOperand(UseMO);
// The first def needs an <undef> flag because there is no live register
// before it.
if (!DefEmitted) {
CopyMI->getOperand(0).setIsUndef(true);
// Return an iterator pointing to the first inserted instr.
MBBI = CopyMI;
}
DefEmitted = true;
// Update LiveVariables' kill info.
if (LV && isKill && !TargetRegisterInfo::isPhysicalRegister(SrcReg))
LV->replaceKillInstruction(SrcReg, MI, CopyMI);
DEBUG(dbgs() << "Inserted: " << *CopyMI);
}
if (!DefEmitted) {
DEBUG(dbgs() << "Turned: " << *MI << " into an IMPLICIT_DEF");
MI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF));
for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j)
MI->RemoveOperand(j);
} else {
DEBUG(dbgs() << "Eliminated: " << *MI);
MI->eraseFromParent();
}
} }

View File

@ -12,7 +12,7 @@ target triple = "thumbv7-apple-ios"
; ;
; CHECK: f1 ; CHECK: f1
; CHECK: vmov d0, r0, r0 ; CHECK: vmov d0, r0, r0
; CHECK: vldr s0, LCPI ; CHECK: vldr s1, LCPI
; The vector must be spilled: ; The vector must be spilled:
; CHECK: vstr d0, ; CHECK: vstr d0,
; CHECK: asm clobber d0 ; CHECK: asm clobber d0
@ -20,8 +20,8 @@ target triple = "thumbv7-apple-ios"
; CHECK: vldr [[D16:d[0-9]+]], ; CHECK: vldr [[D16:d[0-9]+]],
; CHECK: vstr [[D16]], [r1] ; CHECK: vstr [[D16]], [r1]
define void @f1(float %x, <2 x float>* %p) { define void @f1(float %x, <2 x float>* %p) {
%v1 = insertelement <2 x float> undef, float %x, i32 1 %v1 = insertelement <2 x float> undef, float %x, i32 0
%v2 = insertelement <2 x float> %v1, float 0x400921FB60000000, i32 0 %v2 = insertelement <2 x float> %v1, float 0x400921FB60000000, i32 1
%y = call double asm sideeffect "asm clobber $0", "=w,0,~{d1},~{d2},~{d3},~{d4},~{d5},~{d6},~{d7},~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15},~{d16},~{d17},~{d18},~{d19},~{d20},~{d21},~{d22},~{d23},~{d24},~{d25},~{d26},~{d27},~{d28},~{d29},~{d30},~{d31}"(<2 x float> %v2) nounwind %y = call double asm sideeffect "asm clobber $0", "=w,0,~{d1},~{d2},~{d3},~{d4},~{d5},~{d6},~{d7},~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15},~{d16},~{d17},~{d18},~{d19},~{d20},~{d21},~{d22},~{d23},~{d24},~{d25},~{d26},~{d27},~{d28},~{d29},~{d30},~{d31}"(<2 x float> %v2) nounwind
store <2 x float> %v2, <2 x float>* %p, align 8 store <2 x float> %v2, <2 x float>* %p, align 8
ret void ret void