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]

RFA: Make ARM use UNSPECs instead of complicated CONSTs


This patch makes the arm port use UNSPECs instead of things like
(const (minus ...)).  It's part of my ongoing quest to enforce
a grammar for CONSTs.  See:

    http://gcc.gnu.org/ml/gcc-patches/2008-10/msg00339.html

for details.

There are two types of CONST that don't fit the proposed grammar.
One is the:

    (plus (match_operand ...)
          (const (plus (pc) (const_int ...))))

idiom used in UNSPEC_PIC_BASE.  We could avoid this by refactoring
the expression without the CONST, but since the PLUS, CONST and PC
parts are purely decorative, it seemed easier to list only the
non-PC parts of the sum:

    (match_operand ...)
    (const_int ...)

(Judging by the comments, it looks like the current form harks
back to the days before an UNSPEC wrapper was needed.  The wrapper
was added to stop the generic code from refactoring the expression,
which is a similar problem to the one I'm trying to fix.)

The other type of CONST are the:

    (const (minus (symbol_ref "_GLOBAL_OFFSET_TABLE_")
                  (const (plus (pc) (const_int ...)))))

and:

    (const (minus (const (plus (symbol_ref "_GLOBAL_OFFSET_TABLE_") (pc)))
                  (const (plus (pc) (const_int ...)))))

expressions used to set up the PIC register.  As with SH, these nested
consts appear to be there to enforce a particular bracketing, but I
don't think that behaviour is documented or guaranteed.  The patch
avoids this by adding a new unspec.

It looks like the UNSPEC_PIC_BASE documentation and associated
peephole2 are out of date; I tried to fix that at the same time.

Tested by comparing the before and after assembly output for
gcc.c-torture, gcc.dg and g++.dg on arm-linux-gnu, using the
options:

  {-O0,-O2} x {-fpic} x {-mno-thumb,-mthumb,-march=armv6t2/-mthumb}

There were no differences.  OK to install?

Richard


gcc/
	* config/arm/arm.md (UNSPEC_PIC_BASE): Update documentation.
	(UNSPEC_GOTSYM_OFF): New unspec.
	(pic_add_dot_plus_four): Simplify the UNSPEC_PIC_BASE operands.
	(pic_add_dot_plus_eight): Likewise.
	(tls_load_dot_plus_eight): Likewise.  Update peephole2.
	* config/arm/thumb2.md (pic_load_dot_plus_four): Simplify the
	UNSPEC_PIC_BASE operands.
	* config/arm/arm.c (arm_load_pic_register): Use UNSPEC_GOTSYM_OFF.
	(arm_output_addr_const_extra): Handle it.

Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md	2008-10-10 11:15:30.000000000 +0100
+++ gcc/config/arm/arm.md	2008-10-10 11:15:33.000000000 +0100
@@ -67,10 +67,9 @@ (define_constants
    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
 			;   usage, that is, we will add the pic_register
 			;   value to it before trying to dereference it.
-   (UNSPEC_PIC_BASE  4)	; Adding the PC value to the offset to the
-			;   GLOBAL_OFFSET_TABLE.  The operation is fully
-			;   described by the RTL but must be wrapped to
-			;   prevent combine from trying to rip it apart.
+   (UNSPEC_PIC_BASE  4)	; Add PC and all but the last operand together,
+			;   The last operand is the number of a PIC_LABEL
+			;   that points at the containing instruction.
    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
 			;   being scheduled before the stack adjustment insn.
    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
@@ -98,6 +97,8 @@ (define_constants
 			   ; generate correct unwind information.
    (UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
 			  ; correctly for PIC usage.
+   (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
+			  ; a given symbolic address.
   ]
 )
 
@@ -5033,8 +5034,8 @@ (define_insn "pic_load_addr_thumb1"
 
 (define_insn "pic_add_dot_plus_four"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
-			     (const (plus:SI (pc) (const_int 4))))
+	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
+		    (const_int 4)
 		    (match_operand 2 "" "")]
 		   UNSPEC_PIC_BASE))]
   "TARGET_THUMB1"
@@ -5048,8 +5049,8 @@ (define_insn "pic_add_dot_plus_four"
 
 (define_insn "pic_add_dot_plus_eight"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
-			     (const (plus:SI (pc) (const_int 8))))
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+		    (const_int 8)
 		    (match_operand 2 "" "")]
 		   UNSPEC_PIC_BASE))]
   "TARGET_ARM"
