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: 4.2 reload infrastructure (PR 25027)


> Given how little I know about the PA, and how convoluted the code 
> especially in emit_move_sequence is, you better double-check that this 
> does what you need.

This is what I committed.  I have improved the ordering of checks
in pa_secondary_reload a bit, and I also updated the inline copy of
symbolic operand which was missing some TLS stuff.

Tested on hppa-unknown-linux-gnu, hppa2.0w-hp-hpux11.11 and
hppa64-hp-hpux11.11.

Thanks,
Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

2005-11-30  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
	    Bernd Schmidt  <bernd.schmidt@analog.com>

	PR middle-end/25027
	* pa/predicates.md (symbolic_operand): Add comment.
	* pa/pa.md (reload_insi_r1, reload_indi_r1): New reload expanders.
	* pa/pa-protos.h (pa_secondary_reload_class): Delete.
	* pa/pa.c (TARGET_SECONDARY_RELOAD): Define.
	(pa_secondary_reload_class): Delete.
	(pa_secondary_reload): New function derived from SECONDARY_RELOAD_CLASS
	and pa_secondary_reload_class.  Reorder some checks.  Update inline
	copy of symbolic operand.
	* pa/pa.h (SECONDARY_RELOAD_CLASS): Delete.

Index: config/pa/predicates.md
===================================================================
--- config/pa/predicates.md	(revision 107694)
+++ config/pa/predicates.md	(working copy)
@@ -60,7 +60,8 @@
   return (memory_address_p (mode, op) && IS_INDEX_ADDR_P (op));
 })
 
-;; TODO: Add a comment.
+;; Return 1 iff OP is a symbolic operand.
+;; Note: an inline copy of this code is present in pa_secondary_reload.
 
 (define_predicate "symbolic_operand"
   (match_code "symbol_ref,label_ref,const")
Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md	(revision 107694)
+++ config/pa/pa.md	(working copy)
@@ -2255,9 +2255,24 @@
     DONE;
 }")
 
