From 5ae27cfaed756438a433459dcb6fd840c9e4112e Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 6 May 2004 07:19:24 +0200 Subject: [PATCH] optabs.h (enum optab_index): Add new OTI_fmod and OTI_drem. * 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 | 31 +++++ gcc/builtins.c | 14 +++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.c | 21 ++++ gcc/config/i386/i386.md | 174 ++++++++++++++++++++++++++++- gcc/genopinit.c | 2 + gcc/optabs.c | 2 + gcc/optabs.h | 5 + gcc/reg-stack.c | 4 + gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/builtins-40.c | 47 ++++++++ 11 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtins-40.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0831dc0dabe..0159b7ae958 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2004-05-05 Uros Bizjak + + * 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 * reload1.c (inherit_piecemeal_p): Mark parameters potentially unused. diff --git a/gcc/builtins.c b/gcc/builtins.c index c42a42392df..612684262b5 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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); diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index d95be60e23f..636d50b20e1 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 2890d04f5db..a561d4fe0e1 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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" diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 26132f1f5c9..e5edad4d5d2 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -129,6 +129,10 @@ (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) @@ -941,9 +945,9 @@ ;; 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") @@ -14858,6 +14862,172 @@ (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))] diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 87934496b76..307849adcdf 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -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$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index 1632ecfe8c9..719fbb434c6 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -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); diff --git a/gcc/optabs.h b/gcc/optabs.h index a7aac1934f3..84d8957f22d 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -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]) diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 8464ab43bc6..bab401ff0bd 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aeff648ee30..c08a35e68fc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-05-05 Uros Bizjak + + * gcc.dg/builtins-40.c: New test. + 2004-05-05 Richard Sandiford * 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 index 00000000000..405c8723309 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-40.c @@ -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); +} -- 2.30.2