diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-03-15 14:30:04 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-03-15 14:30:04 +0100 |
commit | ff63ac4d66fdcd9e0952b31b5dae947ffc638814 (patch) | |
tree | 9c5c685efbb7fcf5539bf495c5fc114ab6f1a24f /gcc | |
parent | b3781fcb265e24fd61be94e716027a33c0712ed0 (diff) | |
download | gcc-ff63ac4d66fdcd9e0952b31b5dae947ffc638814.zip gcc-ff63ac4d66fdcd9e0952b31b5dae947ffc638814.tar.gz gcc-ff63ac4d66fdcd9e0952b31b5dae947ffc638814.tar.bz2 |
re PR middle-end/52592 (compilation failure with undefined reference to `__builtin_iround')
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.
Co-Authored-By: Andrew Pinski <apinski@cavium.com>
From-SVN: r185431
Diffstat (limited to 'gcc')
-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 fbaaab3..1217833 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 b937d3d..a086a8c 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 03fbf87..0bcdd03 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 0000000..b71eb62 --- /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" } } */ |