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]

Re: [ira] Minor fix to REG_CLASS_UNION computation


Jeff Law wrote:


Let's say a port has defined some register classes.  DATA_REGS,
EXTENDED_REGS and DATA_OR_EXTENDED_REGS.    Pretty normal stuff, two
fundamental classes and a union of those classes.

Now on the mn103, the registers in EXTENED_REGS are not available in the
base mn103 chip -- they are only available on follow-on chips.  So, when
compiling for the bare mn103, we consider the registers in EXTENED_REGS
to be unavailable.  In that situation I'd expect the compiler to never
choose EXTENDED_REGS or DATA_OR_EXTENED_REGS for any preferred or
alternate register class.

However, if we look at the dumps when IRA is enabled we see:

    a80 (r128,l4) best DATA_OR_EXTENDED_REGS, cover DATA_OR_ADDRESS_REGS
    a66 (r126,l3) best DATA_OR_EXTENDED_REGS, cover DATA_OR_ADDRESS_REGS
    a49 (r123,l2) best DATA_OR_EXTENDED_REGS, cover DATA_OR_ADDRESS_REGS
    a28 (r122,l1) best DATA_OR_EXTENDED_REGS, cover DATA_OR_ADDRESS_REGS
    a27 (r121,l1) best DATA_OR_EXTENDED_REGS, cover DATA_OR_ADDRESS_REGS
    a24 (r118,l1) best DATA_OR_EXTENDED_REGS, cover DATA_OR_ADDRESS_REGS


This is a trivial problem in how IRA computes union sets. It should
find the smallest (according to the enumeration values in REG_CLASS) set
which is the union of the input sets. Instead it'll find the largest
(according to the enumeration values in REG_CLASS) -- note carefully
that the active contents are the same since the extra registers in
DATA_OR_EXTENED_REGS are unavailable when compiling for the base mn103 port.



With this trivial fix we get the much more sane looking:



a80 (r128,l4) best DATA_REGS, cover DATA_OR_ADDRESS_REGS a66 (r126,l3) best DATA_REGS, cover DATA_OR_ADDRESS_REGS a49 (r123,l2) best DATA_REGS, cover DATA_OR_ADDRESS_REGS a28 (r122,l1) best DATA_REGS, cover DATA_OR_ADDRESS_REGS a27 (r121,l1) best DATA_REGS, cover DATA_OR_ADDRESS_REGS a24 (r118,l1) best DATA_REGS, cover DATA_OR_ADDRESS_REGS


This change just tells the union code to ignore larger enumerated sets
which are identical to any union set that has already been found. It shouldn't ever change the generated code, just the debugging dumps.


    * ira.c (setup_reg_class_intersect_union): Choose smallest
    union class containing the desired registers, not the largest
    union class.

Thanks for finding the problem and for the patch. I've submitted practically the same patch into the branch.

2008-08-24  Jeff Law  <law@redhat.com>
       Vladimir Makarov  <vmakarov@redhat.com>

   * ira.c (setup_reg_class_intersect_union): Prefer smallest class
   when ignoring unavailable registers.







Index: ira.c
===================================================================
--- ira.c	(revision 139535)
+++ ira.c	(working copy)
@@ -909,7 +909,14 @@ setup_reg_class_intersect_union (void)
 		     reg_class_contents[(int)
 					ira_reg_class_intersect[cl1][cl2]]);
 		  AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
-	 	  if (! hard_reg_set_subset_p (temp_hard_regset, temp_set2))
+	 	  if (! hard_reg_set_subset_p (temp_hard_regset, temp_set2)
+		      /* Ignore unavailable hard registers and prefer
+			 smallest class for debugging purposes.  */
+		      || (hard_reg_set_equal_p (temp_hard_regset, temp_set2)
+			  && hard_reg_set_subset_p
+			     (reg_class_contents[cl3],
+			      reg_class_contents
+			      [(int) ira_reg_class_intersect[cl1][cl2]])))
 		    ira_reg_class_intersect[cl1][cl2] = (enum reg_class) cl3;
 		}
 	      if (hard_reg_set_subset_p (temp_hard_regset, union_set))
@@ -918,7 +925,18 @@ setup_reg_class_intersect_union (void)
 		    (temp_set2,
 		     reg_class_contents[(int) ira_reg_class_union[cl1][cl2]]);
 		  AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
-	 	  if (hard_reg_set_subset_p (temp_set2, temp_hard_regset))
+	 	  if (ira_reg_class_union[cl1][cl2] == NO_REGS
+		      || (hard_reg_set_subset_p (temp_set2, temp_hard_regset)
+		      
+			  && (! hard_reg_set_equal_p (temp_set2,
+						      temp_hard_regset)
+			      /* Ignore unavailable hard registers and
+				 prefer smallest class for debugging
+				 purposes.  */
+			      || hard_reg_set_subset_p
+			         (reg_class_contents[cl3],
+				  reg_class_contents
+				  [(int) ira_reg_class_union[cl1][cl2]]))))
 		    ira_reg_class_union[cl1][cl2] = (enum reg_class) cl3;
 		}
 	    }

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