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
This commit is contained in:
Evan Cheng 2006-01-09 18:33:28 +00:00
parent 05a2d568c6
commit e3413160ca
4 changed files with 311 additions and 101 deletions

View File

@ -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<MVT::ValueType> Tys;
Tys.push_back(MVT::Other);
Tys.push_back(MVT::Flag);
std::vector<SDOperand> 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<MVT::ValueType> NodeTys;
NodeTys.push_back(MVT::Other); // Returns a chain
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(Callee);
@ -991,7 +996,6 @@ X86TargetLowering::LowerFastCCCallTo(SDOperand Chain, const Type *RetTy,
std::vector<MVT::ValueType> NodeTys;
NodeTys.push_back(MVT::Other); // Returns a chain
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
std::vector<SDOperand> 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<MVT::ValueType> Tys;
Tys.push_back(MVT::i32);
Tys.push_back(MVT::Flag);
std::vector<SDOperand> 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<MVT::ValueType> Tys;
Tys.push_back(MVT::i32);
Tys.push_back(MVT::Flag);
std::vector<SDOperand> 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<MVT::ValueType> Tys;
Tys.push_back(Op.getValueType());
Tys.push_back(MVT::Flag);
std::vector<SDOperand> 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";
}
}

View File

@ -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,

View File

@ -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<dag ops, FPFormat fp, list<dag> 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

View File

@ -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