This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fix 21291


The problem demonstrated in this PR is 

	"+mr"(x)

being split into

	"=mr"(x.0) : "0"(x)

The register allocator can resolve this via registers, by copying
x and x.0 into the same hard register.  However, since these are
not the same pseudo register, it can't fall back to memory because
the stack slot for these two variables is not the same.

One could argue that this would be solvable by coalesing stack
slots in the register allocator.  And indeed, that is something
that we should do at some point.

But for the nonce, I think it's a benefit all around if we go
ahead and notice the in/out properties of the asm, and use them
to avoid unnecessary splitting of the live range.

Tested on i686-linux.


r~


        PR 21291
        * tree-outof-ssa.c (coalesce_asm_operands): New.
        (coalesce_ssa_name): Use it.  Split out ...
        (coalesce_phi_operands, coalesce_result_decls): ... these.

Index: tree-outof-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-outof-ssa.c,v
retrieving revision 2.65
diff -u -p -d -r2.65 tree-outof-ssa.c
--- tree-outof-ssa.c	30 Jul 2005 22:14:16 -0000	2.65
+++ tree-outof-ssa.c	4 Aug 2005 23:33:32 -0000
@@ -676,49 +676,26 @@ coalesce_abnormal_edges (var_map map, co
 	  }
 }
 
+/* Coalesce potential copies via PHI arguments.  */
 
