]> gcc.gnu.org Git - gcc.git/commitdiff
re PR tree-optimization/17739 (tree-optimizers extend the lifetime of a hard register...
authorRichard Henderson <rth@redhat.com>
Thu, 30 Sep 2004 01:22:07 +0000 (18:22 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 30 Sep 2004 01:22:07 +0000 (18:22 -0700)
        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

12 files changed:
gcc/ChangeLog
gcc/gimplify.c
gcc/testsuite/gcc.dg/tree-ssa/asm-3.c [new file with mode: 0644]
gcc/tree-gimple.c
gcc/tree-gimple.h
gcc/tree-outof-ssa.c
gcc/tree-pretty-print.c
gcc/tree-ssa-copy.c
gcc/tree-ssa-copyrename.c
gcc/tree-ssa-pre.c
gcc/tree-ssa.c
gcc/tree.h

index a99fd42a0030cc14998d25b9b912dab2819bb7ca..c58b388c96a2022cfd68cf7d2c6acb578ef73eab 100644 (file)
@@ -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
index 27744bcb6893452f0f52b6f3e0cb626daa00fcb1..ca233617b897467877425a6a4184c1120cb3559b 100644 (file)
@@ -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 (file)
index 0000000..ddb0ddc
--- /dev/null
@@ -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" } } */
index 82b82a43fed3c8b00385924c1f2786e8ffbc02b5..b2a2ad9a2bda0397164e260fbd7fca904fe387f9 100644 (file)
@@ -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.  */
 
index d0f8ff5ed909d9be6bbaa51d3c7083fbf10e8f59..b3fb9c69c912c93193850ede338041b27bdf820f 100644 (file)
@@ -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.  */
index 4d9986d1953c48a181e8ac14baf6899c9362cf10..827f91d151106d7bf86965f0139751e77bce4e42 100644 (file)
@@ -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;
index b59e6dd4ed2d3b6ad3481d5c33b8d899b65243ba..9337c3856fd33614b5c3fcb85fe9eda3d87f6e33 100644 (file)
@@ -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.  */
index 63a3c20417d7c0314562d2491b048fd837b26ec1..dc41e8e058ec4b37a1ad1fbabb1718a6974a4391 100644 (file)
@@ -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)));
 }
 
index 4ef5b3dbd1c66657642ab3e6f268c7709d1f4598..7495c6b8753ec1772ab7d912ad615c507720be5c 100644 (file)
@@ -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);
 
index b0809d14b73a97ae7fe6709717cd488a4c6a1f93..3d505b5579be41b90ed59e3ed20587d940c91b88 100644 (file)
@@ -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);
 }
 
 
index 5b9b3ccd185253ce97a112a9857b2478c2b2084e..1ddaf7d3e660a3b640aa6e4e1c75d8d6027cec1b 100644 (file)
@@ -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
index 3814fda2eb18b6a9a48435eb3c166b311e72f0be..b40253ccfaf60e121d05d4ba66503c4a33a1156d 100644 (file)
@@ -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)
This page took 0.174228 seconds and 5 git commands to generate.