diff options
author | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-08-12 01:56:10 +0000 |
---|---|---|
committer | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-08-12 01:56:10 +0000 |
commit | cc1900961aebe17dc7ff52e21a54ec71148bd951 (patch) | |
tree | 7e0d274b9d7e3a3888aa3d22cd6cba4854e43f24 /gcc/simplify-rtx.c | |
parent | 9dc9d0d3203a4285c79fb71ff4c5c92531ac45aa (diff) | |
download | gcc-cc1900961aebe17dc7ff52e21a54ec71148bd951.tar.gz |
* toplev.c (set_float_handler): Make static.
* toplev.h: Don't prototype set_float_handler.
* simplify-rtx.c: Don't include setjmp.h.
(simplify_unary_real, simplify_binary_real, simplify_binary_is2orm1):
New functions.
(simplify_unary_operation, simplify_binary_operation): Use them,
via do_float_handler.
* fold-const.c: Don't include setjmp.h.
(exact_real_inverse_1): New function.
(exact_real_inverse): Use it, via do_float_handler.
* varasm.c: Don't include setjmp.h.
(assemble_real_1): New function.
(assemble_real): Use it, via do_float_handler.
Call internal_error if we get a trap here.
* c-parse.in, cse.c, cselib.c, ch/lex.c, config/i386/i386.c,
config/pj/pj.c, config/s390/s390.c: Don't include setjmp.h.
* java/lex.h: Don't include setjmp.h. Don't define
SET_FLOAT_HANDLER or prototype set_float_handler.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44815 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 331 |
1 files changed, 187 insertions, 144 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 11254da5e1b..08adde25963 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -22,7 +22,6 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" -#include <setjmp.h> #include "rtl.h" #include "tm_p.h" @@ -99,6 +98,12 @@ Boston, MA 02111-1307, USA. */ static rtx simplify_plus_minus PARAMS ((enum rtx_code, enum machine_mode, rtx, rtx)); static void check_fold_consts PARAMS ((PTR)); +#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) +static void simplify_unary_real PARAMS ((PTR)); +static void simplify_binary_real PARAMS ((PTR)); +#endif +static void simplify_binary_is2orm1 PARAMS ((PTR)); + /* Make a binary operation by properly ordering the operands and seeing if the expression folds. */ @@ -324,10 +329,70 @@ simplify_replace_rtx (x, old, new) return x; } +#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) +/* Subroutine of simplify_unary_operation, called via do_float_handler. + Handles simplification of unary ops on floating point values. */ +struct simplify_unary_real_args +{ + rtx operand; + rtx result; + enum machine_mode mode; + enum rtx_code code; + bool want_integer; +}; +#define REAL_VALUE_ABS(d_) \ + (REAL_VALUE_NEGATIVE (d_) ? REAL_VALUE_NEGATE (d_) : (d_)) + +static void +simplify_unary_real (p) + PTR p; +{ + REAL_VALUE_TYPE d; + + struct simplify_unary_real_args *args = + (struct simplify_unary_real_args *) p; + + REAL_VALUE_FROM_CONST_DOUBLE (d, args->operand); + + if (args->want_integer) + { + HOST_WIDE_INT i; + + switch (args->code) + { + case FIX: i = REAL_VALUE_FIX (d); break; + case UNSIGNED_FIX: i = REAL_VALUE_UNSIGNED_FIX (d); break; + default: + abort (); + } + args->result = GEN_INT (trunc_int_for_mode (i, args->mode)); + } + else + { + switch (args->code) + { + case SQRT: + /* We don't attempt to optimize this. */ + args->result = 0; + return; + + case ABS: d = REAL_VALUE_ABS (d); break; + case NEG: d = REAL_VALUE_NEGATE (d); break; + case FLOAT_TRUNCATE: d = real_value_truncate (args->mode, d); break; + case FLOAT_EXTEND: /* All this does is change the mode. */ break; + case FIX: d = REAL_VALUE_RNDZINT (d); break; + case UNSIGNED_FIX: d = REAL_VALUE_UNSIGNED_RNDZINT (d); break; + default: + abort (); + } + args->result = CONST_DOUBLE_FROM_REAL_VALUE (d, args->mode); + } +} +#endif + /* Try to simplify a unary operation CODE whose output mode is to be MODE with input operand OP whose mode was originally OP_MODE. Return zero if no simplification can be made. */ - rtx simplify_unary_operation (code, mode, op, op_mode) enum rtx_code code; @@ -586,57 +651,16 @@ simplify_unary_operation (code, mode, op, op_mode) else if (GET_CODE (trueop) == CONST_DOUBLE && GET_MODE_CLASS (mode) == MODE_FLOAT) { - REAL_VALUE_TYPE d; - jmp_buf handler; - rtx x; - - if (setjmp (handler)) - /* There used to be a warning here, but that is inadvisable. - People may want to cause traps, and the natural way - to do it should not get a warning. */ - return 0; - - set_float_handler (handler); - - REAL_VALUE_FROM_CONST_DOUBLE (d, trueop); - - switch (code) - { - case NEG: - d = REAL_VALUE_NEGATE (d); - break; + struct simplify_unary_real_args args; + args.operand = trueop; + args.mode = mode; + args.code = code; + args.want_integer = false; - case ABS: - if (REAL_VALUE_NEGATIVE (d)) - d = REAL_VALUE_NEGATE (d); - break; - - case FLOAT_TRUNCATE: - d = real_value_truncate (mode, d); - break; + if (do_float_handler (simplify_unary_real, (PTR) &args)) + return args.result; - case FLOAT_EXTEND: - /* All this does is change the mode. */ - break; - - case FIX: - d = REAL_VALUE_RNDZINT (d); - break; - - case UNSIGNED_FIX: - d = REAL_VALUE_UNSIGNED_RNDZINT (d); - break; - - case SQRT: - return 0; - - default: - abort (); - } - - x = CONST_DOUBLE_FROM_REAL_VALUE (d, mode); - set_float_handler (NULL); - return x; + return 0; } else if (GET_CODE (trueop) == CONST_DOUBLE @@ -644,36 +668,16 @@ simplify_unary_operation (code, mode, op, op_mode) && GET_MODE_CLASS (mode) == MODE_INT && width <= HOST_BITS_PER_WIDE_INT && width > 0) { - REAL_VALUE_TYPE d; - jmp_buf handler; - HOST_WIDE_INT val; - - if (setjmp (handler)) - return 0; - - set_float_handler (handler); - - REAL_VALUE_FROM_CONST_DOUBLE (d, trueop); - - switch (code) - { - case FIX: - val = REAL_VALUE_FIX (d); - break; - - case UNSIGNED_FIX: - val = REAL_VALUE_UNSIGNED_FIX (d); - break; - - default: - abort (); - } + struct simplify_unary_real_args args; + args.operand = trueop; + args.mode = mode; + args.code = code; + args.want_integer = true; - set_float_handler (NULL); + if (do_float_handler (simplify_unary_real, (PTR) &args)) + return args.result; - val = trunc_int_for_mode (val, mode); - - return GEN_INT (val); + return 0; } #endif /* This was formerly used only for non-IEEE float. @@ -749,12 +753,101 @@ simplify_unary_operation (code, mode, op, op_mode) } } +#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) +/* Subroutine of simplify_binary_operation, called via do_float_handler. + Handles simplification of binary ops on floating point values. */ +struct simplify_binary_real_args +{ + rtx trueop0, trueop1; + rtx result; + enum rtx_code code; + enum machine_mode mode; +}; + +static void +simplify_binary_real (p) + PTR p; +{ + REAL_VALUE_TYPE f0, f1, value; + struct simplify_binary_real_args *args = + (struct simplify_binary_real_args *) p; + + REAL_VALUE_FROM_CONST_DOUBLE (f0, args->trueop0); + REAL_VALUE_FROM_CONST_DOUBLE (f1, args->trueop1); + f0 = real_value_truncate (args->mode, f0); + f1 = real_value_truncate (args->mode, f1); + +#ifdef REAL_ARITHMETIC +#ifndef REAL_INFINITY + if (args->code == DIV && REAL_VALUES_EQUAL (f1, dconst0)) + { + args->result = 0; + return; + } +#endif + REAL_ARITHMETIC (value, rtx_to_tree_code (args->code), f0, f1); +#else + switch (args->code) + { + case PLUS: + value = f0 + f1; + break; + case MINUS: + value = f0 - f1; + break; + case MULT: + value = f0 * f1; + break; + case DIV: +#ifndef REAL_INFINITY + if (f1 == 0) + return 0; +#endif + value = f0 / f1; + break; + case SMIN: + value = MIN (f0, f1); + break; + case SMAX: + value = MAX (f0, f1); + break; + default: + abort (); + } +#endif + + value = real_value_truncate (args->mode, value); + args->result = CONST_DOUBLE_FROM_REAL_VALUE (value, args->mode); +} +#endif + +/* Another subroutine called via do_float_handler. This one tests + the floating point value given against 2. and -1. */ +struct simplify_binary_is2orm1_args +{ + rtx value; + bool is_2; + bool is_m1; +}; + +static void +simplify_binary_is2orm1 (p) + PTR p; +{ + REAL_VALUE_TYPE d; + struct simplify_binary_is2orm1_args *args = + (struct simplify_binary_is2orm1_args *) p; + + REAL_VALUE_FROM_CONST_DOUBLE (d, args->value); + args->is_2 = REAL_VALUES_EQUAL (d, dconst2); + args->is_m1 = REAL_VALUES_EQUAL (d, dconstm1); +} + /* Simplify a binary operation CODE with result mode MODE, operating on OP0 and OP1. Return 0 if no simplification is possible. Don't use this for relational operations such as EQ or LT. Use simplify_relational_operation instead. */ - rtx simplify_binary_operation (code, mode, op0, op1) enum rtx_code code; @@ -790,58 +883,15 @@ simplify_binary_operation (code, mode, op0, op1) && GET_CODE (trueop1) == CONST_DOUBLE && mode == GET_MODE (op0) && mode == GET_MODE (op1)) { - REAL_VALUE_TYPE f0, f1, value; - jmp_buf handler; - - if (setjmp (handler)) - return 0; - - set_float_handler (handler); - - REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0); - REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1); - f0 = real_value_truncate (mode, f0); - f1 = real_value_truncate (mode, f1); - -#ifdef REAL_ARITHMETIC -#ifndef REAL_INFINITY - if (code == DIV && REAL_VALUES_EQUAL (f1, dconst0)) - return 0; -#endif - REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1); -#else - switch (code) - { - case PLUS: - value = f0 + f1; - break; - case MINUS: - value = f0 - f1; - break; - case MULT: - value = f0 * f1; - break; - case DIV: -#ifndef REAL_INFINITY - if (f1 == 0) - return 0; -#endif - value = f0 / f1; - break; - case SMIN: - value = MIN (f0, f1); - break; - case SMAX: - value = MAX (f0, f1); - break; - default: - abort (); - } -#endif - - value = real_value_truncate (mode, value); - set_float_handler (NULL); - return CONST_DOUBLE_FROM_REAL_VALUE (value, mode); + struct simplify_binary_real_args args; + args.trueop0 = trueop0; + args.trueop1 = trueop1; + args.mode = mode; + args.code = code; + + if (do_float_handler (simplify_binary_real, (PTR) &args)) + return args.result; + return 0; } #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ @@ -1263,24 +1313,17 @@ simplify_binary_operation (code, mode, op0, op1) if (GET_CODE (trueop1) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT) { - REAL_VALUE_TYPE d; - jmp_buf handler; - int op1is2, op1ism1; + struct simplify_binary_is2orm1_args args; - if (setjmp (handler)) + args.value = trueop1; + if (! do_float_handler (simplify_binary_is2orm1, (PTR) &args)) return 0; - set_float_handler (handler); - REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); - op1is2 = REAL_VALUES_EQUAL (d, dconst2); - op1ism1 = REAL_VALUES_EQUAL (d, dconstm1); - set_float_handler (NULL); - /* x*2 is x+x and x*(-1) is -x */ - if (op1is2 && GET_MODE (op0) == mode) + if (args.is_2 && GET_MODE (op0) == mode) return gen_rtx_PLUS (mode, op0, copy_rtx (op0)); - else if (op1ism1 && GET_MODE (op0) == mode) + else if (args.is_m1 && GET_MODE (op0) == mode) return gen_rtx_NEG (mode, op0); } break; |