This commit merges the latest LLVM sources from the vendor space. It also updates the build glue to match the new sources. Clang's version number is changed to match LLVM's, which means /usr/include/clang/2.0 has been renamed to /usr/include/clang/2.8. Obtained from: projects/clangbsd
244 lines
8.6 KiB
C++
244 lines
8.6 KiB
C++
//===-- 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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"
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
struct LowerSubregsInstructionPass : public MachineFunctionPass {
|
|
private:
|
|
const TargetRegisterInfo *TRI;
|
|
const TargetInstrInfo *TII;
|
|
|
|
public:
|
|
static char ID; // Pass identification, replacement for typeid
|
|
LowerSubregsInstructionPass() : MachineFunctionPass(&ID) {}
|
|
|
|
const char *getPassName() const {
|
|
return "Subregister lowering instruction pass";
|
|
}
|
|
|
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.setPreservesCFG();
|
|
AU.addPreservedID(MachineLoopInfoID);
|
|
AU.addPreservedID(MachineDominatorsID);
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
}
|
|
|
|
/// runOnMachineFunction - pass entry point
|
|
bool runOnMachineFunction(MachineFunction&);
|
|
|
|
private:
|
|
bool LowerSubregToReg(MachineInstr *MI);
|
|
bool LowerCopy(MachineInstr *MI);
|
|
|
|
void TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
|
|
const TargetRegisterInfo *TRI);
|
|
void TransferKillFlag(MachineInstr *MI, unsigned SrcReg,
|
|
const TargetRegisterInfo *TRI,
|
|
bool AddIfNotFound = false);
|
|
void TransferImplicitDefs(MachineInstr *MI);
|
|
};
|
|
|
|
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,
|
|
const TargetRegisterInfo *TRI) {
|
|
for (MachineBasicBlock::iterator MII =
|
|
prior(MachineBasicBlock::iterator(MI)); ; --MII) {
|
|
if (MII->addRegisterDead(DstReg, TRI))
|
|
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,
|
|
const TargetRegisterInfo *TRI,
|
|
bool AddIfNotFound) {
|
|
for (MachineBasicBlock::iterator MII =
|
|
prior(MachineBasicBlock::iterator(MI)); ; --MII) {
|
|
if (MII->addRegisterKilled(SrcReg, TRI, AddIfNotFound))
|
|
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::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");
|
|
|
|
unsigned DstReg = MI->getOperand(0).getReg();
|
|
unsigned InsReg = MI->getOperand(2).getReg();
|
|
assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?");
|
|
unsigned SubIdx = MI->getOperand(3).getImm();
|
|
|
|
assert(SubIdx != 0 && "Invalid index for insert_subreg");
|
|
unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx);
|
|
|
|
assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
|
|
"Insert destination 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 identify copy instruction.
|
|
// Watch out for case like this:
|
|
// %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;
|
|
}
|
|
DEBUG(dbgs() << "subreg: eliminated!");
|
|
} 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;
|
|
dbgs() << "subreg: " << *(--dMI);
|
|
});
|
|
}
|
|
|
|
DEBUG(dbgs() << '\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;
|
|
}
|
|
|
|
/// runOnMachineFunction - Reduce subregister inserts and extracts to register
|
|
/// copies.
|
|
///
|
|
bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
|
|
DEBUG(dbgs() << "Machine Function\n"
|
|
<< "********** LOWERING SUBREG INSTRS **********\n"
|
|
<< "********** Function: "
|
|
<< MF.getFunction()->getName() << '\n');
|
|
TRI = MF.getTarget().getRegisterInfo();
|
|
TII = MF.getTarget().getInstrInfo();
|
|
|
|
bool MadeChange = false;
|
|
|
|
for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end();
|
|
mbbi != mbbe; ++mbbi) {
|
|
for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end();
|
|
mi != me;) {
|
|
MachineBasicBlock::iterator nmi = llvm::next(mi);
|
|
MachineInstr *MI = mi;
|
|
assert(!MI->isInsertSubreg() && "INSERT_SUBREG should no longer appear");
|
|
assert(MI->getOpcode() != TargetOpcode::EXTRACT_SUBREG &&
|
|
"EXTRACT_SUBREG should no longer appear");
|
|
if (MI->isSubregToReg()) {
|
|
MadeChange |= LowerSubregToReg(MI);
|
|
} else if (MI->isCopy()) {
|
|
MadeChange |= LowerCopy(MI);
|
|
}
|
|
mi = nmi;
|
|
}
|
|
}
|
|
|
|
return MadeChange;
|
|
}
|