diff mbox

Improve reload's handling of classes with only fixed registers

Message ID 4C379741.6000507@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt July 9, 2010, 9:40 p.m. UTC
The ARM port supports instructions of the form "add reg, sp, #const"
with "k" constraints, which allow only only the stack pointer register,
on some alternatives.  It has to strongly discourage these with "!"
constraints, since otherwise it is conceivable that reload would choose
such an alternative, and try to reload a value into the stack pointer -
not good.  However, this means such an alternative will never be chosen
unless it already matches exactly.

The following patch improves reload's handling of such register classes.
 A new array, class_only_fixed_regs is used to determine if an
alternative can be used for reloading.  Currently, if an alternative
allows any kind of register, it is considered good; with this patch, the
existing operand either has to match the class already (which should be
the case for SP), or the class has to allow nonfixed registers.

Typical results for Thumb-1 code:
-       mov     r3, sp
-       add     r3, r3, #24
+       add     r3, sp, #24

or even

-       mov     r1, #138
-       lsl     r1, r1, #1
-       add     r1, r1, sp
+       add     r1, sp, #276

Bootstrapped and regression tested on i686-linux.  Also regression
tested for arm-linux (same options as usual).  Given the reload part,
the rest of the patch seems obvious, so I've committed it.


Bernd
* reload.c (find_reloads): Don't clear badop if we have a
	winreg alternative, but not win, and the class only has fixed
	regs.
	* hard-reg-set.h (class_only_fixed_regs): Declare.
	* reginfo.c (class_only_fixed_regs): New array.
	(init_reg_sets_1): Initialize it.
	* config/arm/arm.md (arm_addsi3, thumb1_addsi3, arm_subsi3_insn): Don't
	discourage alternatives using the stack pointer.

testsuite/
	* gcc.dg/pr32370.c: Allow another kind of error message.
diff mbox

Patch

Index: reload.c
===================================================================
--- reload.c	(revision 161824)
+++ reload.c	(working copy)
@@ -3470,7 +3470,8 @@  find_reloads (rtx insn, int replace, int
 
 	  /* If this operand could be handled with a reg,
 	     and some reg is allowed, then this operand can be handled.  */
-	  if (winreg && this_alternative[i] != NO_REGS)
+	  if (winreg && this_alternative[i] != NO_REGS
+	      && (win || !class_only_fixed_regs[this_alternative[i]]))
 	    badop = 0;
 
 	  /* Record which operands fit this alternative.  */
Index: hard-reg-set.h
===================================================================
--- hard-reg-set.h	(revision 161824)
+++ hard-reg-set.h	(working copy)
@@ -643,6 +643,10 @@  extern int inv_reg_alloc_order[FIRST_PSE
 
 extern HARD_REG_SET reg_class_contents[N_REG_CLASSES];
 
+/* For each reg class, a boolean saying whether the class contains only
+   fixed registers.  */
+extern bool class_only_fixed_regs[N_REG_CLASSES];
+
 /* For each reg class, number of regs it contains.  */
 
 extern unsigned int reg_class_size[N_REG_CLASSES];
Index: reginfo.c
===================================================================
--- reginfo.c	(revision 161824)
+++ reginfo.c	(working copy)
@@ -140,6 +140,10 @@  int inv_reg_alloc_order[FIRST_PSEUDO_REG
 /* For each reg class, a HARD_REG_SET saying which registers are in it.  */
 HARD_REG_SET reg_class_contents[N_REG_CLASSES];
 
+/* For each reg class, a boolean saying whether the class contains only
+   fixed registers.  */
+bool class_only_fixed_regs[N_REG_CLASSES];
+
 /* The same information, but as an array of unsigned ints.  We copy from
    these unsigned ints to the table above.  We do this so the tm.h files
    do not have to be aware of the wordsize for machines with <= 64 regs.
@@ -416,10 +420,18 @@  init_reg_sets_1 (void)
   /* Compute number of hard regs in each class.  */
 
   memset (reg_class_size, 0, sizeof reg_class_size);
   for (i = 0; i < N_REG_CLASSES; i++)
-    for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
-      if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
-	reg_class_size[i]++;
+    {
+      bool any_nonfixed = false;
+      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)	
+	if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
+	  {
+	    reg_class_size[i]++;
+	    if (!fixed_regs[j])
+	      any_nonfixed = true;
+	  }
+      class_only_fixed_regs[i] = !any_nonfixed;
+    }
 
   /* Initialize the table of subunions.
      reg_class_subunion[I][J] gets the largest-numbered reg-class
Index: config/arm/arm.md
===================================================================
--- config/arm/arm.md	(revision 161893)
+++ config/arm/arm.md	(working copy)
@@ -610,9 +610,9 @@  (define_peephole2
 ;;  (plus (reg rN) (reg sp)) into (reg rN).  In this case reload will
 ;; put the duplicated register first, and not try the commutative version.
 (define_insn_and_split "*arm_addsi3"
-  [(set (match_operand:SI          0 "s_register_operand" "=r, !k, r,r, !k,r")
-	(plus:SI (match_operand:SI 1 "s_register_operand" "%rk,!k, r,rk,!k,rk")
-		 (match_operand:SI 2 "reg_or_int_operand" "rI, rI,!k,L, L,?n")))]
+  [(set (match_operand:SI          0 "s_register_operand" "=r, k,r,r, k,r")
+	(plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
+		 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
   "TARGET_32BIT"
   "@
    add%?\\t%0, %1, %2
@@ -637,14 +637,10 @@  (define_insn_and_split "*arm_addsi3"
    (set_attr "predicable" "yes")]
 )
 
-;; Register group 'k' is a single register group containing only the stack
-;; register.  Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-
 (define_insn_and_split "*thumb1_addsi3"
-  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,!k,l,l")
-	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k,0,l")
-		 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,!M,!O,Pa,Pb")))]
+  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l")
+	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l")
+		 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb")))]
   "TARGET_THUMB1"
   "*
    static const char * const asms[] = 
@@ -1089,8 +1085,8 @@  (define_insn "*thumb1_subsi3_insn"
 ; ??? Check Thumb-2 split length
 (define_insn_and_split "*arm_subsi3_insn"
   [(set (match_operand:SI           0 "s_register_operand" "=r,r,rk,r,r")
-	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,!k,?n,r")
-		  (match_operand:SI 2 "reg_or_int_operand" "r,rI, r, r,?n")))]
+	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
+		  (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
   "TARGET_32BIT"
   "@
    rsb%?\\t%0, %2, %1
Index: testsuite/gcc.dg/pr32370.c
===================================================================
--- testsuite/gcc.dg/pr32370.c	(revision 161824)
+++ testsuite/gcc.dg/pr32370.c	(working copy)
@@ -19,7 +19,7 @@  unsigned int
 foo (TYPE port)
 {
   unsigned int v;
-  __asm__ __volatile__ ("" : C (v) : "Nd" (port));	/* { dg-error "while reloading\|has impossible" } */
+  __asm__ __volatile__ ("" : C (v) : "Nd" (port));	/* { dg-error "while reloading\|has impossible\|inconsistent operand constraints" } */
   return v;
 }