diff options
| author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-15 13:30:04 +0000 |
|---|---|---|
| committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-15 13:30:04 +0000 |
| commit | e951f9a4e71534f2369175892bfa8783b738de89 (patch) | |
| tree | 9c5c685efbb7fcf5539bf495c5fc114ab6f1a24f | |
| parent | ce1d2364eca9dbd261f14afa6b180b0e174948ea (diff) | |
| download | ppe42-gcc-e951f9a4e71534f2369175892bfa8783b738de89.tar.gz ppe42-gcc-e951f9a4e71534f2369175892bfa8783b738de89.zip | |
PR middle-end/52592
* builtins.c (expand_builtin_int_roundingfn_2): If expanding
BUILT_IN_IR{INT,OUND}* using optab fails, emit lr{int,ound}*
calls instead of __builtin_ir{int,ound}*.
* gcc.dg/pr52592.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185431 138bc75d-0d04-0410-961f-82ee72b054a4
| -rw-r--r-- | gcc/ChangeLog | 8 | ||||
| -rw-r--r-- | gcc/builtins.c | 75 | ||||
| -rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/pr52592.c | 21 |
4 files changed, 87 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fbaaab3375c..12178336bcc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-03-15 Jakub Jelinek <jakub@redhat.com> + Andrew Pinski <apinski@cavium.com> + + PR middle-end/52592 + * builtins.c (expand_builtin_int_roundingfn_2): If expanding + BUILT_IN_IR{INT,OUND}* using optab fails, emit lr{int,ound}* + calls instead of __builtin_ir{int,ound}*. + 2012-03-15 Bernhard Reutner-Fischer <aldot@gcc.gnu.org> * doc/sourcebuild.texi (cleanup-modules, keep-modules): Update diff --git a/gcc/builtins.c b/gcc/builtins.c index b937d3d0938..a086a8cb1a5 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2841,10 +2841,7 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target) tree fndecl = get_callee_fndecl (exp); tree arg; enum machine_mode mode; - - /* There's no easy way to detect the case we need to set EDOM. */ - if (flag_errno_math) - return NULL_RTX; + enum built_in_function fallback_fn = BUILT_IN_NONE; if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) gcc_unreachable (); @@ -2854,46 +2851,78 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx target) switch (DECL_FUNCTION_CODE (fndecl)) { CASE_FLT_FN (BUILT_IN_IRINT): + fallback_fn = BUILT_IN_LRINT; + /* FALLTHRU */ CASE_FLT_FN (BUILT_IN_LRINT): CASE_FLT_FN (BUILT_IN_LLRINT): - builtin_optab = lrint_optab; break; + builtin_optab = lrint_optab; + break; CASE_FLT_FN (BUILT_IN_IROUND): + fallback_fn = BUILT_IN_LROUND; + /* FALLTHRU */ CASE_FLT_FN (BUILT_IN_LROUND): CASE_FLT_FN (BUILT_IN_LLROUND): - builtin_optab = lround_optab; break; + builtin_optab = lround_optab; + break; default: gcc_unreachable (); } + /* There's no easy way to detect the case we need to set EDOM. */ + if (flag_errno_math && fallback_fn == BUILT_IN_NONE) + return NULL_RTX; + /* Make a suitable register to place result in. */ mode = TYPE_MODE (TREE_TYPE (exp)); - target = gen_reg_rtx (mode); + /* There's no easy way to detect the case we need to set EDOM. */ + if (!flag_errno_math) + { + target = gen_reg_rtx (mode); - /* Wrap the computation of the argument in a SAVE_EXPR, as we may - need to expand the argument again. This way, we will not perform - side-effects more the once. */ - CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg); + /* Wrap the computation of the argument in a SAVE_EXPR, as we may + need to expand the argument again. This way, we will not perform + side-effects more the once. */ + CALL_EXPR_ARG (exp, 0) = arg = builtin_save_expr (arg); - op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL); + op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL); - start_sequence (); + start_sequence (); - if (expand_sfix_optab (target, op0, builtin_optab)) - { - /* Output the entire sequence. */ - insns = get_insns (); + if (expand_sfix_optab (target, op0, builtin_optab)) + { + /* Output the entire sequence. */ + insns = get_insns (); + end_sequence (); + emit_insn (insns); + return target; + } + + /* If we were unable to expand via the builtin, stop the sequence + (without outputting the insns) and call to the library function + with the stabilized argument list. */ end_sequence (); - emit_insn (insns); - return target; } - /* If we were unable to expand via the builtin, stop the sequence - (without outputting the insns) and call to the library function - with the stabilized argument list. */ - end_sequence (); + if (fallback_fn != BUILT_IN_NONE) + { + /* Fall back to rounding to long int. Use implicit_p 0 - for non-C99 + targets, (int) round (x) should never be transformed into + BUILT_IN_IROUND and if __builtin_iround is called directly, emit + a call to lround in the hope that the target provides at least some + C99 functions. This should result in the best user experience for + not full C99 targets. */ + tree fallback_fndecl = mathfn_built_in_1 (TREE_TYPE (arg), + fallback_fn, 0); + + exp = build_call_nofold_loc (EXPR_LOCATION (exp), + fallback_fndecl, 1, arg); + + target = expand_call (exp, NULL_RTX, target == const0_rtx); + return convert_to_mode (mode, target, 0); + } target = expand_call (exp, target, target == const0_rtx); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 03fbf871a51..0bcdd035e7e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-03-15 Jakub Jelinek <jakub@redhat.com> + Andrew Pinski <apinski@cavium.com> + + PR middle-end/52592 + * gcc.dg/pr52592.c: New test. + 2012-03-15 Bernhard Reutner-Fischer <aldot@gcc.gnu.org> * gfortran.fortran-torture/compile/compile.exp: Simplify. diff --git a/gcc/testsuite/gcc.dg/pr52592.c b/gcc/testsuite/gcc.dg/pr52592.c new file mode 100644 index 00000000000..b71eb628de2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr52592.c @@ -0,0 +1,21 @@ +/* PR middle-end/52592 */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99 -O2 -ffast-math" } */ + +#define T(type, name) \ +type name (type); \ +__attribute__((cold)) \ +int f##name (type x) \ +{ \ + return (int) name (x); \ +} + +T (double, round) +T (float, roundf) +T (long double, roundl) +T (double, rint) +T (float, rintf) +T (long double, rintl) + +/* { dg-final { scan-assembler-not "__builtin_iround" } } */ +/* { dg-final { scan-assembler-not "__builtin_irint" } } */ |

