diff options
-rw-r--r-- | include/llvm/Target/TargetInstrInfo.h | 10 | ||||
-rw-r--r-- | lib/CodeGen/LowerSubregs.cpp | 24 | ||||
-rw-r--r-- | lib/Target/TargetSelectionDAG.td | 7 | ||||
-rw-r--r-- | lib/Target/X86/X86ATTAsmPrinter.cpp | 8 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelDAGToDAG.cpp | 7 | ||||
-rw-r--r-- | lib/Target/X86/X86Instr64bit.td | 43 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.cpp | 6 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.h | 10 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 4 | ||||
-rw-r--r-- | lib/Target/X86/X86IntelAsmPrinter.cpp | 8 | ||||
-rw-r--r-- | utils/TableGen/DAGISelEmitter.cpp | 17 |
11 files changed, 65 insertions, 79 deletions
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 75260878dd..d19ca12420 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -51,6 +51,15 @@ public: EXTRACT_SUBREG = 4, INSERT_SUBREG = 5 }; + + // 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 + }; unsigned getNumOpcodes() const { return NumOpcodes; } @@ -120,7 +129,6 @@ public: return false; } - /// convertToThreeAddress - This method must be implemented by targets that /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target /// may be able to convert a two-address instruction into one or more true diff --git a/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp index 531713e47f..8945dd57b1 100644 --- a/lib/CodeGen/LowerSubregs.cpp +++ b/lib/CodeGen/LowerSubregs.cpp @@ -96,13 +96,10 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { (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 = 0; - // Check if we're inserting into an implicit value. - if (MI->getOperand(1).isImmediate()) - SrcReg = DstReg; - else - SrcReg = MI->getOperand(1).getReg(); + unsigned SrcReg = isImplicit ? DstReg : MI->getOperand(1).getReg(); unsigned InsReg = MI->getOperand(2).getReg(); unsigned SubIdx = MI->getOperand(3).getImm(); @@ -118,13 +115,20 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { 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) { - if (MI->getOperand(1).isKill()) { + if (revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) { + if (isImplicit || MI->getOperand(1).isKill()) { DstSubReg = TRI.getSubReg(SrcReg, SubIdx); // Insert sub-register copy const TargetRegisterClass *TRC1 = 0; @@ -144,7 +148,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { } } #ifndef NDEBUG - if (InsReg == DstSubReg) { + if (InsReg == DstSubReg && !copyHasSideAffects) { DOUT << "subreg: Eliminated subreg copy\n"; } #endif @@ -174,7 +178,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { } #endif - if (!revCopyOrder && InsReg != DstSubReg) { + if (!revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) { // Insert sub-register copy const TargetRegisterClass *TRC1 = 0; if (TargetRegisterInfo::isPhysicalRegister(InsReg)) { diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td index dc0fcb5443..73280f3f6f 100644 --- a/lib/Target/TargetSelectionDAG.td +++ b/lib/Target/TargetSelectionDAG.td @@ -919,5 +919,10 @@ 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)>; diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index 4fef3827e3..e51e065540 100644 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -637,14 +637,6 @@ bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { ++EmittedInsts; - // See if a truncate instruction can be turned into a nop. - switch (MI->getOpcode()) { - default: break; - case X86::PsMOVZX64rr32: - O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t"; - break; - } - // Call the autogenerated instruction printer routines. printInstruction(MI); } diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index d5601b74ea..bf233bfcbb 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1533,14 +1533,9 @@ 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); break; case MVT::i16: SRIdx = CurDAG->getTargetConstant(X86::SUBREG_16BIT, MVT::i32); @@ -1552,6 +1547,8 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) { 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); diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 3002b2c210..d5a9f0bc66 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -1089,22 +1089,6 @@ def Int_CVTTSS2SI64rm: RSSI<0x2C, MRMSrcMem, (outs GR64:$dst), (ins f32mem:$src) // Alias Instructions //===----------------------------------------------------------------------===// -// Zero-extension -// TODO: Remove this after proper i32 -> i64 zext support. -def PsMOVZX64rr32: I<0x89, MRMDestReg, (outs GR64:$dst), (ins GR32:$src), - "mov{l}\t{$src, ${dst:subreg32}|${dst:subreg32}, $src}", - [(set GR64:$dst, (zext GR32:$src))]>; -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))]>; - - // 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 // encoding. @@ -1220,27 +1204,48 @@ def : Pat<(X86tcret (i64 texternalsym:$dst), imm:$off), def : Pat<(parallel (X86cmp GR64:$src1, 0), (implicit EFLAGS)), (TEST64rr GR64:$src1, GR64:$src1)>; + + +// Zero-extension +def : Pat<(i64 (zext GR32:$src)), (INSERT_SUBREG tii_impl_val_zero, + 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)>; + // 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), (PsMOVZX64rm32 addr:$src)>; +def : Pat<(extloadi64i32 addr:$src), (INSERT_SUBREG tii_impl_val_undef, + (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)), (PsMOVZX64rr32 GR32:$src)>; +def : Pat<(i64 (anyext GR32:$src)), (INSERT_SUBREG tii_impl_val_undef, + 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))), (PsMOVZX64rm32 addr:$src)>; +def : Pat<(i64 (anyext (loadi32 addr:$src))), (INSERT_SUBREG tii_impl_val_undef, + (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)), + x86_subreg_32bit)>; + // (shl x, 1) ==> (add x, x) def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 8497fe3039..ff666ff3c2 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -392,7 +392,6 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::PSHUFDri, X86::PSHUFDmi }, { X86::PSHUFHWri, X86::PSHUFHWmi }, { X86::PSHUFLWri, X86::PSHUFLWmi }, - { X86::PsMOVZX64rr32, X86::PsMOVZX64rm32 }, { X86::RCPPSr, X86::RCPPSm }, { X86::RCPPSr_Int, X86::RCPPSm_Int }, { X86::RSQRTPSr, X86::RSQRTPSm }, @@ -922,8 +921,9 @@ 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 *Ins = - BuildMI(get(X86::INSERT_SUBREG),leaInReg).addImm(X86::IMPL_VAL_UNDEF) - .addReg(Src).addImm(X86::SUBREG_16BIT); + BuildMI(get(X86::INSERT_SUBREG),leaInReg) + .addImm(X86InstrInfo::IMPL_VAL_UNDEF) + .addReg(Src).addImm(X86::SUBREG_16BIT); NewMI = BuildMI(get(Opc), leaOutReg) .addReg(0).addImm(1 << ShAmt).addReg(leaInReg).addImm(0); diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index e0d0342ae6..f4cdb70695 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -45,15 +45,7 @@ namespace X86 { COND_S = 15, 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 4d03dba32d..e32fb9c4b5 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -161,10 +161,6 @@ 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/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp index 6c46b45456..16d819a3d7 100644 --- a/lib/Target/X86/X86IntelAsmPrinter.cpp +++ b/lib/Target/X86/X86IntelAsmPrinter.cpp @@ -314,14 +314,6 @@ bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { ++EmittedInsts; - // See if a truncate instruction can be turned into a nop. - switch (MI->getOpcode()) { - default: break; - case X86::PsMOVZX64rr32: - O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t"; - break; - } - // Call the autogenerated instruction printer routines. printInstruction(MI); } diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 291a913c37..0c6afab4c9 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -975,9 +975,9 @@ public: } } - // Generate MemOperandSDNodes nodes for each memory accesses covered by this - // pattern. - if (isRoot) { + // Generate MemOperandSDNodes nodes for each memory accesses covered by + // this pattern. + if (II.isSimpleLoad | II.mayLoad | II.mayStore) { std::vector<std::string>::const_iterator mi, mie; for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) { emitCode("SDOperand LSI_" + *mi + " = " @@ -1880,14 +1880,9 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { << " SDOperand Tmp = CurDAG->getTargetConstant(C, MVT::i32);\n" << " AddToISelQueue(N1);\n" << " SDOperand Ops[] = { N0, N1, Tmp };\n" - << " if (N0.getOpcode() == ISD::UNDEF) {\n" - << " return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n" - << " N.getValueType(), Ops+1, 2);\n" - << " } else {\n" - << " AddToISelQueue(N0);\n" - << " return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n" - << " N.getValueType(), Ops, 3);\n" - << " }\n" + << " AddToISelQueue(N0);\n" + << " return CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG,\n" + << " N.getValueType(), Ops, 3);\n" << "}\n\n"; OS << "// The main instruction selector code.\n" |