* Simplify floating point conversions @ 2002-11-05 9:14 Jan Hubicka 2002-11-05 9:38 ` Richard Henderson 2002-11-05 11:14 ` Simplify floating point conversions Geoff Keating 0 siblings, 2 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-05 9:14 UTC (permalink / raw) To: gcc-patches, rth, aj Hi, this patch makes us to simplify some of the floating point operations to narrower mode when conversions are present. This include +,-,/,*,abs,neg,sqrt/sin/cos/exp. I believe it is IEEE safe, but some expert would be welcome. The sqrt/sin/cos/exp conversion does not work in fortran mode, since built_in_decls is not initialized. I was trying to get around but never suceeded to produce working call there. Honza Tue Nov 5 02:06:18 PST 2002 Jan Hubicka <jh@suse.cz> * convert.c (convert_to_real): Simplify some special cases. Index: convert.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/convert.c,v retrieving revision 1.19 diff -c -3 -p -r1.19 convert.c *** convert.c 4 Jul 2002 06:38:54 -0000 1.19 --- convert.c 5 Nov 2002 17:09:53 -0000 *************** tree *** 80,85 **** --- 80,203 ---- convert_to_real (type, expr) tree type, expr; { + enum built_in_function fcode = builtin_mathfn_code (expr); + tree itype = TREE_TYPE (expr); + + if ((fcode == BUILT_IN_SQRT + || fcode == BUILT_IN_SQRTL + || fcode == BUILT_IN_SIN + || fcode == BUILT_IN_SINL + || fcode == BUILT_IN_COS + || fcode == BUILT_IN_COSL + || fcode == BUILT_IN_EXP + || fcode == BUILT_IN_EXPL) + && (TYPE_MODE (type) == TYPE_MODE (double_type_node) + || TYPE_MODE (type) == TYPE_MODE (float_type_node))) + { + tree arg0 = TREE_VALUE (TREE_OPERAND (expr, 1)); + tree newtype = type; + + if (TREE_CODE (arg0) == NOP_EXPR) + arg0 = TREE_OPERAND (arg0, 0); + + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) + newtype = TREE_TYPE (arg0); + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && TYPE_PRECISION (newtype) <= TYPE_PRECISION (itype) + && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) + || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) + { + tree arglist, decl; + if (TYPE_MODE (type) == TYPE_MODE (float_type_node)) + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRTF; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SINF; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COSF; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXPF; + break; + default: + abort (); + } + else + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRT; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SIN; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COS; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXP; + break; + default: + abort (); + } + + if (built_in_decls [fcode]) + { + decl = build_function_call_expr (built_in_decls [fcode], arglist); + return decl; + } + } + } + if (itype != type && FLOAT_TYPE_P (type)) + switch (TREE_CODE (expr)) + { + case ABS_EXPR: + case NEGATE_EXPR: + return build1 (TREE_CODE (expr), type, + fold (convert_to_real (type, + TREE_OPERAND (expr, 0)))); + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case RDIV_EXPR: + { + tree arg0 = TREE_OPERAND (expr, 0); + tree arg1 = TREE_OPERAND (expr, 1); + if (TREE_CODE (arg0) == NOP_EXPR) + arg0 = TREE_OPERAND (arg0, 0); + if (TREE_CODE (arg1) == NOP_EXPR) + arg1 = TREE_OPERAND (arg1, 0); + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && FLOAT_TYPE_P (TREE_TYPE (arg1))) + { + tree newtype = type; + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg0); + if (TYPE_PRECISION (TREE_TYPE (arg1)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg1); + if (TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)) + return build (TREE_CODE (expr), newtype, + fold (convert_to_real (newtype, arg0)), + fold (convert_to_real (newtype, arg1))); + } + } + break; + default: + break; + } + switch (TREE_CODE (TREE_TYPE (expr))) { case REAL_TYPE: ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions 2002-11-05 9:14 Simplify floating point conversions Jan Hubicka @ 2002-11-05 9:38 ` Richard Henderson 2002-11-05 9:42 ` Jan Hubicka 2002-11-06 1:23 ` Simplify floating point conversions II Jan Hubicka 2002-11-05 11:14 ` Simplify floating point conversions Geoff Keating 1 sibling, 2 replies; 41+ messages in thread From: Richard Henderson @ 2002-11-05 9:38 UTC (permalink / raw) To: Jan Hubicka; +Cc: gcc-patches, aj On Tue, Nov 05, 2002 at 06:14:00PM +0100, Jan Hubicka wrote: > Hi, > this patch makes us to simplify some of the floating point operations to > narrower mode when conversions are present. This include > +,-,/,*,abs,neg,sqrt/sin/cos/exp. > I believe it is IEEE safe, but some expert would be welcome. You should have commented this. It should not take someone 5 minutes to even figure out what's going on here. To be sure, it's (float)sqrtl(x) -> sqrtf((float)x) correct? Well, clearly this fails for X = 2**(127 * 2), since X is not representable as a float, but its square root is. It would not be hard to identify similar problems with every other operation on your list except for ABS/NEG. r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions 2002-11-05 9:38 ` Richard Henderson @ 2002-11-05 9:42 ` Jan Hubicka 2002-11-06 1:23 ` Simplify floating point conversions II Jan Hubicka 1 sibling, 0 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-05 9:42 UTC (permalink / raw) To: Richard Henderson, Jan Hubicka, gcc-patches, aj > On Tue, Nov 05, 2002 at 06:14:00PM +0100, Jan Hubicka wrote: > > Hi, > > this patch makes us to simplify some of the floating point operations to > > narrower mode when conversions are present. This include > > +,-,/,*,abs,neg,sqrt/sin/cos/exp. > > I believe it is IEEE safe, but some expert would be welcome. > > You should have commented this. It should not take someone 5 Oops... > minutes to even figure out what's going on here. To be sure, it's > > (float)sqrtl(x) -> sqrtf((float)x) It does just (float)sqrt((float)x)->sqrtf(x) This is common in C code when you call sqrt on float value. Honza > > correct? Well, clearly this fails for X = 2**(127 * 2), since > X is not representable as a float, but its square root is. It > would not be hard to identify similar problems with every other > operation on your list except for ABS/NEG. > > > r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Simplify floating point conversions II 2002-11-05 9:38 ` Richard Henderson 2002-11-05 9:42 ` Jan Hubicka @ 2002-11-06 1:23 ` Jan Hubicka 2002-11-06 3:08 ` Michael Matz 2002-11-06 9:54 ` Jan Hubicka 1 sibling, 2 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 1:23 UTC (permalink / raw) To: Richard Henderson, Jan Hubicka, gcc-patches, aj > On Tue, Nov 05, 2002 at 06:14:00PM +0100, Jan Hubicka wrote: > > Hi, > > this patch makes us to simplify some of the floating point operations to > > narrower mode when conversions are present. This include > > +,-,/,*,abs,neg,sqrt/sin/cos/exp. > > I believe it is IEEE safe, but some expert would be welcome. > > You should have commented this. It should not take someone 5 > minutes to even figure out what's going on here. To be sure, it's > > (float)sqrtl(x) -> sqrtf((float)x) > > correct? Well, clearly this fails for X = 2**(127 * 2), since > X is not representable as a float, but its square root is. It > would not be hard to identify similar problems with every other > operation on your list except for ABS/NEG. Hi, here is updated version with the comments. Even when the cases it shoots for looks incommon, they are not. In mesa (real one, not spec2000) I get 110 conversions removed with this patch. I get matches in most of code using floats extensivly because of C conventions to implicitly cast to double in some cases. Interestingly enought I get matches in fortran code too in spec2000, so it may be wortwhile to resolve the builtins problems. Wed Nov 6 10:17:44 CET 2002 Jan Hubicka <jh@suse.cz> * convert.c (convert_to_real): Simplify some special cases. Index: convert.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/convert.c,v retrieving revision 1.19 diff -c -3 -p -r1.19 convert.c *** convert.c 4 Jul 2002 06:38:54 -0000 1.19 --- convert.c 6 Nov 2002 09:16:56 -0000 *************** tree *** 80,85 **** --- 80,223 ---- convert_to_real (type, expr) tree type, expr; { + enum built_in_function fcode = builtin_mathfn_code (expr); + tree itype = TREE_TYPE (expr); + + /* Convert (float)sqrt((double)x) into sqrtf(x) + For fast math it would be safe probably to convert (float)sqrt(x) + into sqrt((float)x), but in strict mode the argument can overflow. */ + if ((fcode == BUILT_IN_SQRT + || fcode == BUILT_IN_SQRTL + || fcode == BUILT_IN_SIN + || fcode == BUILT_IN_SINL + || fcode == BUILT_IN_COS + || fcode == BUILT_IN_COSL + || fcode == BUILT_IN_EXP + || fcode == BUILT_IN_EXPL) + && (TYPE_MODE (type) == TYPE_MODE (double_type_node) + || TYPE_MODE (type) == TYPE_MODE (float_type_node))) + { + tree arg0 = TREE_VALUE (TREE_OPERAND (expr, 1)); + tree newtype = type; + + /* Wind away possible cast. */ + if (TREE_CODE (arg0) == NOP_EXPR) + arg0 = TREE_OPERAND (arg0, 0); + + /* We have (outertype)sqrt((innertype)x). Choose the wider mode from + the both as the safe type for operation. */ + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) + newtype = TREE_TYPE (arg0); + + /* Be curefull about integer to fp conversions. + These may overflow still. */ + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && TYPE_PRECISION (newtype) <= TYPE_PRECISION (itype) + && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) + || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) + { + tree arglist, decl; + if (TYPE_MODE (type) == TYPE_MODE (float_type_node)) + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRTF; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SINF; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COSF; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXPF; + break; + default: + abort (); + } + else + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRT; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SIN; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COS; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXP; + break; + default: + abort (); + } + + /* ??? Fortran frontend does not initialize built_in_decls. + For some reason creating the decl using builtin_function does not + work as it should. */ + if (built_in_decls [fcode]) + { + decl = build_function_call_expr (built_in_decls [fcode], arglist); + return decl; + } + } + } + + /* Propagate the cast into the operation. */ + if (itype != type && FLOAT_TYPE_P (type)) + switch (TREE_CODE (expr)) + { + /* convert (float)-x into -(float)x. This is always safe. */ + case ABS_EXPR: + case NEGATE_EXPR: + return build1 (TREE_CODE (expr), type, + fold (convert_to_real (type, + TREE_OPERAND (expr, 0)))); + /* convert (outertype)((innertype0)a+(innertype1)b) + into ((newtype)a+(newtype)b) where newtype + is the widest mode from all of these. */ + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case RDIV_EXPR: + { + tree arg0 = TREE_OPERAND (expr, 0); + tree arg1 = TREE_OPERAND (expr, 1); + + /* Unwind possible casts. */ + if (TREE_CODE (arg0) == NOP_EXPR) + arg0 = TREE_OPERAND (arg0, 0); + if (TREE_CODE (arg1) == NOP_EXPR) + arg1 = TREE_OPERAND (arg1, 0); + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && FLOAT_TYPE_P (TREE_TYPE (arg1))) + { + tree newtype = type; + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg0); + if (TYPE_PRECISION (TREE_TYPE (arg1)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg1); + if (TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)) + return build (TREE_CODE (expr), newtype, + fold (convert_to_real (newtype, arg0)), + fold (convert_to_real (newtype, arg1))); + } + } + break; + default: + break; + } + switch (TREE_CODE (TREE_TYPE (expr))) { case REAL_TYPE: ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 1:23 ` Simplify floating point conversions II Jan Hubicka @ 2002-11-06 3:08 ` Michael Matz 2002-11-06 4:36 ` Jan Hubicka 2002-11-06 9:54 ` Jan Hubicka 1 sibling, 1 reply; 41+ messages in thread From: Michael Matz @ 2002-11-06 3:08 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Hi, On Wed, 6 Nov 2002, Jan Hubicka wrote: > + /* Convert (float)sqrt((double)x) into sqrtf(x) You probably want to say that you do this when x is float, which is exactly the crucial point in your patch. Ciao, Michael. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 3:08 ` Michael Matz @ 2002-11-06 4:36 ` Jan Hubicka 0 siblings, 0 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 4:36 UTC (permalink / raw) To: Michael Matz; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj > Hi, > > On Wed, 6 Nov 2002, Jan Hubicka wrote: > > > + /* Convert (float)sqrt((double)x) into sqrtf(x) > > You probably want to say that you do this when x is float, which is > exactly the crucial point in your patch. It is writen in the next comment, but you are right, I should do that. Honza > > > Ciao, > Michael. ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 1:23 ` Simplify floating point conversions II Jan Hubicka 2002-11-06 3:08 ` Michael Matz @ 2002-11-06 9:54 ` Jan Hubicka 2002-11-06 10:09 ` Richard Henderson 1 sibling, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 9:54 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Hi, I've noticed that one line of patch got lost for some reason. Honza Wed Nov 6 10:17:44 CET 2002 Jan Hubicka <jh@suse.cz> * convert.c (convert_to_real): Simplify some special cases. Index: convert.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/convert.c,v retrieving revision 1.19 diff -c -3 -p -r1.19 convert.c *** convert.c 4 Jul 2002 06:38:54 -0000 1.19 --- convert.c 6 Nov 2002 17:53:09 -0000 *************** tree *** 80,85 **** --- 80,223 ---- convert_to_real (type, expr) tree type, expr; { + enum built_in_function fcode = builtin_mathfn_code (expr); + tree itype = TREE_TYPE (expr); + + /* Convert (float)sqrt((double)x) into sqrtf(x) + For fast math it would be safe probably to convert (float)sqrt(x) + into sqrt((float)x), but in strict mode the argument can overflow. */ + if ((fcode == BUILT_IN_SQRT + || fcode == BUILT_IN_SQRTL + || fcode == BUILT_IN_SIN + || fcode == BUILT_IN_SINL + || fcode == BUILT_IN_COS + || fcode == BUILT_IN_COSL + || fcode == BUILT_IN_EXP + || fcode == BUILT_IN_EXPL) + && (TYPE_MODE (type) == TYPE_MODE (double_type_node) + || TYPE_MODE (type) == TYPE_MODE (float_type_node))) + { + tree arg0 = TREE_VALUE (TREE_OPERAND (expr, 1)); + tree newtype = type; + + /* Wind away possible cast. */ + if (TREE_CODE (arg0) == NOP_EXPR) + arg0 = TREE_OPERAND (arg0, 0); + + /* We have (outertype)sqrt((innertype)x). Choose the wider mode from + the both as the safe type for operation. */ + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) + newtype = TREE_TYPE (arg0); + + /* Be curefull about integer to fp conversions. + These may overflow still. */ + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && TYPE_PRECISION (newtype) <= TYPE_PRECISION (itype) + && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) + || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) + { + tree arglist, decl; + if (TYPE_MODE (type) == TYPE_MODE (float_type_node)) + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRTF; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SINF; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COSF; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXPF; + break; + default: + abort (); + } + else + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRT; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SIN; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COS; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXP; + break; + default: + abort (); + } + + /* ??? Fortran frontend does not initialize built_in_decls. + For some reason creating the decl using builtin_function does not + work as it should. */ + if (built_in_decls [fcode]) + { + arglist = build_tree_list (NULL_TREE, fold (convert_to_real (newtype, arg0))); + return build_function_call_expr (built_in_decls [fcode], arglist); + } + } + } + + /* Propagate the cast into the operation. */ + if (itype != type && FLOAT_TYPE_P (type)) + switch (TREE_CODE (expr)) + { + /* convert (float)-x into -(float)x. This is always safe. */ + case ABS_EXPR: + case NEGATE_EXPR: + return build1 (TREE_CODE (expr), type, + fold (convert_to_real (type, + TREE_OPERAND (expr, 0)))); + /* convert (outertype)((innertype0)a+(innertype1)b) + into ((newtype)a+(newtype)b) where newtype + is the widest mode from all of these. */ + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case RDIV_EXPR: + { + tree arg0 = TREE_OPERAND (expr, 0); + tree arg1 = TREE_OPERAND (expr, 1); + + /* Unwind possible casts. */ + if (TREE_CODE (arg0) == NOP_EXPR) + arg0 = TREE_OPERAND (arg0, 0); + if (TREE_CODE (arg1) == NOP_EXPR) + arg1 = TREE_OPERAND (arg1, 0); + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && FLOAT_TYPE_P (TREE_TYPE (arg1))) + { + tree newtype = type; + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg0); + if (TYPE_PRECISION (TREE_TYPE (arg1)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg1); + if (TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)) + return build (TREE_CODE (expr), newtype, + fold (convert_to_real (newtype, arg0)), + fold (convert_to_real (newtype, arg1))); + } + } + break; + default: + break; + } + switch (TREE_CODE (TREE_TYPE (expr))) { case REAL_TYPE: ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 9:54 ` Jan Hubicka @ 2002-11-06 10:09 ` Richard Henderson 2002-11-06 13:11 ` Jan Hubicka 2002-11-06 13:48 ` Simplify floating point conversions III Jan Hubicka 0 siblings, 2 replies; 41+ messages in thread From: Richard Henderson @ 2002-11-06 10:09 UTC (permalink / raw) To: Jan Hubicka; +Cc: gcc-patches, aj On Wed, Nov 06, 2002 at 06:54:41PM +0100, Jan Hubicka wrote: > + For fast math it would be safe probably to convert (float)sqrt(x) > + into sqrt((float)x), but in strict mode the argument can overflow. */ I don't believe this to be true. > + /* Wind away possible cast. */ > + if (TREE_CODE (arg0) == NOP_EXPR) > + arg0 = TREE_OPERAND (arg0, 0); Why would you do this? This might be casting down to double from long double. You should only strip casts when they widen the type. > + /* convert (outertype)((innertype0)a+(innertype1)b) > + into ((newtype)a+(newtype)b) where newtype > + is the widest mode from all of these. */ This changes overflow characteristics of +. Consider (double)((float)a + (float)b) where A = B = 2**127. The result should be +Inf, not 2**128. Finally, I think it is alarmingly incorrect that (float)((double)a + (double)b)) does not result in a quantity of type float, as requested. r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 10:09 ` Richard Henderson @ 2002-11-06 13:11 ` Jan Hubicka 2002-11-06 13:19 ` Jan Hubicka 2002-11-06 13:35 ` Gabriel Dos Reis 2002-11-06 13:48 ` Simplify floating point conversions III Jan Hubicka 1 sibling, 2 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 13:11 UTC (permalink / raw) To: Richard Henderson, Jan Hubicka, gcc-patches, aj > On Wed, Nov 06, 2002 at 06:54:41PM +0100, Jan Hubicka wrote: > > + For fast math it would be safe probably to convert (float)sqrt(x) > > + into sqrt((float)x), but in strict mode the argument can overflow. */ > > I don't believe this to be true. What you don't believe? That in ffast-math we can do the transformation? Right, that is possible. I am not sure whehter we can afford the possible overflow there. So I can drop the comment. > > > + /* Wind away possible cast. */ > > + if (TREE_CODE (arg0) == NOP_EXPR) > > + arg0 = TREE_OPERAND (arg0, 0); > > Why would you do this? This might be casting down to double from > long double. You should only strip casts when they widen the type. Right, I will add that. For some reason I believed that these are CONVERT. > > > + /* convert (outertype)((innertype0)a+(innertype1)b) > > + into ((newtype)a+(newtype)b) where newtype > > + is the widest mode from all of these. */ > > This changes overflow characteristics of +. Consider > > (double)((float)a + (float)b) > > where A = B = 2**127. The result should be +Inf, not 2**128. I am doing that only when the mode of + is wider. > > Finally, I think it is alarmingly incorrect that > > (float)((double)a + (double)b)) > > does not result in a quantity of type float, as requested. Here I do that. When a and b are floats, I will produce (a+b) is that wrong? Honza > > > r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 13:11 ` Jan Hubicka @ 2002-11-06 13:19 ` Jan Hubicka 2002-11-06 13:35 ` Gabriel Dos Reis 1 sibling, 0 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 13:19 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj > > On Wed, Nov 06, 2002 at 06:54:41PM +0100, Jan Hubicka wrote: > > > + For fast math it would be safe probably to convert (float)sqrt(x) > > (double)((float)a + (float)b) > > > > where A = B = 2**127. The result should be +Inf, not 2**128. > > I am doing that only when the mode of + is wider. > > > > Finally, I think it is alarmingly incorrect that > > > > (float)((double)a + (double)b)) > > > > does not result in a quantity of type float, as requested. > > Here I do that. When a and b are floats, I will produce > (a+b) > is that wrong? I see, you were shooting for something like (float)((long double)a + (long double)b) for a and b being double. That will result in (a+b) not casted to float that is wrong. I am adding recursive call to convert_to_real when this ahppends. Honza > > Honza > > > > > > r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 13:11 ` Jan Hubicka 2002-11-06 13:19 ` Jan Hubicka @ 2002-11-06 13:35 ` Gabriel Dos Reis 2002-11-06 13:36 ` Jan Hubicka 2002-11-06 14:29 ` Converting floor to rint Jan Hubicka 1 sibling, 2 replies; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-06 13:35 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Jan Hubicka <jh@suse.cz> writes: | > On Wed, Nov 06, 2002 at 06:54:41PM +0100, Jan Hubicka wrote: | > > + For fast math it would be safe probably to convert (float)sqrt(x) | > > + into sqrt((float)x), but in strict mode the argument can overflow. */ | > | > I don't believe this to be true. | | What you don't believe? Likew RTH, I, skeptical that your assertion is right. | That in ffast-math we can do the transformation? Do we really need to do that transformation? That is is there any real evidence that it brings any real benefit? I would be reluctant to include it even in -funsafe-math. -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 13:35 ` Gabriel Dos Reis @ 2002-11-06 13:36 ` Jan Hubicka 2002-11-06 14:06 ` Gabriel Dos Reis 2002-11-06 14:29 ` Converting floor to rint Jan Hubicka 1 sibling, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 13:36 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj > Jan Hubicka <jh@suse.cz> writes: > > | > On Wed, Nov 06, 2002 at 06:54:41PM +0100, Jan Hubicka wrote: > | > > + For fast math it would be safe probably to convert (float)sqrt(x) > | > > + into sqrt((float)x), but in strict mode the argument can overflow. */ > | > > | > I don't believe this to be true. > | > | What you don't believe? > > Likew RTH, I, skeptical that your assertion is right. > > | That in ffast-math we can do the transformation? > > Do we really need to do that transformation? That is is there any > real evidence that it brings any real benefit? > I would be reluctant to include it even in -funsafe-math. I am not implementing that transformation, so I am not sure. Doing the cases I do right now and I believe to be safe brings quite considerable amount of matches in standard C 3d graphics code that does a lot of float and some casts to double coming from implicit C stuff. Honza > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions II 2002-11-06 13:36 ` Jan Hubicka @ 2002-11-06 14:06 ` Gabriel Dos Reis 0 siblings, 0 replies; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-06 14:06 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Jan Hubicka <jh@suse.cz> writes: | I am not implementing that transformation, so I am not sure. Well, OK then I don't think I have any further comment on that side. -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Converting floor to rint 2002-11-06 13:35 ` Gabriel Dos Reis 2002-11-06 13:36 ` Jan Hubicka @ 2002-11-06 14:29 ` Jan Hubicka 2002-11-06 14:47 ` Richard Henderson 2002-11-06 14:55 ` Gabriel Dos Reis 1 sibling, 2 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 14:29 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj > Jan Hubicka <jh@suse.cz> writes: > > | > On Wed, Nov 06, 2002 at 06:54:41PM +0100, Jan Hubicka wrote: > | > > + For fast math it would be safe probably to convert (float)sqrt(x) > | > > + into sqrt((float)x), but in strict mode the argument can overflow. */ > | > > | > I don't believe this to be true. > | > | What you don't believe? > > Likew RTH, I, skeptical that your assertion is right. > > | That in ffast-math we can do the transformation? > > Do we really need to do that transformation? That is is there any > real evidence that it brings any real benefit? > I would be reluctant to include it even in -funsafe-math. On the related note. How bad would you consider converting floor(x) into rint(x-0.5) in the fast-math mode? That transformation would do a miracles for i386, where rint is faster than floor by quite a lot and should suffice for 3D application in reliablility. I can imagine it to fail only for very large numbers... Honza > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-06 14:29 ` Converting floor to rint Jan Hubicka @ 2002-11-06 14:47 ` Richard Henderson 2002-11-06 14:53 ` Jan Hubicka 2002-11-06 14:55 ` Gabriel Dos Reis 1 sibling, 1 reply; 41+ messages in thread From: Richard Henderson @ 2002-11-06 14:47 UTC (permalink / raw) To: Jan Hubicka; +Cc: Gabriel Dos Reis, gcc-patches, aj On Wed, Nov 06, 2002 at 11:29:22PM +0100, Jan Hubicka wrote: > On the related note. How bad would you consider converting > floor(x) into rint(x-0.5) in the fast-math mode? Well, let's see... If the current rounding mode is FE_UPWARD, then rint(1.7 - 0.5) = rint(1.2) = 2.0 I.e. we'd be computing CEIL instead of FLOOR. If the current rounding mode is FE_TONEAREST, which is the case I assume you were thinking about, we round ties to even, so rint(5.0 - 0.5) = rint(4.5) = 4.0 instead of the expected value 5.0. So, I think this would be a very bad idea, even for -ffast-math. r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-06 14:47 ` Richard Henderson @ 2002-11-06 14:53 ` Jan Hubicka 0 siblings, 0 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 14:53 UTC (permalink / raw) To: Richard Henderson, Jan Hubicka, Gabriel Dos Reis, gcc-patches, aj > On Wed, Nov 06, 2002 at 11:29:22PM +0100, Jan Hubicka wrote: > > On the related note. How bad would you consider converting > > floor(x) into rint(x-0.5) in the fast-math mode? > > Well, let's see... > > If the current rounding mode is FE_UPWARD, then > > rint(1.7 - 0.5) = rint(1.2) = 2.0 > > I.e. we'd be computing CEIL instead of FLOOR. > > If the current rounding mode is FE_TONEAREST, which is the case > I assume you were thinking about, we round ties to even, so > > rint(5.0 - 0.5) = rint(4.5) = 4.0 > > instead of the expected value 5.0. > > So, I think this would be a very bad idea, even for -ffast-math. Hmmm... OK then :( Honza > > > > r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-06 14:29 ` Converting floor to rint Jan Hubicka 2002-11-06 14:47 ` Richard Henderson @ 2002-11-06 14:55 ` Gabriel Dos Reis 2002-11-07 1:21 ` Jan Hubicka 1 sibling, 1 reply; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-06 14:55 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Jan Hubicka <jh@suse.cz> writes: | On the related note. How bad would you consider converting | floor(x) into rint(x-0.5) in the fast-math mode? If you think you do want to do that transformation, then I would prefer this floor(x) -> nearbyint(x-0.5) | That transformation would do a miracles for i386, where rint is faster | than floor by quite a lot and should suffice for 3D application in | reliablility. I can imagine it to fail only for very large numbers... Not really. floor(1) == 1 and rint(1 - 0.5) maybe be 0 or 1 depending on the current rounding mode. I don't think that I really like that transformation, even under -funsafe-math. But I would like to hear other people opinons. -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-06 14:55 ` Gabriel Dos Reis @ 2002-11-07 1:21 ` Jan Hubicka 2002-11-07 1:32 ` Jakub Jelinek 2002-11-07 1:33 ` Gabriel Dos Reis 0 siblings, 2 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 1:21 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj > Jan Hubicka <jh@suse.cz> writes: > > | On the related note. How bad would you consider converting > | floor(x) into rint(x-0.5) in the fast-math mode? > > If you think you do want to do that transformation, then I would > prefer this > > floor(x) -> nearbyint(x-0.5) > > | That transformation would do a miracles for i386, where rint is faster > | than floor by quite a lot and should suffice for 3D application in > | reliablility. I can imagine it to fail only for very large numbers... > > Not really. floor(1) == 1 and rint(1 - 0.5) maybe be 0 or 1 depending > on the current rounding mode. Hmm, is rint really expected to be dependent on the rouding mode? Man page claims: The nearbyint functions round their argument to an integer value in floating point format, using the current rounding direction and without raising the inexact exception. The rint functions do the same, but will raise the inexact exception when the result differs in value from the argument. I can builtinize nearbyint too if it makes sense. I am bit confused by rint. Does it imply that rint will raise exception for any non-integral arugment? Honza > > I don't think that I really like that transformation, even under > -funsafe-math. But I would like to hear other people opinons. > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 1:21 ` Jan Hubicka @ 2002-11-07 1:32 ` Jakub Jelinek 2002-11-07 1:33 ` Gabriel Dos Reis 1 sibling, 0 replies; 41+ messages in thread From: Jakub Jelinek @ 2002-11-07 1:32 UTC (permalink / raw) To: Jan Hubicka; +Cc: Gabriel Dos Reis, Richard Henderson, gcc-patches, aj On Thu, Nov 07, 2002 at 10:21:12AM +0100, Jan Hubicka wrote: > > | On the related note. How bad would you consider converting > > | floor(x) into rint(x-0.5) in the fast-math mode? > > > > If you think you do want to do that transformation, then I would > > prefer this > > > > floor(x) -> nearbyint(x-0.5) > > > > | That transformation would do a miracles for i386, where rint is faster > > | than floor by quite a lot and should suffice for 3D application in > > | reliablility. I can imagine it to fail only for very large numbers... > > > > Not really. floor(1) == 1 and rint(1 - 0.5) maybe be 0 or 1 depending > > on the current rounding mode. > Hmm, is rint really expected to be dependent on the rouding mode? > Man page claims: > The nearbyint functions round their argument to an integer value > in floating point format, using the current > rounding direction and without raising the inexact > exception. > > The rint functions do the same, but will raise the > inexact exception when the result differs in value > from the argument. > > I can builtinize nearbyint too if it makes sense. I am bit confused by > rint. Does it imply that rint will raise exception for any non-integral > arugment? If FE_INEXACT is enabled, yes. Jakub ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 1:21 ` Jan Hubicka 2002-11-07 1:32 ` Jakub Jelinek @ 2002-11-07 1:33 ` Gabriel Dos Reis 2002-11-07 1:44 ` Jan Hubicka 2002-11-07 2:04 ` Jan Hubicka 1 sibling, 2 replies; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-07 1:33 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Jan Hubicka <jh@suse.cz> writes: | > Jan Hubicka <jh@suse.cz> writes: | > | > | On the related note. How bad would you consider converting | > | floor(x) into rint(x-0.5) in the fast-math mode? | > | > If you think you do want to do that transformation, then I would | > prefer this | > | > floor(x) -> nearbyint(x-0.5) | > | > | That transformation would do a miracles for i386, where rint is faster | > | than floor by quite a lot and should suffice for 3D application in | > | reliablility. I can imagine it to fail only for very large numbers... | > | > Not really. floor(1) == 1 and rint(1 - 0.5) maybe be 0 or 1 depending | > on the current rounding mode. | Hmm, is rint really expected to be dependent on the rouding mode? | Man page claims: | The nearbyint functions round their argument to an integer value | in floating point format, using the current | rounding direction and without raising the inexact | exception. | | The rint functions do the same, but will raise the | inexact exception when the result differs in value | from the argument. The C definition says: 7.12.9.3 The nearbyint functions Synopsis [#1] #include <math.h> double nearbyint(double x); float nearbyintf(float x); long double nearbyintl(long double x); Description [#2] The nearbyint functions round their argument to an integer value in floating-point format, using the current rounding direction and without raising the ``inexact'' floating-point exception. Returns [#3] The nearbyint functions return the rounded integer value. 7.12.9.4 The rint functions Synopsis [#1] #include <math.h> double rint(double x); float rintf(float x); long double rintl(long double x); Description [#2] The rint functions differ from the nearbyint functions (7.12.9.3) only in that the rint functions may raise the ``inexact'' floating-point exception if the result differs in value from the argument. Returns [#3] The rint functions return the rounded integer value. | I can builtinize nearbyint too if it makes sense. Do we have framework to deal correctly with current rounding mode? I not, I would say, leave it as is until we have the appropriate machinery. | I am bit confused by | rint. Does it imply that rint will raise exception for any non-integral | arugment? And depending on the rounding mode. -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 1:33 ` Gabriel Dos Reis @ 2002-11-07 1:44 ` Jan Hubicka 2002-11-07 1:52 ` Jakub Jelinek 2002-11-07 2:04 ` Jan Hubicka 1 sibling, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 1:44 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj > Jan Hubicka <jh@suse.cz> writes: > > | > Jan Hubicka <jh@suse.cz> writes: > | > > | > | On the related note. How bad would you consider converting > | > | floor(x) into rint(x-0.5) in the fast-math mode? > | > > | > If you think you do want to do that transformation, then I would > | > prefer this > | > > | > floor(x) -> nearbyint(x-0.5) > | > > | > | That transformation would do a miracles for i386, where rint is faster > | > | than floor by quite a lot and should suffice for 3D application in > | > | reliablility. I can imagine it to fail only for very large numbers... > | > > | > Not really. floor(1) == 1 and rint(1 - 0.5) maybe be 0 or 1 depending > | > on the current rounding mode. > | Hmm, is rint really expected to be dependent on the rouding mode? > | Man page claims: > | The nearbyint functions round their argument to an integer value > | in floating point format, using the current > | rounding direction and without raising the inexact > | exception. > | > | The rint functions do the same, but will raise the > | inexact exception when the result differs in value > | from the argument. > > The C definition says: > > 7.12.9.3 The nearbyint functions > > Synopsis > > [#1] > > #include <math.h> > double nearbyint(double x); > float nearbyintf(float x); > long double nearbyintl(long double x); > > Description > > [#2] The nearbyint functions round their argument to an > integer value in floating-point format, using the current > rounding direction and without raising the ``inexact'' > floating-point exception. > > Returns > > [#3] The nearbyint functions return the rounded integer > value. > > 7.12.9.4 The rint functions > > Synopsis > > [#1] > > #include <math.h> > double rint(double x); > float rintf(float x); > long double rintl(long double x); > > Description > > [#2] The rint functions differ from the nearbyint functions > (7.12.9.3) only in that the rint functions may raise the > ``inexact'' floating-point exception if the result differs > in value from the argument. I see, that is quite different than what I have in manpage. I will check the standard for other differences > > Returns > > [#3] The rint functions return the rounded integer value. > > | I can builtinize nearbyint too if it makes sense. > > Do we have framework to deal correctly with current rounding mode? > I not, I would say, leave it as is until we have the appropriate > machinery. RTL truncating expressions are underfined for nonintegral FP values, so we don't have problems with the compiler, only we can't fold at compile time for non-integral constats, since the results depends on runtime conditions. > > | I am bit confused by > | rint. Does it imply that rint will raise exception for any non-integral > | arugment? > > And depending on the rounding mode. Bad :( I will check whether frndint will do the exception. If not, I guess the current glibc rint builtin is wrong and it really should be rint builtin. The other functions (floor and friends) are not throwing inexact I guess, but we can safely mask this out of rounding mode of course. Honza > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 1:44 ` Jan Hubicka @ 2002-11-07 1:52 ` Jakub Jelinek 2002-11-07 1:54 ` Jan Hubicka 0 siblings, 1 reply; 41+ messages in thread From: Jakub Jelinek @ 2002-11-07 1:52 UTC (permalink / raw) To: Jan Hubicka; +Cc: Gabriel Dos Reis, Richard Henderson, gcc-patches, aj On Thu, Nov 07, 2002 at 10:44:01AM +0100, Jan Hubicka wrote: > I will check whether frndint will do the exception. If not, I guess the > current glibc rint builtin is wrong and it really should be rint > builtin. Why? It is __FAST_MATH__ only. Jakub ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 1:52 ` Jakub Jelinek @ 2002-11-07 1:54 ` Jan Hubicka 0 siblings, 0 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 1:54 UTC (permalink / raw) To: Jakub Jelinek Cc: Jan Hubicka, Gabriel Dos Reis, Richard Henderson, gcc-patches, aj > On Thu, Nov 07, 2002 at 10:44:01AM +0100, Jan Hubicka wrote: > > I will check whether frndint will do the exception. If not, I guess the > > current glibc rint builtin is wrong and it really should be rint > > builtin. > > Why? > It is __FAST_MATH__ only. Hmm, I see then. Would be safe to use same builtin for nearbyint in non-ffast-math mode? Honza > > Jakub ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 1:33 ` Gabriel Dos Reis 2002-11-07 1:44 ` Jan Hubicka @ 2002-11-07 2:04 ` Jan Hubicka 2002-11-07 4:47 ` Gabriel Dos Reis 1 sibling, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 2:04 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj > Jan Hubicka <jh@suse.cz> writes: > > | > Jan Hubicka <jh@suse.cz> writes: > | > > | > | On the related note. How bad would you consider converting > | > | floor(x) into rint(x-0.5) in the fast-math mode? > | > > | > If you think you do want to do that transformation, then I would > | > prefer this > | > > | > floor(x) -> nearbyint(x-0.5) > | > > | > | That transformation would do a miracles for i386, where rint is faster > | > | than floor by quite a lot and should suffice for 3D application in > | > | reliablility. I can imagine it to fail only for very large numbers... > | > > | > Not really. floor(1) == 1 and rint(1 - 0.5) maybe be 0 or 1 depending > | > on the current rounding mode. > | Hmm, is rint really expected to be dependent on the rouding mode? > | Man page claims: > | The nearbyint functions round their argument to an integer value > | in floating point format, using the current > | rounding direction and without raising the inexact > | exception. > | > | The rint functions do the same, but will raise the > | inexact exception when the result differs in value > | from the argument. > > The C definition says: > > 7.12.9.3 The nearbyint functions > > Synopsis > > [#1] > > #include <math.h> > double nearbyint(double x); > float nearbyintf(float x); > long double nearbyintl(long double x); > > Description > > [#2] The nearbyint functions round their argument to an > integer value in floating-point format, using the current > rounding direction and without raising the ``inexact'' > floating-point exception. > > Returns > > [#3] The nearbyint functions return the rounded integer > value. > > 7.12.9.4 The rint functions > > Synopsis > > [#1] > > #include <math.h> > double rint(double x); > float rintf(float x); > long double rintl(long double x); > > Description > > [#2] The rint functions differ from the nearbyint functions > (7.12.9.3) only in that the rint functions may raise the ^^^ Does this imply that I can implement rint as nearbyint call and never cause the exception and always use frndint instruction for it that does not trap? Honza > ``inexact'' floating-point exception if the result differs > in value from the argument. > > Returns > > [#3] The rint functions return the rounded integer value. > > | I can builtinize nearbyint too if it makes sense. > > Do we have framework to deal correctly with current rounding mode? > I not, I would say, leave it as is until we have the appropriate > machinery. > > | I am bit confused by > | rint. Does it imply that rint will raise exception for any non-integral > | arugment? > > And depending on the rounding mode. > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 2:04 ` Jan Hubicka @ 2002-11-07 4:47 ` Gabriel Dos Reis 2002-11-07 4:56 ` Jan Hubicka 0 siblings, 1 reply; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-07 4:47 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Jan Hubicka <jh@suse.cz> writes: [...] | > [#2] The rint functions differ from the nearbyint functions | > (7.12.9.3) only in that the rint functions may raise the | ^^^ | Does this imply that I can implement rint as nearbyint call and never | cause the exception and always use frndint instruction for it that does | not trap? If FE_INEXACT is on, that is incorrect. -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 4:47 ` Gabriel Dos Reis @ 2002-11-07 4:56 ` Jan Hubicka 2002-11-07 5:14 ` Andreas Schwab 2002-11-07 5:22 ` Gabriel Dos Reis 0 siblings, 2 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 4:56 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj > Jan Hubicka <jh@suse.cz> writes: > > [...] > > | > [#2] The rint functions differ from the nearbyint functions > | > (7.12.9.3) only in that the rint functions may raise the > | ^^^ > | Does this imply that I can implement rint as nearbyint call and never > | cause the exception and always use frndint instruction for it that does > | not trap? > > If FE_INEXACT is on, that is incorrect. But why the standard don't say that rint function will raise the interrupt? I would interpred may as it can behave that way or don't have to. I've switched to nearbyint in my patch, but would like to understand this detail. Honza > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 4:56 ` Jan Hubicka @ 2002-11-07 5:14 ` Andreas Schwab 2002-11-07 5:27 ` Gabriel Dos Reis 2002-11-07 5:22 ` Gabriel Dos Reis 1 sibling, 1 reply; 41+ messages in thread From: Andreas Schwab @ 2002-11-07 5:14 UTC (permalink / raw) To: Jan Hubicka; +Cc: Gabriel Dos Reis, Richard Henderson, gcc-patches, aj Jan Hubicka <jh@suse.cz> writes: |> > Jan Hubicka <jh@suse.cz> writes: |> > |> > [...] |> > |> > | > [#2] The rint functions differ from the nearbyint functions |> > | > (7.12.9.3) only in that the rint functions may raise the |> > | ^^^ |> > | Does this imply that I can implement rint as nearbyint call and never |> > | cause the exception and always use frndint instruction for it that does |> > | not trap? |> > |> > If FE_INEXACT is on, that is incorrect. |> But why the standard don't say that rint function will raise the |> interrupt? I would interpred may as it can behave that way or don't |> have to. Yes, rint is the weaker function. The implementation of nearbyint must make sure that no inexact exception is raised, whereas for rint this is not necessary. That means that if you have a round instruction that never raises the exception it can be used to implement both functions. Andreas. -- Andreas Schwab, SuSE Labs, schwab@suse.de SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 5:14 ` Andreas Schwab @ 2002-11-07 5:27 ` Gabriel Dos Reis 2002-11-07 5:31 ` Jan Hubicka 0 siblings, 1 reply; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-07 5:27 UTC (permalink / raw) To: Andreas Schwab; +Cc: Jan Hubicka, Richard Henderson, gcc-patches, aj Andreas Schwab <schwab@suse.de> writes: | |> But why the standard don't say that rint function will raise the | |> interrupt? I would interpred may as it can behave that way or don't | |> have to. | | Yes, rint is the weaker function. Thanks. I didn't understand Jan's question in that way. Thanks for clarifying. | The implementation of nearbyint must | make sure that no inexact exception is raised, whereas for rint this is | not necessary. That means that if you have a round instruction that never | raises the exception it can be used to implement both functions. Yes. Or said differently, rint() may be implemented in terms of nearbyint() (+ raising exception where appropriate). -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 5:27 ` Gabriel Dos Reis @ 2002-11-07 5:31 ` Jan Hubicka 2002-11-07 5:35 ` Andreas Schwab 0 siblings, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 5:31 UTC (permalink / raw) To: Gabriel Dos Reis Cc: Andreas Schwab, Jan Hubicka, Richard Henderson, gcc-patches, aj > Andreas Schwab <schwab@suse.de> writes: > > | |> But why the standard don't say that rint function will raise the > | |> interrupt? I would interpred may as it can behave that way or don't > | |> have to. > | > | Yes, rint is the weaker function. > > Thanks. I didn't understand Jan's question in that way. Thanks > for clarifying. > > | The implementation of nearbyint must > | make sure that no inexact exception is raised, whereas for rint this is > | not necessary. That means that if you have a round instruction that never > | raises the exception it can be used to implement both functions. > > Yes. Or said differently, rint() may be implemented in terms of > nearbyint() (+ raising exception where appropriate). Question is whether I am required to raise it when standard say "may raise" Honza > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 5:31 ` Jan Hubicka @ 2002-11-07 5:35 ` Andreas Schwab 0 siblings, 0 replies; 41+ messages in thread From: Andreas Schwab @ 2002-11-07 5:35 UTC (permalink / raw) To: Jan Hubicka; +Cc: gcc-patches Jan Hubicka <jh@suse.cz> writes: |> Question is whether I am required to raise it when standard say "may |> raise" No, it would only be required if it said "shall raise". Andreas. -- Andreas Schwab, SuSE Labs, schwab@suse.de SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 4:56 ` Jan Hubicka 2002-11-07 5:14 ` Andreas Schwab @ 2002-11-07 5:22 ` Gabriel Dos Reis 2002-11-07 5:43 ` Andreas Schwab 1 sibling, 1 reply; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-07 5:22 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, gcc-patches, aj Jan Hubicka <jh@suse.cz> writes: | > Jan Hubicka <jh@suse.cz> writes: | > | > [...] | > | > | > [#2] The rint functions differ from the nearbyint functions | > | > (7.12.9.3) only in that the rint functions may raise the | > | ^^^ | > | Does this imply that I can implement rint as nearbyint call and never | > | cause the exception and always use frndint instruction for it that does | > | not trap? | > | > If FE_INEXACT is on, that is incorrect. | But why the standard don't say that rint function will raise the | interrupt? Sorry for having been unclear. "may" part refers to the fact whether the programmer might want to run rint() under a particular floating-point control mode that would permit rint() to raise the inexact exception. rint() cannot unconditionally set it. If FENV_ACCESS is on and FE_INEXACT is supported then rint() should raise the exception if appropriate. That is my understanding. Am I still unclear? -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 5:22 ` Gabriel Dos Reis @ 2002-11-07 5:43 ` Andreas Schwab 2002-11-07 6:23 ` Gabriel Dos Reis 0 siblings, 1 reply; 41+ messages in thread From: Andreas Schwab @ 2002-11-07 5:43 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Jan Hubicka, gcc-patches Gabriel Dos Reis <gdr@integrable-solutions.net> writes: |> "may" part refers to the fact whether the programmer might want |> to run rint() under a particular floating-point control mode that |> would permit rint() to raise the inexact exception. |> rint() cannot unconditionally set it. If FENV_ACCESS is on and |> FE_INEXACT is supported then rint() should raise the exception if |> appropriate. That is my understanding. If the implementation defines __STDC_IEC_559__ then F.9.6.4 applies. I have no copy of IEC 60559, but if it states that rint must raise the exception then it must do it independent of FENV_ACCESS. Otherwise, if __STDC_IEC_559__ is not defined, then no requirements on the exceptions are stated for rint, since 7.12.9.4 does not have a "shall". Andreas. -- Andreas Schwab, SuSE Labs, schwab@suse.de SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 5:43 ` Andreas Schwab @ 2002-11-07 6:23 ` Gabriel Dos Reis 2002-11-07 7:01 ` Jan Hubicka 0 siblings, 1 reply; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-07 6:23 UTC (permalink / raw) To: Andreas Schwab; +Cc: Jan Hubicka, gcc-patches Andreas Schwab <schwab@suse.de> writes: | Gabriel Dos Reis <gdr@integrable-solutions.net> writes: | | |> "may" part refers to the fact whether the programmer might want | |> to run rint() under a particular floating-point control mode that | |> would permit rint() to raise the inexact exception. | |> rint() cannot unconditionally set it. If FENV_ACCESS is on and | |> FE_INEXACT is supported then rint() should raise the exception if | |> appropriate. That is my understanding. | | If the implementation defines __STDC_IEC_559__ then F.9.6.4 applies. I | have no copy of IEC 60559, but if it states that rint must raise the | exception then it must do it independent of FENV_ACCESS. My concern is this: F.7.1 Environment management [#1] IEC 60559 requires that floating-point operations implicitly raise floating-point exception status flags, and that rounding control modes can be set explicitly to affect result values of floating-point operations. When the state for the FENV_ACCESS pragma (defined in <fenv.h>) is ``on'', these changes to the floating-point state are treated as *side effects* which respect sequence points.304) (my emphasis) | Otherwise, if | __STDC_IEC_559__ is not defined, then no requirements on the exceptions | are stated for rint, since 7.12.9.4 does not have a "shall". Agreed. -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 6:23 ` Gabriel Dos Reis @ 2002-11-07 7:01 ` Jan Hubicka 2002-11-07 7:18 ` Gabriel Dos Reis 0 siblings, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 7:01 UTC (permalink / raw) To: Gabriel Dos Reis; +Cc: Andreas Schwab, Jan Hubicka, gcc-patches > Andreas Schwab <schwab@suse.de> writes: > > | Gabriel Dos Reis <gdr@integrable-solutions.net> writes: > | > | |> "may" part refers to the fact whether the programmer might want > | |> to run rint() under a particular floating-point control mode that > | |> would permit rint() to raise the inexact exception. > | |> rint() cannot unconditionally set it. If FENV_ACCESS is on and > | |> FE_INEXACT is supported then rint() should raise the exception if > | |> appropriate. That is my understanding. > | > | If the implementation defines __STDC_IEC_559__ then F.9.6.4 applies. I > | have no copy of IEC 60559, but if it states that rint must raise the > | exception then it must do it independent of FENV_ACCESS. Yes, IEC seems to be clear about the trap: [#1] The rint functions differ from the nearbyint functions only in that they do raise the ``inexact'' floating-point exception if the result differs in value from the argument. I would love to be enlightened about when this feature is usefull :) I can't think of any use for it. Sadly most people use rint/lrint and not nearbyint/lrint that are more consistent. > > My concern is this: > > F.7.1 Environment management > > [#1] IEC 60559 requires that floating-point operations > implicitly raise floating-point exception status flags, and > that rounding control modes can be set explicitly to affect > result values of floating-point operations. When the state > for the FENV_ACCESS pragma (defined in <fenv.h>) is ``on'', > these changes to the floating-point state are treated as > *side effects* which respect sequence points.304) > > (my emphasis) So one can not consider rint as "attribute((const))" function and we can not do that in strict mode. > > | Otherwise, if > | __STDC_IEC_559__ is not defined, then no requirements on the exceptions > | are stated for rint, since 7.12.9.4 does not have a "shall". Can I detect somehow the cases when __STDC_IEC_559__ is not defined? This seems to be done by glibc in all cases, even with -ffast-math. Perhaps I can do the rint folding only with -ffast-math that would be enought for majority of 3D software that is about the only case where we get some oppurtunities for speedup from this transformations? Honza > > Agreed. > > -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Converting floor to rint 2002-11-07 7:01 ` Jan Hubicka @ 2002-11-07 7:18 ` Gabriel Dos Reis 0 siblings, 0 replies; 41+ messages in thread From: Gabriel Dos Reis @ 2002-11-07 7:18 UTC (permalink / raw) To: Jan Hubicka; +Cc: Andreas Schwab, gcc-patches Jan Hubicka <jh@suse.cz> writes: [...] | > F.7.1 Environment management | > | > [#1] IEC 60559 requires that floating-point operations | > implicitly raise floating-point exception status flags, and | > that rounding control modes can be set explicitly to affect | > result values of floating-point operations. When the state | > for the FENV_ACCESS pragma (defined in <fenv.h>) is ``on'', | > these changes to the floating-point state are treated as | > *side effects* which respect sequence points.304) | > | > (my emphasis) | | So one can not consider rint as "attribute((const))" function and we can | not do that in strict mode. That is exact. | > | > | Otherwise, if | > | __STDC_IEC_559__ is not defined, then no requirements on the exceptions | > | are stated for rint, since 7.12.9.4 does not have a "shall". | Can I detect somehow the cases when __STDC_IEC_559__ is not defined? Also one would need to access thye value of FENV_ACCESS. That is all that I loosenely called "propriate FE exception machinary". | This seems to be done by glibc in all cases, even with -ffast-math. | Perhaps I can do the rint folding only with -ffast-math that would be | enought for majority of 3D software that is about the only case where we | get some oppurtunities for speedup from this transformations? I won't oppose to having it in -funsafe-math. -- Gaby ^ permalink raw reply [flat|nested] 41+ messages in thread
* Simplify floating point conversions III 2002-11-06 10:09 ` Richard Henderson 2002-11-06 13:11 ` Jan Hubicka @ 2002-11-06 13:48 ` Jan Hubicka 2002-11-06 14:55 ` Richard Henderson 1 sibling, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 13:48 UTC (permalink / raw) To: Richard Henderson, Jan Hubicka, gcc-patches, aj > On Wed, Nov 06, 2002 at 06:54:41PM +0100, Jan Hubicka wrote: > > + For fast math it would be safe probably to convert (float)sqrt(x) > > + into sqrt((float)x), but in strict mode the argument can overflow. */ > > I don't believe this to be true. > > > + /* Wind away possible cast. */ > > + if (TREE_CODE (arg0) == NOP_EXPR) > > + arg0 = TREE_OPERAND (arg0, 0); > > Why would you do this? This might be casting down to double from > long double. You should only strip casts when they widen the type. > > > + /* convert (outertype)((innertype0)a+(innertype1)b) > > + into ((newtype)a+(newtype)b) where newtype > > + is the widest mode from all of these. */ > > This changes overflow characteristics of +. Consider > > (double)((float)a + (float)b) > > where A = B = 2**127. The result should be +Inf, not 2**128. > > Finally, I think it is alarmingly incorrect that > > (float)((double)a + (double)b)) > > does not result in a quantity of type float, as requested. Hi, this patch fixes the two problems and removes the comment. Honza Wed Nov 6 10:17:44 CET 2002 Jan Hubicka <jh@suse.cz> * convert.c (convert_to_real): Simplify some special cases. Index: convert.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/convert.c,v retrieving revision 1.19 diff -c -3 -p -r1.19 convert.c *** convert.c 4 Jul 2002 06:38:54 -0000 1.19 --- convert.c 6 Nov 2002 21:45:01 -0000 *************** tree *** 80,85 **** --- 80,233 ---- convert_to_real (type, expr) tree type, expr; { + enum built_in_function fcode = builtin_mathfn_code (expr); + tree itype = TREE_TYPE (expr); + + /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */ + if ((fcode == BUILT_IN_SQRT + || fcode == BUILT_IN_SQRTL + || fcode == BUILT_IN_SIN + || fcode == BUILT_IN_SINL + || fcode == BUILT_IN_COS + || fcode == BUILT_IN_COSL + || fcode == BUILT_IN_EXP + || fcode == BUILT_IN_EXPL) + && (TYPE_MODE (type) == TYPE_MODE (double_type_node) + || TYPE_MODE (type) == TYPE_MODE (float_type_node))) + { + tree arg0 = TREE_VALUE (TREE_OPERAND (expr, 1)); + tree newtype = type; + + /* Wind away possible cast. */ + if (TREE_CODE (arg0) == NOP_EXPR + && (TYPE_PRECISION (TREE_TYPE (arg0)) + > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))) + arg0 = TREE_OPERAND (arg0, 0); + + /* We have (outertype)sqrt((innertype)x). Choose the wider mode from + the both as the safe type for operation. */ + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) + newtype = TREE_TYPE (arg0); + + /* Be curefull about integer to fp conversions. + These may overflow still. */ + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && TYPE_PRECISION (newtype) <= TYPE_PRECISION (itype) + && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) + || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) + { + tree arglist; + if (TYPE_MODE (type) == TYPE_MODE (float_type_node)) + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRTF; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SINF; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COSF; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXPF; + break; + default: + abort (); + } + else + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRT; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SIN; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COS; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXP; + break; + default: + abort (); + } + + /* ??? Fortran frontend does not initialize built_in_decls. + For some reason creating the decl using builtin_function does not + work as it should. */ + if (built_in_decls [fcode]) + { + arglist = build_tree_list (NULL_TREE, fold (convert_to_real (newtype, arg0))); + expr = build_function_call_expr (built_in_decls [fcode], arglist); + if (newtype == type) + return expr; + } + } + } + + /* Propagate the cast into the operation. */ + if (itype != type && FLOAT_TYPE_P (type)) + switch (TREE_CODE (expr)) + { + /* convert (float)-x into -(float)x. This is always safe. */ + case ABS_EXPR: + case NEGATE_EXPR: + return build1 (TREE_CODE (expr), type, + fold (convert_to_real (type, + TREE_OPERAND (expr, 0)))); + /* convert (outertype)((innertype0)a+(innertype1)b) + into ((newtype)a+(newtype)b) where newtype + is the widest mode from all of these. */ + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case RDIV_EXPR: + { + tree arg0 = TREE_OPERAND (expr, 0); + tree arg1 = TREE_OPERAND (expr, 1); + + /* Unwind possible casts. */ + if (TREE_CODE (arg0) == NOP_EXPR + && (TYPE_PRECISION (TREE_TYPE (arg0)) + > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))) + arg0 = TREE_OPERAND (arg0, 0); + if (TREE_CODE (arg1) == NOP_EXPR + && (TYPE_PRECISION (TREE_TYPE (arg1)) + > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))))) + arg1 = TREE_OPERAND (arg1, 0); + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && FLOAT_TYPE_P (TREE_TYPE (arg1))) + { + tree newtype = type; + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg0); + if (TYPE_PRECISION (TREE_TYPE (arg1)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg1); + if (TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)) + { + expr = build (TREE_CODE (expr), newtype, + fold (convert_to_real (newtype, arg0)), + fold (convert_to_real (newtype, arg1))); + if (newtype == type) + return expr; + } + } + } + break; + default: + break; + } + switch (TREE_CODE (TREE_TYPE (expr))) { case REAL_TYPE: ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions III 2002-11-06 13:48 ` Simplify floating point conversions III Jan Hubicka @ 2002-11-06 14:55 ` Richard Henderson 2002-11-07 2:54 ` Simplify floating point conversions IV Jan Hubicka 0 siblings, 1 reply; 41+ messages in thread From: Richard Henderson @ 2002-11-06 14:55 UTC (permalink / raw) To: Jan Hubicka; +Cc: gcc-patches, aj On Wed, Nov 06, 2002 at 10:48:03PM +0100, Jan Hubicka wrote: > + /* Wind away possible cast. */ > + if (TREE_CODE (arg0) == NOP_EXPR > + && (TYPE_PRECISION (TREE_TYPE (arg0)) > + > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))) > + arg0 = TREE_OPERAND (arg0, 0); [...] > + /* Be curefull about integer to fp conversions. > + These may overflow still. */ > + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) I'd rather something like static tree strip_float_extensions (exp) tree exp; { tree sub, expt, subt; if (TREE_CODE (exp) != NOP_EXPR) return exp; sub = TREE_OPERAND (exp, 0); subt = TREE_TYPE (sub); expt = TREE_TYPE (exp); if (!FLOAT_TYPE_P (subt)) return exp; if (TYPE_PRECISION (subt) > TYPE_PRECISION (expt)) return exp; return strip_float_extensions (sub); } > + case RDIV_EXPR: > + { > + tree arg0 = TREE_OPERAND (expr, 0); > + tree arg1 = TREE_OPERAND (expr, 1); > + > + /* Unwind possible casts. */ Useful here as well. r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Simplify floating point conversions IV 2002-11-06 14:55 ` Richard Henderson @ 2002-11-07 2:54 ` Jan Hubicka 2002-11-18 15:01 ` Richard Henderson 0 siblings, 1 reply; 41+ messages in thread From: Jan Hubicka @ 2002-11-07 2:54 UTC (permalink / raw) To: Richard Henderson, Jan Hubicka, gcc-patches, aj > On Wed, Nov 06, 2002 at 10:48:03PM +0100, Jan Hubicka wrote: > > + /* Wind away possible cast. */ > > + if (TREE_CODE (arg0) == NOP_EXPR > > + && (TYPE_PRECISION (TREE_TYPE (arg0)) > > + > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))) > > + arg0 = TREE_OPERAND (arg0, 0); > [...] > > + /* Be curefull about integer to fp conversions. > > + These may overflow still. */ > > + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) > > I'd rather something like > > static tree > strip_float_extensions (exp) > tree exp; > { > tree sub, expt, subt; > > if (TREE_CODE (exp) != NOP_EXPR) > return exp; > > sub = TREE_OPERAND (exp, 0); > subt = TREE_TYPE (sub); > expt = TREE_TYPE (exp); > > if (!FLOAT_TYPE_P (subt)) > return exp; > > if (TYPE_PRECISION (subt) > TYPE_PRECISION (expt)) > return exp; > > return strip_float_extensions (sub); > } > > > + case RDIV_EXPR: > > + { > > + tree arg0 = TREE_OPERAND (expr, 0); > > + tree arg1 = TREE_OPERAND (expr, 1); > > + > > + /* Unwind possible casts. */ > > Useful here as well. Nice. I've added that and suppressed the builtin transformation when not optimizing. OK now? Wed Nov 6 19:48:32 PST 2002 Jan Hubicka <jh@suse.cz> * convert.c (strip_float_extensions): New function. (convert_to_real): Optimize some cases. Index: convert.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/convert.c,v retrieving revision 1.19 diff -c -3 -p -r1.19 convert.c *** convert.c 4 Jul 2002 06:38:54 -0000 1.19 --- convert.c 7 Nov 2002 10:53:27 -0000 *************** Software Foundation, 59 Temple Place - S *** 30,35 **** --- 30,36 ---- #include "convert.h" #include "toplev.h" #include "langhooks.h" + static tree strip_float_extensions PARAMS ((tree)); /* Convert EXPR to some pointer or reference type TYPE. *************** convert_to_pointer (type, expr) *** 71,76 **** --- 72,101 ---- } } + /* Avoid any floating point extensions from EXP. */ + static tree + strip_float_extensions (exp) + tree exp; + { + tree sub, expt, subt; + + if (TREE_CODE (exp) != NOP_EXPR) + return exp; + + sub = TREE_OPERAND (exp, 0); + subt = TREE_TYPE (sub); + expt = TREE_TYPE (exp); + + if (!FLOAT_TYPE_P (subt)) + return exp; + + if (TYPE_PRECISION (subt) > TYPE_PRECISION (expt)) + return exp; + + return strip_float_extensions (sub); + } + + /* Convert EXPR to some floating-point type TYPE. EXPR must be float, integer, or enumeral; *************** tree *** 80,85 **** --- 105,244 ---- convert_to_real (type, expr) tree type, expr; { + enum built_in_function fcode = builtin_mathfn_code (expr); + tree itype = TREE_TYPE (expr); + + /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */ + if ((fcode == BUILT_IN_SQRT + || fcode == BUILT_IN_SQRTL + || fcode == BUILT_IN_SIN + || fcode == BUILT_IN_SINL + || fcode == BUILT_IN_COS + || fcode == BUILT_IN_COSL + || fcode == BUILT_IN_EXP + || fcode == BUILT_IN_EXPL) + && optimize + && (TYPE_MODE (type) == TYPE_MODE (double_type_node) + || TYPE_MODE (type) == TYPE_MODE (float_type_node))) + { + tree arg0 = strip_float_extensions (TREE_VALUE (TREE_OPERAND (expr, 1))); + tree newtype = type; + + /* We have (outertype)sqrt((innertype)x). Choose the wider mode from + the both as the safe type for operation. */ + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) + newtype = TREE_TYPE (arg0); + + /* Be curefull about integer to fp conversions. + These may overflow still. */ + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && TYPE_PRECISION (newtype) <= TYPE_PRECISION (itype) + && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) + || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) + { + tree arglist; + if (TYPE_MODE (type) == TYPE_MODE (float_type_node)) + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRTF; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SINF; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COSF; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXPF; + break; + default: + abort (); + } + else + switch (fcode) + { + case BUILT_IN_SQRT: + case BUILT_IN_SQRTL: + fcode = BUILT_IN_SQRT; + break; + case BUILT_IN_SIN: + case BUILT_IN_SINL: + fcode = BUILT_IN_SIN; + break; + case BUILT_IN_COS: + case BUILT_IN_COSL: + fcode = BUILT_IN_COS; + break; + case BUILT_IN_EXP: + case BUILT_IN_EXPL: + fcode = BUILT_IN_EXP; + break; + default: + abort (); + } + + /* ??? Fortran frontend does not initialize built_in_decls. + For some reason creating the decl using builtin_function does not + work as it should. */ + if (built_in_decls [fcode]) + { + arglist = build_tree_list (NULL_TREE, fold (convert_to_real (newtype, arg0))); + expr = build_function_call_expr (built_in_decls [fcode], arglist); + if (newtype == type) + return expr; + } + } + } + + /* Propagate the cast into the operation. */ + if (itype != type && FLOAT_TYPE_P (type)) + switch (TREE_CODE (expr)) + { + /* convert (float)-x into -(float)x. This is always safe. */ + case ABS_EXPR: + case NEGATE_EXPR: + return build1 (TREE_CODE (expr), type, + fold (convert_to_real (type, + TREE_OPERAND (expr, 0)))); + /* convert (outertype)((innertype0)a+(innertype1)b) + into ((newtype)a+(newtype)b) where newtype + is the widest mode from all of these. */ + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case RDIV_EXPR: + { + tree arg0 = strip_float_extensions (TREE_OPERAND (expr, 0)); + tree arg1 = strip_float_extensions (TREE_OPERAND (expr, 1)); + + if (FLOAT_TYPE_P (TREE_TYPE (arg0)) + && FLOAT_TYPE_P (TREE_TYPE (arg1))) + { + tree newtype = type; + if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg0); + if (TYPE_PRECISION (TREE_TYPE (arg1)) > TYPE_PRECISION (newtype)) + newtype = TREE_TYPE (arg1); + if (TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)) + { + expr = build (TREE_CODE (expr), newtype, + fold (convert_to_real (newtype, arg0)), + fold (convert_to_real (newtype, arg1))); + if (newtype == type) + return expr; + } + } + } + break; + default: + break; + } + switch (TREE_CODE (TREE_TYPE (expr))) { case REAL_TYPE: ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions IV 2002-11-07 2:54 ` Simplify floating point conversions IV Jan Hubicka @ 2002-11-18 15:01 ` Richard Henderson 0 siblings, 0 replies; 41+ messages in thread From: Richard Henderson @ 2002-11-18 15:01 UTC (permalink / raw) To: Jan Hubicka; +Cc: gcc-patches, aj On Thu, Nov 07, 2002 at 11:54:55AM +0100, Jan Hubicka wrote: > * convert.c (strip_float_extensions): New function. > (convert_to_real): Optimize some cases. Ok. r~ ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions 2002-11-05 9:14 Simplify floating point conversions Jan Hubicka 2002-11-05 9:38 ` Richard Henderson @ 2002-11-05 11:14 ` Geoff Keating 2002-11-06 1:09 ` Jan Hubicka 1 sibling, 1 reply; 41+ messages in thread From: Geoff Keating @ 2002-11-05 11:14 UTC (permalink / raw) To: Jan Hubicka; +Cc: gcc-patches Jan Hubicka <jh@suse.cz> writes: > Hi, > this patch makes us to simplify some of the floating point operations to > narrower mode when conversions are present. This include > +,-,/,*,abs,neg,sqrt/sin/cos/exp. > I believe it is IEEE safe, but some expert would be welcome. It's not safe, except for 'abs' and 'neg'. For example, (float)sqrt(2.0 * FLT_MAX) != sqrtf(2.0 * FLT_MAX). I think it would be OK for -ffast-math, though. -- - Geoffrey Keating <geoffk@geoffk.org> ^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: Simplify floating point conversions 2002-11-05 11:14 ` Simplify floating point conversions Geoff Keating @ 2002-11-06 1:09 ` Jan Hubicka 0 siblings, 0 replies; 41+ messages in thread From: Jan Hubicka @ 2002-11-06 1:09 UTC (permalink / raw) To: Geoff Keating; +Cc: Jan Hubicka, gcc-patches > Jan Hubicka <jh@suse.cz> writes: > > > Hi, > > this patch makes us to simplify some of the floating point operations to > > narrower mode when conversions are present. This include > > +,-,/,*,abs,neg,sqrt/sin/cos/exp. > > I believe it is IEEE safe, but some expert would be welcome. > > It's not safe, except for 'abs' and 'neg'. For example, > (float)sqrt(2.0 * FLT_MAX) != sqrtf(2.0 * FLT_MAX). > I think it would be OK for -ffast-math, though. I am doing only (float)sqrt((double)float) that commonly results from C code that uses floats but calls math functions. I can add fast-math code for weaker checks later, but first I would like to know whether this transformation is valid. I will add the comments :) I usually write the automatically and ididn't noticed there are none.. Honza > > -- > - Geoffrey Keating <geoffk@geoffk.org> ^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2002-11-18 23:01 UTC | newest] Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-11-05 9:14 Simplify floating point conversions Jan Hubicka 2002-11-05 9:38 ` Richard Henderson 2002-11-05 9:42 ` Jan Hubicka 2002-11-06 1:23 ` Simplify floating point conversions II Jan Hubicka 2002-11-06 3:08 ` Michael Matz 2002-11-06 4:36 ` Jan Hubicka 2002-11-06 9:54 ` Jan Hubicka 2002-11-06 10:09 ` Richard Henderson 2002-11-06 13:11 ` Jan Hubicka 2002-11-06 13:19 ` Jan Hubicka 2002-11-06 13:35 ` Gabriel Dos Reis 2002-11-06 13:36 ` Jan Hubicka 2002-11-06 14:06 ` Gabriel Dos Reis 2002-11-06 14:29 ` Converting floor to rint Jan Hubicka 2002-11-06 14:47 ` Richard Henderson 2002-11-06 14:53 ` Jan Hubicka 2002-11-06 14:55 ` Gabriel Dos Reis 2002-11-07 1:21 ` Jan Hubicka 2002-11-07 1:32 ` Jakub Jelinek 2002-11-07 1:33 ` Gabriel Dos Reis 2002-11-07 1:44 ` Jan Hubicka 2002-11-07 1:52 ` Jakub Jelinek 2002-11-07 1:54 ` Jan Hubicka 2002-11-07 2:04 ` Jan Hubicka 2002-11-07 4:47 ` Gabriel Dos Reis 2002-11-07 4:56 ` Jan Hubicka 2002-11-07 5:14 ` Andreas Schwab 2002-11-07 5:27 ` Gabriel Dos Reis 2002-11-07 5:31 ` Jan Hubicka 2002-11-07 5:35 ` Andreas Schwab 2002-11-07 5:22 ` Gabriel Dos Reis 2002-11-07 5:43 ` Andreas Schwab 2002-11-07 6:23 ` Gabriel Dos Reis 2002-11-07 7:01 ` Jan Hubicka 2002-11-07 7:18 ` Gabriel Dos Reis 2002-11-06 13:48 ` Simplify floating point conversions III Jan Hubicka 2002-11-06 14:55 ` Richard Henderson 2002-11-07 2:54 ` Simplify floating point conversions IV Jan Hubicka 2002-11-18 15:01 ` Richard Henderson 2002-11-05 11:14 ` Simplify floating point conversions Geoff Keating 2002-11-06 1:09 ` Jan Hubicka
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).