"llvm/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "07bb9eea3369cf7616d2fed31c6a9b21e0efcc70"
Newer
Older
Christopher Lamb
committed
//===-- LowerSubregs.cpp - Subregister Lowering instruction pass ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
Christopher Lamb
committed
//
//===----------------------------------------------------------------------===//
//
// This file defines a MachineFunction pass which runs after register
// allocation that turns subreg insert/extract instructions into register
// copies, as needed. This ensures correct codegen even if the coalescer
// isn't able to remove all subreg instructions.
//
//===----------------------------------------------------------------------===//
Christopher Lamb
committed
#define DEBUG_TYPE "lowersubregs"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
Christopher Lamb
committed
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
Daniel Dunbar
committed
#include "llvm/Support/raw_ostream.h"
Christopher Lamb
committed
using namespace llvm;
namespace {
Nick Lewycky
committed
struct LowerSubregsInstructionPass : public MachineFunctionPass {
private:
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
public:
Christopher Lamb
committed
static char ID; // Pass identification, replacement for typeid
LowerSubregsInstructionPass() : MachineFunctionPass(&ID) {}
Christopher Lamb
committed
const char *getPassName() const {
return "Subregister lowering instruction pass";
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
Evan Cheng
committed
AU.addPreservedID(MachineLoopInfoID);
AU.addPreservedID(MachineDominatorsID);
MachineFunctionPass::getAnalysisUsage(AU);
}
Christopher Lamb
committed
/// runOnMachineFunction - pass entry point
bool runOnMachineFunction(MachineFunction&);
bool LowerExtract(MachineInstr *MI);
bool LowerInsert(MachineInstr *MI);
Christopher Lamb
committed
bool LowerSubregToReg(MachineInstr *MI);
bool LowerCopy(MachineInstr *MI);
void TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
void TransferKillFlag(MachineInstr *MI, unsigned SrcReg,
Evan Cheng
committed
bool AddIfNotFound = false);
void TransferImplicitDefs(MachineInstr *MI);
Christopher Lamb
committed
};
char LowerSubregsInstructionPass::ID = 0;
}
FunctionPass *llvm::createLowerSubregsPass() {
return new LowerSubregsInstructionPass();
}
/// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead,
/// and the lowered replacement instructions immediately precede it.
/// Mark the replacement instructions with the dead flag.
void
LowerSubregsInstructionPass::TransferDeadFlag(MachineInstr *MI,
unsigned DstReg,
for (MachineBasicBlock::iterator MII =
prior(MachineBasicBlock::iterator(MI)); ; --MII) {
break;
assert(MII != MI->getParent()->begin() &&
"copyPhysReg output doesn't reference destination register!");
}
}
/// TransferKillFlag - MI is a pseudo-instruction with SrcReg killed,
/// and the lowered replacement instructions immediately precede it.
/// Mark the replacement instructions with the kill flag.
void
LowerSubregsInstructionPass::TransferKillFlag(MachineInstr *MI,
unsigned SrcReg,
Evan Cheng
committed
bool AddIfNotFound) {
for (MachineBasicBlock::iterator MII =
prior(MachineBasicBlock::iterator(MI)); ; --MII) {
break;
assert(MII != MI->getParent()->begin() &&
"copyPhysReg output doesn't reference source register!");
}
}
/// TransferImplicitDefs - MI is a pseudo-instruction, and the lowered
/// replacement instructions immediately precede it. Copy any implicit-def
/// operands from MI to the replacement instruction.
void
LowerSubregsInstructionPass::TransferImplicitDefs(MachineInstr *MI) {
MachineBasicBlock::iterator CopyMI = MI;
--CopyMI;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg() || !MO.isImplicit() || MO.isUse())
continue;
CopyMI->addOperand(MachineOperand::CreateReg(MO.getReg(), true, true));
}
}
bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) {
Jakob Stoklund Olesen
committed
assert(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
MI->getOperand(1).isReg() && MI->getOperand(1).isUse() &&
MI->getOperand(2).isImm() && "Malformed extract_subreg");
unsigned DstReg = MI->getOperand(0).getReg();
unsigned SuperReg = MI->getOperand(1).getReg();
unsigned SubIdx = MI->getOperand(2).getImm();
assert(TargetRegisterInfo::isPhysicalRegister(SuperReg) &&
"Extract supperg source must be a physical register");
assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
"Extract destination must be in a physical register");
assert(SrcReg && "invalid subregister index for register");
Jakob Stoklund Olesen
committed
if (SrcReg == DstReg) {
Jakob Stoklund Olesen
committed
// No need to insert an identity copy instruction.
if (MI->getOperand(1).isKill()) {
// We must make sure the super-register gets killed. Replace the
// instruction with KILL.
MI->setDesc(TII->get(TargetOpcode::KILL));
Jakob Stoklund Olesen
committed
MI->RemoveOperand(2); // SubIdx
Jakob Stoklund Olesen
committed
return true;
}
} else {
TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstReg, SrcReg, false);
// Transfer the kill/dead flags, if needed.
if (MI->getOperand(0).isDead())
TransferDeadFlag(MI, DstReg, TRI);
if (MI->getOperand(1).isKill())
Evan Cheng
committed
TransferKillFlag(MI, SuperReg, TRI, true);
TransferImplicitDefs(MI);
DEBUG({
MachineBasicBlock::iterator dMI = MI;
Christopher Lamb
committed
bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) {
MachineBasicBlock *MBB = MI->getParent();
assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
MI->getOperand(1).isImm() &&
(MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
MI->getOperand(3).isImm() && "Invalid subreg_to_reg");
Jakob Stoklund Olesen
committed
Christopher Lamb
committed
unsigned DstReg = MI->getOperand(0).getReg();
unsigned InsReg = MI->getOperand(2).getReg();
Jakob Stoklund Olesen
committed
assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?");
unsigned SubIdx = MI->getOperand(3).getImm();
Christopher Lamb
committed
assert(SubIdx != 0 && "Invalid index for insert_subreg");
assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
"Insert destination must be in a physical register");
assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
"Inserted value must be in a physical register");
Christopher Lamb
committed
Jakob Stoklund Olesen
committed
if (DstSubReg == InsReg) {
// No need to insert an identify copy instruction.
// Watch out for case like this:
Jakob Stoklund Olesen
committed
// %RAX<def> = SUBREG_TO_REG 0, %EAX<kill>, 3
// We must leave %RAX live.
if (DstReg != InsReg) {
MI->setDesc(TII->get(TargetOpcode::KILL));
MI->RemoveOperand(3); // SubIdx
MI->RemoveOperand(1); // Imm
DEBUG(dbgs() << "subreg: replace by: " << *MI);
return true;
}
} else {
TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg,
MI->getOperand(2).isKill());
// Transfer the kill/dead flags, if needed.
if (MI->getOperand(0).isDead())
TransferDeadFlag(MI, DstSubReg, TRI);
DEBUG({
MachineBasicBlock::iterator dMI = MI;
MBB->erase(MI);
Christopher Lamb
committed
}
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
MachineBasicBlock *MBB = MI->getParent();
assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
(MI->getOperand(1).isReg() && MI->getOperand(1).isUse()) &&
(MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
MI->getOperand(3).isImm() && "Invalid insert_subreg");
unsigned DstReg = MI->getOperand(0).getReg();
#ifndef NDEBUG
unsigned SrcReg = MI->getOperand(1).getReg();
#endif
unsigned InsReg = MI->getOperand(2).getReg();
unsigned SubIdx = MI->getOperand(3).getImm();
assert(DstReg == SrcReg && "insert_subreg not a two-address instruction?");
assert(SubIdx != 0 && "Invalid index for insert_subreg");
unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx);
assert(DstSubReg && "invalid subregister index for register");
assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
"Insert superreg source must be in a physical register");
assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
"Inserted value must be in a physical register");
DEBUG(dbgs() << "subreg: CONVERTING: " << *MI);
if (DstSubReg == InsReg) {
// No need to insert an identity copy instruction. If the SrcReg was
// <undef>, we need to make sure it is alive by inserting a KILL
if (MI->getOperand(1).isUndef() && !MI->getOperand(0).isDead()) {
MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(),
TII->get(TargetOpcode::KILL), DstReg);
if (MI->getOperand(2).isUndef())
MIB.addReg(InsReg, RegState::Undef);
else
MIB.addReg(InsReg, RegState::Kill);
} else {
DEBUG(dbgs() << "subreg: eliminated!\n");
MBB->erase(MI);
return true;
}
} else {
// Insert sub-register copy
if (MI->getOperand(2).isUndef())
// If the source register being inserted is undef, then this becomes a
// KILL.
BuildMI(*MBB, MI, MI->getDebugLoc(),
TII->get(TargetOpcode::KILL), DstSubReg);
else {
TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg, false);
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
}
MachineBasicBlock::iterator CopyMI = MI;
--CopyMI;
// INSERT_SUBREG is a two-address instruction so it implicitly kills SrcReg.
if (!MI->getOperand(1).isUndef())
CopyMI->addOperand(MachineOperand::CreateReg(DstReg, false, true, true));
// Transfer the kill/dead flags, if needed.
if (MI->getOperand(0).isDead()) {
TransferDeadFlag(MI, DstSubReg, TRI);
} else {
// Make sure the full DstReg is live after this replacement.
CopyMI->addOperand(MachineOperand::CreateReg(DstReg, true, true));
}
// Make sure the inserted register gets killed
if (MI->getOperand(2).isKill() && !MI->getOperand(2).isUndef())
TransferKillFlag(MI, InsReg, TRI);
}
DEBUG({
MachineBasicBlock::iterator dMI = MI;
dbgs() << "subreg: " << *(--dMI) << "\n";
});
MBB->erase(MI);
return true;
}
bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) {
MachineOperand &DstMO = MI->getOperand(0);
MachineOperand &SrcMO = MI->getOperand(1);
if (SrcMO.getReg() == DstMO.getReg()) {
DEBUG(dbgs() << "identity copy: " << *MI);
// No need to insert an identity copy instruction, but replace with a KILL
// if liveness is changed.
if (DstMO.isDead() || SrcMO.isUndef() || MI->getNumOperands() > 2) {
// We must make sure the super-register gets killed. Replace the
// instruction with KILL.
MI->setDesc(TII->get(TargetOpcode::KILL));
DEBUG(dbgs() << "replaced by: " << *MI);
return true;
}
// Vanilla identity copy.
MI->eraseFromParent();
return true;
}
DEBUG(dbgs() << "real copy: " << *MI);
TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(),
DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill());
if (DstMO.isDead())
TransferDeadFlag(MI, DstMO.getReg(), TRI);
if (MI->getNumOperands() > 2)
TransferImplicitDefs(MI);
DEBUG({
MachineBasicBlock::iterator dMI = MI;
dbgs() << "replaced by: " << *(--dMI);
});
MI->eraseFromParent();
return true;
}
Christopher Lamb
committed
/// runOnMachineFunction - Reduce subregister inserts and extracts to register
/// copies.
///
bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
<< "********** LOWERING SUBREG INSTRS **********\n"
<< "********** Function: "
<< MF.getFunction()->getName() << '\n');
TRI = MF.getTarget().getRegisterInfo();
TII = MF.getTarget().getInstrInfo();
Christopher Lamb
committed
Christopher Lamb
committed
for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end();
mbbi != mbbe; ++mbbi) {
for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end();
MachineBasicBlock::iterator nmi = llvm::next(mi);
if (MI->isExtractSubreg()) {
MadeChange |= LowerExtract(MI);
} else if (MI->isInsertSubreg()) {
MadeChange |= LowerInsert(MI);
} else if (MI->isSubregToReg()) {
Christopher Lamb
committed
MadeChange |= LowerSubregToReg(MI);
} else if (MI->isCopy()) {
MadeChange |= LowerCopy(MI);
Christopher Lamb
committed
}
Christopher Lamb
committed
}
}
return MadeChange;
}