optabs.h (enum optab_index): Add new OTI_fmod and OTI_drem.
authorUros Bizjak <uros@kss-loka.si>
Thu, 6 May 2004 05:19:24 +0000 (07:19 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Thu, 6 May 2004 05:19:24 +0000 (07:19 +0200)
        * optabs.h (enum optab_index): Add new OTI_fmod and OTI_drem.
        (fmod_optab): Define corresponding macros.
        * optabs.c (init_optabs): Initialize fmod_optab and drem_optab.
        * genopinit.c (optabs): Implement fmod_optab and drem_optab
        using fmod?f3 and drem?f3 patterns.
        * builtins.c (expand_builtin_mathfn_2): Handle BUILT_IN_FMOD{,F,L}
        using fmod_optab and BUILT_IN_DREM{,F,L} using drem_optab.
        (expand_builtin): Expand BUILT_IN_FMOD{,F,L} and
        BUILT_IN_DREM{,F,L} using expand_builtin_mathfn_2 if
        flag_unsafe_math_optimizations is set.

        * reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_FPREM_F,
        UNSPEC_FPREM_U, UNSPEC_FPREM1_F and UNSPEC_FPREM1_U.

        * config/i386/i386.c (ix86_emit_fp_unordered_jump): New function.
        * config/i386/i386-protos.h (ix86_emit_fp_unordered_jump):
        Prototype here.
        * config/i386/i386.md (UNSPEC_FPREM_F, UNSPEC_FPREM_U,
        UNSPEC_FPREM1_F, UNSPEC_FPREM1_U): New unspecs to represent x87's
        fprem and fprem1 instructions.
        (*x86_fnstsw_1): Change input parameter to (reg:CCFP 18).
        Rename insn definition to x86_fnstsw_1.
        (fpremxf4, fprem1xf4): New patterns to implement fprem and fprem1
        x87 instructions.
        (fmodsf3, fmoddf3, fmodxf3): New expanders to implement fmodf, fmod
        and fmodl built-ins as inline x87 intrinsics.
        (dremsf3, dremdf3, dremxf3): New expanders to implement dremf, drem
        and dreml built-ins as inline x87 intrinsics.

        * testsuite/gcc.dg/builtins-40.c: New test.

From-SVN: r81555

gcc/ChangeLog
gcc/builtins.c
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h
gcc/reg-stack.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-40.c [new file with mode: 0644]

index 0831dc0dabeef20f1b8ec30b406d3bdbe25fc6ba..0159b7ae958b51f4f223900bb39d66a700813cad 100644 (file)
@@ -1,3 +1,34 @@
+2004-05-05  Uros Bizjak  <uros@kss-loka.si>
+
+       * optabs.h (enum optab_index): Add new OTI_fmod and OTI_drem.
+       (fmod_optab): Define corresponding macros.
+       * optabs.c (init_optabs): Initialize fmod_optab and drem_optab.
+       * genopinit.c (optabs): Implement fmod_optab and drem_optab
+       using fmod?f3 and drem?f3 patterns.
+       * builtins.c (expand_builtin_mathfn_2): Handle BUILT_IN_FMOD{,F,L}
+       using fmod_optab and BUILT_IN_DREM{,F,L} using drem_optab.
+       (expand_builtin): Expand BUILT_IN_FMOD{,F,L} and
+       BUILT_IN_DREM{,F,L} using expand_builtin_mathfn_2 if
+       flag_unsafe_math_optimizations is set.
+
+       * reg-stack.c (subst_stack_regs_pat): Handle UNSPEC_FPREM_F,
+       UNSPEC_FPREM_U, UNSPEC_FPREM1_F and UNSPEC_FPREM1_U.
+
+       * config/i386/i386.c (ix86_emit_fp_unordered_jump): New function.
+       * config/i386/i386-protos.h (ix86_emit_fp_unordered_jump):
+       Prototype here.
+       * config/i386/i386.md (UNSPEC_FPREM_F, UNSPEC_FPREM_U,
+       UNSPEC_FPREM1_F, UNSPEC_FPREM1_U): New unspecs to represent x87's
+       fprem and fprem1 instructions.
+       (*x86_fnstsw_1): Change input parameter to (reg:CCFP 18).
+       Rename insn definition to x86_fnstsw_1.
+       (fpremxf4, fprem1xf4): New patterns to implement fprem and fprem1
+       x87 instructions.
+       (fmodsf3, fmoddf3, fmodxf3): New expanders to implement fmodf, fmod
+       and fmodl built-ins as inline x87 intrinsics.
+       (dremsf3, dremdf3, dremxf3): New expanders to implement dremf, drem
+       and dreml built-ins as inline x87 intrinsics.
+
 2004-05-05  Roger Sayle  <roger@eyesopen.com>
 
        * reload1.c (inherit_piecemeal_p): Mark parameters potentially unused.
index c42a42392df495deb92e3b5ca6d018ee4216c8cf..612684262b563a650c5a4b55bce96512513abdf4 100644 (file)
@@ -1793,6 +1793,14 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
     case BUILT_IN_ATAN2F:
     case BUILT_IN_ATAN2L:
       builtin_optab = atan2_optab; break;
+    case BUILT_IN_FMOD:
+    case BUILT_IN_FMODF:
+    case BUILT_IN_FMODL:
+      builtin_optab = fmod_optab; break;
+    case BUILT_IN_DREM:
+    case BUILT_IN_DREMF:
+    case BUILT_IN_DREML:
+      builtin_optab = drem_optab; break;
     default:
       abort ();
     }