-;; Reloading an SImode or DImode value requires a scratch register if
-;; going in to or out of float point registers.
+;; Handle SImode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_insi_r1"
+  [(set (match_operand:SI 0 "register_operand" "=Z")
+	(match_operand:SI 1 "non_hard_reg_operand" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  ""
+  "
+{
+  if (emit_move_sequence (operands, SImode, operands[2]))
+    DONE;
 
+  /* We don't want the clobber emitted, so handle this ourselves.  */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+}")
+
+;; Handle SImode input reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_insi"
   [(set (match_operand:SI 0 "register_operand" "=Z")
 	(match_operand:SI 1 "non_hard_reg_operand" ""))
@@ -2273,6 +2288,8 @@
   DONE;
 }")
 
+;; Handle SImode output reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_outsi"
   [(set (match_operand:SI 0 "non_hard_reg_operand" "")
 	(match_operand:SI 1  "register_operand" "Z"))
@@ -3787,9 +3804,8 @@
     DONE;
 }")
 
-;; Reloading an SImode or DImode value requires a scratch register if
-;; going in to or out of float point registers.
-
+;; Handle DFmode input reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_indf"
   [(set (match_operand:DF 0 "register_operand" "=Z")
 	(match_operand:DF 1 "non_hard_reg_operand" ""))
@@ -3805,6 +3821,8 @@
   DONE;
 }")
 
+;; Handle DFmode output reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_outdf" 
  [(set (match_operand:DF 0 "non_hard_reg_operand" "")
 	(match_operand:DF 1  "register_operand" "Z"))
@@ -4044,6 +4062,24 @@
     DONE;
 }")
 
+;; Handle DImode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_indi_r1"
+  [(set (match_operand:DI 0 "register_operand" "=Z")
+	(match_operand:DI 1 "non_hard_reg_operand" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  ""
+  "
+{
+  if (emit_move_sequence (operands, DImode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves.  */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+}")
+
+;; Handle DImode input reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_indi"
   [(set (match_operand:DI 0 "register_operand" "=Z")
 	(match_operand:DI 1 "non_hard_reg_operand" ""))
@@ -4059,6 +4095,8 @@
   DONE;
 }")
 
+;; Handle DImode output reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_outdi"
   [(set (match_operand:DI 0 "non_hard_reg_operand" "")
 	(match_operand:DI 1 "register_operand" "Z"))
@@ -4306,9 +4344,8 @@
     DONE;
 }")
 
-;; Reloading an SImode or DImode value requires a scratch register if
-;; going in to or out of float point registers.
-
+;; Handle SFmode input reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_insf"
   [(set (match_operand:SF 0 "register_operand" "=Z")
 	(match_operand:SF 1 "non_hard_reg_operand" ""))
@@ -4324,6 +4361,8 @@
   DONE;
 }")
 
+;; Handle SFmode output reloads requiring a general register as a
+;; scratch register.
 (define_expand "reload_outsf"
   [(set (match_operand:SF 0 "non_hard_reg_operand" "")
 	(match_operand:SF 1  "register_operand" "Z"))
Index: config/pa/pa-protos.h
===================================================================
--- config/pa/pa-protos.h	(revision 107694)
+++ config/pa/pa-protos.h	(working copy)
@@ -106,8 +106,6 @@
 extern int emit_hpdiv_const (rtx *, int);
 extern int is_function_label_plus_const (rtx);
 extern int jump_in_call_delay (rtx);
-extern enum reg_class pa_secondary_reload_class (enum reg_class,
-						 enum machine_mode, rtx);
 extern int hppa_fpstore_bypass_p (rtx, rtx);
 extern int attr_length_millicode_call (rtx);
 extern int attr_length_call (rtx, int);
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 107694)
+++ config/pa/pa.c	(working copy)
@@ -150,6 +150,9 @@
 static int pa_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
 				 tree, bool);
 static struct machine_function * pa_init_machine_status (void);
+static enum reg_class pa_secondary_reload (bool, rtx, enum reg_class,
+					   enum machine_mode,
+					   secondary_reload_info *);
 
 
 /* Save the operands last given to a compare for use when we
@@ -299,6 +302,9 @@
 #undef TARGET_CANNOT_FORCE_CONST_MEM
 #define TARGET_CANNOT_FORCE_CONST_MEM pa_tls_referenced_p
 
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD pa_secondary_reload
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Parse the -mfixed-range= option string.  */
@@ -5565,101 +5571,108 @@
   fputc ('\n', asm_out_file);
 }
 
-/* Return the class of any secondary reload register that is needed to
-   move IN into a register in class CLASS using mode MODE.
+static enum reg_class
+pa_secondary_reload (bool in_p, rtx x, enum reg_class class,
+		     enum machine_mode mode, secondary_reload_info *sri)
+{
+  int is_symbolic;
+  int regno = -1;
 
-   Profiling has showed this routine and its descendants account for
-   a significant amount of compile time (~7%).  So it has been
-   optimized to reduce redundant computations and eliminate useless
-   function calls.
+  /* Handle the easy stuff first.  */
+  if (class == R1_REGS)
+    return NO_REGS;
 
-   It might be worthwhile to try and make this a leaf function too.  */
+  if (REG_P (x))
+    {
+      regno = REGNO (x);
+      if (class == BASE_REG_CLASS && regno < FIRST_PSEUDO_REGISTER)
+	return NO_REGS;
+    }
 
-enum reg_class
-pa_secondary_reload_class (enum reg_class class, enum machine_mode mode, rtx in)
-{
-  int regno, is_symbolic;
+  /* If we have something like (mem (mem (...)), we can safely assume the
+     inner MEM will end up in a general register after reloading, so there's
+     no need for a secondary reload.  */
+  if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == MEM)
+    return NO_REGS;
 
   /* Trying to load a constant into a FP register during PIC code
-     generation will require %r1 as a scratch register.  */
+     generation requires %r1 as a scratch register.  */
   if (flag_pic
       && GET_MODE_CLASS (mode) == MODE_INT
       && FP_REG_CLASS_P (class)
-      && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
-    return R1_REGS;
+      && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
+    {
+      gcc_assert (mode == SImode || mode == DImode);
+      sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
+		    : CODE_FOR_reload_indi_r1);
+      return NO_REGS;
+    }
 
   /* Profiling showed the PA port spends about 1.3% of its compilation
      time in true_regnum from calls inside pa_secondary_reload_class.  */
+  if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
+    regno = true_regnum (x);
 
-  if (GET_CODE (in) == REG)
-    {
-      regno = REGNO (in);
-      if (regno >= FIRST_PSEUDO_REGISTER)
-	regno = true_regnum (in);
-    }
-  else if (GET_CODE (in) == SUBREG)
-    regno = true_regnum (in);
-  else
-    regno = -1;
-
-  /* If we have something like (mem (mem (...)), we can safely assume the
-     inner MEM will end up in a general register after reloading, so there's
-     no need for a secondary reload.  */
-  if (GET_CODE (in) == MEM
-      && GET_CODE (XEXP (in, 0)) == MEM)
-    return NO_REGS;
-
   /* Handle out of range displacement for integer mode loads/stores of
      FP registers.  */
   if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
        && GET_MODE_CLASS (mode) == MODE_INT
        && FP_REG_CLASS_P (class))
       || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
-    return GENERAL_REGS;
+    {
+      sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
+      return NO_REGS;
+    }
 
   /* A SAR<->FP register copy requires a secondary register (GPR) as
      well as secondary memory.  */
   if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
       && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
-	  || (class == SHIFT_REGS && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
-    return GENERAL_REGS;
+	  || (class == SHIFT_REGS
+	      && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
+    {
+      sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
+      return NO_REGS;
+    }
 
-  if (GET_CODE (in) == HIGH)
-    in = XEXP (in, 0);
+  /* Secondary reloads of symbolic operands require %r1 as a scratch
+     register when we're generating PIC code and the operand isn't
+     readonly.  */
+  if (GET_CODE (x) == HIGH)
+    x = XEXP (x, 0);
 
   /* Profiling has showed GCC spends about 2.6% of its compilation
      time in symbolic_operand from calls inside pa_secondary_reload_class.
-
-     We use an inline copy and only compute its return value once to avoid
-     useless work.  */
-  switch (GET_CODE (in))
+     So, we use an inline copy to avoid useless work.  */
+  switch (GET_CODE (x))
     {
-      rtx tmp;
+      rtx op;
 
       case SYMBOL_REF:
+        is_symbolic = !SYMBOL_REF_TLS_MODEL (x);
+        break;
       case LABEL_REF:
         is_symbolic = 1;
         break;
       case CONST:
-	tmp = XEXP (in, 0);
-	is_symbolic = ((GET_CODE (XEXP (tmp, 0)) == SYMBOL_REF
-			|| GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
-		       && GET_CODE (XEXP (tmp, 1)) == CONST_INT);
+	op = XEXP (x, 0);
+	is_symbolic = (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+			 && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
+			|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
+		       && GET_CODE (XEXP (op, 1)) == CONST_INT);
         break;
-
       default:
         is_symbolic = 0;
         break;
     }
 
-  if (!flag_pic
-      && is_symbolic
-      && read_only_operand (in, VOIDmode))
-    return NO_REGS;
+  if (is_symbolic && (flag_pic || !read_only_operand (x, VOIDmode)))
+    {
+      gcc_assert (mode == SImode || mode == DImode);
+      sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
+		    : CODE_FOR_reload_indi_r1);
+    }
 
-  if (class != R1_REGS && is_symbolic)
-    return R1_REGS;
-
   return NO_REGS;
 }
 
Index: config/pa/pa.h
===================================================================
--- config/pa/pa.h	(revision 107694)
+++ config/pa/pa.h	(working copy)
@@ -527,16 +527,6 @@
    in some cases it is preferable to use a more restrictive class.  */
 #define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
 
-/* Return the register class of a scratch register needed to copy
-   IN into a register in CLASS in MODE, or a register in CLASS in MODE
-   to IN.  If it can be done directly NO_REGS is returned. 
-
-  Avoid doing any work for the common case calls.  */
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
-  ((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG		\
-    && REGNO (IN) < FIRST_PSEUDO_REGISTER)			\
-   ? NO_REGS : pa_secondary_reload_class (CLASS, MODE, IN))
-
 #define MAYBE_FP_REG_CLASS_P(CLASS) \
   reg_classes_intersect_p ((CLASS), FP_REGS)
 


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