/* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ This would also make life easier when this technology is used
@@ for cross-compilers. */
-/* The entry points in this file are fold, size_int_wide, size_binop
- and force_fit_type_double.
+/* The entry points in this file are fold, size_int_wide and size_binop.
fold takes a tree as argument and returns a simplified tree.
size_int takes an integer value, and creates a tree constant
with type from `sizetype'.
- force_fit_type_double takes a constant, an overflowable flag and a
- prior overflow indicator. It forces the value to fit the type and
- sets TREE_OVERFLOW.
-
Note: Since the folders get called on non-gimple code as well as
gimple code, we need to handle GIMPLE tuples as well as their
corresponding tree equivalents. */
#include "expr.h"
#include "tm_p.h"
#include "target.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
#include "intl.h"
#include "ggc.h"
#include "hashtab.h"
#include "langhooks.h"
#include "md5.h"
#include "gimple.h"
+#include "tree-flow.h"
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
static tree negate_expr (tree);
static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
-static tree const_binop (enum tree_code, tree, tree, int);
+static tree const_binop (enum tree_code, tree, tree);
static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code);
static int operand_equal_for_comparison_p (tree, tree, tree);
static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
static bool reorder_operands_p (const_tree, const_tree);
static tree fold_negate_const (tree, tree);
-static tree fold_not_const (tree, tree);
+static tree fold_not_const (const_tree, tree);
static tree fold_relational_const (enum tree_code, tree, tree, tree);
static tree fold_convert_const (enum tree_code, tree, tree);
+/* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION.
+ Otherwise, return LOC. */
+
+static location_t
+expr_location_or (tree t, location_t loc)
+{
+ location_t tloc = EXPR_LOCATION (t);
+ return tloc != UNKNOWN_LOCATION ? tloc : loc;
+}
+
+/* Similar to protected_set_expr_location, but never modify x in place,
+ if location can and needs to be set, unshare it. */
+
+static inline tree
+protected_set_expr_location_unshare (tree x, location_t loc)
+{
+ if (CAN_HAVE_LOCATION_P (x)
+ && EXPR_LOCATION (x) != loc
+ && !(TREE_CODE (x) == SAVE_EXPR
+ || TREE_CODE (x) == TARGET_EXPR
+ || TREE_CODE (x) == BIND_EXPR))
+ {
+ x = copy_node (x);
+ SET_EXPR_LOCATION (x, loc);
+ }
+ return x;
+}
+
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
tem = fold_negate_expr (loc, t);
if (!tem)
- {
- tem = build1 (NEGATE_EXPR, TREE_TYPE (t), t);
- SET_EXPR_LOCATION (tem, loc);
- }
+ tem = build1_loc (loc, NEGATE_EXPR, TREE_TYPE (t), t);
return fold_convert_loc (loc, type, tem);
}
\f
static tree
associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree type)
{
- tree tem;
-
if (t1 == 0)
return t2;
else if (t2 == 0)
if (code == PLUS_EXPR)
{
if (TREE_CODE (t1) == NEGATE_EXPR)
- tem = build2 (MINUS_EXPR, type, fold_convert_loc (loc, type, t2),
- fold_convert_loc (loc, type, TREE_OPERAND (t1, 0)));
+ return build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, t2),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (t1, 0)));
else if (TREE_CODE (t2) == NEGATE_EXPR)
- tem = build2 (MINUS_EXPR, type, fold_convert_loc (loc, type, t1),
- fold_convert_loc (loc, type, TREE_OPERAND (t2, 0)));
+ return build2_loc (loc, MINUS_EXPR, type,
+ fold_convert_loc (loc, type, t1),
+ fold_convert_loc (loc, type,
+ TREE_OPERAND (t2, 0)));
else if (integer_zerop (t2))
return fold_convert_loc (loc, type, t1);
}
return fold_convert_loc (loc, type, t1);
}
- tem = build2 (code, type, fold_convert_loc (loc, type, t1),
- fold_convert_loc (loc, type, t2));
- goto associate_trees_exit;
+ return build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
+ fold_convert_loc (loc, type, t2));
}
return fold_build2_loc (loc, code, type, fold_convert_loc (loc, type, t1),
- fold_convert_loc (loc, type, t2));
- associate_trees_exit:
- protected_set_expr_location (tem, loc);
- return tem;
+ fold_convert_loc (loc, type, t2));
}
\f
/* Check whether TYPE1 and TYPE2 are equivalent integer types, suitable
/* Combine two integer constants ARG1 and ARG2 under operation CODE
to produce a new constant. Return NULL_TREE if we don't know how
- to evaluate CODE at compile-time.
-
- If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
+ to evaluate CODE at compile-time. */
tree
-int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2, int notrunc)
+int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
{
double_int op1, op2, res, tmp;
tree t;
return NULL_TREE;
}
- if (notrunc)
- {
- t = build_int_cst_wide (TREE_TYPE (arg1), res.low, res.high);
-
- /* Propagate overflow flags ourselves. */
- if (((!uns || is_sizetype) && overflow)
- | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2))
- {
- t = copy_node (t);
- TREE_OVERFLOW (t) = 1;
- }
- }
- else
- t = force_fit_type_double (TREE_TYPE (arg1), res.low, res.high, 1,
- ((!uns || is_sizetype) && overflow)
- | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
+ t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
+ ((!uns || is_sizetype) && overflow)
+ | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
return t;
}
/* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
constant. We assume ARG1 and ARG2 have the same data type, or at least
are the same kind of constant and the same machine mode. Return zero if
- combining the constants is not allowed in the current operating mode.
-
- If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
+ combining the constants is not allowed in the current operating mode. */
static tree
-const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
+const_binop (enum tree_code code, tree arg1, tree arg2)
{
/* Sanity check for the recursive cases. */
if (!arg1 || !arg2)
STRIP_NOPS (arg2);
if (TREE_CODE (arg1) == INTEGER_CST)
- return int_const_binop (code, arg1, arg2, notrunc);
+ return int_const_binop (code, arg1, arg2);
if (TREE_CODE (arg1) == REAL_CST)
{
{
case PLUS_EXPR:
case MINUS_EXPR:
- real = const_binop (code, r1, r2, notrunc);
- imag = const_binop (code, i1, i2, notrunc);
+ real = const_binop (code, r1, r2);
+ imag = const_binop (code, i1, i2);
break;
case MULT_EXPR:
mpc_mul);
real = const_binop (MINUS_EXPR,
- const_binop (MULT_EXPR, r1, r2, notrunc),
- const_binop (MULT_EXPR, i1, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r1, r2),
+ const_binop (MULT_EXPR, i1, i2));
imag = const_binop (PLUS_EXPR,
- const_binop (MULT_EXPR, r1, i2, notrunc),
- const_binop (MULT_EXPR, i1, r2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r1, i2),
+ const_binop (MULT_EXPR, i1, r2));
break;
case RDIV_EXPR:
*/
tree magsquared
= const_binop (PLUS_EXPR,
- const_binop (MULT_EXPR, r2, r2, notrunc),
- const_binop (MULT_EXPR, i2, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r2, r2),
+ const_binop (MULT_EXPR, i2, i2));
tree t1
= const_binop (PLUS_EXPR,
- const_binop (MULT_EXPR, r1, r2, notrunc),
- const_binop (MULT_EXPR, i1, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, r1, r2),
+ const_binop (MULT_EXPR, i1, i2));
tree t2
= const_binop (MINUS_EXPR,
- const_binop (MULT_EXPR, i1, r2, notrunc),
- const_binop (MULT_EXPR, r1, i2, notrunc),
- notrunc);
+ const_binop (MULT_EXPR, i1, r2),
+ const_binop (MULT_EXPR, r1, i2));
- real = const_binop (code, t1, magsquared, notrunc);
- imag = const_binop (code, t2, magsquared, notrunc);
+ real = const_binop (code, t1, magsquared);
+ imag = const_binop (code, t2, magsquared);
}
else
{
ti = (ai * ratio) - ar;
tr = tr / div;
ti = ti / div; */
- tree ratio = const_binop (code, r2, i2, notrunc);
+ tree ratio = const_binop (code, r2, i2);
tree div = const_binop (PLUS_EXPR, i2,
- const_binop (MULT_EXPR, r2, ratio,
- notrunc),
- notrunc);
- real = const_binop (MULT_EXPR, r1, ratio, notrunc);
- real = const_binop (PLUS_EXPR, real, i1, notrunc);
- real = const_binop (code, real, div, notrunc);
-
- imag = const_binop (MULT_EXPR, i1, ratio, notrunc);
- imag = const_binop (MINUS_EXPR, imag, r1, notrunc);
- imag = const_binop (code, imag, div, notrunc);
+ const_binop (MULT_EXPR, r2, ratio));
+ real = const_binop (MULT_EXPR, r1, ratio);
+ real = const_binop (PLUS_EXPR, real, i1);
+ real = const_binop (code, real, div);
+
+ imag = const_binop (MULT_EXPR, i1, ratio);
+ imag = const_binop (MINUS_EXPR, imag, r1);
+ imag = const_binop (code, imag, div);
}
else
{
ti = b - (a * ratio);
tr = tr / div;
ti = ti / div; */
- tree ratio = const_binop (code, i2, r2, notrunc);
+ tree ratio = const_binop (code, i2, r2);
tree div = const_binop (PLUS_EXPR, r2,
- const_binop (MULT_EXPR, i2, ratio,
- notrunc),
- notrunc);
+ const_binop (MULT_EXPR, i2, ratio));
- real = const_binop (MULT_EXPR, i1, ratio, notrunc);
- real = const_binop (PLUS_EXPR, real, r1, notrunc);
- real = const_binop (code, real, div, notrunc);
+ real = const_binop (MULT_EXPR, i1, ratio);
+ real = const_binop (PLUS_EXPR, real, r1);
+ real = const_binop (code, real, div);
- imag = const_binop (MULT_EXPR, r1, ratio, notrunc);
- imag = const_binop (MINUS_EXPR, i1, imag, notrunc);
- imag = const_binop (code, imag, div, notrunc);
+ imag = const_binop (MULT_EXPR, r1, ratio);
+ imag = const_binop (MINUS_EXPR, i1, imag);
+ imag = const_binop (code, imag, div);
}
}
break;
elements2 = TREE_CHAIN (elements2);
}
- elem = const_binop (code, elem1, elem2, notrunc);
+ elem = const_binop (code, elem1, elem2);
/* It is possible that const_binop cannot handle the given
code and return NULL_TREE */
}
/* Handle general case of two integer constants. */
- return int_const_binop (code, arg0, arg1, 0);
+ return int_const_binop (code, arg0, arg1);
}
return fold_build2_loc (loc, code, type, arg0, arg1);
/* Given an integer constant, make new constant with new type,
appropriately sign-extended or truncated. */
- t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1),
- TREE_INT_CST_HIGH (arg1),
+ t = force_fit_type_double (type, tree_to_double_int (arg1),
!POINTER_TYPE_P (TREE_TYPE (arg1)),
(TREE_INT_CST_HIGH (arg1) < 0
&& (TYPE_UNSIGNED (type)
if (! overflow)
real_to_integer2 ((HOST_WIDE_INT *) &val.low, &val.high, &r);
- t = force_fit_type_double (type, val.low, val.high, -1,
- overflow | TREE_OVERFLOW (arg1));
+ t = force_fit_type_double (type, val, -1, overflow | TREE_OVERFLOW (arg1));
return t;
}
/* Given a fixed-point constant, make new constant with new type,
appropriately sign-extended or truncated. */
- t = force_fit_type_double (type, temp.low, temp.high, -1,
+ t = force_fit_type_double (type, temp, -1,
(double_int_negative_p (temp)
&& (TYPE_UNSIGNED (type)
< TYPE_UNSIGNED (TREE_TYPE (arg1))))
static tree
build_zero_vector (tree type)
{
- tree elem, list;
- int i, units;
-
- elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
- units = TYPE_VECTOR_SUBPARTS (type);
+ tree t;
- list = NULL_TREE;
- for (i = 0; i < units; i++)
- list = tree_cons (NULL_TREE, elem, list);
- return build_vector (type, list);
+ t = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ return build_vector_from_val (type, t);
}
/* Returns true, if ARG is convertible to TYPE using a NOP_EXPR. */
case VOID_TYPE:
tem = fold_ignored_result (arg);
- if (TREE_CODE (tem) == MODIFY_EXPR)
- goto fold_convert_exit;
return fold_build1_loc (loc, NOP_EXPR, type, tem);
default:
gcc_unreachable ();
}
fold_convert_exit:
- protected_set_expr_location (tem, loc);
+ protected_set_expr_location_unshare (tem, loc);
return tem;
}
\f
case SSA_NAME:
case COMPONENT_REF:
+ case MEM_REF:
case INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
case ARRAY_REF:
case ARRAY_RANGE_REF:
case BIT_FIELD_REF:
if (! maybe_lvalue_p (x))
return x;
- x = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
- SET_EXPR_LOCATION (x, loc);
- return x;
+ return build1_loc (loc, NON_LVALUE_EXPR, TREE_TYPE (x), x);
}
/* Nonzero means lvalues are limited to those valid in pedantic ANSI C.
{
if (pedantic_lvalues)
return non_lvalue_loc (loc, x);
- protected_set_expr_location (x, loc);
- return x;
+
+ return protected_set_expr_location_unshare (x, loc);
}
\f
/* Given a tree comparison code, return the code that is the logical inverse
equal if they have no side effects. If we have two identical
expressions with side effects that should be treated the same due
to the only side effects being identical SAVE_EXPR's, that will
- be detected in the recursive calls below. */
+ be detected in the recursive calls below.
+ If we are taking an invariant address of two identical objects
+ they are necessarily equal as well. */
if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
&& (TREE_CODE (arg0) == SAVE_EXPR
+ || (flags & OEP_CONSTANT_ADDRESS_OF)
|| (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
return 1;
case ADDR_EXPR:
return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
- 0);
+ TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1)
+ ? OEP_CONSTANT_ADDRESS_OF : 0);
default:
break;
}
switch (TREE_CODE (arg0))
{
case INDIRECT_REF:
- case ALIGN_INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
return OP_SAME (0);
+ case MEM_REF:
+ /* Require equal access sizes, and similar pointer types.
+ We can have incomplete types for array references of
+ variable-sized arrays from the Fortran frontent
+ though. */
+ return ((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1))
+ || (TYPE_SIZE (TREE_TYPE (arg0))
+ && TYPE_SIZE (TREE_TYPE (arg1))
+ && operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
+ TYPE_SIZE (TREE_TYPE (arg1)), flags)))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 1)))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg1, 1))))
+ && OP_SAME (0) && OP_SAME (1));
+
case ARRAY_REF:
case ARRAY_RANGE_REF:
/* Operands 2 and 3 may be null.
case TRUTH_ORIF_EXPR:
return OP_SAME (0) && OP_SAME (1);
+ case FMA_EXPR:
+ case WIDEN_MULT_PLUS_EXPR:
+ case WIDEN_MULT_MINUS_EXPR:
+ if (!OP_SAME (2))
+ return 0;
+ /* The multiplcation operands are commutative. */
+ /* FALLTHRU */
+
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
TREE_OPERAND (arg1, 0), flags));
case COND_EXPR:
+ case VEC_COND_EXPR:
+ case DOT_PROD_EXPR:
return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
default:
/* If the resulting operand is an empty statement, just return the omitted
statement casted to void. */
if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted))
- {
- t = build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
- goto omit_one_operand_exit;
- }
+ return build1_loc (loc, NOP_EXPR, void_type_node,
+ fold_ignored_result (omitted));
if (TREE_SIDE_EFFECTS (omitted))
- {
- t = build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
- goto omit_one_operand_exit;
- }
+ return build2_loc (loc, COMPOUND_EXPR, type,
+ fold_ignored_result (omitted), t);
return non_lvalue_loc (loc, t);
-
- omit_one_operand_exit:
- protected_set_expr_location (t, loc);
- return t;
}
/* Similar, but call pedantic_non_lvalue instead of non_lvalue. */
/* If the resulting operand is an empty statement, just return the omitted
statement casted to void. */
if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted))
- {
- t = build1 (NOP_EXPR, void_type_node, fold_ignored_result (omitted));
- goto pedantic_omit_one_operand_exit;
- }
+ return build1_loc (loc, NOP_EXPR, void_type_node,
+ fold_ignored_result (omitted));
if (TREE_SIDE_EFFECTS (omitted))
- {
- t = build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
- goto pedantic_omit_one_operand_exit;
- }
+ return build2_loc (loc, COMPOUND_EXPR, type,
+ fold_ignored_result (omitted), t);
return pedantic_non_lvalue_loc (loc, t);
-
- pedantic_omit_one_operand_exit:
- protected_set_expr_location (t, loc);
- return t;
}
/* Return a tree for the case when the result of an expression is RESULT
tree
omit_two_operands_loc (location_t loc, tree type, tree result,
- tree omitted1, tree omitted2)
+ tree omitted1, tree omitted2)
{
tree t = fold_convert_loc (loc, type, result);
if (TREE_SIDE_EFFECTS (omitted2))
- {
- t = build2 (COMPOUND_EXPR, type, omitted2, t);
- SET_EXPR_LOCATION (t, loc);
- }
+ t = build2_loc (loc, COMPOUND_EXPR, type, omitted2, t);
if (TREE_SIDE_EFFECTS (omitted1))
- {
- t = build2 (COMPOUND_EXPR, type, omitted1, t);
- SET_EXPR_LOCATION (t, loc);
- }
+ t = build2_loc (loc, COMPOUND_EXPR, type, omitted1, t);
return TREE_CODE (t) != COMPOUND_EXPR ? non_lvalue_loc (loc, t) : t;
}
tree
fold_truth_not_expr (location_t loc, tree arg)
{
- tree t, type = TREE_TYPE (arg);
+ tree type = TREE_TYPE (arg);
enum tree_code code = TREE_CODE (arg);
location_t loc1, loc2;
if (code == ERROR_MARK)
return NULL_TREE;
- t = build2 (code, type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1));
- SET_EXPR_LOCATION (t, loc);
- return t;
+ return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (arg, 1));
}
switch (code)
return constant_boolean_node (integer_zerop (arg), type);
case TRUTH_AND_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
- t = build2 (TRUTH_OR_EXPR, type,
- invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
- invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
- break;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+ return build2_loc (loc, TRUTH_OR_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
case TRUTH_OR_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
- t = build2 (TRUTH_AND_EXPR, type,
- invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
- invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
- break;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+ return build2_loc (loc, TRUTH_AND_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
case TRUTH_XOR_EXPR:
/* Here we can invert either operand. We invert the first operand
negation of the second operand. */
if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
- t = build2 (TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
- TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+ return build2_loc (loc, TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
else
- t = build2 (TRUTH_XOR_EXPR, type,
- invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
- TREE_OPERAND (arg, 1));
- break;
+ return build2_loc (loc, TRUTH_XOR_EXPR, type,
+ invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
+ TREE_OPERAND (arg, 1));
case TRUTH_ANDIF_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
- t = build2 (TRUTH_ORIF_EXPR, type,
- invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
- invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
- break;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+ return build2_loc (loc, TRUTH_ORIF_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
case TRUTH_ORIF_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
- t = build2 (TRUTH_ANDIF_EXPR, type,
- invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
- invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
- break;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+ return build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
+ invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
case TRUTH_NOT_EXPR:
return TREE_OPERAND (arg, 0);
tree arg1 = TREE_OPERAND (arg, 1);
tree arg2 = TREE_OPERAND (arg, 2);
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- loc2 = EXPR_LOCATION (TREE_OPERAND (arg, 2));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- if (loc2 == UNKNOWN_LOCATION)
- loc2 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+ loc2 = expr_location_or (TREE_OPERAND (arg, 2), loc);
/* A COND_EXPR may have a throw as one operand, which
then has void type. Just leave void operands
as they are. */
- t = build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
- VOID_TYPE_P (TREE_TYPE (arg1))
- ? arg1 : invert_truthvalue_loc (loc1, arg1),
- VOID_TYPE_P (TREE_TYPE (arg2))
- ? arg2 : invert_truthvalue_loc (loc2, arg2));
- break;
+ return build3_loc (loc, COND_EXPR, type, TREE_OPERAND (arg, 0),
+ VOID_TYPE_P (TREE_TYPE (arg1))
+ ? arg1 : invert_truthvalue_loc (loc1, arg1),
+ VOID_TYPE_P (TREE_TYPE (arg2))
+ ? arg2 : invert_truthvalue_loc (loc2, arg2));
}
case COMPOUND_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 1));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- t = build2 (COMPOUND_EXPR, type,
- TREE_OPERAND (arg, 0),
- invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 1)));
- break;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 1), loc);
+ return build2_loc (loc, COMPOUND_EXPR, type,
+ TREE_OPERAND (arg, 0),
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 1)));
case NON_LVALUE_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
return invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0));
CASE_CONVERT:
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
- {
- t = build1 (TRUTH_NOT_EXPR, type, arg);
- break;
- }
+ return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
/* ... fall through ... */
case FLOAT_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- t = build1 (TREE_CODE (arg), type,
- invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
- break;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ return build1_loc (loc, TREE_CODE (arg), type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
case BIT_AND_EXPR:
if (!integer_onep (TREE_OPERAND (arg, 1)))
return NULL_TREE;
- t = build2 (EQ_EXPR, type, arg, build_int_cst (type, 0));
- break;
+ return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
case SAVE_EXPR:
- t = build1 (TRUTH_NOT_EXPR, type, arg);
- break;
+ return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
case CLEANUP_POINT_EXPR:
- loc1 = EXPR_LOCATION (TREE_OPERAND (arg, 0));
- if (loc1 == UNKNOWN_LOCATION)
- loc1 = loc;
- t = build1 (CLEANUP_POINT_EXPR, type,
- invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
- break;
+ loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
+ return build1_loc (loc, CLEANUP_POINT_EXPR, type,
+ invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
default:
- t = NULL_TREE;
- break;
+ return NULL_TREE;
}
-
- if (t)
- SET_EXPR_LOCATION (t, loc);
-
- return t;
}
/* Return a simplified tree node for the truth-negation of ARG. This
tem = fold_truth_not_expr (loc, arg);
if (!tem)
- {
- tem = build1 (TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
- SET_EXPR_LOCATION (tem, loc);
- }
+ tem = build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
return tem;
}
|| TYPE_UNSIGNED (bftype) == !unsignedp)
bftype = build_nonstandard_integer_type (bitsize, 0);
- result = build3 (BIT_FIELD_REF, bftype, inner,
- size_int (bitsize), bitsize_int (bitpos));
- SET_EXPR_LOCATION (result, loc);
+ result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
+ size_int (bitsize), bitsize_int (bitpos));
if (bftype != type)
result = fold_convert_loc (loc, type, result);
/* Make the mask to be used against the extracted field. */
mask = build_int_cst_type (unsigned_type, -1);
- mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize), 0);
+ mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize));
mask = const_binop (RSHIFT_EXPR, mask,
- size_int (nbitsize - lbitsize - lbitpos), 0);
+ size_int (nbitsize - lbitsize - lbitpos));
if (! const_p)
/* If not comparing with constant, just rework the comparison
if (! integer_zerop (const_binop (RSHIFT_EXPR,
fold_convert_loc (loc,
unsigned_type, rhs),
- size_int (lbitsize), 0)))
+ size_int (lbitsize))))
{
warning (0, "comparison is always %d due to width of bit-field",
code == NE_EXPR);
{
tree tem = const_binop (RSHIFT_EXPR,
fold_convert_loc (loc, signed_type, rhs),
- size_int (lbitsize - 1), 0);
+ size_int (lbitsize - 1));
if (! integer_zerop (tem) && ! integer_all_onesp (tem))
{
warning (0, "comparison is always %d due to width of bit-field",
rhs = const_binop (BIT_AND_EXPR,
const_binop (LSHIFT_EXPR,
fold_convert_loc (loc, unsigned_type, rhs),
- size_int (lbitpos), 0),
- mask, 0);
+ size_int (lbitpos)),
+ mask);
- lhs = build2 (code, compare_type,
- build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
- rhs);
- SET_EXPR_LOCATION (lhs, loc);
+ lhs = build2_loc (loc, code, compare_type,
+ build2 (BIT_AND_EXPR, unsigned_type, lhs, mask), rhs);
return lhs;
}
\f
mask = build_int_cst_type (unsigned_type, -1);
- mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
- mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
+ mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize));
+ mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize));
/* Merge it with the mask we found in the BIT_AND_EXPR, if any. */
if (and_mask != 0)
tree_int_cst_equal (mask,
const_binop (RSHIFT_EXPR,
const_binop (LSHIFT_EXPR, tmask,
- size_int (precision - size),
- 0),
- size_int (precision - size), 0));
+ size_int (precision - size)),
+ size_int (precision - size)));
}
/* Subroutine for fold: determine if VAL is the INTEGER_CONST that
n_high = range_binop (MINUS_EXPR, exp_type,
build_int_cst (exp_type, 0),
0, low, 0);
- low = n_low, high = n_high;
- exp = arg0;
- continue;
+ if (n_high != 0 && TREE_OVERFLOW (n_high))
+ break;
+ goto normalize;
case BIT_NOT_EXPR:
/* ~ X -> -X - 1 */
- exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
- build_int_cst (exp_type, 1));
- SET_EXPR_LOCATION (exp, loc);
+ exp = build2_loc (loc, MINUS_EXPR, exp_type, negate_expr (arg0),
+ build_int_cst (exp_type, 1));
continue;
case PLUS_EXPR: case MINUS_EXPR:
if (TYPE_OVERFLOW_UNDEFINED (arg0_type))
*strict_overflow_p = true;
+ normalize:
/* Check for an unsigned range which has wrapped around the maximum
value thus making n_high < n_low, and normalize it. */
if (n_low && n_high && tree_int_cst_lt (n_high, n_low))
low = fold_convert_loc (loc, etype, low);
exp = fold_convert_loc (loc, etype, exp);
- value = const_binop (MINUS_EXPR, high, low, 0);
+ value = const_binop (MINUS_EXPR, high, low);
if (POINTER_TYPE_P (etype))
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
{
tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
{
tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (MINUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
{
tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
OEP_ONLY_CONST)
&& operand_equal_p (arg01,
const_binop (PLUS_EXPR, arg2,
- build_int_cst (type, 1), 0),
+ build_int_cst (type, 1)),
OEP_ONLY_CONST))
{
tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
if ((lhs == 0 || rhs == 0 || operand_equal_p (lhs, rhs, 0))
&& merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
in1_p, low1, high1)
- && 0 != (tem = (build_range_check (UNKNOWN_LOCATION, type,
+ && 0 != (tem = (build_range_check (loc, type,
lhs != 0 ? lhs
: rhs != 0 ? rhs : integer_zero_node,
in_p, low, high))))
unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in
which cases we can't do this. */
if (simple_operand_p (lhs))
- {
- tem = build2 (code == TRUTH_ANDIF_EXPR
- ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
- type, op0, op1);
- SET_EXPR_LOCATION (tem, loc);
- return tem;
- }
+ return build2_loc (loc, code == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ type, op0, op1);
- else if (lang_hooks.decls.global_bindings_p () == 0
- && ! CONTAINS_PLACEHOLDER_P (lhs))
+ else if (!lang_hooks.decls.global_bindings_p ()
+ && !CONTAINS_PLACEHOLDER_P (lhs))
{
tree common = save_expr (lhs);
if (strict_overflow_p)
fold_overflow_warning (warnmsg,
WARN_STRICT_OVERFLOW_COMPARISON);
- tem = build2 (code == TRUTH_ANDIF_EXPR
- ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
- type, lhs, rhs);
- SET_EXPR_LOCATION (tem, loc);
- return tem;
+ return build2_loc (loc, code == TRUTH_ANDIF_EXPR
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ type, lhs, rhs);
}
}
}
/* We work by getting just the sign bit into the low-order bit, then
into the high-order bit, then sign-extend. We then XOR that value
with C. */
- temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1), 0);
- temp = const_binop (BIT_AND_EXPR, temp, size_int (1), 0);
+ temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1));
+ temp = const_binop (BIT_AND_EXPR, temp, size_int (1));
/* We must use a signed type in order to get an arithmetic right shift.
However, we must also avoid introducing accidental overflows, so that
if (TYPE_UNSIGNED (type))
temp = fold_convert (signed_type_for (type), temp);
- temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
- temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
+ temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1));
+ temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1));
if (mask != 0)
temp = const_binop (BIT_AND_EXPR, temp,
- fold_convert (TREE_TYPE (c), mask),
- 0);
+ fold_convert (TREE_TYPE (c), mask));
/* If necessary, convert the type back to match the type of C. */
if (TYPE_UNSIGNED (type))
temp = fold_convert (type, temp);
- return fold_convert (type,
- const_binop (BIT_XOR_EXPR, c, temp, 0));
+ return fold_convert (type, const_binop (BIT_XOR_EXPR, c, temp));
}
\f
/* For an expression that has the form
if (simple_operand_p (ll_arg)
&& simple_operand_p (lr_arg))
{
- tree result;
if (operand_equal_p (ll_arg, rl_arg, 0)
&& operand_equal_p (lr_arg, rr_arg, 0))
{
&& rcode == NE_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
&& INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
- {
- result = build2 (NE_EXPR, truth_type,
+ return build2_loc (loc, NE_EXPR, truth_type,
build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
ll_arg, rl_arg),
build_int_cst (TREE_TYPE (ll_arg), 0));
- goto fold_truthop_exit;
- }
/* Convert (a == 0) && (b == 0) into (a | b) == 0. */
if (code == TRUTH_AND_EXPR
&& rcode == EQ_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
&& INTEGRAL_TYPE_P (TREE_TYPE (ll_arg)))
- {
- result = build2 (EQ_EXPR, truth_type,
+ return build2_loc (loc, EQ_EXPR, truth_type,
build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
ll_arg, rl_arg),
build_int_cst (TREE_TYPE (ll_arg), 0));
- goto fold_truthop_exit;
- }
if (LOGICAL_OP_NON_SHORT_CIRCUIT)
{
if (code != orig_code || lhs != orig_lhs || rhs != orig_rhs)
- {
- result = build2 (code, truth_type, lhs, rhs);
- goto fold_truthop_exit;
- }
+ return build2_loc (loc, code, truth_type, lhs, rhs);
return NULL_TREE;
}
}
}
ll_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc, lntype, ll_mask),
- size_int (xll_bitpos), 0);
+ size_int (xll_bitpos));
rl_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc, lntype, rl_mask),
- size_int (xrl_bitpos), 0);
+ size_int (xrl_bitpos));
if (l_const)
{
l_const = fold_convert_loc (loc, lntype, l_const);
l_const = unextend (l_const, ll_bitsize, ll_unsignedp, ll_and_mask);
- l_const = const_binop (LSHIFT_EXPR, l_const, size_int (xll_bitpos), 0);
+ l_const = const_binop (LSHIFT_EXPR, l_const, size_int (xll_bitpos));
if (! integer_zerop (const_binop (BIT_AND_EXPR, l_const,
fold_build1_loc (loc, BIT_NOT_EXPR,
- lntype, ll_mask),
- 0)))
+ lntype, ll_mask))))
{
warning (0, "comparison is always %d", wanted_code == NE_EXPR);
{
r_const = fold_convert_loc (loc, lntype, r_const);
r_const = unextend (r_const, rl_bitsize, rl_unsignedp, rl_and_mask);
- r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos), 0);
+ r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos));
if (! integer_zerop (const_binop (BIT_AND_EXPR, r_const,
fold_build1_loc (loc, BIT_NOT_EXPR,
- lntype, rl_mask),
- 0)))
+ lntype, rl_mask))))
{
warning (0, "comparison is always %d", wanted_code == NE_EXPR);
lr_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc,
rntype, lr_mask),
- size_int (xlr_bitpos), 0);
+ size_int (xlr_bitpos));
rr_mask = const_binop (LSHIFT_EXPR, fold_convert_loc (loc,
rntype, rr_mask),
- size_int (xrr_bitpos), 0);
+ size_int (xrr_bitpos));
/* Make a mask that corresponds to both fields being compared.
Do this for both items being compared. If the operands are the
same size and the bits being compared are in the same position
then we can do this by masking both and comparing the masked
results. */
- ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
- lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask, 0);
+ ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
+ lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask);
if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
{
lhs = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
if (! all_ones_mask_p (lr_mask, rnbitsize))
rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask);
- result = build2 (wanted_code, truth_type, lhs, rhs);
- goto fold_truthop_exit;
+ return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
}
/* There is still another way we can do something: If both pairs of
MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
ll_mask = const_binop (RSHIFT_EXPR, ll_mask,
- size_int (MIN (xll_bitpos, xrl_bitpos)), 0);
+ size_int (MIN (xll_bitpos, xrl_bitpos)));
lr_mask = const_binop (RSHIFT_EXPR, lr_mask,
- size_int (MIN (xlr_bitpos, xrr_bitpos)), 0);
+ size_int (MIN (xlr_bitpos, xrr_bitpos)));
/* Convert to the smaller type before masking out unwanted bits. */
type = lntype;
if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
rhs = build2 (BIT_AND_EXPR, type, rhs, lr_mask);
- result = build2 (wanted_code, truth_type, lhs, rhs);
- goto fold_truthop_exit;
+ return build2_loc (loc, wanted_code, truth_type, lhs, rhs);
}
return 0;
common between the masks, those bits of the constants must be the same.
If not, the condition is always false. Test for this to avoid generating
incorrect code below. */
- result = const_binop (BIT_AND_EXPR, ll_mask, rl_mask, 0);
+ result = const_binop (BIT_AND_EXPR, ll_mask, rl_mask);
if (! integer_zerop (result)
- && simple_cst_equal (const_binop (BIT_AND_EXPR, result, l_const, 0),
- const_binop (BIT_AND_EXPR, result, r_const, 0)) != 1)
+ && simple_cst_equal (const_binop (BIT_AND_EXPR, result, l_const),
+ const_binop (BIT_AND_EXPR, result, r_const)) != 1)
{
if (wanted_code == NE_EXPR)
{
result = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
- ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
+ ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
if (! all_ones_mask_p (ll_mask, lnbitsize))
- {
- result = build2 (BIT_AND_EXPR, lntype, result, ll_mask);
- SET_EXPR_LOCATION (result, loc);
- }
+ result = build2_loc (loc, BIT_AND_EXPR, lntype, result, ll_mask);
- result = build2 (wanted_code, truth_type, result,
- const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
-
- fold_truthop_exit:
- SET_EXPR_LOCATION (result, loc);
- return result;
+ return build2_loc (loc, wanted_code, truth_type, result,
+ const_binop (BIT_IOR_EXPR, l_const, r_const));
}
\f
/* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a
/* For a constant, we can always simplify if we are a multiply
or (for divide and modulus) if it is a multiple of our constant. */
if (code == MULT_EXPR
- || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c, 0)))
+ || integer_zerop (const_binop (TRUNC_MOD_EXPR, t, c)))
return const_binop (code, fold_convert (ctype, t),
- fold_convert (ctype, c), 0);
+ fold_convert (ctype, c));
break;
CASE_CONVERT: case NON_LVALUE_EXPR:
&& 0 != (t1 = fold_convert (ctype,
const_binop (LSHIFT_EXPR,
size_one_node,
- op1, 0)))
+ op1)))
&& !TREE_OVERFLOW (t1))
return extract_muldiv (build2 (tcode == LSHIFT_EXPR
? MULT_EXPR : FLOOR_DIV_EXPR,
/* If it's a multiply or a division/modulus operation of a multiple
of our constant, do the operation and verify it doesn't overflow. */
if (code == MULT_EXPR
- || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+ || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
{
op1 = const_binop (code, fold_convert (ctype, op1),
- fold_convert (ctype, c), 0);
+ fold_convert (ctype, c));
/* We allow the constant to overflow with wrapping semantics. */
if (op1 == 0
|| (TREE_OVERFLOW (op1) && !TYPE_OVERFLOW_WRAPS (ctype)))
|| (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
&& TYPE_IS_SIZETYPE (TREE_TYPE (t))))
&& TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
- && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+ && integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
{
*strict_overflow_p = true;
return omit_one_operand (type, integer_zero_node, op0);
/* If these are the same operation types, we can associate them
assuming no overflow. */
- if (tcode == code
- && 0 != (t1 = int_const_binop (MULT_EXPR,
- fold_convert (ctype, op1),
- fold_convert (ctype, c), 1))
- && 0 != (t1 = force_fit_type_double (ctype, TREE_INT_CST_LOW (t1),
- TREE_INT_CST_HIGH (t1),
- (TYPE_UNSIGNED (ctype)
- && tcode != MULT_EXPR) ? -1 : 1,
- TREE_OVERFLOW (t1)))
- && !TREE_OVERFLOW (t1))
- return fold_build2 (tcode, ctype, fold_convert (ctype, op0), t1);
+ if (tcode == code)
+ {
+ double_int mul;
+ int overflow_p;
+ mul = double_int_mul_with_sign
+ (double_int_ext
+ (tree_to_double_int (op1),
+ TYPE_PRECISION (ctype), TYPE_UNSIGNED (ctype)),
+ double_int_ext
+ (tree_to_double_int (c),
+ TYPE_PRECISION (ctype), TYPE_UNSIGNED (ctype)),
+ false, &overflow_p);
+ overflow_p = (((!TYPE_UNSIGNED (ctype)
+ || (TREE_CODE (ctype) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (ctype)))
+ && overflow_p)
+ | TREE_OVERFLOW (c) | TREE_OVERFLOW (op1));
+ if (!double_int_fits_to_tree_p (ctype, mul)
+ && ((TYPE_UNSIGNED (ctype) && tcode != MULT_EXPR)
+ || !TYPE_UNSIGNED (ctype)
+ || (TREE_CODE (ctype) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (ctype))))
+ overflow_p = 1;
+ if (!overflow_p)
+ return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
+ double_int_to_tree (ctype, mul));
+ }
/* If these operations "cancel" each other, we have the main
optimizations of this pass, which occur when either constant is a
&& code != FLOOR_MOD_EXPR && code != ROUND_MOD_EXPR
&& code != MULT_EXPR)))
{
- if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
+ if (integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c)))
{
if (TYPE_OVERFLOW_UNDEFINED (ctype))
*strict_overflow_p = true;
return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
fold_convert (ctype,
const_binop (TRUNC_DIV_EXPR,
- op1, c, 0)));
+ op1, c)));
}
- else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1, 0)))
+ else if (integer_zerop (const_binop (TRUNC_MOD_EXPR, c, op1)))
{
if (TYPE_OVERFLOW_UNDEFINED (ctype))
*strict_overflow_p = true;
return fold_build2 (code, ctype, fold_convert (ctype, op0),
fold_convert (ctype,
const_binop (TRUNC_DIV_EXPR,
- c, op1, 0)));
+ c, op1)));
}
}
break;
build_real (TREE_TYPE (arg), dconst0));
/* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
- if (lang_hooks.decls.global_bindings_p () != 0
- || CONTAINS_PLACEHOLDER_P (arg))
- return NULL_TREE;
-
arg = save_expr (arg);
return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
fold_build2_loc (loc, GE_EXPR, type, arg,
build_real (TREE_TYPE (arg), c2));
/* sqrt(x) < c is the same as x >= 0 && x < c*c. */
- if (lang_hooks.decls.global_bindings_p () == 0
- && ! CONTAINS_PLACEHOLDER_P (arg))
- {
- arg = save_expr (arg);
- return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
+ arg = save_expr (arg);
+ return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
fold_build2_loc (loc, GE_EXPR, type, arg,
build_real (TREE_TYPE (arg),
dconst0)),
fold_build2_loc (loc, code, type, arg,
build_real (TREE_TYPE (arg),
c2)));
- }
}
}
return omit_one_operand_loc (loc, type, integer_one_node, arg0);
/* x <= +Inf is the same as x == x, i.e. isfinite(x). */
- if (lang_hooks.decls.global_bindings_p () == 0
- && ! CONTAINS_PLACEHOLDER_P (arg0))
- {
- arg0 = save_expr (arg0);
- return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg0);
- }
- break;
+ arg0 = save_expr (arg0);
+ return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg0);
case EQ_EXPR:
case GE_EXPR:
tree prod, tmp, hi, lo;
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
- unsigned HOST_WIDE_INT lpart;
- HOST_WIDE_INT hpart;
+ double_int val;
bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
bool neg_overflow;
int overflow;
/* We have to do this the hard way to detect unsigned overflow.
- prod = int_const_binop (MULT_EXPR, arg01, arg1, 0); */
+ prod = int_const_binop (MULT_EXPR, arg01, arg1); */
overflow = mul_double_with_sign (TREE_INT_CST_LOW (arg01),
TREE_INT_CST_HIGH (arg01),
TREE_INT_CST_LOW (arg1),
TREE_INT_CST_HIGH (arg1),
- &lpart, &hpart, unsigned_p);
- prod = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
- -1, overflow);
+ &val.low, &val.high, unsigned_p);
+ prod = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow);
neg_overflow = false;
if (unsigned_p)
{
tmp = int_const_binop (MINUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1), 0);
+ build_int_cst (TREE_TYPE (arg01), 1));
lo = prod;
- /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0). */
+ /* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp). */
overflow = add_double_with_sign (TREE_INT_CST_LOW (prod),
TREE_INT_CST_HIGH (prod),
TREE_INT_CST_LOW (tmp),
TREE_INT_CST_HIGH (tmp),
- &lpart, &hpart, unsigned_p);
- hi = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart,
+ &val.low, &val.high, unsigned_p);
+ hi = force_fit_type_double (TREE_TYPE (arg00), val,
-1, overflow | TREE_OVERFLOW (prod));
}
else if (tree_int_cst_sgn (arg01) >= 0)
{
tmp = int_const_binop (MINUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1), 0);
+ build_int_cst (TREE_TYPE (arg01), 1));
switch (tree_int_cst_sgn (arg1))
{
case -1:
neg_overflow = true;
- lo = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+ lo = int_const_binop (MINUS_EXPR, prod, tmp);
hi = prod;
break;
break;
case 1:
- hi = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+ hi = int_const_binop (PLUS_EXPR, prod, tmp);
lo = prod;
break;
code = swap_tree_comparison (code);
tmp = int_const_binop (PLUS_EXPR, arg01,
- build_int_cst (TREE_TYPE (arg01), 1), 0);
+ build_int_cst (TREE_TYPE (arg01), 1));
switch (tree_int_cst_sgn (arg1))
{
case -1:
- hi = int_const_binop (MINUS_EXPR, prod, tmp, 0);
+ hi = int_const_binop (MINUS_EXPR, prod, tmp);
lo = prod;
break;
case 1:
neg_overflow = true;
- lo = int_const_binop (PLUS_EXPR, prod, tmp, 0);
+ lo = int_const_binop (PLUS_EXPR, prod, tmp);
hi = prod;
break;
return NULL_TREE;
if (TREE_CODE (arg1) == INTEGER_CST)
- arg1 = force_fit_type_double (inner_type, TREE_INT_CST_LOW (arg1),
- TREE_INT_CST_HIGH (arg1), 0,
- TREE_OVERFLOW (arg1));
+ arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1),
+ 0, TREE_OVERFLOW (arg1));
else
arg1 = fold_convert_loc (loc, inner_type, arg1);
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
- /* Note: doesn't apply to ALIGN_INDIRECT_REF */
- if (TREE_CODE (t) == INDIRECT_REF
- || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+ if (TREE_CODE (t) == INDIRECT_REF)
{
t = TREE_OPERAND (t, 0);
if (TREE_TYPE (t) != ptrtype)
- {
- t = build1 (NOP_EXPR, ptrtype, t);
- SET_EXPR_LOCATION (t, loc);
- }
+ t = build1_loc (loc, NOP_EXPR, ptrtype, t);
}
+ else if (TREE_CODE (t) == MEM_REF
+ && integer_zerop (TREE_OPERAND (t, 1)))
+ return TREE_OPERAND (t, 0);
else if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
{
t = build_fold_addr_expr_loc (loc, TREE_OPERAND (t, 0));
t = fold_convert_loc (loc, ptrtype, t);
}
else
- {
- t = build1 (ADDR_EXPR, ptrtype, t);
- SET_EXPR_LOCATION (t, loc);
- }
+ t = build1_loc (loc, ADDR_EXPR, ptrtype, t);
return t;
}
(TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
&& TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
|| flag_syntax_only))
- {
- tem = build1 (code, type,
- build3 (COND_EXPR,
- TREE_TYPE (TREE_OPERAND
- (TREE_OPERAND (tem, 1), 0)),
- TREE_OPERAND (tem, 0),
- TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
- TREE_OPERAND (TREE_OPERAND (tem, 2), 0)));
- SET_EXPR_LOCATION (tem, loc);
- }
+ tem = build1_loc (loc, code, type,
+ build3 (COND_EXPR,
+ TREE_TYPE (TREE_OPERAND
+ (TREE_OPERAND (tem, 1), 0)),
+ TREE_OPERAND (tem, 0),
+ TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
+ TREE_OPERAND (TREE_OPERAND (tem, 2),
+ 0)));
return tem;
}
- else if (COMPARISON_CLASS_P (arg0))
- {
- if (TREE_CODE (type) == BOOLEAN_TYPE)
- {
- arg0 = copy_node (arg0);
- TREE_TYPE (arg0) = type;
- return arg0;
- }
- else if (TREE_CODE (type) != INTEGER_TYPE)
- return fold_build3_loc (loc, COND_EXPR, type, arg0,
- fold_build1_loc (loc, code, type,
- integer_one_node),
- fold_build1_loc (loc, code, type,
- integer_zero_node));
- }
}
switch (code)
unless assigning a bitfield. */
tem = fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 1));
/* First do the assignment, then return converted constant. */
- tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
+ tem = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
TREE_NO_WARNING (tem) = 1;
TREE_USED (tem) = 1;
- SET_EXPR_LOCATION (tem, loc);
return tem;
}
}
if (change)
{
- tem = force_fit_type_double (type, TREE_INT_CST_LOW (and1),
- TREE_INT_CST_HIGH (and1), 0,
- TREE_OVERFLOW (and1));
+ tem = force_fit_type_double (type, tree_to_double_int (and1),
+ 0, TREE_OVERFLOW (and1));
return fold_build2_loc (loc, BIT_AND_EXPR, type,
fold_convert_loc (loc, type, and0), tem);
}
if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
return fold_build1_loc (loc, VIEW_CONVERT_EXPR,
type, TREE_OPERAND (op0, 0));
+ if (TREE_CODE (op0) == MEM_REF)
+ return fold_build2_loc (loc, MEM_REF, type,
+ TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
/* For integral conversions with the same precision or pointer
conversions use a NOP_EXPR instead. */
case IMAGPART_EXPR:
if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return fold_convert_loc (loc, type, integer_zero_node);
+ return build_zero_cst (type);
if (TREE_CODE (arg0) == COMPLEX_EXPR)
return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg0, 0));
return NULL_TREE;
t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
- cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
+ cst0, build_int_cst (TREE_TYPE (cst0), 1));
if (code0 != INTEGER_CST)
t = fold_build2_loc (loc, code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
&& (TREE_CODE (lhs) != INTEGER_CST
|| !TREE_OVERFLOW (lhs)))
{
- fold_overflow_warning ("assuming signed overflow does not occur "
- "when changing X +- C1 cmp C2 to "
- "X cmp C1 +- C2",
- WARN_STRICT_OVERFLOW_COMPARISON);
+ if (code != EQ_EXPR && code != NE_EXPR)
+ fold_overflow_warning ("assuming signed overflow does not occur "
+ "when changing X +- C1 cmp C2 to "
+ "X cmp C1 +- C2",
+ WARN_STRICT_OVERFLOW_COMPARISON);
return fold_build2_loc (loc, code, type, variable, lhs);
}
}
else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
{
base0 = TREE_OPERAND (arg0, 0);
+ STRIP_SIGN_NOPS (base0);
+ if (TREE_CODE (base0) == ADDR_EXPR)
+ {
+ base0 = TREE_OPERAND (base0, 0);
+ indirect_base0 = true;
+ }
offset0 = TREE_OPERAND (arg0, 1);
}
else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
{
base1 = TREE_OPERAND (arg1, 0);
+ STRIP_SIGN_NOPS (base1);
+ if (TREE_CODE (base1) == ADDR_EXPR)
+ {
+ base1 = TREE_OPERAND (base1, 0);
+ indirect_base1 = true;
+ }
offset1 = TREE_OPERAND (arg1, 1);
}
of lower absolute value than before. */
cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
? MINUS_EXPR : PLUS_EXPR,
- const2, const1, 0);
+ const2, const1);
if (!TREE_OVERFLOW (cst)
&& tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2))
{
cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
? MINUS_EXPR : PLUS_EXPR,
- const1, const2, 0);
+ const1, const2);
if (!TREE_OVERFLOW (cst)
&& tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1))
{
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
&& 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
? MINUS_EXPR : PLUS_EXPR,
- arg1, TREE_OPERAND (arg0, 1), 0))
+ arg1, TREE_OPERAND (arg0, 1)))
&& !TREE_OVERFLOW (tem))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
&& TREE_CODE (arg0) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
&& 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
- arg1, 0))
+ arg1))
&& !TREE_OVERFLOW (tem))
return fold_build2_loc (loc, swap_tree_comparison (code), type,
TREE_OPERAND (arg0, 1), tem);
fold_build2_loc (loc, MULT_EXPR, itype, rpart, rpart),
fold_build2_loc (loc, MULT_EXPR, itype, ipart, ipart));
return fold_build2_loc (loc, COMPLEX_EXPR, type, tem,
- fold_convert_loc (loc, itype, integer_zero_node));
+ build_zero_cst (itype));
}
code = TREE_CODE (expr);
if (code == ADDR_EXPR)
{
- expr = TREE_OPERAND (expr, 0);
- if (handled_component_p (expr))
- {
- HOST_WIDE_INT bitsize, bitpos;
- tree offset;
- enum machine_mode mode;
- int unsignedp, volatilep;
-
- expr = get_inner_reference (expr, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, false);
- *residue = bitpos / BITS_PER_UNIT;
- if (offset)
- {
- if (TREE_CODE (offset) == INTEGER_CST)
- *residue += TREE_INT_CST_LOW (offset);
- else
- /* We don't handle more complicated offset expressions. */
- return 1;
- }
- }
-
- if (DECL_P (expr)
- && (allow_func_align || TREE_CODE (expr) != FUNCTION_DECL))
- return DECL_ALIGN_UNIT (expr);
+ unsigned int bitalign;
+ bitalign = get_object_alignment_1 (TREE_OPERAND (expr, 0), residue);
+ *residue /= BITS_PER_UNIT;
+ return bitalign / BITS_PER_UNIT;
}
else if (code == POINTER_PLUS_EXPR)
{
}
}
- /* If we get here, we were unable to determine anything useful about the
- expression. */
- return 1;
+ /* If we get here, we were unable to determine anything useful about the
+ expression. */
+ return 1;
}
/* Make sure type and arg0 have the same saturating flag. */
gcc_assert (TYPE_SATURATING (type)
== TYPE_SATURATING (TREE_TYPE (arg0)));
- tem = const_binop (code, arg0, arg1, 0);
+ tem = const_binop (code, arg0, arg1);
}
else if (kind == tcc_comparison)
tem = fold_relational_const (code, type, arg0, arg1);
tem = fold_build2_loc (loc, code, type,
fold_convert_loc (loc, TREE_TYPE (op0),
TREE_OPERAND (arg0, 1)), op1);
- tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), tem);
- goto fold_binary_exit;
+ return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+ tem);
}
if (TREE_CODE (arg1) == COMPOUND_EXPR
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
tem = fold_build2_loc (loc, code, type, op0,
fold_convert_loc (loc, TREE_TYPE (op1),
TREE_OPERAND (arg1, 1)));
- tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), tem);
- goto fold_binary_exit;
+ return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+ tem);
}
if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
switch (code)
{
+ case MEM_REF:
+ /* MEM[&MEM[p, CST1], CST2] -> MEM[p, CST1 + CST2]. */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == MEM_REF)
+ {
+ tree iref = TREE_OPERAND (arg0, 0);
+ return fold_build2 (MEM_REF, type,
+ TREE_OPERAND (iref, 0),
+ int_const_binop (PLUS_EXPR, arg1,
+ TREE_OPERAND (iref, 1)));
+ }
+
+ /* MEM[&a.b, CST2] -> MEM[&a, offsetof (a, b) + CST2]. */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && handled_component_p (TREE_OPERAND (arg0, 0)))
+ {
+ tree base;
+ HOST_WIDE_INT coffset;
+ base = get_addr_base_and_unit_offset (TREE_OPERAND (arg0, 0),
+ &coffset);
+ if (!base)
+ return NULL_TREE;
+ return fold_build2 (MEM_REF, type,
+ build_fold_addr_expr (base),
+ int_const_binop (PLUS_EXPR, arg1,
+ size_int (coffset)));
+ }
+
+ return NULL_TREE;
+
case POINTER_PLUS_EXPR:
/* 0 +p index -> (type)index */
if (integer_zerop (arg0))
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
&& integer_zerop (const_binop (BIT_AND_EXPR,
TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0)))
+ TREE_OPERAND (arg1, 1))))
{
code = BIT_IOR_EXPR;
goto bit_ior;
&& ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
{
- tem = build2 (LROTATE_EXPR,
- TREE_TYPE (TREE_OPERAND (arg0, 0)),
- TREE_OPERAND (arg0, 0),
- code0 == LSHIFT_EXPR
- ? tree01 : tree11);
- SET_EXPR_LOCATION (tem, loc);
+ tem = build2_loc (loc, LROTATE_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0),
+ code0 == LSHIFT_EXPR ? tree01 : tree11);
return fold_convert_loc (loc, type, tem);
}
else if (code11 == MINUS_EXPR)
if ((!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
&& operand_equal_p (arg0, arg1, 0))
- return fold_convert_loc (loc, type, integer_zero_node);
+ return build_zero_cst (type);
/* A - B -> A + (-B) if B is easily negatable. */
if (negate_expr_p (arg1)
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
{
tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
- arg1, 0);
+ arg1);
if (tem)
return fold_build2_loc (loc, RDIV_EXPR, type, tem,
TREE_OPERAND (arg0, 1));
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
{
- t1 = fold_convert_loc (loc, type, integer_zero_node);
+ t1 = build_zero_cst (type);
t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
return omit_one_operand_loc (loc, type, t1, arg1);
}
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
{
- t1 = fold_convert_loc (loc, type, integer_zero_node);
+ t1 = build_zero_cst (type);
t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
return omit_one_operand_loc (loc, type, t1, arg0);
}
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
+ /* (X & ~Y) | (~X & Y) is X ^ Y */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (arg1) == BIT_AND_EXPR)
+ {
+ tree a0, a1, l0, l1, n0, n1;
+
+ a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+
+ l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+
+ n0 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l0);
+ n1 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l1);
+
+ if ((operand_equal_p (n0, a0, 0)
+ && operand_equal_p (n1, a1, 0))
+ || (operand_equal_p (n0, a1, 0)
+ && operand_equal_p (n1, a0, 0)))
+ return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
+ }
+
t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
{
- t1 = fold_convert_loc (loc, type, integer_zero_node);
+ t1 = build_zero_cst (type);
t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
return omit_one_operand_loc (loc, type, t1, arg1);
}
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
{
- t1 = fold_convert_loc (loc, type, integer_zero_node);
+ t1 = build_zero_cst (type);
t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
return omit_one_operand_loc (loc, type, t1, arg0);
}
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
&& integer_zerop (const_binop (BIT_AND_EXPR,
TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0)))
+ TREE_OPERAND (arg1, 1))))
{
code = BIT_IOR_EXPR;
goto bit_ior;
fold_convert_loc (loc, type, arg0));
}
+ /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
+ ((A & N) + B) & M -> (A + B) & M
+ Similarly if (N & M) == 0,
+ ((A | N) + B) & M -> (A + B) & M
+ and for - instead of + (or unary - instead of +)
+ and/or ^ instead of |.
+ If B is constant and (B & M) == 0, fold into A & M. */
+ if (host_integerp (arg1, 1))
+ {
+ unsigned HOST_WIDE_INT cst1 = tree_low_cst (arg1, 1);
+ if (~cst1 && (cst1 & (cst1 + 1)) == 0
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && (TREE_CODE (arg0) == PLUS_EXPR
+ || TREE_CODE (arg0) == MINUS_EXPR
+ || TREE_CODE (arg0) == NEGATE_EXPR)
+ && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
+ || TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE))
+ {
+ tree pmop[2];
+ int which = 0;
+ unsigned HOST_WIDE_INT cst0;
+
+ /* Now we know that arg0 is (C + D) or (C - D) or
+ -C and arg1 (M) is == (1LL << cst) - 1.
+ Store C into PMOP[0] and D into PMOP[1]. */
+ pmop[0] = TREE_OPERAND (arg0, 0);
+ pmop[1] = NULL;
+ if (TREE_CODE (arg0) != NEGATE_EXPR)
+ {
+ pmop[1] = TREE_OPERAND (arg0, 1);
+ which = 1;
+ }
+
+ if (!host_integerp (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
+ || (tree_low_cst (TYPE_MAX_VALUE (TREE_TYPE (arg0)), 1)
+ & cst1) != cst1)
+ which = -1;
+
+ for (; which >= 0; which--)
+ switch (TREE_CODE (pmop[which]))
+ {
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (TREE_CODE (TREE_OPERAND (pmop[which], 1))
+ != INTEGER_CST)
+ break;
+ /* tree_low_cst not used, because we don't care about
+ the upper bits. */
+ cst0 = TREE_INT_CST_LOW (TREE_OPERAND (pmop[which], 1));
+ cst0 &= cst1;
+ if (TREE_CODE (pmop[which]) == BIT_AND_EXPR)
+ {
+ if (cst0 != cst1)
+ break;
+ }
+ else if (cst0 != 0)
+ break;
+ /* If C or D is of the form (A & N) where
+ (N & M) == M, or of the form (A | N) or
+ (A ^ N) where (N & M) == 0, replace it with A. */
+ pmop[which] = TREE_OPERAND (pmop[which], 0);
+ break;
+ case INTEGER_CST:
+ /* If C or D is a N where (N & M) == 0, it can be
+ omitted (assumed 0). */
+ if ((TREE_CODE (arg0) == PLUS_EXPR
+ || (TREE_CODE (arg0) == MINUS_EXPR && which == 0))
+ && (TREE_INT_CST_LOW (pmop[which]) & cst1) == 0)
+ pmop[which] = NULL;
+ break;
+ default:
+ break;
+ }
+
+ /* Only build anything new if we optimized one or both arguments
+ above. */
+ if (pmop[0] != TREE_OPERAND (arg0, 0)
+ || (TREE_CODE (arg0) != NEGATE_EXPR
+ && pmop[1] != TREE_OPERAND (arg0, 1)))
+ {
+ tree utype = TREE_TYPE (arg0);
+ if (! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0)))
+ {
+ /* Perform the operations in a type that has defined
+ overflow behavior. */
+ utype = unsigned_type_for (TREE_TYPE (arg0));
+ if (pmop[0] != NULL)
+ pmop[0] = fold_convert_loc (loc, utype, pmop[0]);
+ if (pmop[1] != NULL)
+ pmop[1] = fold_convert_loc (loc, utype, pmop[1]);
+ }
+
+ if (TREE_CODE (arg0) == NEGATE_EXPR)
+ tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[0]);
+ else if (TREE_CODE (arg0) == PLUS_EXPR)
+ {
+ if (pmop[0] != NULL && pmop[1] != NULL)
+ tem = fold_build2_loc (loc, PLUS_EXPR, utype,
+ pmop[0], pmop[1]);
+ else if (pmop[0] != NULL)
+ tem = pmop[0];
+ else if (pmop[1] != NULL)
+ tem = pmop[1];
+ else
+ return build_int_cst (type, 0);
+ }
+ else if (pmop[0] == NULL)
+ tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[1]);
+ else
+ tem = fold_build2_loc (loc, MINUS_EXPR, utype,
+ pmop[0], pmop[1]);
+ /* TEM is now the new binary +, - or unary - replacement. */
+ tem = fold_build2_loc (loc, BIT_AND_EXPR, utype, tem,
+ fold_convert_loc (loc, utype, arg1));
+ return fold_convert_loc (loc, type, tem);
+ }
+ }
+ }
+
t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
{
if (flag_reciprocal_math
&& 0 != (tem = const_binop (code, build_real (type, dconst1),
- arg1, 0)))
+ arg1)))
return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
/* Find the reciprocal if optimizing and the result is exact. */
if (optimize)
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
{
tree tem = const_binop (RDIV_EXPR, arg0,
- TREE_OPERAND (arg1, 1), 0);
+ TREE_OPERAND (arg1, 1));
if (tem)
return fold_build2_loc (loc, RDIV_EXPR, type, tem,
TREE_OPERAND (arg1, 0));
return NULL_TREE;
case TRUNC_DIV_EXPR:
+ /* Optimize (X & (-A)) / A where A is a power of 2,
+ to X >> log2(A) */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST
+ && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0)
+ {
+ tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1),
+ arg1, TREE_OPERAND (arg0, 1));
+ if (sum && integer_zerop (sum)) {
+ unsigned long pow2;
+
+ if (TREE_INT_CST_LOW (arg1))
+ pow2 = exact_log2 (TREE_INT_CST_LOW (arg1));
+ else
+ pow2 = exact_log2 (TREE_INT_CST_HIGH (arg1))
+ + HOST_BITS_PER_WIDE_INT;
+
+ return fold_build2_loc (loc, RSHIFT_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ build_int_cst (integer_type_node, pow2));
+ }
+ }
+
+ /* Fall thru */
+
case FLOOR_DIV_EXPR:
/* Simplify A / (B << N) where A and B are positive and B is
a power of 2, to A >> (N + log2(B)). */
if (integer_pow2p (sval) && tree_int_cst_sgn (sval) > 0)
{
tree sh_cnt = TREE_OPERAND (arg1, 1);
- unsigned long pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+ unsigned long pow2;
+
+ if (TREE_INT_CST_LOW (sval))
+ pow2 = exact_log2 (TREE_INT_CST_LOW (sval));
+ else
+ pow2 = exact_log2 (TREE_INT_CST_HIGH (sval))
+ + HOST_BITS_PER_WIDE_INT;
if (strict_overflow_p)
fold_overflow_warning (("assuming signed overflow does not "
WARN_STRICT_OVERFLOW_MISC);
sh_cnt = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (sh_cnt),
- sh_cnt, build_int_cst (NULL_TREE, pow2));
+ sh_cnt,
+ build_int_cst (TREE_TYPE (sh_cnt),
+ pow2));
return fold_build2_loc (loc, RSHIFT_EXPR, type,
fold_convert_loc (loc, type, arg0), sh_cnt);
}
arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
lshift = build_int_cst (type, -1);
- lshift = int_const_binop (code, lshift, arg1, 0);
+ lshift = int_const_binop (code, lshift, arg1);
return fold_build2_loc (loc, BIT_AND_EXPR, type, arg00, lshift);
}
{
tree tem = build_int_cst (TREE_TYPE (arg1),
TYPE_PRECISION (type));
- tem = const_binop (MINUS_EXPR, tem, arg1, 0);
+ tem = const_binop (MINUS_EXPR, tem, arg1);
return fold_build2_loc (loc, RROTATE_EXPR, type, op0, tem);
}
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return omit_one_operand_loc (loc, type, integer_one_node, arg0);
+ /* (X && !Y) || (!X && Y) is X ^ Y */
+ if (TREE_CODE (arg0) == TRUTH_AND_EXPR
+ && TREE_CODE (arg1) == TRUTH_AND_EXPR)
+ {
+ tree a0, a1, l0, l1, n0, n1;
+
+ a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+
+ l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+
+ n0 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l0);
+ n1 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l1);
+
+ if ((operand_equal_p (n0, a0, 0)
+ && operand_equal_p (n1, a1, 0))
+ || (operand_equal_p (n0, a1, 0)
+ && operand_equal_p (n1, a0, 0)))
+ return fold_build2_loc (loc, TRUTH_XOR_EXPR, type, l0, n1);
+ }
goto truth_andor;
case TRUTH_XOR_EXPR:
case EQ_EXPR:
case NE_EXPR:
+ STRIP_NOPS (arg0);
+ STRIP_NOPS (arg1);
+
tem = fold_comparison (loc, code, type, op0, op1);
if (tem != NULL_TREE)
return tem;
? MINUS_EXPR : PLUS_EXPR,
fold_convert_loc (loc, TREE_TYPE (arg0),
arg1),
- TREE_OPERAND (arg0, 1), 0))
+ TREE_OPERAND (arg0, 1)))
&& !TREE_OVERFLOW (tem))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
/* Similarly for a NEGATE_EXPR. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = negate_expr (arg1))
+ && 0 != (tem = negate_expr (fold_convert_loc (loc, TREE_TYPE (arg0),
+ arg1)))
&& TREE_CODE (tem) == INTEGER_CST
&& !TREE_OVERFLOW (tem))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
if ((TREE_CODE (arg0) == PLUS_EXPR
|| TREE_CODE (arg0) == POINTER_PLUS_EXPR
|| TREE_CODE (arg0) == MINUS_EXPR)
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+ && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
+ 0)),
+ arg1, 0)
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
|| POINTER_TYPE_P (TREE_TYPE (arg0))))
{
/* Transform comparisons of the form C - X CMP X if C % 2 == 1. */
if (TREE_CODE (arg0) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == INTEGER_CST
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)
+ && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
+ 1)),
+ arg1, 0)
&& (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 0)) & 1) == 1)
{
return omit_two_operands_loc (loc, type,
{
tem = fold_build2_loc (loc, LSHIFT_EXPR, itype, arg01, arg001);
tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, arg000, tem);
- return fold_build2_loc (loc, code, type, tem, arg1);
+ return fold_build2_loc (loc, code, type, tem,
+ fold_convert_loc (loc, itype, arg1));
}
/* Otherwise, for signed (arithmetic) shifts,
((X >> C1) & C2) != 0 is rewritten as X < 0, and
tree notc = fold_build1_loc (loc, BIT_NOT_EXPR,
TREE_TYPE (TREE_OPERAND (arg0, 1)),
TREE_OPERAND (arg0, 1));
- tree dandnotc = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
- arg1, notc);
+ tree dandnotc
+ = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+ fold_convert_loc (loc, TREE_TYPE (arg0), arg1),
+ notc);
tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
if (integer_nonzerop (dandnotc))
return omit_one_operand_loc (loc, type, rslt, arg0);
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
tree notd = fold_build1_loc (loc, BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
- tree candnotd = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 1), notd);
+ tree candnotd
+ = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 1),
+ fold_convert_loc (loc, TREE_TYPE (arg0), notd));
tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
if (integer_nonzerop (candnotd))
return omit_one_operand_loc (loc, type, rslt, arg0);
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
- build_int_cst (TREE_TYPE (arg1), 0));
+ build_int_cst (TREE_TYPE (arg0), 0));
/* Likewise (X ^ Y) == X becomes Y == 0. X has no side-effects. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 1),
- build_int_cst (TREE_TYPE (arg1), 0));
+ build_int_cst (TREE_TYPE (arg0), 0));
/* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
tem = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
- TREE_OPERAND (arg0, 1));
+ TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
+ TREE_OPERAND (arg0, 1));
return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
- type, tem, arg1);
+ type, tem,
+ fold_convert_loc (loc, TREE_TYPE (arg0),
+ arg1));
}
/* Fold ((X & C) ^ C) eq/ne 0 into (X & C) ne/eq 0, when the
if (TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg1) == NEGATE_EXPR)
return fold_build2_loc (loc, code, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0));
+ TREE_OPERAND (arg0, 0),
+ fold_convert_loc (loc, TREE_TYPE (arg0),
+ TREE_OPERAND (arg1, 0)));
/* Fold (X & C) op (Y & C) as (X ^ Y) & C op 0", and symmetries. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
operand_equal_p guarantees no side-effects so we don't need
to use omit_one_operand on Z. */
if (operand_equal_p (arg01, arg11, 0))
- return fold_build2_loc (loc, code, type, arg00, arg10);
+ return fold_build2_loc (loc, code, type, arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg10));
if (operand_equal_p (arg01, arg10, 0))
- return fold_build2_loc (loc, code, type, arg00, arg11);
+ return fold_build2_loc (loc, code, type, arg00,
+ fold_convert_loc (loc, TREE_TYPE (arg00),
+ arg11));
if (operand_equal_p (arg00, arg11, 0))
- return fold_build2_loc (loc, code, type, arg01, arg10);
+ return fold_build2_loc (loc, code, type, arg01,
+ fold_convert_loc (loc, TREE_TYPE (arg01),
+ arg10));
if (operand_equal_p (arg00, arg10, 0))
- return fold_build2_loc (loc, code, type, arg01, arg11);
+ return fold_build2_loc (loc, code, type, arg01,
+ fold_convert_loc (loc, TREE_TYPE (arg01),
+ arg11));
/* Optimize (X ^ C1) op (Y ^ C2) as (X ^ (C1 ^ C2)) op Y. */
if (TREE_CODE (arg01) == INTEGER_CST
&& TREE_CODE (arg11) == INTEGER_CST)
- return fold_build2_loc (loc, code, type,
- fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00,
- fold_build2_loc (loc,
- BIT_XOR_EXPR, itype,
- arg01, arg11)),
- arg10);
+ {
+ tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01,
+ fold_convert_loc (loc, itype, arg11));
+ tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem);
+ return fold_build2_loc (loc, code, type, tem,
+ fold_convert_loc (loc, itype, arg10));
+ }
}
/* Attempt to simplify equality/inequality comparisons of complex
{
case GT_EXPR:
arg1 = const_binop (PLUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1), 0);
+ build_int_cst (TREE_TYPE (arg1), 1));
return fold_build2_loc (loc, EQ_EXPR, type,
fold_convert_loc (loc,
TREE_TYPE (arg1), arg0),
arg1);
case LE_EXPR:
arg1 = const_binop (PLUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1), 0);
+ build_int_cst (TREE_TYPE (arg1), 1));
return fold_build2_loc (loc, NE_EXPR, type,
fold_convert_loc (loc, TREE_TYPE (arg1),
arg0),
switch (code)
{
case GE_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
return fold_build2_loc (loc, NE_EXPR, type,
fold_convert_loc (loc,
TREE_TYPE (arg1), arg0),
arg1);
case LT_EXPR:
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node);
return fold_build2_loc (loc, EQ_EXPR, type,
fold_convert_loc (loc, TREE_TYPE (arg1),
arg0),
&& TYPE_UNSIGNED (TREE_TYPE (arg0))
&& TREE_CODE (arg1) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (arg1, 0)))
- {
- tem = build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
- TREE_OPERAND (arg1, 1)),
- build_int_cst (TREE_TYPE (arg0), 0));
- goto fold_binary_exit;
- }
+ return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+ TREE_OPERAND (arg1, 1)),
+ build_int_cst (TREE_TYPE (arg0), 0));
if ((code == LT_EXPR || code == GE_EXPR)
&& TYPE_UNSIGNED (TREE_TYPE (arg0))
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
&& integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
{
- tem = build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
- fold_convert_loc (loc, TREE_TYPE (arg0),
- build2 (RSHIFT_EXPR,
- TREE_TYPE (arg0), arg0,
- TREE_OPERAND (TREE_OPERAND (arg1, 0),
- 1))),
- build_int_cst (TREE_TYPE (arg0), 0));
- goto fold_binary_exit;
+ tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
+ TREE_OPERAND (TREE_OPERAND (arg1, 0), 1));
+ return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
+ fold_convert_loc (loc, TREE_TYPE (arg0), tem),
+ build_int_cst (TREE_TYPE (arg0), 0));
}
return NULL_TREE;
|| (TREE_CODE (arg0) == INTEGER_CST
&& TREE_CODE (arg1) == INTEGER_CST))
return build_complex (type, arg0, arg1);
+ if (TREE_CODE (arg0) == REALPART_EXPR
+ && TREE_CODE (arg1) == IMAGPART_EXPR
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ == TYPE_MAIN_VARIANT (type))
+ && operand_equal_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0));
return NULL_TREE;
case ASSERT_EXPR:
default:
return NULL_TREE;
} /* switch (code) */
- fold_binary_exit:
- protected_set_expr_location (tem, loc);
- return tem;
}
/* Callback for walk_tree, looking for LABEL_EXPR. Return *TP if it is
tree
fold_ternary_loc (location_t loc, enum tree_code code, tree type,
- tree op0, tree op1, tree op2)
+ tree op0, tree op1, tree op2)
{
tree tem;
- tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE, arg2 = NULL_TREE;
enum tree_code_class kind = TREE_CODE_CLASS (code);
gcc_assert (IS_EXPR_CODE_CLASS (kind)
STRIP_NOPS (arg1);
}
+ if (op2)
+ {
+ arg2 = op2;
+ STRIP_NOPS (arg2);
+ }
+
switch (code)
{
case COMPONENT_REF:
TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
{
- tem = fold_truth_not_expr (loc, arg0);
+ location_t loc0 = expr_location_or (arg0, loc);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem && COMPARISON_CLASS_P (tem))
{
tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1);
if (truth_value_p (TREE_CODE (arg0))
&& tree_swap_operands_p (op1, op2, false))
{
+ location_t loc0 = expr_location_or (arg0, loc);
/* See if this can be inverted. If it can't, possibly because
it was a floating-point inequality comparison, don't do
anything. */
- tem = fold_truth_not_expr (loc, arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
return fold_build3_loc (loc, code, type, tem, op2, op1);
}
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
{
+ location_t loc0 = expr_location_or (arg0, loc);
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (loc, arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
fold_convert_loc (loc, type, tem),
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (op2)))
{
+ location_t loc0 = expr_location_or (arg0, loc);
/* Only perform transformation if ARG0 is easily inverted. */
- tem = fold_truth_not_expr (loc, arg0);
+ tem = fold_truth_not_expr (loc0, arg0);
if (tem)
return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
fold_convert_loc (loc, type, tem),
if (elements)
return TREE_VALUE (elements);
else
- return fold_convert_loc (loc, type, integer_zero_node);
+ return build_zero_cst (type);
}
}
return NULL_TREE;
+ case FMA_EXPR:
+ /* For integers we can decompose the FMA if possible. */
+ if (TREE_CODE (arg0) == INTEGER_CST
+ && TREE_CODE (arg1) == INTEGER_CST)
+ return fold_build2_loc (loc, PLUS_EXPR, type,
+ const_binop (MULT_EXPR, arg0, arg1), arg2);
+ if (integer_zerop (arg2))
+ return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
+
+ return fold_fma (loc, type, arg0, arg1, arg2);
+
default:
return NULL_TREE;
} /* switch (code) */
static void
fold_checksum_tree (const_tree expr, struct md5_ctx *ctx, htab_t ht)
{
- const void **slot;
+ void **slot;
enum tree_code code;
union tree_node buf;
int i, len;
&& sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
if (expr == NULL)
return;
- slot = (const void **) htab_find_slot (ht, expr, INSERT);
+ slot = (void **) htab_find_slot (ht, expr, INSERT);
if (*slot != NULL)
return;
- *slot = expr;
+ *slot = CONST_CAST_TREE (expr);
code = TREE_CODE (expr);
if (TREE_CODE_CLASS (code) == tcc_declaration
&& DECL_ASSEMBLER_NAME_SET_P (expr))
if (TREE_CODE_CLASS (code) != tcc_type
&& TREE_CODE_CLASS (code) != tcc_declaration
&& code != TREE_LIST
- && code != SSA_NAME)
+ && code != SSA_NAME
+ && CODE_CONTAINS_STRUCT (code, TS_COMMON))
fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
switch (TREE_CODE_CLASS (code))
{
tem = fold_unary_loc (loc, code, type, op0);
if (!tem)
- {
- tem = build1_stat (code, type, op0 PASS_MEM_STAT);
- SET_EXPR_LOCATION (tem, loc);
- }
+ tem = build1_stat_loc (loc, code, type, op0 PASS_MEM_STAT);
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
tem = fold_binary_loc (loc, code, type, op0, op1);
if (!tem)
- {
- tem = build2_stat (code, type, op0, op1 PASS_MEM_STAT);
- SET_EXPR_LOCATION (tem, loc);
- }
+ tem = build2_stat_loc (loc, code, type, op0, op1 PASS_MEM_STAT);
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
tem = fold_ternary_loc (loc, code, type, op0, op1, op2);
if (!tem)
- {
- tem = build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
- SET_EXPR_LOCATION (tem, loc);
- }
+ tem = build3_stat_loc (loc, code, type, op0, op1, op2 PASS_MEM_STAT);
#ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx);
&& 0 != (t1 = fold_convert (type,
const_binop (LSHIFT_EXPR,
size_one_node,
- op1, 0)))
+ op1)))
&& !TREE_OVERFLOW (t1))
return multiple_of_p (type, t1, bottom);
}
|| tree_int_cst_sgn (bottom) < 0)))
return 0;
return integer_zerop (int_const_binop (TRUNC_MOD_EXPR,
- top, bottom, 0));
+ top, bottom));
default:
return 0;
{
case INTEGER_CST:
{
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int overflow = neg_double (TREE_INT_CST_LOW (arg0),
- TREE_INT_CST_HIGH (arg0),
- &low, &high);
- t = force_fit_type_double (type, low, high, 1,
+ double_int val = tree_to_double_int (arg0);
+ int overflow = neg_double (val.low, val.high, &val.low, &val.high);
+
+ t = force_fit_type_double (type, val, 1,
(overflow | TREE_OVERFLOW (arg0))
&& !TYPE_UNSIGNED (type));
break;
switch (TREE_CODE (arg0))
{
case INTEGER_CST:
- /* If the value is unsigned, then the absolute value is
- the same as the ordinary value. */
- if (TYPE_UNSIGNED (type))
- t = arg0;
- /* Similarly, if the value is non-negative. */
- else if (INT_CST_LT (integer_minus_one_node, arg0))
- t = arg0;
- /* If the value is negative, then the absolute value is
- its negation. */
- else
- {
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- int overflow = neg_double (TREE_INT_CST_LOW (arg0),
- TREE_INT_CST_HIGH (arg0),
- &low, &high);
- t = force_fit_type_double (type, low, high, -1,
- overflow | TREE_OVERFLOW (arg0));
- }
+ {
+ double_int val = tree_to_double_int (arg0);
+
+ /* If the value is unsigned or non-negative, then the absolute value
+ is the same as the ordinary value. */
+ if (TYPE_UNSIGNED (type)
+ || !double_int_negative_p (val))
+ t = arg0;
+
+ /* If the value is negative, then the absolute value is
+ its negation. */
+ else
+ {
+ int overflow;
+
+ overflow = neg_double (val.low, val.high, &val.low, &val.high);
+ t = force_fit_type_double (type, val, -1,
+ overflow | TREE_OVERFLOW (arg0));
+ }
+ }
break;
case REAL_CST:
constant. TYPE is the type of the result. */
static tree
-fold_not_const (tree arg0, tree type)
+fold_not_const (const_tree arg0, tree type)
{
- tree t = NULL_TREE;
+ double_int val;
gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
- t = force_fit_type_double (type, ~TREE_INT_CST_LOW (arg0),
- ~TREE_INT_CST_HIGH (arg0), 0,
- TREE_OVERFLOW (arg0));
-
- return t;
+ val = double_int_not (tree_to_double_int (arg0));
+ return force_fit_type_double (type, val, 0, TREE_OVERFLOW (arg0));
}
/* Given CODE, a relational operator, the target type, TYPE and two
}
/* *(foo *)&fooarray => fooarray[0] */
else if (TREE_CODE (optype) == ARRAY_TYPE
- && type == TREE_TYPE (optype))
+ && type == TREE_TYPE (optype)
+ && (!in_gimple_form
+ || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST))
{
tree type_domain = TYPE_DOMAIN (optype);
tree min_val = size_zero_node;
if (type_domain && TYPE_MIN_VALUE (type_domain))
min_val = TYPE_MIN_VALUE (type_domain);
- op0 = build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
- SET_EXPR_LOCATION (op0, loc);
- return op0;
+ if (in_gimple_form
+ && TREE_CODE (min_val) != INTEGER_CST)
+ return NULL_TREE;
+ return build4_loc (loc, ARRAY_REF, type, op, min_val,
+ NULL_TREE, NULL_TREE);
}
/* *(foo *)&complexfoo => __real__ complexfoo */
else if (TREE_CODE (optype) == COMPLEX_TYPE
}
}
- /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
if (TREE_CODE (sub) == POINTER_PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
{
tree op00 = TREE_OPERAND (sub, 0);
tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
- && type == TREE_TYPE (TREE_TYPE (op00type)))
+ if (TREE_CODE (op00) == ADDR_EXPR)
{
- HOST_WIDE_INT offset = tree_low_cst (op01, 0);
- tree part_width = TYPE_SIZE (type);
- unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
- unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
- tree index = bitsize_int (indexi);
-
- if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
- return fold_build3_loc (loc,
- BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
- part_width, index);
-
- }
- }
+ tree op00type;
+ op00 = TREE_OPERAND (op00, 0);
+ op00type = TREE_TYPE (op00);
+ /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+ if (TREE_CODE (op00type) == VECTOR_TYPE
+ && type == TREE_TYPE (op00type))
+ {
+ HOST_WIDE_INT offset = tree_low_cst (op01, 0);
+ tree part_width = TYPE_SIZE (type);
+ unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+ tree index = bitsize_int (indexi);
- /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
- if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
- {
- tree op00 = TREE_OPERAND (sub, 0);
- tree op01 = TREE_OPERAND (sub, 1);
- tree op00type;
+ if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type))
+ return fold_build3_loc (loc,
+ BIT_FIELD_REF, type, op00,
+ part_width, index);
- STRIP_NOPS (op00);
- op00type = TREE_TYPE (op00);
- if (TREE_CODE (op00) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
- && type == TREE_TYPE (TREE_TYPE (op00type)))
- {
- tree size = TYPE_SIZE_UNIT (type);
- if (tree_int_cst_equal (size, op01))
- return fold_build1_loc (loc, IMAGPART_EXPR, type,
- TREE_OPERAND (op00, 0));
+ }
+ /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+ else if (TREE_CODE (op00type) == COMPLEX_TYPE
+ && type == TREE_TYPE (op00type))
+ {
+ tree size = TYPE_SIZE_UNIT (type);
+ if (tree_int_cst_equal (size, op01))
+ return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
+ }
+ /* ((foo *)&fooarray)[1] => fooarray[1] */
+ else if (TREE_CODE (op00type) == ARRAY_TYPE
+ && type == TREE_TYPE (op00type))
+ {
+ tree type_domain = TYPE_DOMAIN (op00type);
+ tree min_val = size_zero_node;
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ op01 = size_binop_loc (loc, EXACT_DIV_EXPR, op01,
+ TYPE_SIZE_UNIT (type));
+ op01 = size_binop_loc (loc, PLUS_EXPR, op01, min_val);
+ return build4_loc (loc, ARRAY_REF, type, op00, op01,
+ NULL_TREE, NULL_TREE);
+ }
}
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
- && type == TREE_TYPE (TREE_TYPE (subtype)))
+ && type == TREE_TYPE (TREE_TYPE (subtype))
+ && (!in_gimple_form
+ || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST))
{
tree type_domain;
tree min_val = size_zero_node;
type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
if (type_domain && TYPE_MIN_VALUE (type_domain))
min_val = TYPE_MIN_VALUE (type_domain);
- op0 = build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
- SET_EXPR_LOCATION (op0, loc);
- return op0;
+ if (in_gimple_form
+ && TREE_CODE (min_val) != INTEGER_CST)
+ return NULL_TREE;
+ return build4_loc (loc, ARRAY_REF, type, sub, min_val, NULL_TREE,
+ NULL_TREE);
}
return NULL_TREE;
if (sub)
return sub;
- t = build1 (INDIRECT_REF, type, t);
- SET_EXPR_LOCATION (t, loc);
- return t;
+ return build1_loc (loc, INDIRECT_REF, type, t);
}
/* Given an INDIRECT_REF T, return either T or a simplified version. */
{
if (TREE_CODE (value) == INTEGER_CST)
{
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (value);
- unsigned HOST_WIDE_INT high;
+ double_int val = tree_to_double_int (value);
bool overflow_p;
- if ((low & (divisor - 1)) == 0)
+ if ((val.low & (divisor - 1)) == 0)
return value;
overflow_p = TREE_OVERFLOW (value);
- high = TREE_INT_CST_HIGH (value);
- low &= ~(divisor - 1);
- low += divisor;
- if (low == 0)
+ val.low &= ~(divisor - 1);
+ val.low += divisor;
+ if (val.low == 0)
{
- high++;
- if (high == 0)
+ val.high++;
+ if (val.high == 0)
overflow_p = true;
}
- return force_fit_type_double (TREE_TYPE (value), low, high,
+ return force_fit_type_double (TREE_TYPE (value), val,
-1, overflow_p);
}
else