@@ -5364,6 +5372,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_ATAN2:
     case BUILT_IN_ATAN2F:
     case BUILT_IN_ATAN2L:
+    case BUILT_IN_FMOD:
+    case BUILT_IN_FMODF:
+    case BUILT_IN_FMODL:
+    case BUILT_IN_DREM:
+    case BUILT_IN_DREMF:
+    case BUILT_IN_DREML:
       if (! flag_unsafe_math_optimizations)
        break;
       target = expand_builtin_mathfn_2 (exp, target, subtarget);
index d95be60e23f03558a5e05a8be8aa86b6e7431c0f..636d50b20e179db95915b265fabe8c7345571e1b 100644 (file)
@@ -182,6 +182,7 @@ extern bool ix86_fp_jump_nontrivial_p (enum rtx_code);
 extern void x86_order_regs_for_local_alloc (void);
 extern void x86_function_profiler (FILE *, int);
 extern void x86_emit_floatuns (rtx [2]);
+extern void ix86_emit_fp_unordered_jump (rtx);
 
 extern enum rtx_code ix86_reverse_condition (enum rtx_code, enum machine_mode);
 
index 2890d04f5dbecb9c19718f1e1834110fc3392684..a561d4fe0e1d06b32b918e3103bc53e4fedee78e 100644 (file)
@@ -15928,4 +15928,25 @@ output_387_reg_move (rtx insn, rtx *operands)
   return "fst\t%y0";
 }
 
+/* Output code to perform a conditional jump to LABEL, if C2 flag in
+   FP status register is set.  */
+
+void
+ix86_emit_fp_unordered_jump (rtx label)
+{
+  rtx reg = gen_reg_rtx (HImode);
+  rtx temp;
+
+  emit_insn (gen_x86_fnstsw_1 (reg));
+  emit_insn (gen_x86_sahf_1 (reg));
+  
+  temp = gen_rtx_REG (CCmode, FLAGS_REG); 
+  temp = gen_rtx_UNORDERED (VOIDmode, temp, const0_rtx);
+  temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
+                             gen_rtx_LABEL_REF (VOIDmode, label),
+                             pc_rtx);
+  temp = gen_rtx_SET (VOIDmode, pc_rtx, temp);
+  emit_jump_insn (temp);
+}
+
 #include "gt-i386.h"
