done
[oota-llvm.git] / lib / Target / X86 / X86InstrFPStack.td
index 0932416491715f834de591caad745c342996ac89..848d370db4d06969f1e0accd6da7cdc3b2572a2f 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+//===----------------------------------------------------------------------===//
+// FPStack specific DAG Nodes.
+//===----------------------------------------------------------------------===//
+
+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 SDTX86Fild    : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisPtrTy<1>,
+                                         SDTCisVT<2, OtherVT>]>;
+def SDTX86FpToIMem: SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>;
+
+def X86fpget   : SDNode<"X86ISD::FP_GET_RESULT", SDTX86FpGet,
+                        [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
+def X86fpset   : SDNode<"X86ISD::FP_SET_RESULT", SDTX86FpSet,
+                        [SDNPHasChain, SDNPOutFlag]>;
+def X86fld     : SDNode<"X86ISD::FLD",      SDTX86Fld,
+                        [SDNPHasChain]>;
+def X86fst     : SDNode<"X86ISD::FST",      SDTX86Fst,
+                        [SDNPHasChain, SDNPInFlag]>;
+def X86fild    : SDNode<"X86ISD::FILD",     SDTX86Fild,
+                        [SDNPHasChain]>;
+def X86fildflag: SDNode<"X86ISD::FILD_FLAG",SDTX86Fild,
+                        [SDNPHasChain, SDNPOutFlag]>;
+def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem,
+                        [SDNPHasChain]>;
+def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem,
+                        [SDNPHasChain]>;
+def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem,
+                        [SDNPHasChain]>;
+
+//===----------------------------------------------------------------------===//
+// FPStack pattern fragments
+//===----------------------------------------------------------------------===//
+
+def fp64imm0 : PatLeaf<(f64 fpimm), [{
+  return N->isExactlyValue(+0.0);
+}]>;
+
+def fp64immneg0 : PatLeaf<(f64 fpimm), [{
+  return N->isExactlyValue(-0.0);
+}]>;
+
+def fp64imm1 : PatLeaf<(f64 fpimm), [{
+  return N->isExactlyValue(+1.0);
+}]>;
+
+def fp64immneg1 : PatLeaf<(f64 fpimm), [{
+  return N->isExactlyValue(-1.0);
+}]>;
+
+def extloadf64f32  : PatFrag<(ops node:$ptr), (f64 (extloadf32 node:$ptr))>;
+
+// Some 'special' instructions
+let usesCustomDAGSchedInserter = 1 in {  // Expanded by the scheduler.
+  def FP_TO_INT16_IN_MEM : I<0, Pseudo,
+                            (ops i16mem:$dst, RFP:$src),
+                           "#FP_TO_INT16_IN_MEM PSEUDO!",
+                           [(X86fp_to_i16mem RFP:$src, addr:$dst)]>;
+  def FP_TO_INT32_IN_MEM : I<0, Pseudo,
+                            (ops i32mem:$dst, RFP:$src),
+                           "#FP_TO_INT32_IN_MEM PSEUDO!",
+                           [(X86fp_to_i32mem RFP:$src, addr:$dst)]>;
+  def FP_TO_INT64_IN_MEM : I<0, Pseudo,
+                            (ops i64mem:$dst, RFP:$src),
+                           "#FP_TO_INT64_IN_MEM PSEUDO!",
+                           [(X86fp_to_i64mem RFP:$src, addr:$dst)]>;
+}
+
+let isTerminator = 1 in
+  let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
+    def FP_REG_KILL  : I<0, Pseudo, (ops), "#FP_REG_KILL", []>;
+
 // All FP Stack operations are represented with two instructions here.  The
 // first instruction, generated by the instruction selector, uses "RFP"
 // registers: a traditional register file to reference floating point values.
@@ -291,7 +366,7 @@ def FpILD64m : FpI<(ops RFP:$dst, i64mem:$src), ZeroArgFP,
                    [(set RFP:$dst, (X86fild addr:$src, i64))]>;
 
 def FpST32m   : FpI<(ops f32mem:$op, RFP:$src), OneArgFP,
-                [(truncstore RFP:$src, addr:$op, f32)]>;
+                [(truncstoref32 RFP:$src, addr:$op)]>;
 def FpST64m   : FpI<(ops f64mem:$op, RFP:$src), OneArgFP,
                 [(store RFP:$src, addr:$op)]>;
 
@@ -338,10 +413,12 @@ def FSTPrr  : FPI<0xD8, AddRegFrm, (ops RST:$op), "fstp $op">, DD;
 def FXCH    : FPI<0xC8, AddRegFrm, (ops RST:$op), "fxch $op">, D9;
 
 // Floating point constant loads.
+let isReMaterializable = 1 in {
 def FpLD0 : FpI<(ops RFP:$dst), ZeroArgFP,
                 [(set RFP:$dst, fp64imm0)]>;
 def FpLD1 : FpI<(ops RFP:$dst), ZeroArgFP,
                 [(set RFP:$dst, fp64imm1)]>;
+}
 
 def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9;
 def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9;
@@ -379,3 +456,22 @@ def FNSTCW16m : I<0xD9, MRM7m,                   // [mem16] = X87 control world
                   (ops i16mem:$dst), "fnstcw $dst", []>;
 def FLDCW16m  : I<0xD9, MRM5m,                   // X87 control world = [mem16]
                   (ops i16mem:$dst), "fldcw $dst", []>;
+
+//===----------------------------------------------------------------------===//
+// Non-Instruction Patterns
+//===----------------------------------------------------------------------===//
+
+// Required for RET of f32 / f64 values.
+def : Pat<(X86fld addr:$src, f32), (FpLD32m addr:$src)>;
+def : Pat<(X86fld addr:$src, f64), (FpLD64m addr:$src)>;
+
+// Required for CALL which return f32 / f64 values.
+def : Pat<(X86fst RFP:$src, addr:$op, f32), (FpST32m addr:$op, RFP:$src)>;
+def : Pat<(X86fst RFP:$src, addr:$op, f64), (FpST64m addr:$op, RFP:$src)>;
+
+// Floating point constant -0.0 and -1.0
+def : Pat<(f64 fp64immneg0), (FpCHS (FpLD0))>, Requires<[FPStack]>;
+def : Pat<(f64 fp64immneg1), (FpCHS (FpLD1))>, Requires<[FPStack]>;
+
+// Used to conv. i64 to f64 since there isn't a SSE version.
+def : Pat<(X86fildflag addr:$src, i64), (FpILD64m addr:$src)>;