aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-03-15 14:30:04 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2012-03-15 14:30:04 +0100
commitff63ac4d66fdcd9e0952b31b5dae947ffc638814 (patch)
tree9c5c685efbb7fcf5539bf495c5fc114ab6f1a24f /gcc
parentb3781fcb265e24fd61be94e716027a33c0712ed0 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/builtins.c75
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr52592.c21
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" } } */