index 26132f1f5c91a2ef452ada33e60d0f5250eb56df..e5edad4d5d21d9238cc008c1cd2a323a0925ecbe 100644 (file)
    (UNSPEC_XTRACT_EXP          85)
    (UNSPEC_FSCALE_FRACT                86)
    (UNSPEC_FSCALE_EXP          87)
+   (UNSPEC_FPREM_F             88)
+   (UNSPEC_FPREM_U             89)
+   (UNSPEC_FPREM1_F            90)
+   (UNSPEC_FPREM1_U            91)
 
    ; REP instruction
    (UNSPEC_REP                 75)
 ;; FP compares, step 2
 ;; Move the fpsw to ax.
 
-(define_insn "*x86_fnstsw_1"
+(define_insn "x86_fnstsw_1"
   [(set (match_operand:HI 0 "register_operand" "=a")
-       (unspec:HI [(reg 18)] UNSPEC_FNSTSW))]
+       (unspec:HI [(reg:CCFP 18)] UNSPEC_FNSTSW))]
   "TARGET_80387"
   "fnstsw\t%0"
   [(set_attr "length" "2")
    (set_attr "mode" "XF")
    (set_attr "athlon_decode" "direct")])
 
+(define_insn "fpremxf4"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+       (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+                   (match_operand:XF 3 "register_operand" "1")]
+                  UNSPEC_FPREM_F))
+   (set (match_operand:XF 1 "register_operand" "=u")
+       (unspec:XF [(match_dup 2) (match_dup 3)]
+                  UNSPEC_FPREM_U))
+   (set (reg:CCFP 18)
+       (unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
+   && flag_unsafe_math_optimizations"
+  "fprem"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "XF")])
+
+(define_expand "fmodsf3"
+  [(use (match_operand:SF 0 "register_operand" ""))
+   (use (match_operand:SF 1 "register_operand" ""))
+   (use (match_operand:SF 2 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx label = gen_label_rtx ();
+
+  rtx op1 = gen_reg_rtx (XFmode);
+  rtx op2 = gen_reg_rtx (XFmode);
+
+  emit_insn(gen_extendsfxf2 (op1, operands[1]));
+  emit_insn(gen_extendsfxf2 (op2, operands[2]));
+
+  emit_label (label);
+
+  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
+  ix86_emit_fp_unordered_jump (label);
+
+  emit_insn (gen_truncxfsf2_noop (operands[0], op1));
+  DONE;
+})
+
+(define_expand "fmoddf3"
+  [(use (match_operand:DF 0 "register_operand" ""))
+   (use (match_operand:DF 1 "register_operand" ""))
+   (use (match_operand:DF 2 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx label = gen_label_rtx ();
+
+  rtx op1 = gen_reg_rtx (XFmode);
+  rtx op2 = gen_reg_rtx (XFmode);
+
+  emit_insn (gen_extenddfxf2 (op1, operands[1]));
+  emit_insn (gen_extenddfxf2 (op2, operands[2]));
+
+  emit_label (label);
+
+  emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
+  ix86_emit_fp_unordered_jump (label);
+
+  emit_insn (gen_truncxfdf2_noop (operands[0], op1));
+  DONE;
+})
+
+(define_expand "fmodxf3"
+  [(use (match_operand:XF 0 "register_operand" ""))
+   (use (match_operand:XF 1 "register_operand" ""))
+   (use (match_operand:XF 2 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx label = gen_label_rtx ();
+
+  emit_label (label);
+
+  emit_insn (gen_fpremxf4 (operands[1], operands[2],
+                          operands[1], operands[2]));
+  ix86_emit_fp_unordered_jump (label);
+
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+})
+
+(define_insn "fprem1xf4"
+  [(set (match_operand:XF 0 "register_operand" "=f")
+       (unspec:XF [(match_operand:XF 2 "register_operand" "0")
+                   (match_operand:XF 3 "register_operand" "1")]
+                  UNSPEC_FPREM1_F))
+   (set (match_operand:XF 1 "register_operand" "=u")
+       (unspec:XF [(match_dup 2) (match_dup 3)]
+                  UNSPEC_FPREM1_U))
+   (set (reg:CCFP 18)
+       (unspec:CCFP [(const_int 0)] UNSPEC_NOP))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
+   && flag_unsafe_math_optimizations"
+  "fprem1"
+  [(set_attr "type" "fpspc")
+   (set_attr "mode" "XF")])
+
+(define_expand "dremsf3"
+  [(use (match_operand:SF 0 "register_operand" ""))
+   (use (match_operand:SF 1 "register_operand" ""))
+   (use (match_operand:SF 2 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx label = gen_label_rtx ();
+
+  rtx op1 = gen_reg_rtx (XFmode);
+  rtx op2 = gen_reg_rtx (XFmode);
+
+  emit_insn(gen_extendsfxf2 (op1, operands[1]));
+  emit_insn(gen_extendsfxf2 (op2, operands[2]));
+
+  emit_label (label);
+
+  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
+  ix86_emit_fp_unordered_jump (label);
+
+  emit_insn (gen_truncxfsf2_noop (operands[0], op1));
+  DONE;
+})
+
+(define_expand "dremdf3"
+  [(use (match_operand:DF 0 "register_operand" ""))
+   (use (match_operand:DF 1 "register_operand" ""))
+   (use (match_operand:DF 2 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx label = gen_label_rtx ();
+
+  rtx op1 = gen_reg_rtx (XFmode);
+  rtx op2 = gen_reg_rtx (XFmode);
+
+  emit_insn (gen_extenddfxf2 (op1, operands[1]));
+  emit_insn (gen_extenddfxf2 (op2, operands[2]));
+
+  emit_label (label);
+
+  emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
+  ix86_emit_fp_unordered_jump (label);
+
+  emit_insn (gen_truncxfdf2_noop (operands[0], op1));
+  DONE;
+})
+
+(define_expand "dremxf3"
+  [(use (match_operand:XF 0 "register_operand" ""))
+   (use (match_operand:XF 1 "register_operand" ""))
+   (use (match_operand:XF 2 "register_operand" ""))]
+  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+   && flag_unsafe_math_optimizations"
+{
+  rtx label = gen_label_rtx ();
+
+  emit_label (label);
+
+  emit_insn (gen_fprem1xf4 (operands[1], operands[2],
+                           operands[1], operands[2]));
+  ix86_emit_fp_unordered_jump (label);
+
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+})
+
 (define_insn "*sindf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))]
index 87934496b766bfbcdf88cfbfb50201460b0b9b50..307849adcdf0a4b35de27f011eb6fa23d1f2766b 100644 (file)
@@ -91,6 +91,8 @@ static const char * const optabs[] =
   "udivmod_optab->handlers[$A].insn_code = CODE_FOR_$(udivmod$a4$)",
   "smod_optab->handlers[$A].insn_code = CODE_FOR_$(mod$a3$)",
   "umod_optab->handlers[$A].insn_code = CODE_FOR_$(umod$a3$)",
+  "fmod_optab->handlers[$A].insn_code = CODE_FOR_$(fmod$a3$)",
+  "drem_optab->handlers[$A].insn_code = CODE_FOR_$(drem$a3$)",
   "ftrunc_optab->handlers[$A].insn_code = CODE_FOR_$(ftrunc$F$a2$)",
   "and_optab->handlers[$A].insn_code = CODE_FOR_$(and$a3$)",
   "ior_optab->handlers[$A].insn_code = CODE_FOR_$(ior$a3$)",
index 1632ecfe8c9100148c3e7ea530520be9424dcb7c..719fbb434c65f5f56f097763b597e7b76eef8ccc 100644 (file)
@@ -5328,6 +5328,8 @@ init_optabs (void)
   udivmod_optab = init_optab (UNKNOWN);
   smod_optab = init_optab (MOD);
   umod_optab = init_optab (UMOD);
+  fmod_optab = init_optab (UNKNOWN);
+  drem_optab = init_optab (UNKNOWN);
   ftrunc_optab = init_optab (UNKNOWN);
   and_optab = init_optab (AND);
   ior_optab = init_optab (IOR);
index a7aac1934f3e2dcd54406bb61971aae3f4ff57fe..84d8957f22dfe381e92320a416c02dc28d3141a5 100644 (file)
@@ -93,6 +93,9 @@ enum optab_index
   /* Signed remainder */
   OTI_smod,
   OTI_umod,
+  /* Floating point remainder functions */
+  OTI_fmod,
+  OTI_drem,
   /* Convert float to integer in float fmt */
   OTI_ftrunc,
 
@@ -245,6 +248,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define udivmod_optab (optab_table[OTI_udivmod])
 #define smod_optab (optab_table[OTI_smod])
 #define umod_optab (optab_table[OTI_umod])
+#define fmod_optab (optab_table[OTI_fmod])
+#define drem_optab (optab_table[OTI_drem])
 #define ftrunc_optab (optab_table[OTI_ftrunc])
 #define and_optab (optab_table[OTI_and])
 #define ior_optab (optab_table[OTI_ior])
index 8464ab43bc607f9bf4fe0d88d97ed8d6d17249c7..bab401ff0bd0ca22c0fc94e8baa4530845c5efe7 100644 (file)
@@ -1779,6 +1779,8 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                break;
 
              case UNSPEC_FSCALE_FRACT:
+             case UNSPEC_FPREM_F:
+             case UNSPEC_FPREM1_F:
                /* These insns operate on the top two stack slots.
                   first part of double input, double output insn.  */
 
@@ -1808,6 +1810,8 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                break;
 
              case UNSPEC_FSCALE_EXP:
+             case UNSPEC_FPREM_U:
+             case UNSPEC_FPREM1_U:
                /* These insns operate on the top two stack slots./
                   second part of double input, double output insn.  */
 
index aeff648ee3087681b8ff821897a8edbe5b6fd492..c08a35e68fc034fe8ddd05cdfec841d07df32f6a 100644 (file)
@@ -1,3 +1,7 @@
+2004-05-05  Uros Bizjak  <uros@kss-loka.si>
+
+       * gcc.dg/builtins-40.c: New test.
+       
 2004-05-05  Richard Sandiford  <rsandifo@redhat.com>
 
        * gcc.dg/torture/mips-hilo-2.c: Provide dummy __mips16 version.
diff --git a/gcc/testsuite/gcc.dg/builtins-40.c b/gcc/testsuite/gcc.dg/builtins-40.c
new file mode 100644 (file)
index 0000000..405c872
--- /dev/null
@@ -0,0 +1,47 @@
+/* Copyright (C) 2004 Free Software Foundation.
+
+   Check that fmod, fmodf, fmodl, drem, dremf and dreml
+   built-in functions compile.
+
+   Written by Uros Bizjak, 5th May 2004.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern double fmod(double, double);
+extern double drem(double, double);
+extern float fmodf(float, float);
+extern float dremf(float, float);
+extern long double fmodl(long double, long double);
+extern long double dreml(long double, long double);
+
+
+double test1(double x, double y)
+{
+  return fmod(x, y);
+}
+
+double test2(double x, double y)
+{
+  return drem(x, y);
+}
+
+float test1f(float x, float y)
+{
+  return fmodf(x, y);
+}
+
+float test2f(float x, float y)
+{
+  return dremf(x, y);
+}
+
+long double test1l(long double x, long double y)
+{
+  return fmodl(x, y);
+}
+
+long double test2l(long double x, long double y)
+{
+  return dreml(x, y);
+}