This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix errno handling for lrint expansion


errno handling is currently wrong for lrint, which has an integer
return mode while we are checking for HONOR_NANs on this mode
to disable errno handling or later use expand_errno_check which
uses the unordered compare res == res which is pointless for
integer modes again.

Fixed by splitting out this expansion to a separate function and
disabling optab expansion for flag_math_errno.  (I wonder if we
want to move such checks to the optab expanders itself - if we'd
actually know the errno location)

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Ok for mainline after branching?

Thanks,
Richard.

:ADDPATCH middle-end:

2006-08-09  Richard Guenther  <rguenther@suse.de>

	* builtins.c (expand_builtin_int_roundingfn_2): New function.
	(expand_builtin): Use it to expand lrint instead of
	expand_builtin_mathfn.

Index: builtins.c
===================================================================
*** builtins.c	(revision 116085)
--- builtins.c	(working copy)
*************** static rtx expand_builtin_mathfn_2 (tree
*** 96,101 ****
--- 96,102 ----
  static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
  static rtx expand_builtin_sincos (tree);
  static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
+ static rtx expand_builtin_int_roundingfn_2 (tree, rtx, rtx);
  static rtx expand_builtin_args_info (tree);
  static rtx expand_builtin_next_arg (void);
  static rtx expand_builtin_va_start (tree);
*************** expand_builtin_mathfn (tree exp, rtx tar
*** 1851,1859 ****
        builtin_optab = nearbyint_optab; break;
      CASE_FLT_FN (BUILT_IN_RINT):
        builtin_optab = rint_optab; break;
-     CASE_FLT_FN (BUILT_IN_LRINT):
-     CASE_FLT_FN (BUILT_IN_LLRINT):
-       builtin_optab = lrint_optab; break;
      default:
        gcc_unreachable ();
      }
--- 1852,1857 ----
*************** expand_builtin_sincos (tree exp)
*** 2226,2232 ****
    return const0_rtx;
  }
  
! /* Expand a call to one of the builtin rounding functions (lfloor).
     If expanding via optab fails, lower expression to (int)(floor(x)).
     EXP is the expression that is a call to the builtin function;
     if convenient, the result should be placed in TARGET.  SUBTARGET may
--- 2224,2232 ----
    return const0_rtx;
  }
  
! /* Expand a call to one of the builtin rounding functions gcc defines
!    as an extension (lfloor and lceil).  As these are gcc extensions we
!    do not need to worry about setting errno to EDOM.
     If expanding via optab fails, lower expression to (int)(floor(x)).
     EXP is the expression that is a call to the builtin function;
     if convenient, the result should be placed in TARGET.  SUBTARGET may
*************** expand_builtin_int_roundingfn (tree exp,
*** 2325,2330 ****
--- 2325,2412 ----
    return target;
  }
  
+ /* Expand a call to one of the builtin math functions doing integer
+    conversion (lrint).
+    Return 0 if a normal call should be emitted rather than expanding the
+    function in-line.  EXP is the expression that is a call to the builtin
+    function; if convenient, the result should be placed in TARGET.
+    SUBTARGET may be used as the target for computing one of EXP's operands.  */
+ 
+ static rtx
+ expand_builtin_int_roundingfn_2 (tree exp, rtx target, rtx subtarget)
+ {
+   optab builtin_optab;
+   rtx op0, insns;
+   tree fndecl = get_callee_fndecl (exp);
+   tree arglist = TREE_OPERAND (exp, 1);
+   enum machine_mode mode;
+   tree arg, narg;
+ 
+   /* There's no easy way to detect the case we need to set EDOM.  */
+   if (flag_errno_math)
+     return NULL_RTX;
+ 
+   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+     return NULL_RTX;
+ 
+   arg = TREE_VALUE (arglist);
+ 
+   switch (DECL_FUNCTION_CODE (fndecl))
+     {
+     CASE_FLT_FN (BUILT_IN_LRINT):
+     CASE_FLT_FN (BUILT_IN_LLRINT):
+       builtin_optab = lrint_optab; break;
+     default:
+       gcc_unreachable ();
+     }
+ 
+   /* Make a suitable register to place result in.  */
+   mode = TYPE_MODE (TREE_TYPE (exp));
+ 
+   /* Before working hard, check whether the instruction is available.  */
+   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+     {
+       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.  */
+       narg = builtin_save_expr (arg);
+       if (narg != arg)
+ 	{
+ 	  arg = narg;
+ 	  arglist = build_tree_list (NULL_TREE, arg);
+ 	  exp = build_function_call_expr (fndecl, arglist);
+ 	}
+ 
+       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
+ 
+       start_sequence ();
+ 
+       /* Compute into TARGET.
+ 	 Set TARGET to wherever the result comes back.  */
+       target = expand_unop (mode, builtin_optab, op0, target, 0);
+ 
+       if (target != 0)
+ 	{
+ 	  /* 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 ();
+     }
+ 
+   target = expand_call (exp, target, target == const0_rtx);
+ 
+   return target;
+ }
+ 
  /* To evaluate powi(x,n), the floating point value x raised to the
     constant integer exponent n, we use a hybrid algorithm that
     combines the "window method" with look-up tables.  For an
*************** expand_builtin (tree exp, rtx target, rt
*** 5685,5692 ****
      CASE_FLT_FN (BUILT_IN_ROUND):
      CASE_FLT_FN (BUILT_IN_NEARBYINT):
      CASE_FLT_FN (BUILT_IN_RINT):
-     CASE_FLT_FN (BUILT_IN_LRINT):
-     CASE_FLT_FN (BUILT_IN_LLRINT):
        target = expand_builtin_mathfn (exp, target, subtarget);
        if (target)
  	return target;
--- 5767,5772 ----
*************** expand_builtin (tree exp, rtx target, rt
*** 5701,5706 ****
--- 5781,5793 ----
  	return target;
        break;
  
+     CASE_FLT_FN (BUILT_IN_LRINT):
+     CASE_FLT_FN (BUILT_IN_LLRINT):
+       target = expand_builtin_int_roundingfn_2 (exp, target, subtarget);
+       if (target)
+ 	return target;
+       break;
+ 
      CASE_FLT_FN (BUILT_IN_POW):
        target = expand_builtin_pow (exp, target, subtarget);
        if (target)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]