build2 (LE_EXPR, type,
TREE_OPERAND (arg0, 0), arg1)));
- /* Convert ABS_EXPR<x> >= 0 to true. */
- else if (code == GE_EXPR
- && tree_expr_nonnegative_p (arg0)
- && ! TREE_SIDE_EFFECTS (arg0)
- && (integer_zerop (arg1)
- || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
- && real_zerop (arg1))))
- return constant_boolean_node (true, type);
-
- /* Convert ABS_EXPR<x> < 0 to false. */
- else if (code == LT_EXPR
- && tree_expr_nonnegative_p (arg0)
- && ! TREE_SIDE_EFFECTS (arg0)
- && (integer_zerop (arg1) || real_zerop (arg1)))
- return constant_boolean_node (false, type);
-
- /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */
- else if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == ABS_EXPR
- && ! TREE_SIDE_EFFECTS (arg0)
- && (integer_zerop (arg1) || real_zerop (arg1)))
- return fold (build2 (code, type, TREE_OPERAND (arg0, 0), arg1));
-
/* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
two operations, but the latter can be done in one less insn
return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
}
-/* Given a pointer value T, return a simplified version of an indirection
- through T, or NULL_TREE if no simplification is possible. */
+/* Builds an expression for an indirection through T, simplifying some
+ cases. */
-static tree
-fold_indirect_ref_1 (tree t)
+tree
+build_fold_indirect_ref (tree t)
{
tree type = TREE_TYPE (TREE_TYPE (t));
tree sub = t;
tree subtype;
STRIP_NOPS (sub);
- subtype = TREE_TYPE (sub);
- if (!POINTER_TYPE_P (subtype))
- return NULL_TREE;
-
if (TREE_CODE (sub) == ADDR_EXPR)
{
tree op = TREE_OPERAND (sub, 0);
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
+ subtype = TREE_TYPE (sub);
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
&& lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
{
return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
}
- return NULL_TREE;
-}
-
-/* Builds an expression for an indirection through T, simplifying some
- cases. */
-
-tree
-build_fold_indirect_ref (tree t)
-{
- tree sub = fold_indirect_ref_1 (t);
-
- if (sub)
- return sub;
- else
- return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
-}
-
-/* Given an INDIRECT_REF T, return either T or a simplified version. */
-
-tree
-fold_indirect_ref (tree t)
-{
- tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
-
- if (sub)
- return sub;
- else
- return t;
+ return build1 (INDIRECT_REF, type, t);
}
/* Strip non-trapping, non-side-effecting tree nodes from an expression
VARRAY_GENERIC_PTR_NOGC_INIT (stack, 10, "stack");
/* We can handle anything that get_inner_reference can deal with. */
- for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
- {
- /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
- if (TREE_CODE (*p) == INDIRECT_REF)
- *p = fold_indirect_ref (*p);
- if (!handled_component_p (*p))
- break;
- VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
- }
+ for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0))
+ VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
gcc_assert (VARRAY_ACTIVE_SIZE (stack));
This kind of code arises in C++ when an object is bound
to a const reference, and if "x" is a TARGET_EXPR we want
to take advantage of the optimization below. */
- tree t = fold_indirect_ref (*from_p);
- if (t != *from_p)
+ tree pointer;
+
+ pointer = TREE_OPERAND (*from_p, 0);
+ STRIP_NOPS (pointer);
+ if (TREE_CODE (pointer) == ADDR_EXPR
+ && (lang_hooks.types_compatible_p
+ (TREE_TYPE (TREE_OPERAND (pointer, 0)),
+ TREE_TYPE (*from_p))))
{
- *from_p = t;
+ *from_p = TREE_OPERAND (pointer, 0);
ret = GS_OK;
}
else
ret = GS_UNHANDLED;
break;
- case CALL_EXPR:
- /* For calls that return in memory, give *to_p as the CALL_EXPR's
- return slot so that we don't generate a temporary. */
- if (aggregate_value_p (*from_p, *from_p))
- {
- tree init = *from_p;
- tree fn = TREE_OPERAND (init, 0);
- tree args = TREE_OPERAND (init, 1);
- tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn)));
- tree arg = *to_p;
- tree type;
-
- /* Only use the original target if *to_p isn't already
- addressable; if its address escapes, and the called function
- uses the NRV optimization, a conforming program could see
- *to_p change before the called function returns. */
- bool use_temp = !is_gimple_non_addressable (*to_p);
- if (use_temp)
- {
- arg = create_tmp_var (rettype, "ret");
- *from_p = arg;
- }
-
- type = TREE_TYPE (arg);
- /* FIXME: Mark the address as not escaping. */
- lang_hooks.mark_addressable (arg);
- arg = build1 (ADDR_EXPR, build_pointer_type (type), arg);
- /* The return type might have different cv-quals from arg. */
- arg = convert (build_pointer_type (rettype), arg);
- args = tree_cons (NULL_TREE, arg, args);
- init = build3 (CALL_EXPR, rettype, fn, args, NULL_TREE);
- CALL_EXPR_HAS_RETURN_SLOT_ADDR (init) = 1;
- TREE_USED (init) = 1;
-
- if (use_temp)
- gimplify_and_add (init, pre_p);
- else if (want_value)
- {
- gimplify_and_add (init, pre_p);
- *expr_p = *to_p;
- }
- else
- *expr_p = init;
- ret = GS_OK;
- }
- else
- ret = GS_UNHANDLED;
- break;
-
default:
ret = GS_UNHANDLED;
break;
ret = GS_OK;
if (TREE_CODE (init) == BIND_EXPR)
gimplify_bind_expr (&init, temp, pre_p);
- if (init != temp)
+ if (init != temp)
{
init = build (MODIFY_EXPR, void_type_node, temp, init);
ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt,
recalculate_side_effects (*expr_p);
break;
- case INDIRECT_REF:
- *expr_p = fold_indirect_ref (*expr_p);
- if (*expr_p != save_expr)
- break;
- /* else fall through. */
case ALIGN_INDIRECT_REF:
case MISALIGNED_INDIRECT_REF:
+ case INDIRECT_REF:
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
is_gimple_reg, fb_rvalue);
recalculate_side_effects (*expr_p);