#include "config.h"
#include "system.h"
-#include <setjmp.h>
#include "flags.h"
#include "tree.h"
#include "rtl.h"
static void decode PARAMS ((HOST_WIDE_INT *,
unsigned HOST_WIDE_INT *,
HOST_WIDE_INT *));
+#ifndef REAL_ARITHMETIC
+static void exact_real_inverse_1 PARAMS ((PTR));
+#endif
static tree negate_expr PARAMS ((tree));
static tree split_tree PARAMS ((tree, enum tree_code, tree *, tree *,
int));
/* Try to change R into its exact multiplicative inverse in machine mode
MODE. Return nonzero function value if successful. */
+struct exact_real_inverse_args
+{
+ REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
+ int success;
+};
-int
-exact_real_inverse (mode, r)
- enum machine_mode mode;
- REAL_VALUE_TYPE *r;
+static void
+exact_real_inverse_1 (p)
+ PTR p;
{
- jmp_buf float_error;
+ struct exact_real_inverse_args *args =
+ (struct exact_real_inverse_args *) p;
+
+ enum machine_mode mode = args->mode;
+ REAL_VALUE_TYPE *r = args->r;
+
union
- {
- double d;
- unsigned short i[4];
- }x, t, y;
+ {
+ double d;
+ unsigned short i[4];
+ }
+ x, t, y;
#ifdef CHECK_FLOAT_VALUE
int i;
#endif
- /* Usually disable if bounds checks are not reliable. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float)
- return 0;
-
/* Set array index to the less significant bits in the unions, depending
- on the endian-ness of the host doubles.
- Disable if insufficient information on the data structure. */
-#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT
- return 0;
-#else
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define K 2
+ on the endian-ness of the host doubles. */
+#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT \
+ || HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
+# define K 2
#else
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-#define K 2
-#else
-#define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN)
-#endif
-#endif
+# define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN)
#endif
- if (setjmp (float_error))
- {
- /* Don't do the optimization if there was an arithmetic error. */
-fail:
- set_float_handler (NULL_PTR);
- return 0;
- }
- set_float_handler (float_error);
-
/* Domain check the argument. */
x.d = *r;
if (x.d == 0.0)
#endif
/* Output the reciprocal and return success flag. */
- set_float_handler (NULL_PTR);
*r = y.d;
- return 1;
+ args->success = 1;
+ return;
+
+ fail:
+ args->success = 0;
+ return;
+
+#undef K
+}
+
+
+int
+exact_real_inverse (mode, r)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE *r;
+{
+ struct exact_real_inverse_args args;
+
+ /* Disable if insufficient information on the data structure. */
+#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT
+ return 0;
+#endif
+
+ /* Usually disable if bounds checks are not reliable. */
+ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float)
+ return 0;
+
+ args.mode = mode;
+ args.r = r;
+
+ if (do_float_handler (exact_real_inverse_1, (PTR) &args))
+ return args.success;
+ return 0;
}
/* Convert C99 hexadecimal floating point string constant S. Return
REAL_VALUE_TYPE
real_hex_to_f (s, mode)
- char *s;
+ const char *s;
enum machine_mode mode;
{
REAL_VALUE_TYPE ip;
- char *p = s;
+ const char *p = s;
unsigned HOST_WIDE_INT low, high;
int shcount, nrmcount, k;
int sign, expsign, isfloat;
*conp = 0;
*litp = 0;
- /* Strip any conversions that don't change the machine mode or signedness. */
+ /* Strip any conversions that don't change the machine mode or signedness. */
STRIP_SIGN_NOPS (in);
if (TREE_CODE (in) == INTEGER_CST || TREE_CODE (in) == REAL_CST)
*conp = op1, neg_conp_p = neg1_p, op1 = 0;
/* If we haven't dealt with either operand, this is not a case we can
- decompose. Otherwise, VAR is either of the ones remaining, if any. */
+ decompose. Otherwise, VAR is either of the ones remaining, if any. */
if (op0 != 0 && op1 != 0)
var = in;
else if (op0 != 0)
break;
}
- /* ... fall through ... */
+ /* ... fall through ... */
case ROUND_DIV_EXPR:
if (int2h == 0 && int2l == 1)
break;
}
- /* ... fall through ... */
+ /* ... fall through ... */
case ROUND_MOD_EXPR:
overflow = div_and_round_double (code, uns,
args.code = code;
if (do_float_handler (const_binop_1, (PTR) &args))
- /* Receive output from const_binop_1. */
+ /* Receive output from const_binop_1. */
t = args.t;
else
{
- /* We got an exception from const_binop_1. */
+ /* We got an exception from const_binop_1. */
t = copy_node (arg1);
overflow = 1;
}
/* This structure is used to communicate arguments to fold_convert_1. */
struct fc_args
{
- tree arg1; /* Input: value to convert. */
- tree type; /* Input: type to convert value to. */
- tree t; /* Ouput: result of conversion. */
+ tree arg1; /* Input: value to convert. */
+ tree type; /* Input: type to convert value to. */
+ tree t; /* Ouput: result of conversion. */
};
/* Function to convert floating-point constants, protected by floating
case 'r':
/* If either of the pointer (or reference) expressions we are dereferencing
- contain a side effect, these cannot be equal. */
+ contain a side effect, these cannot be equal. */
if (TREE_SIDE_EFFECTS (arg0)
|| TREE_SIDE_EFFECTS (arg1))
return 0;
case COMPONENT_REF:
case ARRAY_REF:
+ case ARRAY_RANGE_REF:
return (operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0), 0)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
the same. But, this is computer arithmetic, where numbers are finite.
We can therefore make the transformation of any unbounded range with
the value Z, Z being greater than any representable number. This permits
- us to treat unbounded ranges as equal. */
+ us to treat unbounded ranges as equal. */
sgn0 = arg0 != 0 ? 0 : (upper0_p ? 1 : -1);
sgn1 = arg1 != 0 ? 0 : (upper1_p ? 1 : -1);
switch (code)
/* The last case is if we are a multiply. In that case, we can
apply the distributive law to commute the multiply and addition
- if the multiplication of the constants doesn't overflow. */
+ if the multiplication of the constants doesn't overflow. */
if (code == MULT_EXPR)
return fold (build (tcode, ctype, fold (build (code, ctype,
convert (ctype, op0),
&& integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
return omit_one_operand (type, integer_zero_node, op0);
- /* ... fall through ... */
+ /* ... fall through ... */
case TRUNC_DIV_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR: case EXACT_DIV_EXPR:
/* Don't try to process an RTL_EXPR since its operands aren't trees.
Likewise for a SAVE_EXPR that's already been evaluated. */
- if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t)) != 0)
+ if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t) != 0))
return t;
/* Return right away if a constant. */
}
else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
{
- register int len = TREE_CODE_LENGTH (code);
+ register int len = first_rtl_op (code);
register int i;
for (i = 0; i < len; i++)
{
associate each group together, the constants with literals,
then the result with variables. This increases the chances of
literals being recombined later and of generating relocatable
- expressions for the sum of a constant and literal. */
+ expressions for the sum of a constant and literal. */
var0 = split_tree (arg0, code, &con0, &lit0, 0);
var1 = split_tree (arg1, code, &con1, &lit1, code == MINUS_EXPR);
&& 0 != (tem = const_binop (code, build_real (type, dconst1),
arg1, 0)))
return fold (build (MULT_EXPR, type, arg0, tem));
- /* Find the reciprocal if optimizing and the result is exact. */
+ /* Find the reciprocal if optimizing and the result is exact. */
else if (optimize)
{
REAL_VALUE_TYPE r;
}
}
}
+ /* Convert A/B/C to A/(B*C). */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg0) == RDIV_EXPR)
+ {
+ return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+ build (MULT_EXPR, type, TREE_OPERAND (arg0, 1),
+ arg1)));
+ }
+ /* Convert A/(B/C) to (A/B)*C. */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg1) == RDIV_EXPR)
+ {
+ return fold (build (MULT_EXPR, type,
+ build (RDIV_EXPR, type, arg0,
+ TREE_OPERAND (arg1, 0)),
+ TREE_OPERAND (arg1, 1)));
+ }
goto binary;
case TRUNC_DIV_EXPR:
truth and/or operations and the transformation will still be
valid. Also note that we only care about order for the
ANDIF and ORIF operators. If B contains side effects, this
- might change the truth-value of A. */
+ might change the truth-value of A. */
if (TREE_CODE (arg0) == TREE_CODE (arg1)
&& (TREE_CODE (arg0) == TRUTH_ANDIF_EXPR
|| TREE_CODE (arg0) == TRUTH_ORIF_EXPR
case EQ_EXPR:
case GE_EXPR:
case LE_EXPR:
- if (INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+ if (! FLOAT_TYPE_P (TREE_TYPE (arg0)))
return constant_boolean_node (1, type);
code = EQ_EXPR;
TREE_SET_CODE (t, code);
case NE_EXPR:
/* For NE, we can only do this simplification if integer. */
- if (! INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
+ if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
break;
/* ... fall through ... */
case GT_EXPR:
else if (TREE_INT_CST_HIGH (arg1) == 0
&& (TREE_INT_CST_LOW (arg1)
== ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
- && TREE_UNSIGNED (TREE_TYPE (arg1)))
+ && TREE_UNSIGNED (TREE_TYPE (arg1))
+ /* signed_type does not work on pointer types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
switch (TREE_CODE (t))
{
< TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (top, 0)))))
return 0;
- /* .. fall through ... */
+ /* .. fall through ... */
case SAVE_EXPR:
return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
{
switch (TREE_CODE (t))
{
+ case ABS_EXPR:
+ case FFS_EXPR:
+ return 1;
case INTEGER_CST:
return tree_int_cst_sgn (t) >= 0;
case COND_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
&& tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
+ case COMPOUND_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case MIN_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case MAX_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case MODIFY_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case BIND_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case RTL_EXPR: