mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 20:59:51 +00:00
Make insert_subreg a two-address instruction, vastly simplifying LowerSubregs pass. Add a new TII, subreg_to_reg, which is like insert_subreg except that it takes an immediate implicit value to insert into rather than a register.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48412 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
606c5aa084
commit
c929823525
@ -50,16 +50,8 @@ public:
|
||||
DECLARE = 3,
|
||||
EXTRACT_SUBREG = 4,
|
||||
INSERT_SUBREG = 5,
|
||||
IMPLICIT_DEF = 6
|
||||
};
|
||||
|
||||
// Target independent implict values for use with subreg insert. All targets
|
||||
// that support insert_subreg support IMPL_VAL_UNDEF. Support for the other
|
||||
// values is target dependent.
|
||||
enum ImplictVal {
|
||||
IMPL_VAL_UNDEF = 0,
|
||||
IMPL_VAL_ZERO = 1,
|
||||
LAST_IMPL_VAL = 3
|
||||
IMPLICIT_DEF = 6,
|
||||
SUBREG_TO_REG = 7
|
||||
};
|
||||
|
||||
unsigned getNumOpcodes() const { return NumOpcodes; }
|
||||
|
@ -35,6 +35,7 @@ namespace {
|
||||
|
||||
bool LowerExtract(MachineInstr *MI);
|
||||
bool LowerInsert(MachineInstr *MI);
|
||||
bool LowerSubregToReg(MachineInstr *MI);
|
||||
};
|
||||
|
||||
char LowerSubregsInstructionPass::ID = 0;
|
||||
@ -54,29 +55,28 @@ bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) {
|
||||
MI->getOperand(1).isRegister() && MI->getOperand(1).isUse() &&
|
||||
MI->getOperand(2).isImmediate() && "Malformed extract_subreg");
|
||||
|
||||
unsigned DstReg = MI->getOperand(0).getReg();
|
||||
unsigned SuperReg = MI->getOperand(1).getReg();
|
||||
unsigned SubIdx = MI->getOperand(2).getImm();
|
||||
unsigned SubIdx = MI->getOperand(2).getImm();
|
||||
unsigned SrcReg = TRI.getSubReg(SuperReg, SubIdx);
|
||||
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(SuperReg) &&
|
||||
"Extract supperg source must be a physical register");
|
||||
unsigned SrcReg = TRI.getSubReg(SuperReg, SubIdx);
|
||||
unsigned DstReg = MI->getOperand(0).getReg();
|
||||
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
|
||||
"Insert destination must be in a physical register");
|
||||
|
||||
DOUT << "subreg: CONVERTING: " << *MI;
|
||||
|
||||
if (SrcReg != DstReg) {
|
||||
const TargetRegisterClass *TRC = 0;
|
||||
if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
|
||||
TRC = TRI.getPhysicalRegisterRegClass(DstReg);
|
||||
} else {
|
||||
TRC = MF.getRegInfo().getRegClass(DstReg);
|
||||
}
|
||||
const TargetRegisterClass *TRC = TRI.getPhysicalRegisterRegClass(DstReg);
|
||||
assert(TRC == TRI.getPhysicalRegisterRegClass(SrcReg) &&
|
||||
"Extract subreg and Dst must be of same register class");
|
||||
|
||||
TII.copyRegToReg(*MBB, MI, DstReg, SrcReg, TRC, TRC);
|
||||
|
||||
#ifndef NDEBUG
|
||||
MachineBasicBlock::iterator dMI = MI;
|
||||
DOUT << "subreg: " << *(--dMI);
|
||||
#endif
|
||||
}
|
||||
|
||||
DOUT << "\n";
|
||||
@ -84,6 +84,44 @@ bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) {
|
||||
MachineBasicBlock *MBB = MI->getParent();
|
||||
MachineFunction &MF = *MBB->getParent();
|
||||
const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo();
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
assert((MI->getOperand(0).isRegister() && MI->getOperand(0).isDef()) &&
|
||||
MI->getOperand(1).isImmediate() &&
|
||||
(MI->getOperand(2).isRegister() && MI->getOperand(2).isUse()) &&
|
||||
MI->getOperand(3).isImmediate() && "Invalid subreg_to_reg");
|
||||
|
||||
unsigned DstReg = MI->getOperand(0).getReg();
|
||||
unsigned InsReg = MI->getOperand(2).getReg();
|
||||
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");
|
||||
|
||||
DOUT << "subreg: CONVERTING: " << *MI;
|
||||
|
||||
// Insert sub-register copy
|
||||
const TargetRegisterClass *TRC0 = TRI.getPhysicalRegisterRegClass(DstSubReg);
|
||||
const TargetRegisterClass *TRC1 = TRI.getPhysicalRegisterRegClass(InsReg);
|
||||
TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1);
|
||||
|
||||
#ifndef NDEBUG
|
||||
MachineBasicBlock::iterator dMI = MI;
|
||||
DOUT << "subreg: " << *(--dMI);
|
||||
#endif
|
||||
|
||||
DOUT << "\n";
|
||||
MBB->remove(MI);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
|
||||
MachineBasicBlock *MBB = MI->getParent();
|
||||
@ -91,108 +129,35 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
|
||||
const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo();
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
assert((MI->getOperand(0).isRegister() && MI->getOperand(0).isDef()) &&
|
||||
((MI->getOperand(1).isRegister() && MI->getOperand(1).isUse()) ||
|
||||
MI->getOperand(1).isImmediate()) &&
|
||||
(MI->getOperand(1).isRegister() && MI->getOperand(1).isUse()) &&
|
||||
(MI->getOperand(2).isRegister() && MI->getOperand(2).isUse()) &&
|
||||
MI->getOperand(3).isImmediate() && "Invalid insert_subreg");
|
||||
|
||||
// Check if we're inserting into an implicit undef value.
|
||||
bool isImplicit = MI->getOperand(1).isImmediate();
|
||||
unsigned DstReg = MI->getOperand(0).getReg();
|
||||
unsigned SrcReg = isImplicit ? DstReg : MI->getOperand(1).getReg();
|
||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||
unsigned InsReg = MI->getOperand(2).getReg();
|
||||
unsigned SubIdx = MI->getOperand(3).getImm();
|
||||
|
||||
assert(SubIdx != 0 && "Invalid index for extract_subreg");
|
||||
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(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
|
||||
"Insert superreg source must be in a physical register");
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
|
||||
"Insert destination must be in a physical register");
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
|
||||
"Inserted value must be in a physical register");
|
||||
|
||||
DOUT << "subreg: CONVERTING: " << *MI;
|
||||
|
||||
// Check whether the implict subreg copy has side affects or not. Only copies
|
||||
// into an undef value have no side affects, that is they can be eliminated
|
||||
// without changing the semantics of the program.
|
||||
bool copyHasSideAffects = isImplicit?
|
||||
MI->getOperand(1).getImm() != TargetInstrInfo::IMPL_VAL_UNDEF
|
||||
: false;
|
||||
|
||||
// If the inserted register is already allocated into a subregister
|
||||
// of the destination, we copy the subreg into the source
|
||||
// However, this is only safe if the insert instruction is the kill
|
||||
// of the source register
|
||||
bool revCopyOrder = TRI.isSubRegister(DstReg, InsReg);
|
||||
if (revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
|
||||
if (isImplicit || MI->getOperand(1).isKill()) {
|
||||
DstSubReg = TRI.getSubReg(SrcReg, SubIdx);
|
||||
// Insert sub-register copy
|
||||
const TargetRegisterClass *TRC1 = 0;
|
||||
if (TargetRegisterInfo::isPhysicalRegister(InsReg)) {
|
||||
TRC1 = TRI.getPhysicalRegisterRegClass(InsReg);
|
||||
} else {
|
||||
TRC1 = MF.getRegInfo().getRegClass(InsReg);
|
||||
}
|
||||
TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC1, TRC1);
|
||||
|
||||
// Insert sub-register copy
|
||||
const TargetRegisterClass *TRC0 = TRI.getPhysicalRegisterRegClass(DstSubReg);
|
||||
const TargetRegisterClass *TRC1 = TRI.getPhysicalRegisterRegClass(InsReg);
|
||||
TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1);
|
||||
|
||||
#ifndef NDEBUG
|
||||
MachineBasicBlock::iterator dMI = MI;
|
||||
DOUT << "subreg: " << *(--dMI);
|
||||
MachineBasicBlock::iterator dMI = MI;
|
||||
DOUT << "subreg: " << *(--dMI);
|
||||
#endif
|
||||
} else {
|
||||
assert(0 && "Don't know how to convert this insert");
|
||||
}
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
if (InsReg == DstSubReg && !copyHasSideAffects) {
|
||||
DOUT << "subreg: Eliminated subreg copy\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SrcReg != DstReg) {
|
||||
// Insert super-register copy
|
||||
const TargetRegisterClass *TRC0 = 0;
|
||||
if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
|
||||
TRC0 = TRI.getPhysicalRegisterRegClass(DstReg);
|
||||
} else {
|
||||
TRC0 = MF.getRegInfo().getRegClass(DstReg);
|
||||
}
|
||||
assert(TRC0 == TRI.getPhysicalRegisterRegClass(SrcReg) &&
|
||||
"Insert superreg and Dst must be of same register class");
|
||||
|
||||
TII.copyRegToReg(*MBB, MI, DstReg, SrcReg, TRC0, TRC0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
MachineBasicBlock::iterator dMI = MI;
|
||||
DOUT << "subreg: " << *(--dMI);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (SrcReg == DstReg) {
|
||||
DOUT << "subreg: Eliminated superreg copy\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
|
||||
// Insert sub-register copy
|
||||
const TargetRegisterClass *TRC1 = 0;
|
||||
if (TargetRegisterInfo::isPhysicalRegister(InsReg)) {
|
||||
TRC1 = TRI.getPhysicalRegisterRegClass(InsReg);
|
||||
} else {
|
||||
TRC1 = MF.getRegInfo().getRegClass(InsReg);
|
||||
}
|
||||
TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC1, TRC1);
|
||||
|
||||
#ifndef NDEBUG
|
||||
MachineBasicBlock::iterator dMI = MI;
|
||||
DOUT << "subreg: " << *(--dMI);
|
||||
#endif
|
||||
}
|
||||
|
||||
DOUT << "\n";
|
||||
MBB->remove(MI);
|
||||
@ -220,6 +185,8 @@ bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
|
||||
MadeChange |= LowerExtract(MI);
|
||||
} else if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) {
|
||||
MadeChange |= LowerInsert(MI);
|
||||
} else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) {
|
||||
MadeChange |= LowerSubregToReg(MI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -661,26 +661,24 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node,
|
||||
DenseMap<SDOperand, unsigned> &VRBaseMap) {
|
||||
unsigned VRBase = 0;
|
||||
unsigned Opc = Node->getTargetOpcode();
|
||||
if (Opc == TargetInstrInfo::EXTRACT_SUBREG) {
|
||||
// If the node is only used by a CopyToReg and the dest reg is a vreg, use
|
||||
// the CopyToReg'd destination register instead of creating a new vreg.
|
||||
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
|
||||
UI != E; ++UI) {
|
||||
SDNode *Use = *UI;
|
||||
if (Use->getOpcode() == ISD::CopyToReg &&
|
||||
Use->getOperand(2).Val == Node) {
|
||||
unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
|
||||
VRBase = DestReg;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the node is only used by a CopyToReg and the dest reg is a vreg, use
|
||||
// the CopyToReg'd destination register instead of creating a new vreg.
|
||||
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
|
||||
UI != E; ++UI) {
|
||||
SDNode *Use = *UI;
|
||||
if (Use->getOpcode() == ISD::CopyToReg &&
|
||||
Use->getOperand(2).Val == Node) {
|
||||
unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
|
||||
VRBase = DestReg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Opc == TargetInstrInfo::EXTRACT_SUBREG) {
|
||||
unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getValue();
|
||||
|
||||
// TODO: If the node is a use of a CopyFromReg from a physical register
|
||||
// fold the extract into the copy now
|
||||
|
||||
// Create the extract_subreg machine instruction.
|
||||
MachineInstr *MI =
|
||||
@ -707,36 +705,14 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node,
|
||||
AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap);
|
||||
MI->addOperand(MachineOperand::CreateImm(SubIdx));
|
||||
|
||||
} else if (Opc == TargetInstrInfo::INSERT_SUBREG) {
|
||||
} else if (Opc == TargetInstrInfo::INSERT_SUBREG ||
|
||||
Opc == TargetInstrInfo::SUBREG_TO_REG) {
|
||||
SDOperand N0 = Node->getOperand(0);
|
||||
SDOperand N1 = Node->getOperand(1);
|
||||
SDOperand N2 = Node->getOperand(2);
|
||||
unsigned SubReg = getVR(N1, VRBaseMap);
|
||||
unsigned SubIdx = cast<ConstantSDNode>(N2)->getValue();
|
||||
|
||||
// TODO: Add tracking info to MachineRegisterInfo of which vregs are subregs
|
||||
// to allow coalescing in the allocator
|
||||
|
||||
// If the node is only used by a CopyToReg and the dest reg is a vreg, use
|
||||
// the CopyToReg'd destination register instead of creating a new vreg.
|
||||
// If the CopyToReg'd destination register is physical, then fold the
|
||||
// insert into the copy
|
||||
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
|
||||
UI != E; ++UI) {
|
||||
SDNode *Use = *UI;
|
||||
if (Use->getOpcode() == ISD::CopyToReg &&
|
||||
Use->getOperand(2).Val == Node) {
|
||||
unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
|
||||
VRBase = DestReg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the insert_subreg machine instruction.
|
||||
MachineInstr *MI =
|
||||
new MachineInstr(BB, TII->get(TargetInstrInfo::INSERT_SUBREG));
|
||||
|
||||
// Figure out the register class to create for the destreg.
|
||||
const TargetRegisterClass *TRC = 0;
|
||||
@ -749,19 +725,23 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node,
|
||||
VRBase = MRI.createVirtualRegister(TRC); // Create the reg
|
||||
}
|
||||
|
||||
// Create the insert_subreg or subreg_to_reg machine instruction.
|
||||
MachineInstr *MI =
|
||||
new MachineInstr(BB, TII->get(Opc));
|
||||
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
|
||||
|
||||
// If N0 is a constant then it indicates the insert is being done
|
||||
// into a target specific constant value, not a register.
|
||||
if (const ConstantSDNode *SD = dyn_cast<ConstantSDNode>(N0))
|
||||
// If creating a subreg_to_reg, then the first input operand
|
||||
// is an implicit value immediate, otherwise it's a register
|
||||
if (Opc == TargetInstrInfo::SUBREG_TO_REG) {
|
||||
const ConstantSDNode *SD = cast<ConstantSDNode>(N0);
|
||||
MI->addOperand(MachineOperand::CreateImm(SD->getValue()));
|
||||
else
|
||||
} else
|
||||
AddOperand(MI, N0, 0, 0, VRBaseMap);
|
||||
// Add the subregster being inserted
|
||||
AddOperand(MI, N1, 0, 0, VRBaseMap);
|
||||
MI->addOperand(MachineOperand::CreateImm(SubIdx));
|
||||
} else
|
||||
assert(0 && "Node is not a subreg insert or extract");
|
||||
assert(0 && "Node is not insert_subreg, extract_subreg, or subreg_to_reg");
|
||||
|
||||
bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,0), VRBase));
|
||||
assert(isNew && "Node emitted out of order - early");
|
||||
@ -777,7 +757,8 @@ void ScheduleDAG::EmitNode(SDNode *Node, unsigned InstanceNo,
|
||||
|
||||
// Handle subreg insert/extract specially
|
||||
if (Opc == TargetInstrInfo::EXTRACT_SUBREG ||
|
||||
Opc == TargetInstrInfo::INSERT_SUBREG) {
|
||||
Opc == TargetInstrInfo::INSERT_SUBREG ||
|
||||
Opc == TargetInstrInfo::SUBREG_TO_REG) {
|
||||
EmitSubregNode(Node, VRBaseMap);
|
||||
return;
|
||||
}
|
||||
|
@ -366,6 +366,7 @@ def INSERT_SUBREG : Instruction {
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetInstrInfo";
|
||||
let neverHasSideEffects = 1;
|
||||
let Constraints = "$supersrc = $dst";
|
||||
}
|
||||
def IMPLICIT_DEF : Instruction {
|
||||
let OutOperandList = (ops unknown:$dst);
|
||||
@ -374,6 +375,13 @@ def IMPLICIT_DEF : Instruction {
|
||||
let Namespace = "TargetInstrInfo";
|
||||
let neverHasSideEffects = 1;
|
||||
}
|
||||
def SUBREG_TO_REG : Instruction {
|
||||
let OutOperandList = (ops unknown:$dst);
|
||||
let InOperandList = (ops unknown:$implsrc, unknown:$subsrc, i32imm:$subidx);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetInstrInfo";
|
||||
let neverHasSideEffects = 1;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AsmWriter - This class can be implemented by targets that need to customize
|
||||
|
@ -918,11 +918,3 @@ class ComplexPattern<ValueType ty, int numops, string fn,
|
||||
def SDT_dwarf_loc : SDTypeProfile<0, 3,
|
||||
[SDTCisInt<0>, SDTCisInt<1>, SDTCisInt<2>]>;
|
||||
def dwarf_loc : SDNode<"ISD::DEBUG_LOC", SDT_dwarf_loc,[SDNPHasChain]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Implict value insert subreg support.
|
||||
//
|
||||
// These should match the enum TargetInstrInfo::ImplictVal.
|
||||
def tii_impl_val_undef : PatLeaf<(i32 0)>;
|
||||
def tii_impl_val_zero : PatLeaf<(i32 1)>;
|
||||
|
||||
|
@ -1529,39 +1529,36 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
|
||||
}
|
||||
|
||||
case ISD::ANY_EXTEND: {
|
||||
// Check if the type extended to supports subregs.
|
||||
if (NVT == MVT::i8)
|
||||
break;
|
||||
|
||||
SDOperand N0 = Node->getOperand(0);
|
||||
// Get the subregsiter index for the type to extend.
|
||||
MVT::ValueType N0VT = N0.getValueType();
|
||||
unsigned Idx = (N0VT == MVT::i32) ? X86::SUBREG_32BIT :
|
||||
(N0VT == MVT::i16) ? X86::SUBREG_16BIT :
|
||||
(Subtarget->is64Bit()) ? X86::SUBREG_8BIT : 0;
|
||||
|
||||
// If we don't have a subreg Idx, let generated ISel have a try.
|
||||
if (Idx == 0)
|
||||
break;
|
||||
|
||||
// If we have an index, generate an insert_subreg into undef.
|
||||
AddToISelQueue(N0);
|
||||
if (NVT == MVT::i64 || NVT == MVT::i32 || NVT == MVT::i16) {
|
||||
SDOperand SRIdx;
|
||||
switch(N0.getValueType()) {
|
||||
case MVT::i32:
|
||||
SRIdx = CurDAG->getTargetConstant(X86::SUBREG_32BIT, MVT::i32);
|
||||
break;
|
||||
case MVT::i16:
|
||||
SRIdx = CurDAG->getTargetConstant(X86::SUBREG_16BIT, MVT::i32);
|
||||
break;
|
||||
case MVT::i8:
|
||||
if (Subtarget->is64Bit())
|
||||
SRIdx = CurDAG->getTargetConstant(X86::SUBREG_8BIT, MVT::i32);
|
||||
break;
|
||||
default: assert(0 && "Unknown any_extend!");
|
||||
}
|
||||
if (SRIdx.Val) {
|
||||
SDOperand ImplVal =
|
||||
CurDAG->getTargetConstant(X86InstrInfo::IMPL_VAL_UNDEF, MVT::i32);
|
||||
SDNode *ResNode = CurDAG->getTargetNode(X86::INSERT_SUBREG,
|
||||
NVT, ImplVal, N0, SRIdx);
|
||||
SDOperand Undef =
|
||||
SDOperand(CurDAG->getTargetNode(X86::IMPLICIT_DEF, NVT), 0);
|
||||
SDOperand SRIdx = CurDAG->getTargetConstant(Idx, MVT::i32);
|
||||
SDNode *ResNode = CurDAG->getTargetNode(X86::INSERT_SUBREG,
|
||||
NVT, Undef, N0, SRIdx);
|
||||
|
||||
#ifndef NDEBUG
|
||||
DOUT << std::string(Indent-2, ' ') << "=> ";
|
||||
DEBUG(ResNode->dump(CurDAG));
|
||||
DOUT << "\n";
|
||||
Indent -= 2;
|
||||
DOUT << std::string(Indent-2, ' ') << "=> ";
|
||||
DEBUG(ResNode->dump(CurDAG));
|
||||
DOUT << "\n";
|
||||
Indent -= 2;
|
||||
#endif
|
||||
return ResNode;
|
||||
} // Otherwise let generated ISel handle it.
|
||||
}
|
||||
break;
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
case ISD::SIGN_EXTEND_INREG: {
|
||||
|
@ -1202,43 +1202,43 @@ def : Pat<(parallel (X86cmp GR64:$src1, 0), (implicit EFLAGS)),
|
||||
|
||||
|
||||
// Zero-extension
|
||||
def : Pat<(i64 (zext GR32:$src)), (INSERT_SUBREG tii_impl_val_zero,
|
||||
GR32:$src, x86_subreg_32bit)>;
|
||||
def : Pat<(i64 (zext GR32:$src)),
|
||||
(SUBREG_TO_REG (i64 0), GR32:$src, x86_subreg_32bit)>;
|
||||
|
||||
// zextload bool -> zextload byte
|
||||
def : Pat<(zextloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>;
|
||||
|
||||
def : Pat<(zextloadi64i32 addr:$src), (INSERT_SUBREG tii_impl_val_zero,
|
||||
(MOV32rm addr:$src), x86_subreg_32bit)>;
|
||||
def : Pat<(zextloadi64i32 addr:$src),
|
||||
(SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), x86_subreg_32bit)>;
|
||||
|
||||
// extload
|
||||
def : Pat<(extloadi64i1 addr:$src), (MOVZX64rm8 addr:$src)>;
|
||||
def : Pat<(extloadi64i8 addr:$src), (MOVZX64rm8 addr:$src)>;
|
||||
def : Pat<(extloadi64i16 addr:$src), (MOVZX64rm16 addr:$src)>;
|
||||
def : Pat<(extloadi64i32 addr:$src), (INSERT_SUBREG tii_impl_val_undef,
|
||||
(MOV32rm addr:$src), x86_subreg_32bit)>;
|
||||
def : Pat<(extloadi64i32 addr:$src),
|
||||
(INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV32rm addr:$src),
|
||||
x86_subreg_32bit)>;
|
||||
|
||||
// anyext -> zext
|
||||
def : Pat<(i64 (anyext GR8 :$src)), (MOVZX64rr8 GR8 :$src)>;
|
||||
def : Pat<(i64 (anyext GR16:$src)), (MOVZX64rr16 GR16:$src)>;
|
||||
def : Pat<(i64 (anyext GR32:$src)), (INSERT_SUBREG tii_impl_val_undef,
|
||||
GR32:$src, x86_subreg_32bit)>;
|
||||
def : Pat<(i64 (anyext GR32:$src)),
|
||||
(INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, x86_subreg_32bit)>;
|
||||
|
||||
def : Pat<(i64 (anyext (loadi8 addr:$src))), (MOVZX64rm8 addr:$src)>;
|
||||
def : Pat<(i64 (anyext (loadi16 addr:$src))), (MOVZX64rm16 addr:$src)>;
|
||||
def : Pat<(i64 (anyext (loadi32 addr:$src))), (INSERT_SUBREG tii_impl_val_undef,
|
||||
(MOV32rm addr:$src),
|
||||
x86_subreg_32bit)>;
|
||||
def : Pat<(i64 (anyext (loadi32 addr:$src))),
|
||||
(INSERT_SUBREG (i64 (IMPLICIT_DEF)), (MOV32rm addr:$src),
|
||||
x86_subreg_32bit)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Some peepholes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
// r & (2^32-1) ==> mov32 + implicit zext
|
||||
def : Pat<(and GR64:$src, i64immFFFFFFFF),
|
||||
(INSERT_SUBREG tii_impl_val_zero,
|
||||
(MOV32rr (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)),
|
||||
(SUBREG_TO_REG (i64 0),
|
||||
(i32 (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)),
|
||||
x86_subreg_32bit)>;
|
||||
|
||||
// (shl x, 1) ==> (add x, x)
|
||||
|
@ -920,10 +920,11 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
|
||||
// Build and insert into an implicit UNDEF value. This is OK because
|
||||
// well be shifting and then extracting the lower 16-bits.
|
||||
MachineInstr *Undef = BuildMI(get(X86::IMPLICIT_DEF), leaInReg);
|
||||
|
||||
MachineInstr *Ins =
|
||||
BuildMI(get(X86::INSERT_SUBREG),leaInReg)
|
||||
.addImm(X86InstrInfo::IMPL_VAL_UNDEF)
|
||||
.addReg(Src).addImm(X86::SUBREG_16BIT);
|
||||
.addReg(leaInReg).addReg(Src).addImm(X86::SUBREG_16BIT);
|
||||
|
||||
NewMI = BuildMI(get(Opc), leaOutReg)
|
||||
.addReg(0).addImm(1 << ShAmt).addReg(leaInReg).addImm(0);
|
||||
@ -933,6 +934,7 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
.addReg(leaOutReg).addImm(X86::SUBREG_16BIT);
|
||||
Ext->copyKillDeadInfo(MI);
|
||||
|
||||
MFI->insert(MBBI, Undef);
|
||||
MFI->insert(MBBI, Ins); // Insert the insert_subreg
|
||||
LV.instructionChanged(MI, NewMI); // Update live variables
|
||||
LV.addVirtualRegisterKilled(leaInReg, NewMI);
|
||||
|
@ -30,7 +30,8 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
|
||||
R->getName() == "DECLARE" ||
|
||||
R->getName() == "EXTRACT_SUBREG" ||
|
||||
R->getName() == "INSERT_SUBREG" ||
|
||||
R->getName() == "IMPLICIT_DEF") continue;
|
||||
R->getName() == "IMPLICIT_DEF" ||
|
||||
R->getName() == "SUBREG_TO_REG") continue;
|
||||
|
||||
BitsInit *BI = R->getValueAsBitsInit("Inst");
|
||||
|
||||
@ -105,7 +106,8 @@ void CodeEmitterGen::run(std::ostream &o) {
|
||||
R->getName() == "DECLARE" ||
|
||||
R->getName() == "EXTRACT_SUBREG" ||
|
||||
R->getName() == "INSERT_SUBREG" ||
|
||||
R->getName() == "IMPLICIT_DEF") {
|
||||
R->getName() == "IMPLICIT_DEF" ||
|
||||
R->getName() == "SUBREG_TO_REG") {
|
||||
o << " 0U";
|
||||
continue;
|
||||
}
|
||||
@ -139,7 +141,8 @@ void CodeEmitterGen::run(std::ostream &o) {
|
||||
InstName == "DECLARE"||
|
||||
InstName == "EXTRACT_SUBREG" ||
|
||||
InstName == "INSERT_SUBREG" ||
|
||||
InstName == "IMPLICIT_DEF") continue;
|
||||
InstName == "IMPLICIT_DEF" ||
|
||||
InstName == "SUBREG_TO_REG") continue;
|
||||
|
||||
BitsInit *BI = R->getValueAsBitsInit("Inst");
|
||||
const std::vector<RecordVal> &Vals = R->getValues();
|
||||
|
@ -309,6 +309,11 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
|
||||
throw "Could not find 'IMPLICIT_DEF' instruction!";
|
||||
const CodeGenInstruction *IMPLICIT_DEF = &I->second;
|
||||
|
||||
I = getInstructions().find("SUBREG_TO_REG");
|
||||
if (I == Instructions.end())
|
||||
throw "Could not find 'SUBREG_TO_REG' instruction!";
|
||||
const CodeGenInstruction *SUBREG_TO_REG = &I->second;
|
||||
|
||||
// Print out the rest of the instructions now.
|
||||
NumberedInstructions.push_back(PHI);
|
||||
NumberedInstructions.push_back(INLINEASM);
|
||||
@ -317,6 +322,7 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
|
||||
NumberedInstructions.push_back(EXTRACT_SUBREG);
|
||||
NumberedInstructions.push_back(INSERT_SUBREG);
|
||||
NumberedInstructions.push_back(IMPLICIT_DEF);
|
||||
NumberedInstructions.push_back(SUBREG_TO_REG);
|
||||
for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
|
||||
if (&II->second != PHI &&
|
||||
&II->second != INLINEASM &&
|
||||
@ -324,7 +330,8 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
|
||||
&II->second != DECLARE &&
|
||||
&II->second != EXTRACT_SUBREG &&
|
||||
&II->second != INSERT_SUBREG &&
|
||||
&II->second != IMPLICIT_DEF)
|
||||
&II->second != IMPLICIT_DEF &&
|
||||
&II->second != SUBREG_TO_REG)
|
||||
NumberedInstructions.push_back(&II->second);
|
||||
}
|
||||
|
||||
|
@ -411,7 +411,8 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
|
||||
R->getName() != "DECLARE" &&
|
||||
R->getName() != "EXTRACT_SUBREG" &&
|
||||
R->getName() != "INSERT_SUBREG" &&
|
||||
R->getName() != "IMPLICIT_DEF")
|
||||
R->getName() != "IMPLICIT_DEF" &&
|
||||
R->getName() != "SUBREG_TO_REG")
|
||||
throw R->getName() + " doesn't have a field named '" +
|
||||
Val->getValue() + "'!";
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user