+2004-08-18 Richard Henderson <rth@redhat.com>
+
+ * tree.h (struct tree_decl): Add gimple_formal_temp.
+ (DECL_GIMPLE_FORMAL_TEMP_P): New.
+ * gimplify.c (pop_gimplify_context): Clear it.
+ (lookup_tmp_var): Set it, if is_formal.
+ (gimplify_init_constructor): Use rhs_predicate_for for COMPLEX.
+ Use is_gimple_val for VECTOR. Simplify return value.
+ (gimplify_save_expr): Use and set DECL_GIMPLE_FORMAL_TEMP_P.
+ (gimplify_expr): Likewise.
+ * tree-gimple.c (is_gimple_formal_tmp_rhs): Rename from
+ is_gimple_tmp_rhs for clarity. Update all callers.
+ (is_gimple_reg_rhs): Simplify logic.
+ (is_gimple_formal_tmp_var): Rename from is_gimple_tmp_var for
+ clarity; use DECL_GIMPLE_FORMAL_TEMP_P.
+ (is_gimple_formal_tmp_reg): Similarly.
+ * tree-gimple.h: Update decls.
+ * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Use
+ DECL_IGNORED_P, not DECL_ARTIFICIAL. Tidy formatting.
+ * tree-ssa-live.c (var_union, type_var_init): Likewise.
+
2004-08-18 Paolo Bonzini <bonzini@gnu.org>
* c4x.c (legitimize_operands): Remove calls to
void
pop_gimplify_context (tree body)
{
+ tree t;
+
if (!gimplify_ctxp || gimplify_ctxp->current_bind_expr)
abort ();
+ for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
+ DECL_GIMPLE_FORMAL_TEMP_P (t) = 0;
+
if (body)
declare_tmp_vars (gimplify_ctxp->temps, body);
else
static tree
lookup_tmp_var (tree val, bool is_formal)
{
+ tree ret;
+
if (!is_formal || TREE_SIDE_EFFECTS (val))
- return create_tmp_from_val (val);
+ ret = create_tmp_from_val (val);
else
{
elt_t elt, *elt_p;
{
elt_p = xmalloc (sizeof (*elt_p));
elt_p->val = val;
- elt_p->temp = create_tmp_from_val (val);
- TREE_READONLY (elt_p->temp) = 1;
+ elt_p->temp = ret = create_tmp_from_val (val);
*slot = (void *) elt_p;
}
else
- elt_p = (elt_t *) *slot;
-
- return elt_p->temp;
+ {
+ elt_p = (elt_t *) *slot;
+ ret = elt_p->temp;
+ }
}
+
+ if (is_formal)
+ DECL_GIMPLE_FORMAL_TEMP_P (ret) = 1;
+
+ return ret;
}
/* Returns a formal temporary variable initialized with VAL. PRE_P is as
tree t, mod;
char class;
- gimplify_expr (&val, pre_p, post_p, is_gimple_tmp_rhs, fb_rvalue);
+ gimplify_expr (&val, pre_p, post_p, is_gimple_formal_tmp_rhs, fb_rvalue);
t = lookup_tmp_var (val, is_formal);
{
TREE_OPERAND (t, 2) = low;
tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
- is_gimple_tmp_reg, fb_rvalue);
+ is_gimple_formal_tmp_reg, fb_rvalue);
ret = MIN (ret, tret);
}
}
{
TREE_OPERAND (t, 3) = elmt_size;
tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
- is_gimple_tmp_reg, fb_rvalue);
+ is_gimple_formal_tmp_reg, fb_rvalue);
ret = MIN (ret, tret);
}
}
{
TREE_OPERAND (t, 2) = offset;
tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
- is_gimple_tmp_reg, fb_rvalue);
+ is_gimple_formal_tmp_reg, fb_rvalue);
ret = MIN (ret, tret);
}
}
if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)))
{
tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
- is_gimple_tmp_reg, fb_rvalue);
+ is_gimple_formal_tmp_reg, fb_rvalue);
ret = MIN (ret, tret);
}
}
ctor = build (COMPLEX_EXPR, type, r, i);
TREE_OPERAND (*expr_p, 1) = ctor;
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
- is_gimple_tmp_rhs, fb_rvalue);
+ rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
+ fb_rvalue);
}
}
break;
{
enum gimplify_status tret;
tret = gimplify_expr (&TREE_VALUE (elt_list), pre_p, post_p,
- is_gimple_constructor_elt, fb_rvalue);
+ is_gimple_val, fb_rvalue);
if (tret == GS_ERROR)
ret = GS_ERROR;
}
}
}
- /* If the destination is already simple, nothing else needed. */
- if (is_gimple_tmp_var (*to_p) || !want_value)
- ret = GS_ALL_DONE;
- else
- ret = GS_OK;
-
if (want_value)
{
append_to_statement_list (*expr_p, pre_p);
*expr_p = *to_p;
+ return GS_OK;
}
- return ret;
+ return GS_ALL_DONE;
}
/* Gimplify a comparison between two variable-sized objects. Do this
/* If the operand is already a GIMPLE temporary, just re-write the
SAVE_EXPR node. */
- if (is_gimple_tmp_var (val))
+ if (TREE_CODE (val) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (val))
*expr_p = val;
/* The operand may be a void-valued expression such as SAVE_EXPRs
generated by the Java frontend for class initialization. It is
*expr_p = NULL;
}
else
- *expr_p = TREE_OPERAND (*expr_p, 0)
- = get_initialized_tmp_var (val, pre_p, post_p);
+ {
+ val = get_initialized_tmp_var (val, pre_p, post_p);
+ DECL_GIMPLE_FORMAL_TEMP_P (val) = 1;
+ *expr_p = TREE_OPERAND (*expr_p, 0) = val;
+ }
return ret;
}
gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
*expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp);
}
- else if ((fallback & fb_rvalue) && is_gimple_tmp_rhs (*expr_p))
+ else if ((fallback & fb_rvalue) && is_gimple_formal_tmp_rhs (*expr_p))
{
#if defined ENABLE_CHECKING
if (VOID_TYPE_P (TREE_TYPE (*expr_p)))
*expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
else
*expr_p = get_formal_tmp_var (*expr_p, pre_p);
+ DECL_GIMPLE_FORMAL_TEMP_P (*expr_p) = 1;
}
else if (fallback & fb_mayfail)
{
+2004-08-18 Richard Henderson <rth@redhat.com>
+
+ * java-gimplify.c (java_gimplify_expr): Move '2' handling into
+ default case. Treat '<' similarly. Update for
+ is_gimple_formal_tmp_var name change.
+
2004-08-17 Andrew Haley <aph@redhat.com>
* lang.c (lang_printable_name): Obey verbose flag.
java_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
tree *post_p ATTRIBUTE_UNUSED)
{
- char code_class = TREE_CODE_CLASS(TREE_CODE (*expr_p));
-
- /* Java insists on strict left-to-right evaluation of expressions.
- A problem may arise if a variable used in the LHS of a binary
- operation is altered by an assignment to that value in the RHS
- before we've performed the operation. So, we always copy every
- LHS to a temporary variable.
-
- FIXME: Are there any other cases where we should do this?
- Parameter lists, maybe? Or perhaps that's unnecessary because
- the front end already generates SAVE_EXPRs. */
- if (code_class == '2')
- {
- tree lhs = TREE_OPERAND (*expr_p, 0);
- enum gimplify_status stat
- = gimplify_expr (&lhs, pre_p, post_p, is_gimple_tmp_var, fb_rvalue);
- if (stat == GS_ERROR)
- return stat;
- TREE_OPERAND (*expr_p, 0) = lhs;
- }
+ enum tree_code code = TREE_CODE (*expr_p);
- switch (TREE_CODE (*expr_p))
+ switch (code)
{
case BLOCK:
*expr_p = java_gimplify_block (*expr_p);
abort ();
default:
+ /* Java insists on strict left-to-right evaluation of expressions.
+ A problem may arise if a variable used in the LHS of a binary
+ operation is altered by an assignment to that value in the RHS
+ before we've performed the operation. So, we always copy every
+ LHS to a temporary variable.
+
+ FIXME: Are there any other cases where we should do this?
+ Parameter lists, maybe? Or perhaps that's unnecessary because
+ the front end already generates SAVE_EXPRs. */
+
+ if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
+ {
+ enum gimplify_status stat
+ = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ is_gimple_formal_tmp_var, fb_rvalue);
+ if (stat == GS_ERROR)
+ return stat;
+ }
+
return GS_UNHANDLED;
}
+2004-08-18 Richard Henderson <rth@redhat.com>
+
+ * gcc.dg/20040206-1.c: XFAIL.
+
2004-08-17 Mark Mitchell <mark@codesourcery.com>
PR c++/16246
returning non-void" is PR 13000. */
static int foo (int a __attribute__((unused)) ) { } /* { dg-warning "return" "" { xfail *-*-* } } */
-int main (void) { return foo (0); }
+int main (void) { return foo (0); } /* { dg-bogus "uninitialized" "" { xfail *-*-* } } */
/* Return true if T is a GIMPLE RHS for an assignment to a temporary. */
bool
-is_gimple_tmp_rhs (tree t)
+is_gimple_formal_tmp_rhs (tree t)
{
enum tree_code code = TREE_CODE (t);
return is_gimple_lvalue (t) || is_gimple_val (t);
}
-/* Returns true iff T is a valid RHS for an assignment to a renamed user
- variable. */
+/* Returns true iff T is a valid RHS for an assignment to a renamed
+ user -- or front-end generated artificial -- variable. */
bool
is_gimple_reg_rhs (tree t)
{
- /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto and
- the LHS is a user variable, then we need to introduce a temporary.
- ie temp = RHS; LHS = temp.
+ /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
+ and the LHS is a user variable, then we need to introduce a formal
+ temporary. This way the optimizers can determine that the user
+ variable is only modified if evaluation of the RHS does not throw.
+
+ Don't force a temp of a non-renamable type; the copy could be
+ arbitrarily expensive. Instead we will generate a V_MAY_DEF for
+ the assignment. */
- This way the optimizers can determine that the user variable is
- only modified if evaluation of the RHS does not throw. */
if (is_gimple_reg_type (TREE_TYPE (t))
- && TREE_SIDE_EFFECTS (t)
- && (TREE_CODE (t) == CALL_EXPR
- || (flag_non_call_exceptions && tree_could_trap_p (t))))
- return is_gimple_val (t);
- else
- /* Don't force a temp of a non-renamable type; the copy could be
- arbitrarily expensive. Instead we will generate a V_MAY_DEF for
- the assignment. */
- return is_gimple_tmp_rhs (t);
+ && ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
+ || tree_could_throw_p (t)))
+ return false;
+
+ return is_gimple_formal_tmp_rhs (t);
}
/* Returns true iff T is a valid RHS for an assignment to an un-renamed
if (is_gimple_reg_type (TREE_TYPE (t)))
return is_gimple_val (t);
else
- return is_gimple_tmp_rhs (t);
+ return is_gimple_formal_tmp_rhs (t);
}
/* Returns the appropriate RHS predicate for this LHS. */
gimple_predicate
rhs_predicate_for (tree lhs)
{
- if (is_gimple_tmp_var (lhs))
- return is_gimple_tmp_rhs;
+ if (is_gimple_formal_tmp_var (lhs))
+ return is_gimple_formal_tmp_rhs;
else if (is_gimple_reg (lhs))
return is_gimple_reg_rhs;
else
&& ! needs_to_live_in_memory (t));
}
-/* Returns true if T is a GIMPLE temporary variable, false otherwise. */
+/* Returns true if T is a GIMPLE formal temporary variable. */
bool
-is_gimple_tmp_var (tree t)
+is_gimple_formal_tmp_var (tree t)
{
- /* FIXME this could trigger for other local artificials, too. */
- return (TREE_CODE (t) == VAR_DECL && DECL_ARTIFICIAL (t)
- && !TREE_STATIC (t) && !DECL_EXTERNAL (t));
+ return TREE_CODE (t) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (t);
}
-/* Returns true if T is a GIMPLE temporary register variable. */
+/* Returns true if T is a GIMPLE formal temporary register variable. */
bool
-is_gimple_tmp_reg (tree t)
+is_gimple_formal_tmp_reg (tree t)
{
/* The intent of this is to get hold of a value that won't change.
An SSA_NAME qualifies no matter if its of a user variable or not. */
return true;
/* We don't know the lifetime characteristics of user variables. */
- if (TREE_CODE (t) != VAR_DECL || !DECL_ARTIFICIAL (t))
+ if (!is_gimple_formal_tmp_var (t))
return false;
/* Finally, it must be capable of being placed in a register. */
/* Returns true iff T is a scalar register variable. */
extern bool is_gimple_reg (tree);
/* Returns true if T is a GIMPLE temporary variable, false otherwise. */
-extern bool is_gimple_tmp_var (tree);
+extern bool is_gimple_formal_tmp_var (tree);
/* Returns true if T is a GIMPLE temporary register variable. */
-extern bool is_gimple_tmp_reg (tree);
+extern bool is_gimple_formal_tmp_reg (tree);
/* Returns true iff T is any sort of variable. */
extern bool is_gimple_variable (tree);
/* Returns true iff T is a variable or an INDIRECT_REF (of a variable). */
/* Returns true iff T is a valid rhs for a MODIFY_EXPR where the LHS is a
GIMPLE temporary, a renamed user variable, or something else,
respectively. */
-extern bool is_gimple_tmp_rhs (tree);
+extern bool is_gimple_formal_tmp_rhs (tree);
extern bool is_gimple_reg_rhs (tree);
extern bool is_gimple_mem_rhs (tree);
/* Returns the appropriate one of the above three predicates for the LHS
int p1, p2, p3;
tree root1, root2;
var_ann_t ann1, ann2, ann3;
- bool gimp1, gimp2;
+ bool ign1, ign2;
#ifdef ENABLE_CHECKING
if (TREE_CODE (var1) != SSA_NAME || TREE_CODE (var2) != SSA_NAME)
return;
}
- gimp1 = (TREE_CODE (root1) == VAR_DECL && DECL_ARTIFICIAL (root1));
- gimp2 = (TREE_CODE (root2) == VAR_DECL && DECL_ARTIFICIAL (root2));
+ ign1 = TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1);
+ ign2 = TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2);
/* Never attempt to coalesce 2 user variables unless one is an inline
variable. */
- if (!gimp1 && !gimp2)
+ if (!ign1 && !ign2)
{
if (DECL_FROM_INLINE (root2))
- gimp2 = true;
- else
- if (DECL_FROM_INLINE (root1))
- gimp1 = true;
- else
- {
- if (debug)
- fprintf (debug, " : 2 different USER vars. No coalesce.\n");
- return;
- }
+ ign2 = true;
+ else if (DECL_FROM_INLINE (root1))
+ ign1 = true;
+ else
+ {
+ if (debug)
+ fprintf (debug, " : 2 different USER vars. No coalesce.\n");
+ return;
+ }
}
-
/* Don't coalesce if there are two different memory tags. */
if (ann1->type_mem_tag && ann2->type_mem_tag
&& ann1->type_mem_tag != ann2->type_mem_tag)
}
else
{
- gimp2 = true;
- gimp1 = false;
+ ign2 = true;
+ ign1 = false;
}
}
- else
- if (default_def (root2))
- {
- gimp1 = true;
- gimp2 = false;
- }
+ else if (default_def (root2))
+ {
+ ign1 = true;
+ ign2 = false;
+ }
/* Don't coalesce if the two variables aren't type compatible. */
if (!lang_hooks.types_compatible_p (TREE_TYPE (root1), TREE_TYPE (root2)))
/* Set the root variable of the partition to the better choice, if there is
one. */
- if (!gimp2)
+ if (!ign2)
replace_ssa_name_symbol (partition_to_var (map, p3), root2);
- else
- if (!gimp1)
- replace_ssa_name_symbol (partition_to_var (map, p3), root1);
+ else if (!ign1)
+ replace_ssa_name_symbol (partition_to_var (map, p3), root1);
/* Update the various flag widgitry of the current base representative. */
ann3 = var_ann (SSA_NAME_VAR (partition_to_var (map, p3)));
/* If there is no root_var set, or its not a user variable, set the
root_var to this one. */
- if (!root_var
- || (TREE_CODE (root_var) == VAR_DECL && DECL_ARTIFICIAL (root_var)))
+ if (!root_var || (DECL_P (root_var) && DECL_IGNORED_P (root_var)))
{
other_var = root_var;
root_var = var2;
|| TREE_CODE (t) == PARM_DECL
|| (DECL_P (t)
&& (DECL_REGISTER (t)
- || !DECL_ARTIFICIAL (t)
+ || !DECL_IGNORED_P (t)
|| DECL_RTL_SET_P (t))))
continue;
#define DECL_PRESERVE_P(DECL) \
DECL_CHECK (DECL)->decl.preserve_flag
+/* Internal to the gimplifier. Indicates that the value is a formal
+ temporary controlled by the gimplifier. */
+#define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
+ DECL_CHECK (DECL)->decl.gimple_formal_temp
+
/* Enumerate visibility settings. */
#ifndef SYMBOL_VISIBILITY_DEFINED
#define SYMBOL_VISIBILITY_DEFINED
unsigned possibly_inlined : 1;
unsigned preserve_flag: 1;
+ unsigned gimple_formal_temp : 1;
/* 13 unused bits. */
union tree_decl_u1 {