From e3413160ca2fb42854b2a23be6b2114c1da2778c Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 9 Jan 2006 18:33:28 +0000 Subject: [PATCH] Support for ADD_PARTS, SUB_PARTS, SHL_PARTS, SHR_PARTS, and SRA_PARTS. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25158 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 126 +++++++++++++- lib/Target/X86/X86ISelLowering.h | 21 ++- lib/Target/X86/X86InstrInfo.td | 263 +++++++++++++++++++---------- lib/Target/X86/X86RegisterInfo.cpp | 2 - 4 files changed, 311 insertions(+), 101 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8a98d5c940a..fe6b9d00d95 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -133,6 +133,12 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::RET , MVT::Other, Custom); // Darwin ABI issue. setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom); + // 64-bit addm sub, shl, sra, srl (iff 32-bit x86) + setOperationAction(ISD::ADD_PARTS , MVT::i32 , Custom); + setOperationAction(ISD::SUB_PARTS , MVT::i32 , Custom); + setOperationAction(ISD::SHL_PARTS , MVT::i32 , Custom); + setOperationAction(ISD::SRA_PARTS , MVT::i32 , Custom); + setOperationAction(ISD::SRL_PARTS , MVT::i32 , Custom); } // We don't have line number support yet. @@ -243,13 +249,13 @@ SDOperand X86TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op, case MVT::f32: case MVT::f64: if (!X86ScalarSSE) { + if (OpVT == MVT::f32) + Op = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Op); std::vector Tys; Tys.push_back(MVT::Other); Tys.push_back(MVT::Flag); std::vector Ops; Ops.push_back(Chain); - if (OpVT == MVT::f32) - Op = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Op); Ops.push_back(Op); Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops); } else { @@ -476,7 +482,6 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy, std::vector NodeTys; NodeTys.push_back(MVT::Other); // Returns a chain NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. - std::vector Ops; Ops.push_back(Chain); Ops.push_back(Callee); @@ -991,7 +996,6 @@ X86TargetLowering::LowerFastCCCallTo(SDOperand Chain, const Type *RetTy, std::vector NodeTys; NodeTys.push_back(MVT::Other); // Returns a chain NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. - std::vector Ops; Ops.push_back(Chain); Ops.push_back(Callee); @@ -1193,6 +1197,99 @@ static unsigned CCToX86CondCode(SDOperand CC, bool isFP) { SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Should not custom lower this!"); + case ISD::ADD_PARTS: + case ISD::SUB_PARTS: { + assert(Op.getNumOperands() == 4 && Op.getValueType() == MVT::i32 && + "Not an i64 add/sub!"); + bool isAdd = Op.getOpcode() == ISD::ADD_PARTS; + std::vector Tys; + Tys.push_back(MVT::i32); + Tys.push_back(MVT::Flag); + std::vector Ops; + Ops.push_back(Op.getOperand(0)); + Ops.push_back(Op.getOperand(2)); + SDOperand Lo = DAG.getNode(isAdd ? X86ISD::ADD_FLAG : X86ISD::SUB_FLAG, + Tys, Ops); + SDOperand Hi = DAG.getNode(isAdd ? X86ISD::ADC : X86ISD::SBB, MVT::i32, + Op.getOperand(1), Op.getOperand(3), + Lo.getValue(1)); + Tys.clear(); + Tys.push_back(MVT::i32); + Tys.push_back(MVT::i32); + Ops.clear(); + Ops.push_back(Lo); + Ops.push_back(Hi); + return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops); + } + case ISD::SHL_PARTS: + case ISD::SRA_PARTS: + case ISD::SRL_PARTS: { + assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 && + "Not an i64 shift!"); + bool isSRA = Op.getOpcode() == ISD::SRA_PARTS; + SDOperand ShOpLo = Op.getOperand(0); + SDOperand ShOpHi = Op.getOperand(1); + SDOperand ShAmt = Op.getOperand(2); + SDOperand Tmp1 = isSRA ? DAG.getNode(ISD::SRA, MVT::i32, ShOpHi, + DAG.getConstant(32, MVT::i32)) + : DAG.getConstant(0, MVT::i32); + + SDOperand Tmp2, Tmp3; + if (Op.getOpcode() == ISD::SHL_PARTS) { + Tmp2 = DAG.getNode(X86ISD::SHLD, MVT::i32, ShOpHi, ShOpLo, ShAmt); + Tmp3 = DAG.getNode(ISD::SHL, MVT::i32, ShOpLo, ShAmt); + } else { + Tmp2 = DAG.getNode(X86ISD::SHRD, MVT::i32, ShOpLo, ShOpHi, ShAmt); + Tmp3 = DAG.getNode(isSRA ? ISD::SRA : ISD::SHL, MVT::i32, ShOpHi, ShAmt); + } + + SDOperand InFlag = DAG.getNode(X86ISD::TEST, MVT::Flag, + ShAmt, DAG.getConstant(32, MVT::i8)); + + SDOperand Hi, Lo; + SDOperand CC = DAG.getConstant(X86ISD::COND_E, MVT::i8); + + std::vector Tys; + Tys.push_back(MVT::i32); + Tys.push_back(MVT::Flag); + std::vector Ops; + if (Op.getOpcode() == ISD::SHL_PARTS) { + Ops.push_back(Tmp2); + Ops.push_back(Tmp3); + Ops.push_back(CC); + Ops.push_back(InFlag); + Hi = DAG.getNode(X86ISD::CMOV, Tys, Ops); + InFlag = Hi.getValue(1); + + Ops.clear(); + Ops.push_back(Tmp3); + Ops.push_back(Tmp1); + Ops.push_back(CC); + Ops.push_back(InFlag); + Lo = DAG.getNode(X86ISD::CMOV, Tys, Ops); + } else { + Ops.push_back(Tmp2); + Ops.push_back(Tmp3); + Ops.push_back(CC); + Lo = DAG.getNode(X86ISD::CMOV, Tys, Ops); + InFlag = Lo.getValue(1); + + Ops.clear(); + Ops.push_back(Tmp3); + Ops.push_back(Tmp1); + Ops.push_back(CC); + Ops.push_back(InFlag); + Hi = DAG.getNode(X86ISD::CMOV, Tys, Ops); + } + + Tys.clear(); + Tys.push_back(MVT::i32); + Tys.push_back(MVT::i32); + Ops.clear(); + Ops.push_back(Lo); + Ops.push_back(Hi); + return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops); + } case ISD::SINT_TO_FP: { assert(Op.getValueType() == MVT::f64 && Op.getOperand(0).getValueType() == MVT::i64 && @@ -1362,8 +1459,16 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { CC = DAG.getConstant(X86ISD::COND_E, MVT::i8); Cond = DAG.getNode(X86ISD::TEST, MVT::Flag, Cond, Cond); } - return DAG.getNode(X86ISD::CMOV, Op.getValueType(), - Op.getOperand(1), Op.getOperand(2), CC, Cond); + + std::vector Tys; + Tys.push_back(Op.getValueType()); + Tys.push_back(MVT::Flag); + std::vector Ops; + Ops.push_back(Op.getOperand(1)); + Ops.push_back(Op.getOperand(2)); + Ops.push_back(CC); + Ops.push_back(Cond); + return DAG.getNode(X86ISD::CMOV, Tys, Ops); } case ISD::BRCOND: { SDOperand Cond = Op.getOperand(1); @@ -1389,7 +1494,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { } case ISD::RET: { // Can only be return void. - return DAG.getNode(X86ISD::RET, MVT::Other, Op.getOperand(0), + return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Op.getOperand(0), DAG.getConstant(getBytesToPopOnReturn(), MVT::i16)); } case ISD::GlobalAddress: { @@ -1414,6 +1519,12 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { default: return NULL; + case X86ISD::ADD_FLAG: return "X86ISD::ADD_FLAG"; + case X86ISD::SUB_FLAG: return "X86ISD::SUB_FLAG"; + case X86ISD::ADC: return "X86ISD::ADC"; + case X86ISD::SBB: return "X86ISD::SBB"; + case X86ISD::SHLD: return "X86ISD::SHLD"; + case X86ISD::SHRD: return "X86ISD::SHRD"; case X86ISD::FILD64m: return "X86ISD::FILD64m"; case X86ISD::FP_TO_INT16_IN_MEM: return "X86ISD::FP_TO_INT16_IN_MEM"; case X86ISD::FP_TO_INT32_IN_MEM: return "X86ISD::FP_TO_INT32_IN_MEM"; @@ -1430,7 +1541,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::SETCC: return "X86ISD::SETCC"; case X86ISD::CMOV: return "X86ISD::CMOV"; case X86ISD::BRCOND: return "X86ISD::BRCOND"; - case X86ISD::RET: return "X86ISD::RET"; case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG"; } } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 440f635fd00..c3d7ae06c20 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -25,6 +25,21 @@ namespace llvm { // Start the numbering where the builtin ops leave off. FIRST_NUMBER = ISD::BUILTIN_OP_END+X86::INSTRUCTION_LIST_END, + /// ADD_FLAG, SUB_FLAG - Same as ISD::ADD and ISD::SUB except it also + /// produces a flag result. + ADD_FLAG, + SUB_FLAG, + + /// ADC, SBB - Add with carry and subtraction with borrow. These + /// correspond to X86::ADCxx and X86::SBBxx instructions. + ADC, + SBB, + + /// SHLD, SHRD - Double shift instructions. These correspond to + /// X86::SHLDxx and X86::SHRDxx instructions. + SHLD, + SHRD, + /// FILD64m - This instruction implements SINT_TO_FP with a /// 64-bit source in memory and a FP reg result. This corresponds to /// the X86::FILD64m instruction. It has two inputs (token chain and @@ -99,7 +114,7 @@ namespace llvm { /// X86 conditional moves. Operand 1 and operand 2 are the two values /// to select from (operand 1 is a R/W operand). Operand 3 is the condition /// code, and operand 4 is the flag operand produced by a CMP or TEST - /// instruction. + /// instruction. It also writes a flag result. CMOV, /// X86 conditional branches. Operand 1 is the chain operand, operand 2 @@ -108,10 +123,6 @@ namespace llvm { /// or TEST instruction. BRCOND, - /// Return without a flag operand. Operand 1 is the number of bytes of - /// stack to pop, and operand 2 is the chain. - RET, - /// Return with a flag operand. Operand 1 is the number of bytes of stack /// to pop, operand 2 is the chain and operand 3 is a flag operand. RET_FLAG, diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index d38840083db..23bee2e972d 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -17,6 +17,10 @@ // X86 specific DAG Nodes. // +def SDTIntShiftDOp: SDTypeProfile<1, 3, + [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, + SDTCisInt<0>, SDTCisInt<3>]>; + def SDTX86CmpTest : SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisSameAs<1, 2>]>; def SDTX86Cmov : SDTypeProfile<1, 4, @@ -33,43 +37,67 @@ def SDTX86SetCC : SDTypeProfile<1, 2, def SDTX86Ret : SDTypeProfile<0, 1, [SDTCisVT<0, i16>]>; +def SDT_X86CallSeqStart : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>; +def SDT_X86CallSeqEnd : SDTypeProfile<0, 2, [ SDTCisVT<0, i32>, + SDTCisVT<1, i32> ]>; + +def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; + +def SDTX86FpGet : SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>; +def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>; + def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; +def SDTX86RdTsc : SDTypeProfile<0, 0, []>; -def SDTX86FpGet : SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>; -def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>; +def X86addflag : SDNode<"X86ISD::ADD_FLAG", SDTIntBinOp , + [SDNPCommutative, SDNPAssociative, SDNPOutFlag]>; +def X86subflag : SDNode<"X86ISD::SUB_FLAG", SDTIntBinOp, + [SDNPOutFlag]>; +def X86adc : SDNode<"X86ISD::ADC" , SDTIntBinOp , + [SDNPCommutative, SDNPAssociative]>; +def X86sbb : SDNode<"X86ISD::SBB" , SDTIntBinOp>; + +def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; +def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>; def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>; -def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>; -def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>; +def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, + [SDNPOutFlag]>; +def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, + [SDNPHasChain]>; def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC, []>; -def X86ret : SDNode<"X86ISD::RET", SDTX86Ret, [SDNPHasChain]>; -def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, [SDNPHasChain]>; +def X86retflag : SDNode<"X86ISD::RET_FLAG", SDTX86Ret, + [SDNPHasChain, SDNPOptInFlag]>; -def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, [SDNPHasChain]>; -def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, [SDNPHasChain]>; +def X86callseq_start : + SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, + [SDNPHasChain]>; +def X86callseq_end : + SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, + [SDNPHasChain]>; -def X86fpget : SDNode<"X86ISD::FP_GET_RESULT", - SDTX86FpGet, [SDNPHasChain]>; -def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", - SDTX86FpSet, [SDNPHasChain]>; +def X86call : SDNode<"X86ISD::CALL", SDT_X86Call, + [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>; -def SDT_X86CallSeqStart : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>; -def SDT_X86CallSeqEnd : SDTypeProfile<0, 2, [ SDTCisVT<0, i32>, - SDTCisVT<1, i32> ]>; -def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_X86CallSeqStart, - [SDNPHasChain]>; -def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_X86CallSeqEnd, - [SDNPHasChain]>; +def X86fpget : SDNode<"X86ISD::FP_GET_RESULT", SDTX86FpGet, + [SDNPHasChain, SDNPInFlag]>; +def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", SDTX86FpSet, + [SDNPHasChain, SDNPOutFlag]>; -def SDT_X86Call : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; -def call : SDNode<"X86ISD::CALL", SDT_X86Call, [SDNPHasChain]>; +def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, + [SDNPHasChain]>; +def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, + [SDNPHasChain]>; + +def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc, + [SDNPHasChain, SDNPOutFlag]>; //===----------------------------------------------------------------------===// // X86 Operand Definitions. @@ -334,10 +362,10 @@ def PHI : I<0, Pseudo, (ops variable_ops), "PHINODE", []>; // PHI node. def NOOP : I<0x90, RawFrm, (ops), "nop", []>; // nop def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN", - [(callseq_start imm:$amt)]>; + [(X86callseq_start imm:$amt)]>; def ADJCALLSTACKUP : I<0, Pseudo, (ops i32imm:$amt1, i32imm:$amt2), "#ADJCALLSTACKUP", - [(callseq_end imm:$amt1, imm:$amt2)]>; + [(X86callseq_end imm:$amt1, imm:$amt2)]>; def IMPLICIT_USE : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_USE", []>; def IMPLICIT_DEF : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_DEF", []>; let isTerminator = 1 in @@ -351,15 +379,9 @@ let isTerminator = 1 in // Return instructions. let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1, noResults = 1 in { - // FIXME: temporary workaround for return without an incoming flag. - def RETVOID : I<0xC3, RawFrm, (ops), "ret", [(X86ret 0)]>; - def RETIVOID : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", - [(X86ret imm:$amt)]>; - let hasInFlag = 1 in { - def RET : I<0xC3, RawFrm, (ops), "ret", [(X86retflag 0)]>; - def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", - [(X86retflag imm:$amt)]>; - } + def RET : I<0xC3, RawFrm, (ops), "ret", [(X86retflag 0)]>; + def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", + [(X86retflag imm:$amt)]>; } // All branches are RawFrm, Void, Branch, and Terminators @@ -404,23 +426,21 @@ def JNP : IBr<0x8B, (ops brtarget:$dst), "jnp $dst", //===----------------------------------------------------------------------===// // Call Instructions... // -// FIXME: How about hasInFlag = 1? A fastcall would require an incoming flag -// to stick the CopyToRegs to the call. -let isCall = 1, noResults = 1, hasOutFlag = 1 in +let isCall = 1, noResults = 1 in // All calls clobber the non-callee saved registers... let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7] in { def CALLpcrel32 : I<0xE8, RawFrm, (ops calltarget:$dst), "call $dst", []>; def CALL32r : I<0xFF, MRM2r, (ops R32:$dst), "call {*}$dst", - [(call R32:$dst)]>; + [(X86call R32:$dst)]>; def CALL32m : I<0xFF, MRM2m, (ops i32mem:$dst), "call {*}$dst", - [(call (loadi32 addr:$dst))]>; + [(X86call (loadi32 addr:$dst))]>; } -def : Pat<(call tglobaladdr:$dst), +def : Pat<(X86call tglobaladdr:$dst), (CALLpcrel32 tglobaladdr:$dst)>; -def : Pat<(call externalsym:$dst), +def : Pat<(X86call externalsym:$dst), (CALLpcrel32 externalsym:$dst)>; // Tail call stuff. @@ -1544,64 +1564,94 @@ let isTwoAddress = 0 in { // Double shift instructions (generalizations of rotate) def SHLD32rrCL : I<0xA5, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), - "shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(set R32:$dst, (X86shld R32:$src1, R32:$src2, CL))]>, Imp<[CL],[]>, TB; def SHRD32rrCL : I<0xAD, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), - "shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(set R32:$dst, (X86shrd R32:$src1, R32:$src2, CL))]>, Imp<[CL],[]>, TB; def SHLD16rrCL : I<0xA5, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2), - "shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(set R16:$dst, (X86shld R16:$src1, R16:$src2, CL))]>, Imp<[CL],[]>, TB, OpSize; def SHRD16rrCL : I<0xAD, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2), - "shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(set R16:$dst, (X86shrd R16:$src1, R16:$src2, CL))]>, Imp<[CL],[]>, TB, OpSize; let isCommutable = 1 in { // These instructions commute to each other. def SHLD32rri8 : Ii8<0xA4, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3), - "shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, TB; + "shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(set R32:$dst, (X86shld R32:$src1, R32:$src2, + (i8 imm:$src3)))]>, + TB; def SHRD32rri8 : Ii8<0xAC, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3), - "shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, TB; + "shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(set R32:$dst, (X86shrd R32:$src1, R32:$src2, + (i8 imm:$src3)))]>, + TB; def SHLD16rri8 : Ii8<0xA4, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2, i8imm:$src3), - "shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, + "shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(set R16:$dst, (X86shld R16:$src1, R16:$src2, + (i8 imm:$src3)))]>, TB, OpSize; def SHRD16rri8 : Ii8<0xAC, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2, i8imm:$src3), - "shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, + "shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(set R16:$dst, (X86shrd R16:$src1, R16:$src2, + (i8 imm:$src3)))]>, TB, OpSize; } let isTwoAddress = 0 in { def SHLD32mrCL : I<0xA5, MRMDestMem, (ops i32mem:$dst, R32:$src2), - "shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(store (X86shld (loadi32 addr:$dst), R32:$src2, CL), + addr:$dst)]>, Imp<[CL],[]>, TB; def SHRD32mrCL : I<0xAD, MRMDestMem, (ops i32mem:$dst, R32:$src2), - "shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(store (X86shrd (loadi32 addr:$dst), R32:$src2, CL), + addr:$dst)]>, Imp<[CL],[]>, TB; def SHLD32mri8 : Ii8<0xA4, MRMDestMem, (ops i32mem:$dst, R32:$src2, i8imm:$src3), - "shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, + "shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shld (loadi32 addr:$dst), R32:$src2, + (i8 imm:$src3)), addr:$dst)]>, TB; def SHRD32mri8 : Ii8<0xAC, MRMDestMem, (ops i32mem:$dst, R32:$src2, i8imm:$src3), - "shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, + "shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shrd (loadi32 addr:$dst), R32:$src2, + (i8 imm:$src3)), addr:$dst)]>, TB; def SHLD16mrCL : I<0xA5, MRMDestMem, (ops i16mem:$dst, R16:$src2), - "shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(store (X86shld (loadi16 addr:$dst), R16:$src2, CL), + addr:$dst)]>, Imp<[CL],[]>, TB, OpSize; def SHRD16mrCL : I<0xAD, MRMDestMem, (ops i16mem:$dst, R16:$src2), - "shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}", []>, + "shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}", + [(store (X86shrd (loadi16 addr:$dst), R16:$src2, CL), + addr:$dst)]>, Imp<[CL],[]>, TB, OpSize; def SHLD16mri8 : Ii8<0xA4, MRMDestMem, (ops i16mem:$dst, R16:$src2, i8imm:$src3), - "shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, + "shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shld (loadi16 addr:$dst), R16:$src2, + (i8 imm:$src3)), addr:$dst)]>, TB, OpSize; def SHRD16mri8 : Ii8<0xAC, MRMDestMem, (ops i16mem:$dst, R16:$src2, i8imm:$src3), - "shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}", []>, + "shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}", + [(store (X86shrd (loadi16 addr:$dst), R16:$src2, + (i8 imm:$src3)), addr:$dst)]>, TB, OpSize; } @@ -1684,22 +1734,29 @@ let isTwoAddress = 0 in { let isCommutable = 1 in { // X = ADC Y, Z --> X = ADC Z, Y def ADC32rr : I<0x11, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), - "adc{l} {$src2, $dst|$dst, $src2}", []>; + "adc{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86adc R32:$src1, R32:$src2))]>; } def ADC32rm : I<0x13, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$src2), - "adc{l} {$src2, $dst|$dst, $src2}", []>; + "adc{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86adc R32:$src1, (load addr:$src2)))]>; def ADC32ri : Ii32<0x81, MRM2r, (ops R32:$dst, R32:$src1, i32imm:$src2), - "adc{l} {$src2, $dst|$dst, $src2}", []>; -def ADC32ri8 : Ii8<0x83, MRM2r, (ops R32:$dst, R32:$src1, i8imm:$src2), - "adc{l} {$src2, $dst|$dst, $src2}", []>; + "adc{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86adc R32:$src1, imm:$src2))]>; +def ADC32ri8 : Ii8<0x83, MRM2r, (ops R32:$dst, R32:$src1, i32i8imm:$src2), + "adc{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86adc R32:$src1, i32immSExt8:$src2))]>; let isTwoAddress = 0 in { def ADC32mr : I<0x11, MRMDestMem, (ops i32mem:$dst, R32:$src2), - "adc{l} {$src2, $dst|$dst, $src2}", []>; + "adc{l} {$src2, $dst|$dst, $src2}", + [(store (X86adc (load addr:$dst), R32:$src2), addr:$dst)]>; def ADC32mi : Ii32<0x81, MRM2m, (ops i32mem:$dst, i32imm:$src2), - "adc{l} {$src2, $dst|$dst, $src2}", []>; - def ADC32mi8 : Ii8<0x83, MRM2m, (ops i32mem:$dst, i8imm :$src2), - "adc{l} {$src2, $dst|$dst, $src2}", []>; + "adc{l} {$src2, $dst|$dst, $src2}", + [(store (X86adc (loadi32 addr:$dst), imm:$src2), addr:$dst)]>; + def ADC32mi8 : Ii8<0x83, MRM2m, (ops i32mem:$dst, i32i8imm :$src2), + "adc{l} {$src2, $dst|$dst, $src2}", + [(store (X86adc (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>; } def SUB8rr : I<0x28, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2), @@ -1768,36 +1825,52 @@ let isTwoAddress = 0 in { } def SBB32rr : I<0x19, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), - "sbb{l} {$src2, $dst|$dst, $src2}", []>; + "sbb{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86sbb R32:$src1, R32:$src2))]>; let isTwoAddress = 0 in { def SBB32mr : I<0x19, MRMDestMem, (ops i32mem:$dst, R32:$src2), - "sbb{l} {$src2, $dst|$dst, $src2}", []>; + "sbb{l} {$src2, $dst|$dst, $src2}", + [(store (X86sbb (load addr:$dst), R32:$src2), addr:$dst)]>; def SBB8mi : Ii32<0x80, MRM3m, (ops i8mem:$dst, i8imm:$src2), - "sbb{b} {$src2, $dst|$dst, $src2}", []>; + "sbb{b} {$src2, $dst|$dst, $src2}", + [(store (X86sbb (loadi8 addr:$dst), imm:$src2), addr:$dst)]>; def SBB16mi : Ii32<0x81, MRM3m, (ops i16mem:$dst, i16imm:$src2), - "sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize; + "sbb{w} {$src2, $dst|$dst, $src2}", + [(store (X86sbb (loadi16 addr:$dst), imm:$src2), addr:$dst)]>, + OpSize; def SBB32mi : Ii32<0x81, MRM3m, (ops i32mem:$dst, i32imm:$src2), - "sbb{l} {$src2, $dst|$dst, $src2}", []>; - def SBB16mi8 : Ii8<0x83, MRM3m, (ops i16mem:$dst, i8imm :$src2), - "sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize; - def SBB32mi8 : Ii8<0x83, MRM3m, (ops i32mem:$dst, i8imm :$src2), - "sbb{l} {$src2, $dst|$dst, $src2}", []>; + "sbb{l} {$src2, $dst|$dst, $src2}", + [(store (X86sbb (loadi32 addr:$dst), imm:$src2), addr:$dst)]>; + def SBB16mi8 : Ii8<0x83, MRM3m, (ops i16mem:$dst, i16i8imm :$src2), + "sbb{w} {$src2, $dst|$dst, $src2}", + [(store (X86sbb (load addr:$dst), i16immSExt8:$src2), addr:$dst)]>, + OpSize; + def SBB32mi8 : Ii8<0x83, MRM3m, (ops i32mem:$dst, i32i8imm :$src2), + "sbb{l} {$src2, $dst|$dst, $src2}", + [(store (X86sbb (load addr:$dst), i32immSExt8:$src2), addr:$dst)]>; } def SBB8ri : Ii8<0x80, MRM3r, (ops R8:$dst, R8:$src1, i8imm:$src2), - "sbb{b} {$src2, $dst|$dst, $src2}", []>; + "sbb{b} {$src2, $dst|$dst, $src2}", + [(set R8:$dst, (X86sbb R8:$src1, imm:$src2))]>; def SBB16ri : Ii16<0x81, MRM3r, (ops R16:$dst, R16:$src1, i16imm:$src2), - "sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize; + "sbb{w} {$src2, $dst|$dst, $src2}", + [(set R16:$dst, (X86sbb R16:$src1, imm:$src2))]>, OpSize; def SBB32rm : I<0x1B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2), - "sbb{l} {$src2, $dst|$dst, $src2}", []>; + "sbb{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86sbb R32:$src1, (load addr:$src2)))]>; def SBB32ri : Ii32<0x81, MRM3r, (ops R32:$dst, R32:$src1, i32imm:$src2), - "sbb{l} {$src2, $dst|$dst, $src2}", []>; + "sbb{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86sbb R32:$src1, imm:$src2))]>; -def SBB16ri8 : Ii8<0x83, MRM3r, (ops R16:$dst, R16:$src1, i8imm:$src2), - "sbb{w} {$src2, $dst|$dst, $src2}", []>, OpSize; -def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i8imm:$src2), - "sbb{l} {$src2, $dst|$dst, $src2}", []>; +def SBB16ri8 : Ii8<0x83, MRM3r, (ops R16:$dst, R16:$src1, i16i8imm:$src2), + "sbb{w} {$src2, $dst|$dst, $src2}", + [(set R16:$dst, (X86sbb R16:$src1, i16immSExt8:$src2))]>, + OpSize; +def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i32i8imm:$src2), + "sbb{l} {$src2, $dst|$dst, $src2}", + [(set R32:$dst, (X86sbb R32:$src1, i32immSExt8:$src2))]>; let isCommutable = 1 in { // X = IMUL Y, Z --> X = IMUL Z, Y def IMUL16rr : I<0xAF, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2), @@ -1817,6 +1890,25 @@ def IMUL32rm : I<0xAF, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2), } // end Two Address instructions +// X86 specific add which produces a flag. +def : Pat<(X86addflag R32:$src1, R32:$src2), + (ADD32rr R32:$src1, R32:$src2)>; +def : Pat<(X86addflag R32:$src1, (load addr:$src2)), + (ADD32rm R32:$src1, addr:$src2)>; +def : Pat<(X86addflag R32:$src1, imm:$src2), + (ADD32ri R32:$src1, imm:$src2)>; +def : Pat<(X86addflag R32:$src1, i32immSExt8:$src2), + (ADD32ri8 R32:$src1, i32immSExt8:$src2)>; + +def : Pat<(X86subflag R32:$src1, R32:$src2), + (SUB32rr R32:$src1, R32:$src2)>; +def : Pat<(X86subflag R32:$src1, (load addr:$src2)), + (SUB32rm R32:$src1, addr:$src2)>; +def : Pat<(X86subflag R32:$src1, imm:$src2), + (SUB32ri R32:$src1, imm:$src2)>; +def : Pat<(X86subflag R32:$src1, i32immSExt8:$src2), + (SUB32ri8 R32:$src1, i32immSExt8:$src2)>; + // Suprisingly enough, these are not two address instructions! def IMUL16rri : Ii16<0x69, MRMSrcReg, // R16 = R16*I16 (ops R16:$dst, R16:$src1, i16imm:$src2), @@ -2471,13 +2563,12 @@ class FpI pattern> } // Random Pseudo Instructions. -let hasInFlag = 1 in - def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0) +def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, []>; // FPR = ST(0) // Do not inline into instruction def. since it isn't predicated on FPStack. def : Pat<(X86fpget), (FpGETRESULT)>; -let noResults = 1, hasOutFlag = 1 in +let noResults = 1 in def FpSETRESULT : FpI<(ops RFP:$src), SpecialFP, []>, Imp<[], [ST0]>; // ST(0) = FPR @@ -2754,8 +2845,8 @@ def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] // Miscellaneous Instructions //===----------------------------------------------------------------------===// -def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", []>, TB, Imp<[],[EAX,EDX]>; - +def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", [(X86rdtsc)]>, + TB, Imp<[],[EAX,EDX]>; //===----------------------------------------------------------------------===// // Some peepholes diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index ae82f984f07..787e562c65b 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -568,8 +568,6 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF, switch (MBBI->getOpcode()) { case X86::RET: case X86::RETI: - case X86::RETVOID: // FIXME: See X86InstrInfo.td - case X86::RETIVOID: // FIXME: See X86InstrInfo.td case X86::TAILJMPd: case X86::TAILJMPr: case X86::TAILJMPm: break; // These are ok