-/* Reduce the number of live ranges in MAP.  Live range information is 
-   returned if FLAGS indicates that we are combining temporaries, otherwise 
-   NULL is returned.  The only partitions which are associated with actual 
-   variables at this point are those which are forced to be coalesced for 
-   various reason. (live on entry, live across abnormal edges, etc.).  */
-
-static tree_live_info_p
-coalesce_ssa_name (var_map map, int flags)
+static void
+coalesce_phi_operands (var_map map, coalesce_list_p cl)
 {
-  unsigned num, x, i;
-  sbitmap live;
-  tree var, phi;
-  root_var_p rv;
-  tree_live_info_p liveinfo;
-  var_ann_t ann;
-  conflict_graph graph;
   basic_block bb;
-  coalesce_list_p cl = NULL;
-  sbitmap_iterator sbi;
-
-  if (num_var_partitions (map) <= 1)
-    return NULL;
-
-  liveinfo = calculate_live_on_entry (map);
-  calculate_live_on_exit (liveinfo);
-  rv = root_var_init (map);
-
-  /* Remove single element variable from the list.  */
-  root_var_compact (rv);
-
-  cl = create_coalesce_list (map);
+  tree phi;
 
-  /* Add all potential copies via PHI arguments to the list.  */
   FOR_EACH_BB (bb)
     {
       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
 	{
 	  tree res = PHI_RESULT (phi);
 	  int p = var_to_partition (map, res);
+	  int x;
+
 	  if (p == NO_PARTITION)
 	    continue;
-	  for (x = 0; x < (unsigned)PHI_NUM_ARGS (phi); x++)
+
+	  for (x = 0; x < PHI_NUM_ARGS (phi); x++)
 	    {
 	      tree arg = PHI_ARG_DEF (phi, x);
 	      int p2;
@@ -739,14 +716,20 @@ coalesce_ssa_name (var_map map, int flag
 	    }
 	}
     }
+}
 
-  /* Coalesce all the result decls together.  */
-  var = NULL_TREE;
-  i = 0;
-  for (x = 0; x < num_var_partitions (map); x++)
+/* Coalesce all the result decls together.  */
+
+static void
+coalesce_result_decls (var_map map, coalesce_list_p cl)
+{
+  unsigned int i, x;
+  tree var = NULL;
+
+  for (i = x = 0; x < num_var_partitions (map); x++)
     {
       tree p = partition_to_var (map, x);
-      if (TREE_CODE (SSA_NAME_VAR(p)) == RESULT_DECL)
+      if (TREE_CODE (SSA_NAME_VAR (p)) == RESULT_DECL)
 	{
 	  if (var == NULL_TREE)
 	    {
@@ -760,6 +743,100 @@ coalesce_ssa_name (var_map map, int flag
 					 false));
 	}
     }
+}
+
+/* Coalesce matching constraints in asms.  */
+
+static void
+coalesce_asm_operands (var_map map, coalesce_list_p cl)
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator bsi;
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+	{
+	  tree stmt = bsi_stmt (bsi);
+	  unsigned long noutputs, i;
+	  tree *outputs, link;
+
+	  if (TREE_CODE (stmt) != ASM_EXPR)
+	    continue;
+
+	  noutputs = list_length (ASM_OUTPUTS (stmt));
+	  outputs = (tree *) alloca (noutputs * sizeof (tree));
+	  for (i = 0, link = ASM_OUTPUTS (stmt); link;
+	       ++i, link = TREE_CHAIN (link))
+	    outputs[i] = TREE_VALUE (link);
+
+	  for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+	    {
+	      const char *constraint
+		= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+	      tree input = TREE_VALUE (link);
+	      char *end;
+	      unsigned long match;
+	      int p1, p2;
+
+	      if (TREE_CODE (input) != SSA_NAME && !DECL_P (input))
+		continue;
+
+	      match = strtoul (constraint, &end, 10);
+	      if (match >= noutputs || end == constraint)
+		continue;
+
+	      if (TREE_CODE (outputs[match]) != SSA_NAME
+		  && !DECL_P (outputs[match]))
+		continue;
+
+	      p1 = var_to_partition (map, outputs[match]);
+	      if (p1 == NO_PARTITION)
+		continue;
+	      p2 = var_to_partition (map, input);
+	      if (p2 == NO_PARTITION)
+		continue;
+
+	      add_coalesce (cl, p1, p2, coalesce_cost (REG_BR_PROB_BASE,
+						       maybe_hot_bb_p (bb),
+						       false));
+	    }
+	}
+    }
+}
+
+/* Reduce the number of live ranges in MAP.  Live range information is 
+   returned if FLAGS indicates that we are combining temporaries, otherwise 
+   NULL is returned.  The only partitions which are associated with actual 
+   variables at this point are those which are forced to be coalesced for 
+   various reason. (live on entry, live across abnormal edges, etc.).  */
+
+static tree_live_info_p
+coalesce_ssa_name (var_map map, int flags)
+{
+  unsigned num, x;
+  sbitmap live;
+  root_var_p rv;
+  tree_live_info_p liveinfo;
+  conflict_graph graph;
+  coalesce_list_p cl = NULL;
+  sbitmap_iterator sbi;
+
+  if (num_var_partitions (map) <= 1)
+    return NULL;
+
+  liveinfo = calculate_live_on_entry (map);
+  calculate_live_on_exit (liveinfo);
+  rv = root_var_init (map);
+
+  /* Remove single element variable from the list.  */
+  root_var_compact (rv);
+
+  cl = create_coalesce_list (map);
+
+  coalesce_phi_operands (map, cl);
+  coalesce_result_decls (map, cl);
+  coalesce_asm_operands (map, cl);
 
   /* Build a conflict graph.  */
   graph = build_tree_conflict_graph (liveinfo, rv, cl);
@@ -787,14 +864,14 @@ coalesce_ssa_name (var_map map, int flag
   /* First, coalesce all live on entry variables to their root variable. 
      This will ensure the first use is coming from the correct location.  */
 
-  live = sbitmap_alloc (num_var_partitions (map));
+  num = num_var_partitions (map);
+  live = sbitmap_alloc (num);
   sbitmap_zero (live);
 
   /* Set 'live' vector to indicate live on entry partitions.  */
-  num = num_var_partitions (map);
   for (x = 0 ; x < num; x++)
     {
-      var = partition_to_var (map, x);
+      tree var = partition_to_var (map, x);
       if (default_def (SSA_NAME_VAR (var)) == var)
 	SET_BIT (live, x);
     }
@@ -809,8 +886,8 @@ coalesce_ssa_name (var_map map, int flag
      partition.  */
   EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
     {
-      var = root_var (rv, root_var_find (rv, x));
-      ann = var_ann (var);
+      tree var = root_var (rv, root_var_find (rv, x));
+      var_ann_t ann = var_ann (var);
       /* If these aren't already coalesced...  */
       if (partition_to_var (map, x) != var)
 	{
Index: testsuite/gcc.target/i386/pr21291.c
===================================================================
RCS file: testsuite/gcc.target/i386/pr21291.c
diff -N testsuite/gcc.target/i386/pr21291.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.target/i386/pr21291.c	4 Aug 2005 23:33:32 -0000
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+typedef unsigned long bngdigit;
+typedef bngdigit *bng;
+typedef unsigned int bngcarry;
+typedef unsigned long bngsize;
+
+bngdigit
+bng_ia32_mult_sub_digit (bng a, bngsize alen, bng b, bngsize blen, bngdigit d)
+{
+  bngdigit out, tmp;
+  bngcarry carry;
+  bngdigit a11;
+
+  alen -= blen;
+  out = 0;
+  asm (""
+       : "+r" (a), "+r" (b), "+mr" (blen), "+mr" (out), "=&r" (tmp)
+       : "mr" (d)
+       : "eax", "edx");
+  if (alen == 0)
+    {
+      a11 = out;
+      goto t;
+    }
+
+  a11 = 1;
+ t:
+  return a11;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]