diff options
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/Target.td | 12 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelDAGToDAG.cpp | 13 | ||||
-rw-r--r-- | lib/Target/X86/X86Instr64bit.td | 11 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.cpp | 12 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.h | 8 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 4 | ||||
-rw-r--r-- | lib/Target/X86/X86RegisterInfo.h | 9 | ||||
-rw-r--r-- | lib/Target/X86/X86RegisterInfo.td | 4 |
8 files changed, 55 insertions, 18 deletions
diff --git a/lib/Target/Target.td b/lib/Target/Target.td index cebac7a..ea8f6ec 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -263,6 +263,10 @@ 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. @@ -351,15 +355,15 @@ def DECLARE : Instruction { let hasCtrlDep = 1; } def EXTRACT_SUBREG : Instruction { - let OutOperandList = (ops variable_ops); - let InOperandList = (ops variable_ops); + let OutOperandList = (ops unknown:$dst); + let InOperandList = (ops unknown:$supersrc, i32imm:$subidx); let AsmString = ""; let Namespace = "TargetInstrInfo"; let neverHasSideEffects = 1; } def INSERT_SUBREG : Instruction { - let OutOperandList = (ops variable_ops); - let InOperandList = (ops variable_ops); + let OutOperandList = (ops unknown:$dst); + let InOperandList = (ops unknown:$supersrc, unknown:$subsrc, i32imm:$subidx); let AsmString = ""; let Namespace = "TargetInstrInfo"; let neverHasSideEffects = 1; diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 6036dcb..ac7957c 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1491,22 +1491,27 @@ 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(3, MVT::i32); // SubRegSet 3 + 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); break; case MVT::i16: - SRIdx = CurDAG->getTargetConstant(2, MVT::i32); // SubRegSet 2 + SRIdx = CurDAG->getTargetConstant(X86::SUBREG_16BIT, MVT::i32); break; case MVT::i8: if (Subtarget->is64Bit()) - SRIdx = CurDAG->getTargetConstant(1, MVT::i32); // SubRegSet 1 + SRIdx = CurDAG->getTargetConstant(X86::SUBREG_8BIT, MVT::i32); break; default: assert(0 && "Unknown any_extend!"); } if (SRIdx.Val) { SDNode *ResNode = CurDAG->getTargetNode(X86::INSERT_SUBREG, - NVT, N0, SRIdx); + NVT, ImplVal, N0, SRIdx); #ifndef NDEBUG DOUT << std::string(Indent-2, ' ') << "=> "; diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 3002b2c..4a65dfc 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -1098,12 +1098,11 @@ 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))]>; -/// 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))]>; - +// 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)>; // 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 3c12fa1..b588130 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -903,16 +903,20 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, ? X86::LEA64_32r : X86::LEA32r; unsigned leaInReg = RegInfo.createVirtualRegister(&X86::GR32RegClass); unsigned leaOutReg = RegInfo.createVirtualRegister(&X86::GR32RegClass); - - MachineInstr *Ins = - BuildMI(get(X86::INSERT_SUBREG), leaInReg).addReg(Src).addImm(2); + + // 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); 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(2); + BuildMI(get(X86::EXTRACT_SUBREG), Dest) + .addReg(leaOutReg).addImm(X86::SUBREG_16BIT); 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 839a0f2..e0d0342 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -46,6 +46,14 @@ 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 223889c..9202756 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -161,6 +161,10 @@ def i32i8imm : Operand<i32>; // Branch targets have OtherVT type. def brtarget : Operand<OtherVT>; +// 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 8b010a9..1c8f5e2 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -32,6 +32,15 @@ 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 cb376c0..ab4e838 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -176,6 +176,10 @@ 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, |