From 73a1ad975e637ad72253bfc5ba65c53e004740c8 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 10 Jan 2006 20:26:56 +0000 Subject: [PATCH] FP_TO_INT*_IN_MEM and x87 FP Select support. llvm-svn: 25188 --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 58 +++++++++++++++++++++++++ llvm/lib/Target/X86/X86ISelLowering.cpp | 53 +++++++++++++++++----- llvm/lib/Target/X86/X86InstrInfo.td | 41 ++++++++++++----- 3 files changed, 131 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 723cb4dd3500..e4cd61191cca 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -18,6 +18,7 @@ #include "llvm/GlobalValue.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/Debug.h" @@ -550,6 +551,63 @@ SDOperand X86DAGToDAGISel::Select(SDOperand N) { return CodeGenMap[N] = CurDAG->getTargetNode(Opc, VT, Result); 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); diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 6898e24ac42a..6b67241d065e 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1192,6 +1192,26 @@ static unsigned CCToX86CondCode(SDOperand CC, bool isFP) { 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. /// SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { @@ -1444,21 +1464,32 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { } } case ISD::SELECT: { - SDOperand Cond = Op.getOperand(0); - SDOperand CC; - if (Cond.getOpcode() == X86ISD::SETCC) { - CC = Cond.getOperand(0); - Cond = Cond.getOperand(1); - } else if (Cond.getOpcode() == ISD::SETCC) { - CC = Cond.getOperand(2); - bool isFP = MVT::isFloatingPoint(Cond.getOperand(1).getValueType()); + MVT::ValueType VT = Op.getValueType(); + bool isFP = MVT::isFloatingPoint(VT); + bool isFPStack = isFP && (X86Vector < SSE2); + bool isFPSSE = isFP && (X86Vector >= SSE2); + bool isValid = false; + SDOperand Op0 = Op.getOperand(0); + SDOperand Cond, CC; + if (Op0.getOpcode() == X86ISD::SETCC) { + CC = Op0.getOperand(0); + Cond = Op0.getOperand(1); + isValid = + !(isFPStack && + !SupportedByFPCMOV(cast(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); CC = DAG.getConstant(X86CC, MVT::i8); Cond = DAG.getNode(X86ISD::CMP, MVT::Flag, - Cond.getOperand(0), Cond.getOperand(1)); - } else { + Op0.getOperand(0), Op0.getOperand(1)); + isValid = true; + } + + if (!isValid) { 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 Tys; diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 833f1eaf4c33..ed826bd9f35f 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -377,6 +377,13 @@ def IMPLICIT_DEF_R16 : I<0, Pseudo, (ops R16:$dst), def IMPLICIT_DEF_R32 : I<0, Pseudo, (ops R32:$dst), "#IMPLICIT_DEF $dst", [(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 Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in @@ -2687,14 +2694,30 @@ def FTST : FPI<0xE4, RawFrm, (ops), "ftst">, D9; // Floating point cmovs. let isTwoAddress = 1 in { - def FpCMOVB : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; - def FpCMOVBE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; - def FpCMOVE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; - def FpCMOVP : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; - def FpCMOVAE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; - def FpCMOVA : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; - def FpCMOVNE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; - def FpCMOVNP : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, + [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, + X86_COND_B, STATUS))]>; + def FpCMOVBE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, + [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, + X86_COND_BE, STATUS))]>; + def FpCMOVE : FpI<(ops RFP:$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), @@ -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 fp64immneg1), (FpCHS (FpLD1))>, Requires<[FPStack]>; -// FR64 undef -def : Pat<(f64 (undef)), (FLD0SD)>, Requires<[HasSSE2]>; // RFP undef def : Pat<(f64 (undef)), (FpLD0)>, Requires<[FPStack]>;