#include "tm_p.h"
#include "target.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "intl.h"
#include "ggc.h"
#include "hashtab.h"
static tree fold_convert_const (enum tree_code, tree, tree);
+/* 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,
and SUM1. Then this yields nonzero if overflow occurred during the
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
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. */
gcc_unreachable ();
}
fold_convert_exit:
- protected_set_expr_location (tem, loc);
+ protected_set_expr_location_unshare (tem, loc);
return tem;
}
\f
case COMPONENT_REF:
case MEM_REF:
case 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
switch (TREE_CODE (arg0))
{
case INDIRECT_REF:
- case MISALIGNED_INDIRECT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
return OP_SAME (0);
case MEM_REF:
- /* Require equal access sizes. We can have incomplete types
- for array references of variable-sized arrays from the
- Fortran frontent though. */
+ /* 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 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)
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;
+ 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));
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;
+ 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));
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;
+ 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));
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;
+ 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);
/* 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;
+ 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));
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 ... */
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;
+ 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;
+ 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);
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
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:
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))
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);
}
}
}
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;
}
}
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
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;
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 (wanted_code, truth_type, result,
- const_binop (BIT_IOR_EXPR, l_const, r_const));
+ result = build2_loc (loc, BIT_AND_EXPR, lntype, result, ll_mask);
- 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
if (TREE_CODE (t) == WITH_SIZE_EXPR)
t = TREE_OPERAND (t, 0);
- 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)))
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))
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;
}
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));
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);
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);
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));
}
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))
&& ((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)
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);
}
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);
}
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;
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 (NULL_TREE, 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 "
&& 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;
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:
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))
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);
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;
+ 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);
+ if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type))
+ return fold_build3_loc (loc,
+ BIT_FIELD_REF, type, op00,
+ part_width, index);
- /* ((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;
-
- 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);
+ }
}
}
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;
+ 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. */