mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-14 13:57:51 +00:00
FP_TO_INT*_IN_MEM and x87 FP Select support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25188 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bb90a7aa7b
commit
aaca22ca91
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/GlobalValue.h"
|
#include "llvm/GlobalValue.h"
|
||||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
@ -550,6 +551,63 @@ SDOperand X86DAGToDAGISel::Select(SDOperand N) {
|
|||||||
return CodeGenMap[N] = CurDAG->getTargetNode(Opc, VT, Result);
|
return CodeGenMap[N] = CurDAG->getTargetNode(Opc, VT, Result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case X86ISD::FP_TO_INT16_IN_MEM:
|
||||||
|
case X86ISD::FP_TO_INT32_IN_MEM:
|
||||||
|
case X86ISD::FP_TO_INT64_IN_MEM: {
|
||||||
|
assert(N.getOperand(1).getValueType() == MVT::f64);
|
||||||
|
|
||||||
|
// Change the floating point control register to use "round towards zero"
|
||||||
|
// mode when truncating to an integer value.
|
||||||
|
MachineFunction &MF = CurDAG->getMachineFunction();
|
||||||
|
int CWFI = MF.getFrameInfo()->CreateStackObject(2, 2);
|
||||||
|
SDOperand CWSlot = CurDAG->getFrameIndex(CWFI, MVT::i32);
|
||||||
|
SDOperand Base, Scale, Index, Disp;
|
||||||
|
(void)SelectAddr(CWSlot, Base, Scale, Index, Disp);
|
||||||
|
SDOperand Chain = N.getOperand(0);
|
||||||
|
|
||||||
|
// Save the control word.
|
||||||
|
Chain = CurDAG->getTargetNode(X86::FNSTCW16m, MVT::Other,
|
||||||
|
Base, Scale, Index, Disp, Chain);
|
||||||
|
|
||||||
|
// Load the old value of the high byte of the control word.
|
||||||
|
SDOperand OldCW =
|
||||||
|
CurDAG->getTargetNode(X86::MOV16rm, MVT::i16, MVT::Other,
|
||||||
|
Base, Scale, Index, Disp, Chain);
|
||||||
|
Chain = OldCW.getValue(1);
|
||||||
|
|
||||||
|
// Set the high part to be round to zero...
|
||||||
|
Chain = CurDAG->getTargetNode(X86::MOV16mi, MVT::Other,
|
||||||
|
Base, Scale, Index, Disp,
|
||||||
|
CurDAG->getConstant(0xC7F, MVT::i16),
|
||||||
|
Chain);
|
||||||
|
|
||||||
|
// Reload the modified control word now...
|
||||||
|
Chain = CurDAG->getTargetNode(X86::FLDCW16m, MVT::Other,
|
||||||
|
Base, Scale, Index, Disp, Chain);
|
||||||
|
|
||||||
|
// Restore the memory image of control word to original value
|
||||||
|
Chain = CurDAG->getTargetNode(X86::MOV16mr, MVT::Other,
|
||||||
|
Base, Scale, Index, Disp, OldCW, Chain);
|
||||||
|
|
||||||
|
switch (Opcode) {
|
||||||
|
case X86ISD::FP_TO_INT16_IN_MEM: Opc = X86::FpIST16m; break;
|
||||||
|
case X86ISD::FP_TO_INT32_IN_MEM: Opc = X86::FpIST32m; break;
|
||||||
|
case X86ISD::FP_TO_INT64_IN_MEM: Opc = X86::FpIST64m; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand N1 = Select(N.getOperand(1));
|
||||||
|
SDOperand Base2, Scale2, Index2, Disp2;
|
||||||
|
(void)SelectAddr(N.getOperand(2), Base2, Scale2, Index2, Disp2);
|
||||||
|
Chain = CurDAG->getTargetNode(Opc, MVT::Other,
|
||||||
|
Base2, Scale2, Index2, Disp2, N1, Chain);
|
||||||
|
|
||||||
|
// Reload the modified control word now...
|
||||||
|
CodeGenMap[N] =
|
||||||
|
Chain = CurDAG->getTargetNode(X86::FLDCW16m, MVT::Other,
|
||||||
|
Base, Scale, Index, Disp, Chain);
|
||||||
|
return Chain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SelectCode(N);
|
return SelectCode(N);
|
||||||
|
@ -1192,6 +1192,26 @@ static unsigned CCToX86CondCode(SDOperand CC, bool isFP) {
|
|||||||
return X86CC;
|
return X86CC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SupportedByFPCMOV - is there a floating point cmov for the specific
|
||||||
|
/// X86 condition code.
|
||||||
|
/// Current x86 isa includes the following FP cmov instructions:
|
||||||
|
/// fcmovb, fcomvbe, fcomve, fcmovu, fcmovae, fcmova, fcmovne, fcmovnu.
|
||||||
|
static bool SupportedByFPCMOV(unsigned X86CC) {
|
||||||
|
switch (X86CC) {
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
case X86ISD::COND_B:
|
||||||
|
case X86ISD::COND_BE:
|
||||||
|
case X86ISD::COND_E:
|
||||||
|
case X86ISD::COND_P:
|
||||||
|
case X86ISD::COND_A:
|
||||||
|
case X86ISD::COND_AE:
|
||||||
|
case X86ISD::COND_NE:
|
||||||
|
case X86ISD::COND_NP:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
///
|
///
|
||||||
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||||
@ -1444,21 +1464,32 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ISD::SELECT: {
|
case ISD::SELECT: {
|
||||||
SDOperand Cond = Op.getOperand(0);
|
MVT::ValueType VT = Op.getValueType();
|
||||||
SDOperand CC;
|
bool isFP = MVT::isFloatingPoint(VT);
|
||||||
if (Cond.getOpcode() == X86ISD::SETCC) {
|
bool isFPStack = isFP && (X86Vector < SSE2);
|
||||||
CC = Cond.getOperand(0);
|
bool isFPSSE = isFP && (X86Vector >= SSE2);
|
||||||
Cond = Cond.getOperand(1);
|
bool isValid = false;
|
||||||
} else if (Cond.getOpcode() == ISD::SETCC) {
|
SDOperand Op0 = Op.getOperand(0);
|
||||||
CC = Cond.getOperand(2);
|
SDOperand Cond, CC;
|
||||||
bool isFP = MVT::isFloatingPoint(Cond.getOperand(1).getValueType());
|
if (Op0.getOpcode() == X86ISD::SETCC) {
|
||||||
|
CC = Op0.getOperand(0);
|
||||||
|
Cond = Op0.getOperand(1);
|
||||||
|
isValid =
|
||||||
|
!(isFPStack &&
|
||||||
|
!SupportedByFPCMOV(cast<ConstantSDNode>(CC)->getSignExtended()));
|
||||||
|
} else if (Op0.getOpcode() == ISD::SETCC) {
|
||||||
|
CC = Op0.getOperand(2);
|
||||||
|
bool isFP = MVT::isFloatingPoint(Op0.getOperand(1).getValueType());
|
||||||
unsigned X86CC = CCToX86CondCode(CC, isFP);
|
unsigned X86CC = CCToX86CondCode(CC, isFP);
|
||||||
CC = DAG.getConstant(X86CC, MVT::i8);
|
CC = DAG.getConstant(X86CC, MVT::i8);
|
||||||
Cond = DAG.getNode(X86ISD::CMP, MVT::Flag,
|
Cond = DAG.getNode(X86ISD::CMP, MVT::Flag,
|
||||||
Cond.getOperand(0), Cond.getOperand(1));
|
Op0.getOperand(0), Op0.getOperand(1));
|
||||||
} else {
|
isValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
CC = DAG.getConstant(X86ISD::COND_E, MVT::i8);
|
CC = DAG.getConstant(X86ISD::COND_E, MVT::i8);
|
||||||
Cond = DAG.getNode(X86ISD::TEST, MVT::Flag, Cond, Cond);
|
Cond = DAG.getNode(X86ISD::TEST, MVT::Flag, Op0, Op0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MVT::ValueType> Tys;
|
std::vector<MVT::ValueType> Tys;
|
||||||
|
@ -377,6 +377,13 @@ def IMPLICIT_DEF_R16 : I<0, Pseudo, (ops R16:$dst),
|
|||||||
def IMPLICIT_DEF_R32 : I<0, Pseudo, (ops R32:$dst),
|
def IMPLICIT_DEF_R32 : I<0, Pseudo, (ops R32:$dst),
|
||||||
"#IMPLICIT_DEF $dst",
|
"#IMPLICIT_DEF $dst",
|
||||||
[(set R32:$dst, (undef))]>;
|
[(set R32:$dst, (undef))]>;
|
||||||
|
def IMPLICIT_DEF_FR32 : I<0, Pseudo, (ops FR32:$dst),
|
||||||
|
"#IMPLICIT_DEF $dst",
|
||||||
|
[(set FR32:$dst, (undef))]>, Requires<[HasSSE2]>;
|
||||||
|
def IMPLICIT_DEF_FR64 : I<0, Pseudo, (ops FR64:$dst),
|
||||||
|
"#IMPLICIT_DEF $dst",
|
||||||
|
[(set FR64:$dst, (undef))]>, Requires<[HasSSE2]>;
|
||||||
|
|
||||||
|
|
||||||
let isTerminator = 1 in
|
let isTerminator = 1 in
|
||||||
let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
|
let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
|
||||||
@ -2687,14 +2694,30 @@ def FTST : FPI<0xE4, RawFrm, (ops), "ftst">, D9;
|
|||||||
|
|
||||||
// Floating point cmovs.
|
// Floating point cmovs.
|
||||||
let isTwoAddress = 1 in {
|
let isTwoAddress = 1 in {
|
||||||
def FpCMOVB : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
def FpCMOVB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
def FpCMOVBE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
def FpCMOVE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
X86_COND_B, STATUS))]>;
|
||||||
def FpCMOVP : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
def FpCMOVBE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
def FpCMOVAE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
def FpCMOVA : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
X86_COND_BE, STATUS))]>;
|
||||||
def FpCMOVNE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
def FpCMOVE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
def FpCMOVNP : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>;
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
|
X86_COND_E, STATUS))]>;
|
||||||
|
def FpCMOVP : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
|
X86_COND_P, STATUS))]>;
|
||||||
|
def FpCMOVAE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
|
X86_COND_AE, STATUS))]>;
|
||||||
|
def FpCMOVA : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
|
X86_COND_A, STATUS))]>;
|
||||||
|
def FpCMOVNE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
|
X86_COND_NE, STATUS))]>;
|
||||||
|
def FpCMOVNP : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
|
||||||
|
[(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
|
||||||
|
X86_COND_NP, STATUS))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
def FCMOVB : FPI<0xC0, AddRegFrm, (ops RST:$op),
|
def FCMOVB : FPI<0xC0, AddRegFrm, (ops RST:$op),
|
||||||
@ -2866,8 +2889,6 @@ def : Pat<(X86fst RFP:$src, addr:$op, f64), (FpST64m addr:$op, RFP:$src)>;
|
|||||||
def : Pat<(f64 fp64immneg0), (FpCHS (FpLD0))>, Requires<[FPStack]>;
|
def : Pat<(f64 fp64immneg0), (FpCHS (FpLD0))>, Requires<[FPStack]>;
|
||||||
def : Pat<(f64 fp64immneg1), (FpCHS (FpLD1))>, Requires<[FPStack]>;
|
def : Pat<(f64 fp64immneg1), (FpCHS (FpLD1))>, Requires<[FPStack]>;
|
||||||
|
|
||||||
// FR64 undef
|
|
||||||
def : Pat<(f64 (undef)), (FLD0SD)>, Requires<[HasSSE2]>;
|
|
||||||
// RFP undef
|
// RFP undef
|
||||||
def : Pat<(f64 (undef)), (FpLD0)>, Requires<[FPStack]>;
|
def : Pat<(f64 (undef)), (FpLD0)>, Requires<[FPStack]>;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user