[PATCH][RFC] Fix issues with setting errno (PR29887)

Richard Guenther rguenther@suse.de
Sat Nov 18 17:25:00 GMT 2006


At the moment we try to do errno setting via the expand_errno_check
function for the math builtins where required.  Unfortunately this is
only possible if the argument is NaN in all cases where errno has to
be set.  We at the moment generate wrong-code if the return type of
the math builtin is integer, the target does not honor NaNs or errno
is required to be set on Overflow which typically results in a +Inf
or -Inf return value (or even just FLOAT_MIN/MAX for other than default
rounding modes).

This patch tries to provide a central place to decide whether 
expand_errno_check is sufficient for fulfilling the C99 requirements on
errno setting (regardless of -fno-errno-math or HONOR_NANS).  It also
corrects _one_ expander function (because this is just a RFC for now).

The question remains on the use of HONOR_NANS to disable correct errno
handling.  I believe this is a mistake and so we should not do this.
If we want to do it we ought to warn about -ferrno-math in case of
HONOR_NANS being false.  Defering to the library is the most conservative
approach if -ferrno-math is set.

Another possibility would be to just get rid of expand_errno_check
completely and defer to the target to control expansion for the
-ferrno-math and -fno-errno-math cases.

Thoughts?

Thanks,
Richard.


2006-11-18  Richard Guenther  <rguenther@suse.de>

	PR middle-end/29887
	* builtins.c (can_expand_errno_check): New static function.
	(expand_builtin_mathfn): Use it to detect whether expand_errno_check
	is able to correctly set errno.

Index: builtins.c
===================================================================
*** builtins.c	(revision 118972)
--- builtins.c	(working copy)
*************** expand_errno_check (tree exp, rtx target
*** 1772,1777 ****
--- 1772,1838 ----
    emit_label (lab);
  }
  
+ /* Returns true if expand_errno_check can be used to set the errno
+    variable based on the result of the builtin function with code CODE.
+    Note that if we do not honor NaNs the errno check cannot be emitted
+    correctly.  Otherwise returns false.  */
+ 
+ static bool
+ can_expand_errno_check (enum built_in_function code)
+ {
+   switch (code)
+     {
+     CASE_FLT_FN (BUILT_IN_SQRT):
+       /* A domain error occurs if the argument is less than zero.
+          IEEE requires NaN returned in this case.  */
+       return true;
+ 
+     CASE_FLT_FN (BUILT_IN_EXP):
+     CASE_FLT_FN (BUILT_IN_EXP2):
+     CASE_FLT_FN (BUILT_IN_EXPM1):
+       /* exp (x): A range error occurs if the magnitude of x is too large.
+          In the overflow case Inf is returned.  */
+       return false;
+ 
+     CASE_FLT_FN (BUILT_IN_ILOGB):
+       /* A range error may occur if the argument is zero.  */
+       return false;
+ 
+     CASE_FLT_FN (BUILT_IN_LOGB):
+     CASE_FLT_FN (BUILT_IN_LOG):
+     CASE_FLT_FN (BUILT_IN_LOG2):
+     CASE_FLT_FN (BUILT_IN_LOG10):
+     CASE_FLT_FN (BUILT_IN_LOG1P):
+       /* A domain error occurs if the argument is negative.  A range erro
+ 	 may occur if the argument is zero.
+ 	 log (+-0) returns -Inf, log (+Inf) returns +Inf.  */
+       return false;
+ 
+     CASE_FLT_FN (BUILT_IN_ASIN):
+     CASE_FLT_FN (BUILT_IN_ACOS):
+       /* A domain error occurs for arguments not in the interval [-1, 1].  */
+       return true;
+ 
+     CASE_FLT_FN (BUILT_IN_FLOOR):
+     CASE_FLT_FN (BUILT_IN_CEIL):
+     CASE_FLT_FN (BUILT_IN_TRUNC):
+     CASE_FLT_FN (BUILT_IN_ROUND):
+     CASE_FLT_FN (BUILT_IN_NEARBYINT):
+     CASE_FLT_FN (BUILT_IN_RINT):
+     CASE_FLT_FN (BUILT_IN_TAN):
+     CASE_FLT_FN (BUILT_IN_ATAN):
+       /* No required error conditions.  */
+       return true;
+ 
+     CASE_FLT_FN (BUILT_IN_EXP10):
+     CASE_FLT_FN (BUILT_IN_POW10):
+       /* GNU extension.  Nothing specified.  */
+       return true;
+ 
+     default:
+       gcc_unreachable ();
+     }
+ }
  
  /* Expand a call to one of the builtin math functions (sqrt, exp, or log).
     Return 0 if a normal call should be emitted rather than expanding the
*************** expand_builtin_mathfn (tree exp, rtx tar
*** 1856,1862 ****
      errno_set = false;
  
    /* 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);
  
--- 1917,1925 ----
      errno_set = false;
  
    /* Before working hard, check whether the instruction is available.  */
!   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
!       && (! errno_set
! 	  || can_expand_errno_check (DECL_FUNCTION_CODE (fndecl))))
      {
        target = gen_reg_rtx (mode);
  



More information about the Gcc-patches mailing list