summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/gimplify.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/asm-3.c26
-rw-r--r--gcc/tree-gimple.c45
-rw-r--r--gcc/tree-gimple.h2
-rw-r--r--gcc/tree-outof-ssa.c5
-rw-r--r--gcc/tree-pretty-print.c8
-rw-r--r--gcc/tree-ssa-copy.c8
-rw-r--r--gcc/tree-ssa-copyrename.c13
-rw-r--r--gcc/tree-ssa-pre.c3
-rw-r--r--gcc/tree-ssa.c2
-rw-r--r--gcc/tree.h2
12 files changed, 99 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a99fd42a003..c58b388c96a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+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
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 27744bcb689..ca233617b89 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c b/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c
new file mode 100644
index 00000000000..ddb0ddcbc6a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c
@@ -0,0 +1,26 @@
+/* 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" } } */
diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c
index 82b82a43fed..b2a2ad9a2bd 100644
--- a/gcc/tree-gimple.c
+++ b/gcc/tree-gimple.c
@@ -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. */
diff --git a/gcc/tree-gimple.h b/gcc/tree-gimple.h
index d0f8ff5ed90..b3fb9c69c91 100644
--- a/gcc/tree-gimple.h
+++ b/gcc/tree-gimple.h
@@ -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. */
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 4d9986d1953..827f91d1511 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -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;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index b59e6dd4ed2..9337c3856fd 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -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. */
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index 63a3c20417d..dc41e8e058e 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -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)));
}
diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c
index 4ef5b3dbd1c..7495c6b8753 100644
--- a/gcc/tree-ssa-copyrename.c
+++ b/gcc/tree-ssa-copyrename.c
@@ -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);
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index b0809d14b73..3d505b5579b 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -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);
}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 5b9b3ccd185..1ddaf7d3e66 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -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
diff --git a/gcc/tree.h b/gcc/tree.h
index 3814fda2eb1..b40253ccfaf 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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)