egcs 1.1 sparc pic tablejump fix

Richard Henderson rth@cygnus.com
Mon Jan 11 20:48:00 GMT 1999


This is a backport of some egcs 1.2 code to fix an ICE
reported against egcs 1.1 -O2 -fpic on sparc.


r~



Mon Jan 11 20:23:34 1999  Richard Henderson  <rth@cygnus.com>

	* sparc.c (legitimize_pic_address): Treat labels like symbols.
	(emit_move_sequence): Likewise.
	* sparc.h (PRINT_OPERAND_ADDRESS): Likewise.
	(ASM_OUTPUT_ADDR_VEC_ELT): Don't special case CM_MEDLOW.
	(ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.  Don't reference magic `1b'.
	* sparc.md (move_pic_label_si): Kill.
	(move_label_di): Kill.
	(pic_tablejump_32, pic_tablejump_64): Kill.
	(tablejump): Expose pic arithmetic to the compiler.
	
Index: gcc/config/sparc/sparc.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/sparc/sparc.c,v
retrieving revision 1.33
diff -c -p -d -r1.33 sparc.c
*** sparc.c	1998/07/14 00:18:55	1.33
--- sparc.c	1999/01/12 04:20:40
*************** legitimize_pic_address (orig, mode, reg)
*** 1449,1455 ****
       enum machine_mode mode ATTRIBUTE_UNUSED;
       rtx reg;
  {
!   if (GET_CODE (orig) == SYMBOL_REF)
      {
        rtx pic_ref, address;
        rtx insn;
--- 1449,1456 ----
       enum machine_mode mode ATTRIBUTE_UNUSED;
       rtx reg;
  {
!   if (GET_CODE (orig) == SYMBOL_REF
!       || GET_CODE (orig) == LABEL_REF)
      {
        rtx pic_ref, address;
        rtx insn;
*************** legitimize_pic_address (orig, mode, reg)
*** 1531,1539 ****
  	}
        return gen_rtx_PLUS (Pmode, base, offset);
      }
-   else if (GET_CODE (orig) == LABEL_REF)
-     /* ??? Why do we do this?  */
-     current_function_uses_pic_offset_table = 1;
  
    return orig;
  }
--- 1532,1537 ----
*************** emit_move_sequence (operands, mode)
*** 1670,1695 ****
  	}
      }
  
-   if (GET_CODE (operand1) == LABEL_REF
-       && mode == SImode && flag_pic)
-     {
-       if (TARGET_ARCH64)
- 	abort ();
-       emit_insn (gen_move_pic_label_si (operand0, operand1));
-       return 1;
-     }
-   /* Non-pic LABEL_REF's in sparc64 are expensive to do the normal way,
-      so always use special code.  */
-   else if (GET_CODE (operand1) == LABEL_REF
- 	   && mode == DImode)
-     {
-       if (! TARGET_ARCH64)
- 	abort ();
-       emit_insn (gen_move_label_di (operand0, operand1));
-       return 1;
-     }
    /* DImode HIGH values in sparc64 need a clobber added.  */
!   else if (TARGET_ARCH64
        && GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode)
      {
        emit_insn (gen_sethi_di_sp64 (operand0, XEXP (operand1, 0)));
--- 1668,1675 ----
  	}
      }
  
    /* DImode HIGH values in sparc64 need a clobber added.  */
