diff options
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/builtins.c | 4 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 38 | ||||
-rw-r--r-- | gcc/genopinit.c | 1 | ||||
-rw-r--r-- | gcc/optabs.c | 2 | ||||
-rw-r--r-- | gcc/optabs.h | 5 | ||||
-rw-r--r-- | gcc/reg-stack.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-63.c | 28 |
9 files changed, 121 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8c0bbcbea07..ba55b7c30db 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2007-01-31 Uros Bizjak <ubizjak@gmail.com> + + * optabs.h (enum optab_index): Add new OTI_isinf. + (isinf_optab): Define corresponding macro. + * optabs.c (init_optabs): Initialize isinf_optab. + * genopinit.c (optabs): Implement isinf_optab using isinf?f2 + patterns. + * builtins.c (mathfn_built_in): Handle BUILT_IN_ISINF{,F,L}. + (expand_builtin_interclass_mathfn): Expand BUILT_IN_ISINF{,F,L} + using isinf_optab. + (expand_builtin): Expand BUILT_IN_ISINF{,F,L} using + expand_builtin_interclass_mathfn. + * reg_stack.c (subst_stack_regs_pat): Handle UNSPEC_FXAM. + * config/i386/i386.md (UNSPEC_FXAM): New constant. + (fxam<mode>2_i387): New insn pattern. + (isinf<mode>2) New expander to implement isinf, isinff and isinfl + built-in functions as x87 inline asm. + 2007-01-31 Kazu Hirata <kazu@codesourcery.com> * gcc/config/arm/unwind-arm.h (_sleb128_t, _uleb128_t): New. diff --git a/gcc/builtins.c b/gcc/builtins.c index 5ba1eae5eb6..777206c83a0 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1676,6 +1676,7 @@ mathfn_built_in (tree type, enum built_in_function fn) CASE_MATHFN (BUILT_IN_HYPOT) CASE_MATHFN (BUILT_IN_ILOGB) CASE_MATHFN (BUILT_IN_INF) + CASE_MATHFN (BUILT_IN_ISINF) CASE_MATHFN (BUILT_IN_J0) CASE_MATHFN (BUILT_IN_J1) CASE_MATHFN (BUILT_IN_JN) @@ -2198,6 +2199,8 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) { CASE_FLT_FN (BUILT_IN_ILOGB): errno_set = true; builtin_optab = ilogb_optab; break; + CASE_FLT_FN (BUILT_IN_ISINF): + builtin_optab = isinf_optab; break; default: gcc_unreachable (); } @@ -5923,6 +5926,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_FLT_FN (BUILT_IN_ILOGB): if (! flag_unsafe_math_optimizations) break; + CASE_FLT_FN (BUILT_IN_ISINF): target = expand_builtin_interclass_mathfn (exp, target, subtarget); if (target) return target; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a9620e2242b..cfe48c446da 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -122,6 +122,7 @@ (UNSPEC_FIST 66) (UNSPEC_F2XM1 67) (UNSPEC_TAN 68) + (UNSPEC_FXAM 69) ; x87 Rounding (UNSPEC_FRNDINT_FLOOR 70) @@ -17597,6 +17598,43 @@ DONE; }) +(define_insn "fxam<mode>2_i387" + [(set (match_operand:HI 0 "register_operand" "=a") + (unspec:HI + [(match_operand:X87MODEF 1 "register_operand" "f")] + UNSPEC_FXAM))] + "TARGET_USE_FANCY_MATH_387" + "fxam\n\tfnstsw\t%0" + [(set_attr "type" "multi") + (set_attr "unit" "i387") + (set_attr "mode" "<MODE>")]) + +(define_expand "isinf<mode>2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:X87MODEF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && (!(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH) + || TARGET_MIX_SSE_I387)" +{ + rtx mask = GEN_INT (0x45); + rtx val = GEN_INT (0x05); + + rtx cond; + + rtx scratch = gen_reg_rtx (HImode); + rtx res = gen_reg_rtx (QImode); + + emit_insn (gen_fxam<mode>2_i387 (scratch, operands[1])); + emit_insn (gen_andqi_ext_0 (scratch, scratch, mask)); + emit_insn (gen_cmpqi_ext_3 (scratch, val)); + cond = gen_rtx_fmt_ee (EQ, QImode, + gen_rtx_REG (CCmode, FLAGS_REG), + const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, res, cond)); + emit_insn (gen_zero_extendqisi2 (operands[0], res)); + DONE; +}) + ;; Block operation instructions diff --git a/gcc/genopinit.c b/gcc/genopinit.c index ad72637b902..1e70c6d07a8 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -118,6 +118,7 @@ static const char * const optabs[] = abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$F$a2$)", "absv_optab->handlers[$A].insn_code = CODE_FOR_$(absv$I$a2$)", "copysign_optab->handlers[$A].insn_code = CODE_FOR_$(copysign$F$a3$)", + "isinf_optab->handlers[$A].insn_code = CODE_FOR_$(isinf$a2$)", "sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)", "floor_optab->handlers[$A].insn_code = CODE_FOR_$(floor$a2$)", "lfloor_optab->handlers[$B][$A].insn_code = CODE_FOR_$(lfloor$F$a$I$b2$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index c7f16c29e59..e66c115c0c0 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5378,6 +5378,8 @@ init_optabs (void) atan_optab = init_optab (UNKNOWN); copysign_optab = init_optab (UNKNOWN); + isinf_optab = init_optab (UNKNOWN); + strlen_optab = init_optab (UNKNOWN); cbranch_optab = init_optab (UNKNOWN); cmov_optab = init_optab (UNKNOWN); diff --git a/gcc/optabs.h b/gcc/optabs.h index 85d9ca7f32f..d3cfd742136 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -204,6 +204,9 @@ enum optab_index /* Copy sign */ OTI_copysign, + /* Test for infinite value */ + OTI_isinf, + /* Compare insn; two operands. */ OTI_cmp, /* Used only for libcalls for unsigned comparisons. */ @@ -370,6 +373,8 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define atan_optab (optab_table[OTI_atan]) #define copysign_optab (optab_table[OTI_copysign]) +#define isinf_optab (optab_table[OTI_isinf]) + #define cmp_optab (optab_table[OTI_cmp]) #define ucmp_optab (optab_table[OTI_ucmp]) #define tst_optab (optab_table[OTI_tst]) diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 0df425eebeb..f21d833c00b 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -1629,6 +1629,27 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) replace_reg (src1, FIRST_STACK_REG); break; + case UNSPEC_FXAM: + + /* This insn only operate on the top of the stack. */ + + src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); + emit_swap_insn (insn, regstack, *src1); + + src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); + + replace_reg (src1, FIRST_STACK_REG); + + if (src1_note) + { + remove_regno_note (insn, REG_DEAD, + REGNO (XEXP (src1_note, 0))); + emit_pop_insn (insn, regstack, XEXP (src1_note, 0), + EMIT_AFTER); + } + + break; + case UNSPEC_SIN: case UNSPEC_COS: case UNSPEC_FRNDINT: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d28f8e6d5d7..97bf5f17fca 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-01-31 Uros Bizjak <ubizjak@gmail.com> + + * gcc.dg/builtins-63.c: New test. + 2007-01-31 Tobias Burnus <burnus@net-b.de> PR fortran/27588 diff --git a/gcc/testsuite/gcc.dg/builtins-63.c b/gcc/testsuite/gcc.dg/builtins-63.c new file mode 100644 index 00000000000..8fcbc68e6f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-63.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2007 Free Software Foundation. + + Check that isinf, isinff and isinfl built-in functions compile. + + Written by Uros Bizjak, 31st January 2007. */ + +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern int isinf(double); +extern int isinff(float); +extern int isinfl(long double); + +int test1(double x) +{ + return isinf(x); +} + +int test1f(float x) +{ + return isinff(x); +} + +int test1l(long double x) +{ + return isinfl(x); +} + |