Bernd Schmidt writes:

> On 09/16/2016 09:02 PM, Senthil Kumar Selvaraj wrote:
>>   Does this make sense? I ran a reg test for the avr target with a
>>   slightly older version of this patch, it did not show any regressions.
>>   If this is the right fix, I'll make sure to run reg tests on x86_64
>>   after backporting to a gcc version where that target used reload.
>
> It's hard to say, and could have different effects on different targets.
> One thing though, at the very least the reg_class_size test would have 
> to be adapted - the idea is to find the largest class, and there's a 
> risk here of ending up with a large class that only has one valid register.

Agreed - I've updated the patch to compute rclass sizes based on regno
availability i.e., only if in_hard_reg_set_p and HARD_REGNO_MODE_OK, and
then use the computed sizes when calculating best_size.

>
> You'll also want to verify this against
>    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54814

Yes, this patch doesn't break the fix for PR54814. The change to
in_hard_reg_set_p was what fixed that, and that remains unmodified.

Reg tested this on top of trunk@190252 with the in_hard_reg_set_p
backport. x86_64-pc-linux bootstrapped and regtested ok. avr showed
no regressions either.

Ok for trunk?

Regards
Senthil

gcc/ChangeLog:

2016-10-13  Senthil Kumar Selvaraj  <senthil_kumar.selva...@atmel.com>

        * reload.c (find_valid_class_1): Allow regclass if atleast one
        regno in class is ok. Compute and use rclass size based on
        actually available regnos for mode in rclass.

gcc/testsuite/ChangeLog:

2016-10-13  Senthil Kumar Selvaraj  <senthil_kumar.selva...@atmel.com>
        
        * gcc.target/avr/pr71627.c: New.


Index: gcc/reload.c
===================================================================
--- gcc/reload.c        (revision 240989)
+++ gcc/reload.c        (working copy)
@@ -711,31 +711,36 @@
   enum reg_class best_class = NO_REGS;
   unsigned int best_size = 0;
   int cost;
+  unsigned int computed_rclass_sizes[N_REG_CLASSES] = { 0 };
 
   for (rclass = 1; rclass < N_REG_CLASSES; rclass++)
     {
-      int bad = 0;
-      for (regno = 0; regno < FIRST_PSEUDO_REGISTER && !bad; regno++)
-       {
-         if (in_hard_reg_set_p (reg_class_contents[rclass], mode, regno)
-             && !HARD_REGNO_MODE_OK (regno, mode))
-           bad = 1;
-       }
-      
-      if (bad)
-       continue;
+      int atleast_one_regno_ok = 0;
 
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+        {
+          if (in_hard_reg_set_p (reg_class_contents[rclass], mode, regno))
+            {
+              atleast_one_regno_ok = 1;
+              if (HARD_REGNO_MODE_OK (regno, mode))
+                computed_rclass_sizes[rclass]++;
+            }
+        }
+
+      if (!atleast_one_regno_ok)
+        continue;
+
       cost = register_move_cost (outer, (enum reg_class) rclass, dest_class);
 
-      if ((reg_class_size[rclass] > best_size
-          && (best_cost < 0 || best_cost >= cost))
-         || best_cost > cost)
-       {
-         best_class = (enum reg_class) rclass;
-         best_size = reg_class_size[rclass];
-         best_cost = register_move_cost (outer, (enum reg_class) rclass,
-                                         dest_class);
-       }
+      if ((computed_rclass_sizes[rclass] > best_size
+           && (best_cost < 0 || best_cost >= cost))
+          || best_cost > cost)
+        {
+          best_class = (enum reg_class) rclass;
+          best_size = computed_rclass_sizes[rclass];
+          best_cost = register_move_cost (outer, (enum reg_class) rclass,
+                                          dest_class);
+        }
     }
 
   gcc_assert (best_size != 0);

Index: gcc/testsuite/gcc.target/avr/pr71627.c
===================================================================
--- gcc/testsuite/gcc.target/avr/pr71627.c      (nonexistent)
+++ gcc/testsuite/gcc.target/avr/pr71627.c      (working copy)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+
+extern volatile __memx const long  a, b, c, d, e, f;
+extern volatile long result;
+
+extern void vfunc (const char*, ...);
+
+void foo (void)
+{
+       result = a + b + c + d + e + f;
+       vfunc ("text", a, b, c, d, e, f, result);
+}

Reply via email to