!   if (TARGET_ARCH64
        && GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode)
      {
        emit_insn (gen_sethi_di_sp64 (operand0, XEXP (operand1, 0)));
Index: gcc/config/sparc/sparc.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/sparc/sparc.h,v
retrieving revision 1.32.2.1
diff -c -p -d -r1.32.2.1 sparc.h
*** sparc.h	1998/08/29 21:14:49	1.32.2.1
--- sparc.h	1999/01/12 04:20:40
*************** do {									\
*** 2933,2944 ****
    ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);			\
    if (Pmode == SImode)							\
      fprintf (FILE, "\t.word\t");					\
-   else if (TARGET_CM_MEDLOW)						\
-     fprintf (FILE, "\t.word\t0\n\t.word\t");				\
    else									\
      fprintf (FILE, "\t.xword\t");					\
    assemble_name (FILE, label);						\
!   fprintf (FILE, "\n");							\
  } while (0)
  
  /* This is how to output an element of a case-vector that is relative.
--- 2933,2942 ----
    ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);			\
    if (Pmode == SImode)							\
      fprintf (FILE, "\t.word\t");					\
    else									\
      fprintf (FILE, "\t.xword\t");					\
    assemble_name (FILE, label);						\
!   fputc ('\n', FILE);							\
  } while (0)
  
  /* This is how to output an element of a case-vector that is relative.
*************** do {									\
*** 2950,2961 ****
    ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);			\
    if (Pmode == SImode)							\
      fprintf (FILE, "\t.word\t");					\
-   else if (TARGET_CM_MEDLOW)						\
-     fprintf (FILE, "\t.word\t0\n\t.word\t");				\
    else									\
      fprintf (FILE, "\t.xword\t");					\
    assemble_name (FILE, label);						\
!   fprintf (FILE, "-1b\n");						\
  } while (0)
  
  /* This is how to output an assembler line
--- 2948,2960 ----
    ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);			\
    if (Pmode == SImode)							\
      fprintf (FILE, "\t.word\t");					\
    else									\
      fprintf (FILE, "\t.xword\t");					\
    assemble_name (FILE, label);						\
!   ASM_GENERATE_INTERNAL_LABEL (label, "L", (REL));			\
!   fputc ('-', FILE);							\
!   assemble_name (FILE, label);						\
!   fputc ('\n', FILE);							\
  } while (0)
  
  /* This is how to output an assembler line
*************** do {									\
*** 3106,3111 ****
--- 3105,3111 ----
        else if (GET_CODE (index) == REG)				\
  	fprintf (FILE, "+%s", reg_names[REGNO (index)]);	\
        else if (GET_CODE (index) == SYMBOL_REF			\
+ 	       || GET_CODE (index) == LABEL_REF			\
  	       || GET_CODE (index) == CONST)			\
  	fputc ('+', FILE), output_addr_const (FILE, index);	\
        else abort ();						\
Index: gcc/config/sparc/sparc.md
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/sparc/sparc.md,v
retrieving revision 1.30.2.1
diff -c -p -d -r1.30.2.1 sparc.md
*** sparc.md	1998/08/29 21:14:50	1.30.2.1
--- sparc.md	1999/01/12 04:20:40
***************
*** 1727,1787 ****
    "rd %%pc,%0"
    [(set_attr "type" "move")])
  
- ;; Special pic pattern, for loading the address of a label into a register.
- ;; It clobbers o7 because the call puts the return address (i.e. pc value)
- ;; there.  The pic tablejump pattern also uses this.
- 
- (define_insn "move_pic_label_si"
-   [(set (match_operand:SI 0 "register_operand" "=r")
- 	; This was previously (label_ref:SI (match_operand 1 "" "")) but that
- 	; loses the volatil and other flags of the original label_ref.
- 	(match_operand:SI 1 "label_ref_operand" ""))
-    (set (reg:SI 15) (pc))]
-   "flag_pic"
-   "*
- {
-   if (get_attr_length (insn) == 2)
-     return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\";
-   else
-     return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\";
- }"
-   [(set_attr "type" "multi")
-    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
-    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
- 					   (const_int 960))
- 				      (const_int 2)
- 				      (const_int 4)))])
- 
- ;; Special sparc64 pattern for loading the address of a label into a register.
- ;; The pic and non-pic cases are the same since it's the most efficient way.
- ;;
- ;; ??? The non-pic case doesn't need to use %o7, we could use a scratch
- ;; instead.  But the pic case doesn't need to use %o7 either.  We handle them
- ;; both here so that when this is fixed, they can both be fixed together.
- ;; Don't forget that the pic jump table stuff uses %o7 (that will need to be
- ;; changed too).
- 
- (define_insn "move_label_di"
-   [(set (match_operand:DI 0 "register_operand" "=r")
- 	; This was previously (label_ref:DI (match_operand 1 "" "")) but that
- 	; loses the volatil and other flags of the original label_ref.
- 	(match_operand:DI 1 "label_ref_operand" ""))
-    (set (reg:DI 15) (pc))]
-   "TARGET_ARCH64"
-   "*
- {
-   if (get_attr_length (insn) == 2)
-     return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\";
-   else
-     return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\";
- }"
-   [(set_attr "type" "multi")
-    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
-    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
- 					   (const_int 960))
- 				      (const_int 2)
- 				      (const_int 5)))])
- 
  (define_insn "*sethi_hi"
    [(set (match_operand:HI 0 "register_operand" "=r")
  	(high:HI (match_operand 1 "" "")))]
--- 1727,1732 ----
*************** if (! TARGET_ARCH64)
*** 5604,5636 ****
    if (GET_MODE (operands[0]) != Pmode)
      abort ();
  
!   /* We need to use the PC value in %o7 that was set up when the address
!      of the label was loaded into a register, so we need different RTL.  */
    if (flag_pic)
      {
!       if (!TARGET_PTR64)
! 	emit_jump_insn (gen_pic_tablejump_32 (operands[0], operands[1]));
!       else
! 	emit_jump_insn (gen_pic_tablejump_64 (operands[0], operands[1]));
!       DONE;
      }
  }")
- 
- (define_insn "pic_tablejump_32"
-   [(set (pc) (match_operand:SI 0 "register_operand" "r"))
-    (use (label_ref (match_operand 1 "" "")))
-    (use (reg:SI 15))]
-   "! TARGET_PTR64"
-   "jmp %%o7+%0%#"
-   [(set_attr "type" "uncond_branch")])
- 
- (define_insn "pic_tablejump_64"
-   [(set (pc) (match_operand:DI 0 "register_operand" "r"))
-    (use (label_ref (match_operand 1 "" "")))
-    (use (reg:DI 15))]
-   "TARGET_PTR64"
-   "jmp %%o7+%0%#"
-   [(set_attr "type" "uncond_branch")])
  
  (define_insn "*tablejump_sp32"
    [(set (pc) (match_operand:SI 0 "address_operand" "p"))
--- 5549,5566 ----
    if (GET_MODE (operands[0]) != Pmode)
      abort ();
  
!   /* In pic mode, our address differences are against the base of the
!      table.  Add that base value back in; CSE ought to be able to combine
!      the two address loads.  */
    if (flag_pic)
      {
!       rtx tmp, tmp2;
!       tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
!       tmp2 = operands[0];
!       tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
!       operands[0] = memory_address (Pmode, tmp);
      }
  }")
  
  (define_insn "*tablejump_sp32"
    [(set (pc) (match_operand:SI 0 "address_operand" "p"))



More information about the Gcc-patches mailing list