mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
Simplify EXTRACT_SUBREG emission.
EXTRACT_SUBREG is emitted as %dst = COPY %src:sub, so there is no need to constrain the %dst register class. RegisterCoalescer will apply the necessary constraints if it decides to eliminate the COPY. The %src register class does need to be constrained to something with the right sub-registers, though. This is currently done manually with COPY_TO_REGCLASS nodes. They can possibly be removed after this patch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141207 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9bb272c900
commit
d2ed2d71c9
@ -30,6 +30,12 @@
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
using namespace llvm;
|
||||
|
||||
/// MinRCSize - Smallest register class we allow when constraining virtual
|
||||
/// registers. If satisfying all register class constraints would require
|
||||
/// using a smaller register class, emit a COPY to a new virtual register
|
||||
/// instead.
|
||||
const unsigned MinRCSize = 4;
|
||||
|
||||
/// CountResults - The results of target nodes have register or immediate
|
||||
/// operands first, then an optional chain, and optional glue operands (which do
|
||||
/// not go into the resulting MachineInstr).
|
||||
@ -284,7 +290,6 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op,
|
||||
// a new virtual register and copy the value into it, but first attempt to
|
||||
// shrink VReg's register class within reason. For example, if VReg == GR32
|
||||
// and II requires a GR32_NOSP, just constrain VReg to GR32_NOSP.
|
||||
const unsigned MinRCSize = 4;
|
||||
if (II) {
|
||||
const TargetRegisterClass *DstRC = 0;
|
||||
if (IIOpNum < II->getNumOperands())
|
||||
@ -392,6 +397,30 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op,
|
||||
}
|
||||
}
|
||||
|
||||
unsigned InstrEmitter::ConstrainForSubReg(unsigned VReg, unsigned SubIdx,
|
||||
EVT VT, DebugLoc DL) {
|
||||
const TargetRegisterClass *VRC = MRI->getRegClass(VReg);
|
||||
const TargetRegisterClass *RC = TRI->getSubClassWithSubReg(VRC, SubIdx);
|
||||
|
||||
// RC is a sub-class of VRC that supports SubIdx. Try to constrain VReg
|
||||
// within reason.
|
||||
if (RC && RC != VRC)
|
||||
RC = MRI->constrainRegClass(VReg, RC, MinRCSize);
|
||||
|
||||
// VReg has been adjusted. It can be used with SubIdx operands now.
|
||||
if (RC)
|
||||
return VReg;
|
||||
|
||||
// VReg couldn't be reasonably constrained. Emit a COPY to a new virtual
|
||||
// register instead.
|
||||
RC = TRI->getSubClassWithSubReg(TLI->getRegClassFor(VT), SubIdx);
|
||||
assert(RC && "No legal register class for VT supports that SubIdx");
|
||||
unsigned NewReg = MRI->createVirtualRegister(RC);
|
||||
BuildMI(*MBB, InsertPos, DL, TII->get(TargetOpcode::COPY), NewReg)
|
||||
.addReg(VReg);
|
||||
return NewReg;
|
||||
}
|
||||
|
||||
/// EmitSubregNode - Generate machine code for subreg nodes.
|
||||
///
|
||||
void InstrEmitter::EmitSubregNode(SDNode *Node,
|
||||
@ -416,10 +445,12 @@ void InstrEmitter::EmitSubregNode(SDNode *Node,
|
||||
}
|
||||
|
||||
if (Opc == TargetOpcode::EXTRACT_SUBREG) {
|
||||
// EXTRACT_SUBREG is lowered as %dst = COPY %src:sub
|
||||
// EXTRACT_SUBREG is lowered as %dst = COPY %src:sub. There are no
|
||||
// constraints on the %dst register, COPY can target all legal register
|
||||
// classes.
|
||||
unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
|
||||
const TargetRegisterClass *TRC = TLI->getRegClassFor(Node->getValueType(0));
|
||||
|
||||
// Figure out the register class to create for the destreg.
|
||||
unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
|
||||
MachineInstr *DefMI = MRI->getVRegDef(VReg);
|
||||
unsigned SrcReg, DstReg, DefSubIdx;
|
||||
@ -431,36 +462,24 @@ void InstrEmitter::EmitSubregNode(SDNode *Node,
|
||||
// r1026 = extract_subreg r1025, 4
|
||||
// to a copy
|
||||
// r1026 = copy r1024
|
||||
const TargetRegisterClass *TRC = MRI->getRegClass(SrcReg);
|
||||
VRBase = MRI->createVirtualRegister(TRC);
|
||||
BuildMI(*MBB, InsertPos, Node->getDebugLoc(),
|
||||
TII->get(TargetOpcode::COPY), VRBase).addReg(SrcReg);
|
||||
} else {
|
||||
const TargetRegisterClass *TRC = MRI->getRegClass(VReg);
|
||||
const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx);
|
||||
assert(SRC && "Invalid subregister index in EXTRACT_SUBREG");
|
||||
// VReg may not support a SubIdx sub-register, and we may need to
|
||||
// constrain its register class or issue a COPY to a compatible register
|
||||
// class.
|
||||
VReg = ConstrainForSubReg(VReg, SubIdx,
|
||||
Node->getOperand(0).getValueType(),
|
||||
Node->getDebugLoc());
|
||||
|
||||
// Figure out the register class to create for the destreg.
|
||||
// Note that if we're going to directly use an existing register,
|
||||
// it must be precisely the required class, and not a subclass
|
||||
// thereof.
|
||||
if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) {
|
||||
// Create the reg
|
||||
assert(SRC && "Couldn't find source register class");
|
||||
VRBase = MRI->createVirtualRegister(SRC);
|
||||
}
|
||||
// Create the destreg if it is missing.
|
||||
if (VRBase == 0)
|
||||
VRBase = MRI->createVirtualRegister(TRC);
|
||||
|
||||
// Create the extract_subreg machine instruction.
|
||||
MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(),
|
||||
TII->get(TargetOpcode::COPY), VRBase);
|
||||
|
||||
// Add source, and subreg index
|
||||
AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap, /*IsDebug=*/false,
|
||||
IsClone, IsCloned);
|
||||
assert(TargetRegisterInfo::isVirtualRegister(MI->getOperand(1).getReg())&&
|
||||
"Cannot yet extract from physregs");
|
||||
MI->getOperand(1).setSubReg(SubIdx);
|
||||
MBB->insert(InsertPos, MI);
|
||||
BuildMI(*MBB, InsertPos, Node->getDebugLoc(),
|
||||
TII->get(TargetOpcode::COPY), VRBase).addReg(VReg, 0, SubIdx);
|
||||
}
|
||||
} else if (Opc == TargetOpcode::INSERT_SUBREG ||
|
||||
Opc == TargetOpcode::SUBREG_TO_REG) {
|
||||
|
@ -77,6 +77,12 @@ class InstrEmitter {
|
||||
DenseMap<SDValue, unsigned> &VRBaseMap,
|
||||
bool IsDebug, bool IsClone, bool IsCloned);
|
||||
|
||||
/// ConstrainForSubReg - Try to constrain VReg to a register class that
|
||||
/// supports SubIdx sub-registers. Emit a copy if that isn't possible.
|
||||
/// Return the virtual register to use.
|
||||
unsigned ConstrainForSubReg(unsigned VReg, unsigned SubIdx,
|
||||
EVT VT, DebugLoc DL);
|
||||
|
||||
/// EmitSubregNode - Generate machine code for subreg nodes.
|
||||
///
|
||||
void EmitSubregNode(SDNode *Node, DenseMap<SDValue, unsigned> &VRBaseMap,
|
||||
|
Loading…
Reference in New Issue
Block a user