On Thu, Mar 15, 2012 at 2:06 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > If __builtin_ir{int,ound}{,f,l} expansion through optab fails, > we would end up generating a call to __builtin_ir{int,ound}{,f,l} > function (there is no ir{int,ound}{,f,l} in libm), which is wrong, > we should expand it as (int) lr{int,ound}{,f,l} in that case (similarly > to what we already do with __builtin_{i,l,ll}{ceil,floor}{,f,l}). > > This has been reported as a failure to build mplayer on x86_64-linux > as well as a failure to build pulseaudio on s390x-linux. > > Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, > ok for trunk and 4.7.0?
Yes. Thanks, Richard. > 2012-03-15 Jakub Jelinek <ja...@redhat.com> > Andrew Pinski <apin...@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}*. > > * gcc.dg/pr52592.c: New test. > > --- gcc/builtins.c.jj 2012-02-12 15:46:32.000000000 +0100 > +++ gcc/builtins.c 2012-03-15 10:20:59.335215596 +0100 > @@ -2841,10 +2841,7 @@ expand_builtin_int_roundingfn_2 (tree ex > 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,47 +2851,79 @@ expand_builtin_int_roundingfn_2 (tree ex > 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); > + > + start_sequence (); > + > + 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 (); > + } > > - op0 = expand_expr (arg, NULL, VOIDmode, EXPAND_NORMAL); > + 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); > > - start_sequence (); > + exp = build_call_nofold_loc (EXPR_LOCATION (exp), > + fallback_fndecl, 1, arg); > > - if (expand_sfix_optab (target, op0, builtin_optab)) > - { > - /* Output the entire sequence. */ > - insns = get_insns (); > - end_sequence (); > - emit_insn (insns); > - return target; > + target = expand_call (exp, NULL_RTX, target == const0_rtx); > + return convert_to_mode (mode, target, 0); > } > > - /* 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 (); > - > target = expand_call (exp, target, target == const0_rtx); > > return target; > --- gcc/testsuite/gcc.dg/pr52592.c.jj 2012-03-15 10:23:51.701213103 +0100 > +++ gcc/testsuite/gcc.dg/pr52592.c 2012-03-15 10:20:18.000000000 +0100 > @@ -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" } } */ > > Jakub