@@ -5063,8 +5064,8 @@ (define_insn "pic_add_dot_plus_eight"
 
 (define_insn "tls_load_dot_plus_eight"
   [(set (match_operand:SI 0 "register_operand" "+r")
-	(mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
-				     (const (plus:SI (pc) (const_int 8))))
+	(mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+			    (const_int 8)
 			    (match_operand 2 "" "")]
 			   UNSPEC_PIC_BASE)))]
   "TARGET_ARM"
@@ -5081,18 +5082,18 @@ (define_insn "tls_load_dot_plus_eight"
 ;; tls_load_dot_plus_eight by a peephole.
 
 (define_peephole2
-  [(parallel [(set (match_operand:SI 0 "register_operand" "")
-		   (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
-			     	 	(const (plus:SI (pc) (const_int 8))))]
-			      UNSPEC_PIC_BASE))
-   	      (use (label_ref (match_operand 1 "" "")))])
+  [(set (match_operand:SI 0 "register_operand" "")
+	(unspec:SI [(match_operand:SI 3 "register_operand" "")
+		    (const_int 8)
+		    (match_operand 1 "" "")]
+		   UNSPEC_PIC_BASE))
    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
-  [(parallel [(set (match_dup 2)
-		   (mem:SI (unspec:SI [(plus:SI (match_dup 3)
-						(const (plus:SI (pc) (const_int 8))))]
-				      UNSPEC_PIC_BASE)))
-   	      (use (label_ref (match_dup 1)))])]
+  [(set (match_dup 2)
+	(mem:SI (unspec:SI [(match_dup 3)
+			    (const_int 8)
+			    (match_dup 1)]
+			   UNSPEC_PIC_BASE)))]
   ""
 )
 
Index: gcc/config/arm/thumb2.md
===================================================================
--- gcc/config/arm/thumb2.md	2008-10-10 11:15:30.000000000 +0100
+++ gcc/config/arm/thumb2.md	2008-10-10 11:15:33.000000000 +0100
@@ -259,8 +259,8 @@ (define_insn "pic_load_addr_thumb2"
 ;; word aligned.
 (define_insn "pic_load_dot_plus_four"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(unspec:SI [(const (plus:SI (pc) (const_int 4)))
-		    (use (match_operand 1 "" ""))]
+	(unspec:SI [(const_int 4)
+		    (match_operand 1 "" "")]
 		   UNSPEC_PIC_BASE))]
   "TARGET_THUMB2"
   "*
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2008-10-10 11:15:30.000000000 +0100
+++ gcc/config/arm/arm.c	2008-10-10 11:15:33.000000000 +0100
@@ -3659,8 +3659,7 @@ static GTY(()) int pic_labelno;
 void
 arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
 {
-  rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx, pic_reg;
-  rtx global_offset_table;
+  rtx l1, labelno, pic_tmp, pic_rtx, pic_reg;
 
   if (crtl->uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
     return;
@@ -3688,20 +3687,11 @@ arm_load_pic_register (unsigned long sav
       l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
       l1 = gen_rtx_CONST (VOIDmode, l1);
 
-      global_offset_table
-	= gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
       /* On the ARM the PC register contains 'dot + 8' at the time of the
 	 addition, on the Thumb it is 'dot + 4'.  */
-      pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
-      if (GOT_PCREL)
-	{
-	  pic_tmp2 = gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx);
-	  pic_tmp2 = gen_rtx_CONST (VOIDmode, pic_tmp2);
-	}
-      else
-	pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
-
-      pic_rtx = gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp);
+      pic_rtx = plus_constant (l1, TARGET_ARM ? 8 : 4);
+      pic_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pic_rtx),
+				UNSPEC_GOTSYM_OFF);
       pic_rtx = gen_rtx_CONST (Pmode, pic_rtx);
 
       if (TARGET_ARM)
@@ -18996,6 +18986,16 @@ arm_output_addr_const_extra (FILE *fp, r
 
       return TRUE;
     }
+  else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_GOTSYM_OFF)
+    {
+      assemble_name (fp, "_GLOBAL_OFFSET_TABLE_");
+      if (GOT_PCREL)
+	fputs ("+.", fp);
+      fputs ("-(", fp);
+      output_addr_const (fp, XVECEXP (x, 0, 0));
+      fputc (')', fp);
+      return TRUE;
+    }
   else if (GET_CODE (x) == CONST_VECTOR)
     return arm_emit_vector_const (fp, x);
 


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