diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 13e242fe62a..b2c354dae1d 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -322,12 +322,9 @@ namespace ISD { // This node takes a superreg and a constant sub-register index as operands. EXTRACT_SUBREG, - // INSERT_SUBREG - This node is used to insert a sub-register value into - // either explicitly into a superreg, or implicitly into a superreg value. + // INSERT_SUBREG - This node is used to insert a sub-register value. // This node takes a superreg, a subreg value, and a constant sub-register - // index as operands. The superreg may be either a superregister operand or a - // target constant indicating that the insert is being done into a target - // specific implicit value. + // index as operands. INSERT_SUBREG, // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing diff --git a/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp index e7812d48867..232dc061e58 100644 --- a/lib/CodeGen/LowerSubregs.cpp +++ b/lib/CodeGen/LowerSubregs.cpp @@ -105,21 +105,32 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { 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).isRegister() && MI->getOperand(1).isUse()) || - MI->getOperand(1).isImmediate()) && - (MI->getOperand(2).isRegister() && MI->getOperand(2).isUse()) && - MI->getOperand(3).isImmediate() && "Invalid insert_subreg"); - - unsigned DstReg = MI->getOperand(0).getReg(); + unsigned DstReg = 0; unsigned SrcReg = 0; - // Check if we're inserting into an implicit value. - if (MI->getOperand(1).isImmediate()) + unsigned InsReg = 0; + unsigned SubIdx = 0; + + // If only have 3 operands, then the source superreg is undef + // and we can supress the copy from the undef value + if (MI->getNumOperands() == 3) { + assert((MI->getOperand(0).isRegister() && MI->getOperand(0).isDef()) && + (MI->getOperand(1).isRegister() && MI->getOperand(1).isUse()) && + MI->getOperand(2).isImmediate() && "Invalid extract_subreg"); + DstReg = MI->getOperand(0).getReg(); SrcReg = DstReg; - else + InsReg = MI->getOperand(1).getReg(); + SubIdx = MI->getOperand(2).getImm(); + } else if (MI->getNumOperands() == 4) { + assert((MI->getOperand(0).isRegister() && MI->getOperand(0).isDef()) && + (MI->getOperand(1).isRegister() && MI->getOperand(1).isUse()) && + (MI->getOperand(2).isRegister() && MI->getOperand(2).isUse()) && + MI->getOperand(3).isImmediate() && "Invalid extract_subreg"); + DstReg = MI->getOperand(0).getReg(); SrcReg = MI->getOperand(1).getReg(); - unsigned InsReg = MI->getOperand(2).getReg(); - unsigned SubIdx = MI->getOperand(3).getImm(); + InsReg = MI->getOperand(2).getReg(); + SubIdx = MI->getOperand(3).getImm(); + } else + assert(0 && "Malformed extract_subreg"); assert(SubIdx != 0 && "Invalid index for extract_subreg"); unsigned DstSubReg = TRI.getSubReg(DstReg, SubIdx); diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp index 078fa602307..31a784eca88 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp @@ -693,13 +693,19 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node, MI->addOperand(MachineOperand::CreateImm(SubIdx)); } else if (Opc == TargetInstrInfo::INSERT_SUBREG) { - assert((Node->getNumOperands() == 3) && + assert((Node->getNumOperands() == 2 || Node->getNumOperands() == 3) && "Malformed insert_subreg node"); - SDOperand N0 = Node->getOperand(0); - SDOperand N1 = Node->getOperand(1); - SDOperand N2 = Node->getOperand(2); - unsigned SubReg = getVR(N1, VRBaseMap); - unsigned SubIdx = cast(N2)->getValue(); + bool isUndefInput = (Node->getNumOperands() == 2); + unsigned SubReg = 0; + unsigned SubIdx = 0; + + if (isUndefInput) { + SubReg = getVR(Node->getOperand(0), VRBaseMap); + SubIdx = cast(Node->getOperand(1))->getValue(); + } else { + SubReg = getVR(Node->getOperand(1), VRBaseMap); + SubIdx = cast(Node->getOperand(2))->getValue(); + } // TODO: Add tracking info to MachineRegisterInfo of which vregs are subregs // to allow coalescing in the allocator @@ -737,15 +743,9 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node, } 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(N0)) - MI->addOperand(MachineOperand::CreateImm(SD->getValue())); - else - AddOperand(MI, N0, 0, 0, VRBaseMap); - // Add the subregster being inserted - AddOperand(MI, N1, 0, 0, VRBaseMap); + AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap); + if (!isUndefInput) + AddOperand(MI, Node->getOperand(1), 0, 0, VRBaseMap); MI->addOperand(MachineOperand::CreateImm(SubIdx)); } else assert(0 && "Node is not a subreg insert or extract"); diff --git a/lib/Target/Target.td b/lib/Target/Target.td index ea8f6ec3a15..cebac7a2636 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -263,10 +263,6 @@ def variable_ops; /// flags. But currently we have but one flag. def ptr_rc; -/// unknown definition - Mark this operand as being of unknown type, causing -/// it to be resolved by inference in the context it is used. -def unknown; - /// Operand Types - These provide the built-in operand types that may be used /// by a target. Targets can optionally provide their own operand types as /// needed, though this should not be needed for RISC targets. @@ -355,15 +351,15 @@ def DECLARE : Instruction { let hasCtrlDep = 1; } def EXTRACT_SUBREG : Instruction { - let OutOperandList = (ops unknown:$dst); - let InOperandList = (ops unknown:$supersrc, i32imm:$subidx); + let OutOperandList = (ops variable_ops); + let InOperandList = (ops variable_ops); let AsmString = ""; let Namespace = "TargetInstrInfo"; let neverHasSideEffects = 1; } def INSERT_SUBREG : Instruction { - let OutOperandList = (ops unknown:$dst); - let InOperandList = (ops unknown:$supersrc, unknown:$subsrc, i32imm:$subidx); + let OutOperandList = (ops variable_ops); + let InOperandList = (ops variable_ops); let AsmString = ""; let Namespace = "TargetInstrInfo"; let neverHasSideEffects = 1; diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index ac7957c07f8..6036dcbf2e0 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1491,27 +1491,22 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) { AddToISelQueue(N0); if (NVT == MVT::i64 || NVT == MVT::i32 || NVT == MVT::i16) { SDOperand SRIdx; - SDOperand ImplVal = CurDAG->getTargetConstant(X86::IMPL_VAL_UNDEF, - MVT::i32); switch(N0.getValueType()) { case MVT::i32: - SRIdx = CurDAG->getTargetConstant(X86::SUBREG_32BIT, MVT::i32); - // x86-64 zero extends 32-bit inserts int 64-bit registers - if (Subtarget->is64Bit()) - ImplVal = CurDAG->getTargetConstant(X86::IMPL_VAL_ZERO, MVT::i32); + SRIdx = CurDAG->getTargetConstant(3, MVT::i32); // SubRegSet 3 break; case MVT::i16: - SRIdx = CurDAG->getTargetConstant(X86::SUBREG_16BIT, MVT::i32); + SRIdx = CurDAG->getTargetConstant(2, MVT::i32); // SubRegSet 2 break; case MVT::i8: if (Subtarget->is64Bit()) - SRIdx = CurDAG->getTargetConstant(X86::SUBREG_8BIT, MVT::i32); + SRIdx = CurDAG->getTargetConstant(1, MVT::i32); // SubRegSet 1 break; default: assert(0 && "Unknown any_extend!"); } if (SRIdx.Val) { SDNode *ResNode = CurDAG->getTargetNode(X86::INSERT_SUBREG, - NVT, ImplVal, N0, SRIdx); + NVT, N0, SRIdx); #ifndef NDEBUG DOUT << std::string(Indent-2, ' ') << "=> "; diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 4a65dfc5ea0..3002b2c2108 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -1098,11 +1098,12 @@ def PsMOVZX64rm32: I<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src), "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}", [(set GR64:$dst, (zextloadi64i32 addr:$src))]>; -// r & (2^32-1) -def : Pat<(and GR64:$src, i64immFFFFFFFF), - (INSERT_SUBREG x86_impl_val_zero, - (MOV32rr (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)), - x86_subreg_32bit)>; +/// PsAND64rrFFFFFFFF - r = r & (2^32-1) +def PsAND64rrFFFFFFFF + : I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR64:$src), + "mov{l}\t{${src:subreg32}, ${dst:subreg32}|${dst:subreg32}, ${src:subreg32}}", + [(set GR64:$dst, (and GR64:$src, i64immFFFFFFFF))]>; + // Alias instructions that map movr0 to xor. Use xorl instead of xorq; it's // equivalent due to implicit zero-extending, and it sometimes has a smaller diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index b5881309b20..3c12fa17356 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -903,20 +903,16 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, ? X86::LEA64_32r : X86::LEA32r; unsigned leaInReg = RegInfo.createVirtualRegister(&X86::GR32RegClass); unsigned leaOutReg = RegInfo.createVirtualRegister(&X86::GR32RegClass); - - // Build and insert into an implicit UNDEF value. This is OK because - // well be shifting and then extracting the lower 16-bits. - MachineInstr *Ins = - BuildMI(get(X86::INSERT_SUBREG),leaInReg).addImm(X86::IMPL_VAL_UNDEF) - .addReg(Src).addImm(X86::SUBREG_16BIT); + + MachineInstr *Ins = + BuildMI(get(X86::INSERT_SUBREG), leaInReg).addReg(Src).addImm(2); Ins->copyKillDeadInfo(MI); NewMI = BuildMI(get(Opc), leaOutReg) .addReg(0).addImm(1 << ShAmt).addReg(leaInReg).addImm(0); MachineInstr *Ext = - BuildMI(get(X86::EXTRACT_SUBREG), Dest) - .addReg(leaOutReg).addImm(X86::SUBREG_16BIT); + BuildMI(get(X86::EXTRACT_SUBREG), Dest).addReg(leaOutReg).addImm(2); Ext->copyKillDeadInfo(MI); MFI->insert(MBBI, Ins); // Insert the insert_subreg diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index e0d0342ae6d..839a0f248b6 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -46,14 +46,6 @@ namespace X86 { COND_INVALID }; - // X86 specific implict values used for subregister inserts. - // This can be used to model the fact that x86-64 by default - // inserts 32-bit values into 64-bit registers implicitly containing zeros. - enum ImplicitVal { - IMPL_VAL_UNDEF = 0, - IMPL_VAL_ZERO = 1 - }; - // Turn condition code into conditional branch opcode. unsigned GetCondBranchFromCond(CondCode CC); diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 92027561701..223889c4089 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -161,10 +161,6 @@ def i32i8imm : Operand; // Branch targets have OtherVT type. def brtarget : Operand; -// These should match the enum X86::ImplicitVal -def x86_impl_val_undef : PatLeaf<(i32 0)>; -def x86_impl_val_zero : PatLeaf<(i32 1)>; - //===----------------------------------------------------------------------===// // X86 Complex Pattern Definitions. // diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index 1c8f5e28b99..8b010a92404 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -32,15 +32,6 @@ namespace N86 { }; } -namespace X86 { - /// SubregIndex - The index of various sized subregister classes. Note that - /// these indices must be kept in sync with the class indices in the - /// X86RegisterInfo.td file. - enum SubregIndex { - SUBREG_8BIT = 1, SUBREG_16BIT = 2, SUBREG_32BIT = 3 - }; -} - /// DWARFFlavour - Flavour of dwarf regnumbers /// namespace DWARFFlavour { diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index ab4e838c367..cb376c03cb8 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -176,10 +176,6 @@ let Namespace = "X86" in { // sub registers for each register. // -def x86_subreg_8bit : PatLeaf<(i32 1)>; -def x86_subreg_16bit : PatLeaf<(i32 2)>; -def x86_subreg_32bit : PatLeaf<(i32 3)>; - def : SubRegSet<1, [AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W], [AL, CL, DL, BL, SPL, BPL, SIL, DIL, diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index e5d70cd084e..003f108fa4c 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -872,10 +872,6 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { std::vector VT; VT.push_back(MVT::iPTR); MadeChange = UpdateNodeType(VT, TP); - } else if (ResultNode->getName() == "unknown") { - std::vector VT; - VT.push_back(MVT::isUnknown); - MadeChange = UpdateNodeType(VT, TP); } else { assert(ResultNode->isSubClassOf("RegisterClass") && "Operands should be register classes!"); @@ -914,15 +910,13 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= Child->UpdateNodeType(VT, TP); } else if (OperandNode->getName() == "ptr_rc") { MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP); - } else if (OperandNode->getName() == "unknown") { - MadeChange |= Child->UpdateNodeType(MVT::isUnknown, TP); } else { assert(0 && "Unknown operand type!"); abort(); } MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); } - + if (ChildNo != getNumChildren()) TP.error("Instruction '" + getOperator()->getName() + "' was provided too many operands!"); diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 8b706479077..0ee6b41d908 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -163,7 +163,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) isVariadic = true; continue; } else if (!Rec->isSubClassOf("RegisterClass") && - Rec->getName() != "ptr_rc" && Rec->getName() != "unknown") + Rec->getName() != "ptr_rc") throw "Unknown operand class '" + Rec->getName() + "' in instruction '" + R->getName() + "' instruction!";