Add a new target independent COPY instruction and code to lower it.

The COPY instruction is intended to replace the target specific copy
instructions for virtual registers as well as the EXTRACT_SUBREG and
INSERT_SUBREG instructions in MachineFunctions. It won't we used in a selection
DAG.

COPY is lowered to native register copies by LowerSubregs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107529 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2010-07-02 22:29:50 +00:00
parent f5cd8c51e3
commit a4e1ba53dd
5 changed files with 66 additions and 3 deletions

View File

@ -227,7 +227,10 @@ public:
bool isRegSequence() const { bool isRegSequence() const {
return getOpcode() == TargetOpcode::REG_SEQUENCE; return getOpcode() == TargetOpcode::REG_SEQUENCE;
} }
bool isCopy() const {
return getOpcode() == TargetOpcode::COPY;
}
/// readsRegister - Return true if the MachineInstr reads the specified /// readsRegister - Return true if the MachineInstr reads the specified
/// register. If TargetRegisterInfo is passed, then it also checks if there /// register. If TargetRegisterInfo is passed, then it also checks if there
/// is a read of a super-register. /// is a read of a super-register.

View File

@ -476,7 +476,6 @@ def DBG_VALUE : Instruction {
let AsmString = "DBG_VALUE"; let AsmString = "DBG_VALUE";
let isAsCheapAsAMove = 1; let isAsCheapAsAMove = 1;
} }
def REG_SEQUENCE : Instruction { def REG_SEQUENCE : Instruction {
let OutOperandList = (outs unknown:$dst); let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins variable_ops); let InOperandList = (ins variable_ops);
@ -484,6 +483,13 @@ def REG_SEQUENCE : Instruction {
let neverHasSideEffects = 1; let neverHasSideEffects = 1;
let isAsCheapAsAMove = 1; let isAsCheapAsAMove = 1;
} }
def COPY : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins unknown:$src);
let AsmString = "";
let neverHasSideEffects = 1;
let isAsCheapAsAMove = 1;
}
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -75,7 +75,11 @@ namespace TargetOpcode {
/// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5 /// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5
/// After register coalescing references of v1024 should be replace with /// After register coalescing references of v1024 should be replace with
/// v1027:3, v1025 with v1027:4, etc. /// v1027:3, v1025 with v1027:4, etc.
REG_SEQUENCE = 12 REG_SEQUENCE = 12,
/// COPY - Target-independent register copy. This instruction can also be
/// used to copy between subregisters of virtual registers.
COPY = 13
}; };
} // end namespace TargetOpcode } // end namespace TargetOpcode
} // end namespace llvm } // end namespace llvm

View File

@ -56,6 +56,7 @@ namespace {
bool LowerExtract(MachineInstr *MI); bool LowerExtract(MachineInstr *MI);
bool LowerInsert(MachineInstr *MI); bool LowerInsert(MachineInstr *MI);
bool LowerSubregToReg(MachineInstr *MI); bool LowerSubregToReg(MachineInstr *MI);
bool LowerCopy(MachineInstr *MI);
void TransferDeadFlag(MachineInstr *MI, unsigned DstReg, void TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
const TargetRegisterInfo *TRI); const TargetRegisterInfo *TRI);
@ -321,6 +322,52 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
return true; 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);
// Ask target for a lowered copy instruction.
const TargetRegisterClass *DstRC =
TRI->getPhysicalRegisterRegClass(DstMO.getReg());
const TargetRegisterClass *SrcRC =
TRI->getPhysicalRegisterRegClass(SrcMO.getReg());
bool Emitted = TII->copyRegToReg(*MI->getParent(), MI,
DstMO.getReg(), SrcMO.getReg(),
DstRC, SrcRC, MI->getDebugLoc());
(void)Emitted;
assert(Emitted && "Cannot emit copy");
if (DstMO.isDead())
TransferDeadFlag(MI, DstMO.getReg(), TRI);
if (SrcMO.isKill())
TransferKillFlag(MI, SrcMO.getReg(), TRI, true);
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 /// runOnMachineFunction - Reduce subregister inserts and extracts to register
/// copies. /// copies.
/// ///
@ -346,6 +393,8 @@ bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
MadeChange |= LowerInsert(MI); MadeChange |= LowerInsert(MI);
} else if (MI->isSubregToReg()) { } else if (MI->isSubregToReg()) {
MadeChange |= LowerSubregToReg(MI); MadeChange |= LowerSubregToReg(MI);
} else if (MI->isCopy()) {
MadeChange |= LowerCopy(MI);
} }
mi = nmi; mi = nmi;
} }

View File

@ -344,6 +344,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
"COPY_TO_REGCLASS", "COPY_TO_REGCLASS",
"DBG_VALUE", "DBG_VALUE",
"REG_SEQUENCE", "REG_SEQUENCE",
"COPY",
0 0
}; };
const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();