------- Comment #5 from hubicka at gcc dot gnu dot org  2006-08-07 09:09 -------
The IA-64 problem shall be fixed by my patch for PR target/26655.
The x86 problem is trickier.  Reload is decided to merge all classes mentioned
in given alternative, so "ad" is equivalent to "A", while recog.c is working
the oposite way.  
The best way to fix it I can think of is to make reload ignore the classes that
are too small to fit the register themselves.  It does not fix the problem
quite in general but at least deals with the x86 cases.

(in general one can have multiple register mode, join together two multiple reg
classes but reload might place the result just on the boundary still making
recog unhappy.)


Better ideas?

Honza

Index: reload.c
===================================================================
-cp -L reload.c (revision 115987) -L reload.c   (working copy)
.svn/text-base/reload.c.svn-base reload.c
*** reload.c    (revision 115987)
--- reload.c    (working copy)
*************** find_reloads (rtx insn, int replace, int
*** 2913,2918 ****
--- 2913,2919 ----
             operand.  */
          int constmemok = 0;
          int earlyclobber = 0;
+         enum reg_class class = NO_REGS;

          /* If the predicate accepts a unary operator, it means that
             we need to reload the operand, but do not do this for
*************** find_reloads (rtx insn, int replace, int
*** 3309,3314 ****
--- 3310,3316 ----
                /* Drop through into 'r' case.  */

              case 'r':
+               class = GENERAL_REGS;
                this_alternative[i]
                  = (int) reg_class_subunion[this_alternative[i]][(int)
GENERAL_REGS];
                goto reg;
*************** find_reloads (rtx insn, int replace, int
*** 3368,3384 ****
                    break;
                  }

                this_alternative[i]
                  = (int) (reg_class_subunion
                           [this_alternative[i]]
!                          [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
              reg:
                if (GET_MODE (operand) == BLKmode)
                  break;
                winreg = 1;
                if (REG_P (operand)
!                   && reg_fits_class_p (operand, this_alternative[i],
!                                        offset, GET_MODE
(recog_data.operand[i])))
                  win = 1;
                break;
              }
--- 3370,3409 ----
                    break;
                  }

+               class = REG_CLASS_FROM_CONSTRAINT (c, p);
+               /* When class is too tiny to hold the operand, ignore it.
+                  See PR21299.  First quickly test if things looks slopy
+                  and if they does try to look if register is really
+                  available.  */
+               if (CLASS_MAX_NREGS (class, GET_MODE (recog_data.operand[i]))
+                   > (int)reg_class_size [class])
+                 {
+                   int regno;
+                   enum machine_mode mode;
+                   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+                     if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+                         && HARD_REGNO_MODE_OK (regno, mode)
+                         && (regno + hard_regno_nregs[regno][mode]
+                             < FIRST_PSEUDO_REGISTER)
+                         && TEST_HARD_REG_BIT
+                                (reg_class_contents[class],
+                                 regno + hard_regno_nregs[regno][mode]))
+                    break;
+                  if (regno == FIRST_PSEUDO_REGISTER)
+                    break;
+                 }
                this_alternative[i]
                  = (int) (reg_class_subunion
                           [this_alternative[i]]
!                          [(int) class]);
              reg:
                if (GET_MODE (operand) == BLKmode)
                  break;
                winreg = 1;
                if (REG_P (operand)
!                   && reg_fits_class_p (operand, class,
!                                        offset,
!                                        GET_MODE (recog_data.operand[i])))
                  win = 1;
                break;
              }


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21299

Reply via email to