diff options
author | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-20 13:33:51 +0000 |
---|---|---|
committer | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-20 13:33:51 +0000 |
commit | 73a954a137a4ad3aff3c816a4a401887669ab5f7 (patch) | |
tree | 95fa0014104dcb6887115c27e24a726801ecd2a0 | |
parent | 19636773804cc810ffb5dec03069184ff71404bc (diff) | |
download | gcc-73a954a137a4ad3aff3c816a4a401887669ab5f7.tar.gz |
* optabs.h (enum optab_index): Add new OTI_scalb.
(scalb_optab): Define corresponding macro.
* optabs.c (init_optabs): Initialize scalb_optab.
* genopinit.c (optabs): Implement scalb_optab using scalb?f3
patterns.
* builtins.c (expand_builtin_mathfn_2, expand_builtin): Handle
BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L} and BUILT_IN_SCALBLN{,F,L}.
(expand_builtin): Expand BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L}
and BUILT_IN_SCALBLN{,F,L} using expand_builtin_mathfn_2 if
flag_unsafe_math_optimizations is set.
* config/i386/i386.md (scalbxf3, scalb<mode>3): New expanders
to implement scalbf, scalb and scalbl built-ins as inline x87
intrinsics.
testsuite/ChangeLog
* gcc.dg/builtins-34.c: Add scalb/scalbn/scalbln cases.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122162 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/builtins.c | 25 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 34 | ||||
-rw-r--r-- | gcc/genopinit.c | 1 | ||||
-rw-r--r-- | gcc/optabs.c | 1 | ||||
-rw-r--r-- | gcc/optabs.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-34.c | 54 |
8 files changed, 140 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ebceb404f1a..292bfbc1533 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2007-02-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + Uros Bizjak <ubizjak@gmail.com> + + * optabs.h (enum optab_index): Add new OTI_scalb. + (scalb_optab): Define corresponding macro. + * optabs.c (init_optabs): Initialize scalb_optab. + * genopinit.c (optabs): Implement scalb_optab using scalb?f3 + patterns. + * builtins.c (expand_builtin_mathfn_2, expand_builtin): Handle + BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L} and BUILT_IN_SCALBLN{,F,L}. + (expand_builtin): Expand BUILT_IN_SCALB{,F,L}, BUILT_IN_SCALBN{,F,L} + and BUILT_IN_SCALBLN{,F,L} using expand_builtin_mathfn_2 if + flag_unsafe_math_optimizations is set. + + * config/i386/i386.md (scalbxf3, scalb<mode>3): New expanders + to implement scalbf, scalb and scalbl built-ins as inline x87 + intrinsics. + 2007-02-20 Manuel Lopez-Ibanez <manu@gcc.gnu.org> DJ Delorie <dj@redhat.com> diff --git a/gcc/builtins.c b/gcc/builtins.c index 67d9bf63f25..e1c2deef647 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1973,10 +1973,15 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget) bool errno_set = true; bool stable = true; - if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP - || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF - || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL) - op1_type = INTEGER_TYPE; + switch (DECL_FUNCTION_CODE (fndecl)) + { + CASE_FLT_FN (BUILT_IN_SCALBN): + CASE_FLT_FN (BUILT_IN_SCALBLN): + CASE_FLT_FN (BUILT_IN_LDEXP): + op1_type = INTEGER_TYPE; + default: + break; + } if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE)) return NULL_RTX; @@ -1990,6 +1995,15 @@ expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget) builtin_optab = pow_optab; break; CASE_FLT_FN (BUILT_IN_ATAN2): builtin_optab = atan2_optab; break; + CASE_FLT_FN (BUILT_IN_SCALB): + if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2) + return 0; + builtin_optab = scalb_optab; break; + CASE_FLT_FN (BUILT_IN_SCALBN): + CASE_FLT_FN (BUILT_IN_SCALBLN): + if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (exp)))->b != 2) + return 0; + /* Fall through... */ CASE_FLT_FN (BUILT_IN_LDEXP): builtin_optab = ldexp_optab; break; CASE_FLT_FN (BUILT_IN_FMOD): @@ -5963,6 +5977,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_FLT_FN (BUILT_IN_ATAN2): CASE_FLT_FN (BUILT_IN_LDEXP): + CASE_FLT_FN (BUILT_IN_SCALB): + CASE_FLT_FN (BUILT_IN_SCALBN): + CASE_FLT_FN (BUILT_IN_SCALBLN): if (! flag_unsafe_math_optimizations) break; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 7dae8e1e0b7..920b9dde8a1 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -17228,6 +17228,40 @@ emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0)); DONE; }) + +(define_expand "scalbxf3" + [(parallel [(set (match_operand:XF 0 " register_operand" "") + (unspec:XF [(match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 3) + (unspec:XF [(match_dup 1) (match_dup 2)] + UNSPEC_FSCALE_EXP))])] + "TARGET_USE_FANCY_MATH_387 + && flag_unsafe_math_optimizations && !optimize_size" +{ + operands[3] = gen_reg_rtx (XFmode); +}) + +(define_expand "scalb<mode>3" + [(use (match_operand:X87MODEF12 0 "register_operand" "")) + (use (match_operand:X87MODEF12 1 "general_operand" "")) + (use (match_operand:X87MODEF12 2 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387) + && flag_unsafe_math_optimizations && !optimize_size" +{ + rtx op0 = gen_reg_rtx (XFmode); + rtx op1 = gen_reg_rtx (XFmode); + rtx op2 = gen_reg_rtx (XFmode); + + emit_insn (gen_extend<mode>xf2 (op1, operands[1])); + emit_insn (gen_extend<mode>xf2 (op2, operands[2])); + emit_insn (gen_scalbxf3 (op0, op1, op2)); + emit_insn (gen_truncxf<mode>2_i387_noop (operands[0], op0)); + DONE; +}) (define_insn "frndintxf2" diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 1e70c6d07a8..3c06639f075 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -140,6 +140,7 @@ static const char * const optabs[] = "exp2_optab->handlers[$A].insn_code = CODE_FOR_$(exp2$a2$)", "expm1_optab->handlers[$A].insn_code = CODE_FOR_$(expm1$a2$)", "ldexp_optab->handlers[$A].insn_code = CODE_FOR_$(ldexp$a3$)", + "scalb_optab->handlers[$A].insn_code = CODE_FOR_$(scalb$a3$)", "logb_optab->handlers[$A].insn_code = CODE_FOR_$(logb$a2$)", "ilogb_optab->handlers[$A].insn_code = CODE_FOR_$(ilogb$a2$)", "log_optab->handlers[$A].insn_code = CODE_FOR_$(log$a2$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index 6a78b3785ac..51c84c82352 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5449,6 +5449,7 @@ init_optabs (void) exp2_optab = init_optab (UNKNOWN); expm1_optab = init_optab (UNKNOWN); ldexp_optab = init_optab (UNKNOWN); + scalb_optab = init_optab (UNKNOWN); logb_optab = init_optab (UNKNOWN); ilogb_optab = init_optab (UNKNOWN); log_optab = init_optab (UNKNOWN); diff --git a/gcc/optabs.h b/gcc/optabs.h index d3cfd742136..0f8c7966809 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -179,6 +179,8 @@ enum optab_index OTI_expm1, /* Load exponent of a floating point number */ OTI_ldexp, + /* Multiply floating-point number by integral power of radix */ + OTI_scalb, /* Radix-independent exponent */ OTI_logb, OTI_ilogb, @@ -357,6 +359,7 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define exp2_optab (optab_table[OTI_exp2]) #define expm1_optab (optab_table[OTI_expm1]) #define ldexp_optab (optab_table[OTI_ldexp]) +#define scalb_optab (optab_table[OTI_scalb]) #define logb_optab (optab_table[OTI_logb]) #define ilogb_optab (optab_table[OTI_ilogb]) #define log_optab (optab_table[OTI_log]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b5f91c5e7dd..80c712cb454 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-02-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * gcc.dg/builtins-34.c: Add scalb/scalbn/scalbln cases. + 2007-02-20 Manuel Lopez-Ibanez <manu@gcc.gnu.org> DJ Delorie <dj@redhat.com> @@ -76,7 +80,7 @@ 2007-02-18 Roger Sayle <roger@eyesopen.com> - * gfortran.dg/forall_10.f90: New test case. + * gfortran.dg/forall_10.f90: New test case. 2007-02-18 Eric Botcazou <ebotcazou@adacore.com> @@ -1199,9 +1203,9 @@ 2007-01-06 Lee Millward <lee.millward@codesourcery.com> - PR c++/19439 - * g++.dg/template/duplicate1.C: New test - * g++.dg/template/memfriend6.C: Adjust error markers. + PR c++/19439 + * g++.dg/template/duplicate1.C: New test + * g++.dg/template/memfriend6.C: Adjust error markers. 2007-01-05 Andrew Pinski <Andrew_Pinski@playstation.sony.com> diff --git a/gcc/testsuite/gcc.dg/builtins-34.c b/gcc/testsuite/gcc.dg/builtins-34.c index f2625d5ef59..ee8d7513f91 100644 --- a/gcc/testsuite/gcc.dg/builtins-34.c +++ b/gcc/testsuite/gcc.dg/builtins-34.c @@ -13,16 +13,25 @@ extern double exp2(double); extern double pow10(double); extern double expm1(double); extern double ldexp(double, int); +extern double scalb(double, double); +extern double scalbn(double, int); +extern double scalbln(double, long); extern float exp10f(float); extern float exp2f(float); extern float pow10f(float); extern float expm1f(float); extern float ldexpf(float, int); +extern float scalbf(float, float); +extern float scalbnf(float, int); +extern float scalblnf(float, long); extern long double exp10l(long double); extern long double exp2l(long double); extern long double pow10l(long double); extern long double expm1l(long double); extern long double ldexpl(long double, int); +extern long double scalbl(long double, long double); +extern long double scalbnl(long double, int); +extern long double scalblnl(long double, long); double test1(double x) @@ -50,6 +59,21 @@ double test5(double x, int exp) return ldexp(x, exp); } +double test6(double x, double exp) +{ + return scalb(x, exp); +} + +double test7(double x, int exp) +{ + return scalbn(x, exp); +} + +double test8(double x, long exp) +{ + return scalbln(x, exp); +} + float test1f(float x) { return exp10f(x); @@ -75,6 +99,21 @@ float test5f(float x, int exp) return ldexpf(x, exp); } +float test6f(float x, float exp) +{ + return scalbf(x, exp); +} + +float test7f(float x, int exp) +{ + return scalbnf(x, exp); +} + +float test8f(float x, long exp) +{ + return scalblnf(x, exp); +} + long double test1l(long double x) { return exp10l(x); @@ -99,3 +138,18 @@ long double test5l(long double x, int exp) { return ldexpl(x, exp); } + +long double test6l(long double x, long double exp) +{ + return scalbl(x, exp); +} + +long double test7l(long double x, int exp) +{ + return scalbnl(x, exp); +} + +long double test8l(long double x, long exp) +{ + return scalblnl(x, exp); +} |