Commit e670d9e4 by Richard Henderson Committed by Richard Henderson

re PR tree-optimization/17739 (tree-optimizers extend the lifetime of a hard register variable)

        PR 17739
        * tree-gimple.c (is_gimple_reg): Reject hard registers.
        (is_gimple_asm_val): New.
        * tree-gimple.h (is_gimple_asm_val): Declare.
        * gimplify.c (gimplify_asm_expr): Use it.
        * tree-pretty-print.c (print_declaration): Dump hard regs.
        * tree-outof-ssa.c (check_replaceable): Don't check for hard regs.
        * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Likewise.
        * tree-ssa-pre.c (is_undefined_value): Likewise.
        * tree-ssa-copy.c (may_propagate_copy): Likewise.
        (may_propagate_copy_into_asm): Protect DECL_HARD_REGISTER.
        * tree-ssa.c (warn_uninit): Likewise.
        * tree.h (DECL_HARD_REGISTER): Check for VAR_DECL.

From-SVN: r88321
parent 67a74146
2004-09-29 Richard Henderson <rth@redhat.com>
PR 17739
* tree-gimple.c (is_gimple_reg): Reject hard registers.
(is_gimple_asm_val): New.
* tree-gimple.h (is_gimple_asm_val): Declare.
* gimplify.c (gimplify_asm_expr): Use it.
* tree-pretty-print.c (print_declaration): Dump hard regs.
* tree-outof-ssa.c (check_replaceable): Don't check for hard regs.
* tree-ssa-copyrename.c (copy_rename_partition_coalesce): Likewise.
* tree-ssa-pre.c (is_undefined_value): Likewise.
* tree-ssa-copy.c (may_propagate_copy): Likewise.
(may_propagate_copy_into_asm): Protect DECL_HARD_REGISTER.
* tree-ssa.c (warn_uninit): Likewise.
* tree.h (DECL_HARD_REGISTER): Check for VAR_DECL.
2004-09-29 Fariborz Jahanian <fjahanian@apple.com>
* c-decl.c (merge_decls): Use comptype when comparing
......
......@@ -3215,7 +3215,7 @@ gimplify_asm_expr (tree *expr_p, tree *pre_p, tree *post_p)
else
{
tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
is_gimple_val, fb_rvalue);
is_gimple_asm_val, fb_rvalue);
if (tret == GS_ERROR)
ret = tret;
}
......
/* PR 17739 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
#define REGISTER "0"
static inline int source(void)
{
register int hardreg __asm__(REGISTER);
asm("" : "=r"(hardreg));
return hardreg;
}
void test(void)
{
int t = source();
foo(t);
bar(t);
}
/* Hardreg should appear exactly 3 times -- declaration, asm stmt,
and copy out. */
/* { dg-final { scan-tree-dump-times "hardreg" 3 "optimized" } } */
/* In particular, hardreg should *not* appear in the call to bar. */
/* { dg-final { scan-tree-dump-times "bar \[(\]t\[)\]" 1 "optimized" } } */
......@@ -282,12 +282,35 @@ is_gimple_reg (tree t)
if (TREE_CODE (t) == SSA_NAME)
t = SSA_NAME_VAR (t);
return (is_gimple_variable (t)
&& is_gimple_reg_type (TREE_TYPE (t))
/* A volatile decl is not acceptable because we can't reuse it as
needed. We need to copy it into a temp first. */
&& ! TREE_THIS_VOLATILE (t)
&& ! needs_to_live_in_memory (t));
if (!is_gimple_variable (t))
return false;
if (!is_gimple_reg_type (TREE_TYPE (t)))
return false;
/* A volatile decl is not acceptable because we can't reuse it as
needed. We need to copy it into a temp first. */
if (TREE_THIS_VOLATILE (t))
return false;
/* We define "registers" as things that can be renamed as needed,
which with our infrastructure does not apply to memory. */
if (needs_to_live_in_memory (t))
return false;
/* Hard register variables are an interesting case. For those that
are call-clobbered, we don't know where all the calls are, since
we don't (want to) take into account which operations will turn
into libcalls at the rtl level. For those that are call-saved,
we don't currently model the fact that calls may in fact change
global hard registers, nor do we examine ASM_CLOBBERS at the tree
level, and so miss variable changes that might imply. All around,
it seems safest to not do too much optimization with these at the
tree level at all. We'll have to rely on the rtl optimizers to
clean this up, as there we've got all the appropriate bits exposed. */
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
return false;
return true;
}
/* Returns true if T is a GIMPLE formal temporary variable. */
......@@ -349,6 +372,16 @@ is_gimple_val (tree t)
return (is_gimple_variable (t) || is_gimple_min_invariant (t));
}
/* Similarly, but accept hard registers as inputs to asm statements. */
bool
is_gimple_asm_val (tree t)
{
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
return true;
return is_gimple_val (t);
}
/* Return true if T is a GIMPLE minimal lvalue. */
......
......@@ -64,6 +64,8 @@ extern bool is_gimple_lvalue (tree);
extern bool is_gimple_min_invariant (tree);
/* Returns true iff T is a GIMPLE rvalue. */
extern bool is_gimple_val (tree);
/* Returns true iff T is a GIMPLE asm statement input. */
extern bool is_gimple_asm_val (tree);
/* 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. */
......
......@@ -1476,11 +1476,6 @@ check_replaceable (temp_expr_table_p tab, tree stmt)
if (version_ref_count (map, def) != 1)
return false;
/* Assignments to variables assigned to hard registers are not
replaceable. */
if (DECL_HARD_REGISTER (SSA_NAME_VAR (def)))
return false;
/* There must be no V_MAY_DEFS. */
if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) != 0)
return false;
......
......@@ -1566,6 +1566,14 @@ print_declaration (pretty_printer *buffer, tree t, int spc, int flags)
dump_generic_node (buffer, t, spc, flags, false);
}
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
{
pp_string (buffer, " __asm__ ");
pp_character (buffer, '(');
dump_generic_node (buffer, DECL_ASSEMBLER_NAME (t), spc, flags, false);
pp_character (buffer, ')');
}
/* The initial value of a function serves to determine wether the function
is declared or defined. So the following does not apply to function
nodes. */
......
......@@ -145,11 +145,10 @@ may_propagate_copy (tree dest, tree orig)
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
return false;
/* If DEST is an SSA_NAME that flows from an abnormal edge or if it
represents a hard register, then it cannot be replaced. */
/* If DEST is an SSA_NAME that flows from an abnormal edge, then it
cannot be replaced. */
if (TREE_CODE (dest) == SSA_NAME
&& (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest)
|| DECL_HARD_REGISTER (SSA_NAME_VAR (dest))))
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
return false;
/* Anything else is OK. */
......@@ -163,6 +162,7 @@ may_propagate_copy_into_asm (tree dest)
{
/* Hard register operands of asms are special. Do not bypass. */
return !(TREE_CODE (dest) == SSA_NAME
&& TREE_CODE (SSA_NAME_VAR (dest)) == VAR_DECL
&& DECL_HARD_REGISTER (SSA_NAME_VAR (dest)));
}
......
......@@ -146,19 +146,6 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
root1 = SSA_NAME_VAR (rep1);
root2 = SSA_NAME_VAR (rep2);
if (DECL_HARD_REGISTER (root1) || DECL_HARD_REGISTER (root2))
{
if (debug)
{
if (DECL_HARD_REGISTER (root1))
print_generic_expr (debug, var1, TDF_SLIM);
else
print_generic_expr (debug, var2, TDF_SLIM);
fprintf (debug, " is a hardware register. No Coalescing.\n");
}
return;
}
ann1 = var_ann (root1);
ann2 = var_ann (root2);
......
......@@ -1624,8 +1624,7 @@ is_undefined_value (tree expr)
return (TREE_CODE (expr) == SSA_NAME
&& IS_EMPTY_STMT (SSA_NAME_DEF_STMT (expr))
/* PARM_DECLs and hard registers are always defined. */
&& TREE_CODE (SSA_NAME_VAR (expr)) != PARM_DECL
&& !DECL_HARD_REGISTER (SSA_NAME_VAR (expr)));
&& TREE_CODE (SSA_NAME_VAR (expr)) != PARM_DECL);
}
......
......@@ -1273,7 +1273,7 @@ warn_uninit (tree t, const char *msgid, location_t *locus)
return;
/* Hard register variables get their initial value from the ether. */
if (DECL_HARD_REGISTER (var))
if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
return;
/* TREE_NO_WARNING either means we already warned, or the front end
......
......@@ -2123,7 +2123,7 @@ struct tree_binfo GTY (())
/* In a VAR_DECL, nonzero if the decl is a register variable with
an explicit asm specification. */
#define DECL_HARD_REGISTER(NODE) (DECL_CHECK (NODE)->decl.inline_flag)
#define DECL_HARD_REGISTER(NODE) (VAR_DECL_CHECK (NODE)->decl.inline_flag)
/* Value of the decls's visibility attribute */
#define DECL_VISIBILITY(NODE) (DECL_CHECK (NODE)->decl.visibility)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment