[3.4-BIB] updated patch for x86_64 PIC

Jan Hubicka jh@suse.cz
Mon Nov 11 14:37:00 GMT 2002


Hi,
this is updated patch I sent some time ago with some changes suggested
by Jakub.  It's purpose is to make the whole code more consistent so it
will be easier to understand I hope and it produces better code in some
side cases.

Honza

Tue Oct 29 23:41:46 CET 2002  Jan Hubicka  <jh@suse.cz>

	* i386-protos.h (x86_64_sign_extended_value): Fix prototype.
	* i386.c (x86_64_general_operand, x86_64_szext_general_operand,
	x86_64_nonmemory_operand, x86_64_movabs_operand, 
	x86_64_szext_nonmemory_operand, x86_64_immediate_operand,
	ix86_expand_int_movcc): Update call of x86_64_sign_extended_value.
	(local_symbolic_operand): Do not care the 64bit limits.
	(x86_64_sign_extended_value): Remove allow_rip support.
	(legitimate_pic_address_disp_p): Handle all cases allowed
	with RIP addressing.
	(legitimate_address_p): Use legitimate_pic_address_disp_p for PIC.
	(legitimize_pic_address): Reorganize.
	* i386.h (EXTRA_CONSTRAINT): Update call of x86_64_sign_extended_value.
Index: i386-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386-protos.h,v
retrieving revision 1.77.4.5
diff -c -3 -p -r1.77.4.5 i386-protos.h
*** i386-protos.h	29 Oct 2002 19:49:58 -0000	1.77.4.5
--- i386-protos.h	11 Nov 2002 22:31:09 -0000
*************** extern int ix86_attr_length_address_defa
*** 154,160 ****
  
  extern enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code));
  
! extern int x86_64_sign_extended_value PARAMS ((rtx, int));
  extern int x86_64_zero_extended_value PARAMS ((rtx));
  extern rtx ix86_libcall_value PARAMS ((enum machine_mode));
  extern bool ix86_function_value_regno_p PARAMS ((int));
--- 154,160 ----
  
  extern enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code));
  
! extern int x86_64_sign_extended_value PARAMS ((rtx));
  extern int x86_64_zero_extended_value PARAMS ((rtx));
  extern rtx ix86_libcall_value PARAMS ((enum machine_mode));
  extern bool ix86_function_value_regno_p PARAMS ((int));
Index: i386.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.447.2.23
diff -c -3 -p -r1.447.2.23 i386.c
*** i386.c	8 Nov 2002 23:14:28 -0000	1.447.2.23
--- i386.c	11 Nov 2002 22:31:17 -0000
*************** x86_64_general_operand (op, mode)
*** 2968,2974 ****
      return general_operand (op, mode);
    if (nonimmediate_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op, 1);
  }
  
  /* Return nonzero if OP is general operand representable on x86_64
--- 2968,2974 ----
      return general_operand (op, mode);
    if (nonimmediate_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op);
  }
  
  /* Return nonzero if OP is general operand representable on x86_64
*************** x86_64_szext_general_operand (op, mode)
*** 2983,2989 ****
      return general_operand (op, mode);
    if (nonimmediate_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op, 1) || x86_64_zero_extended_value (op);
  }
  
  /* Return nonzero if OP is nonmemory operand representable on x86_64.  */
--- 2983,2989 ----
      return general_operand (op, mode);
    if (nonimmediate_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op);
  }
  
  /* Return nonzero if OP is nonmemory operand representable on x86_64.  */
*************** x86_64_nonmemory_operand (op, mode)
*** 2997,3003 ****
      return nonmemory_operand (op, mode);
    if (register_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op, 1);
  }
  
  /* Return nonzero if OP is nonmemory operand acceptable by movabs patterns.  */
--- 2997,3003 ----
      return nonmemory_operand (op, mode);
    if (register_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op);
  }
  
  /* Return nonzero if OP is nonmemory operand acceptable by movabs patterns.  */
*************** x86_64_movabs_operand (op, mode)
*** 3009,3015 ****
  {
    if (!TARGET_64BIT || !flag_pic)
      return nonmemory_operand (op, mode);
!   if (register_operand (op, mode) || x86_64_sign_extended_value (op, 0))
      return 1;
    if (CONSTANT_P (op) && !symbolic_reference_mentioned_p (op))
      return 1;
--- 3009,3015 ----
  {
    if (!TARGET_64BIT || !flag_pic)
      return nonmemory_operand (op, mode);
!   if (register_operand (op, mode) || x86_64_sign_extended_value (op))
      return 1;
    if (CONSTANT_P (op) && !symbolic_reference_mentioned_p (op))
      return 1;
*************** x86_64_szext_nonmemory_operand (op, mode
*** 3027,3033 ****
      return nonmemory_operand (op, mode);
    if (register_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op, 0) || x86_64_zero_extended_value (op);
  }
  
  /* Return nonzero if OP is immediate operand representable on x86_64.  */
--- 3027,3033 ----
      return nonmemory_operand (op, mode);
    if (register_operand (op, mode))
      return 1;
!   return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op);
  }
  
  /* Return nonzero if OP is immediate operand representable on x86_64.  */
*************** x86_64_immediate_operand (op, mode)
*** 3039,3045 ****
  {
    if (!TARGET_64BIT)
      return immediate_operand (op, mode);
!   return x86_64_sign_extended_value (op, 0);
  }
  
  /* Return nonzero if OP is immediate operand representable on x86_64.  */
--- 3039,3045 ----
  {
    if (!TARGET_64BIT)
      return immediate_operand (op, mode);
!   return x86_64_sign_extended_value (op);
  }
  
  /* Return nonzero if OP is immediate operand representable on x86_64.  */
*************** local_symbolic_operand (op, mode)
*** 3159,3168 ****
  {
    if (GET_CODE (op) == CONST
        && GET_CODE (XEXP (op, 0)) == PLUS
!       && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
!       && (ix86_cmodel != CM_SMALL_PIC
! 	  || (INTVAL (XEXP (XEXP (op, 0), 1)) >= -16*1024*1024
! 	      && INTVAL (XEXP (XEXP (op, 0), 1)) < 16*1024*1024)))
      op = XEXP (XEXP (op, 0), 0);
  
    if (GET_CODE (op) == LABEL_REF)
--- 3159,3165 ----
  {
    if (GET_CODE (op) == CONST
        && GET_CODE (XEXP (op, 0)) == PLUS
!       && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
      op = XEXP (XEXP (op, 0), 0);
  
    if (GET_CODE (op) == LABEL_REF)
*************** ix86_can_use_return_insn_p ()
*** 3964,3972 ****
  
  /* Return 1 if VALUE can be stored in the sign extended immediate field.  */
  int
! x86_64_sign_extended_value (value, allow_rip)
       rtx value;
-      int allow_rip;
  {
    switch (GET_CODE (value))
      {
--- 3961,3968 ----
  
  /* Return 1 if VALUE can be stored in the sign extended immediate field.  */
  int
! x86_64_sign_extended_value (value)
       rtx value;
  {
    switch (GET_CODE (value))
      {
*************** x86_64_sign_extended_value (value, allow
*** 3988,4004 ****
  	 library.  Don't count TLS SYMBOL_REFs here, since they should fit
  	 only if inside of UNSPEC handled below.  */
        case SYMBOL_REF:
! 	return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
! 		|| (allow_rip
! 		    && ix86_cmodel == CM_SMALL_PIC
! 		    && (CONSTANT_POOL_ADDRESS_P (value)
! 			|| SYMBOL_REF_FLAG (value))
! 		    && ! tls_symbolic_operand (value, GET_MODE (value))));
  
        /* For certain code models, the code is near as well.  */
        case LABEL_REF:
! 	return ix86_cmodel != CM_LARGE
! 	       && (allow_rip || ix86_cmodel != CM_SMALL_PIC);
  
        /* We also may accept the offsetted memory references in certain special
           cases.  */
--- 3984,3995 ----
  	 library.  Don't count TLS SYMBOL_REFs here, since they should fit
  	 only if inside of UNSPEC handled below.  */
        case SYMBOL_REF:
! 	return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL);
  
        /* For certain code models, the code is near as well.  */
        case LABEL_REF:
! 	return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM
! 		|| ix86_cmodel == CM_KERNEL);
  
        /* We also may accept the offsetted memory references in certain special
           cases.  */
*************** x86_64_sign_extended_value (value, allow
*** 4044,4069 ****
  		      && offset > 0
  		      && trunc_int_for_mode (offset, SImode) == offset)
  		    return 1;
- 		  /* For CM_SMALL_PIC, we can make similar assumptions
- 		     as for CM_SMALL model, if we know the symbol is local
- 		     to the shared library.  Disallow any TLS symbols,
- 		     since they should always be enclosed in an UNSPEC.  */
- 		  if (ix86_cmodel == CM_SMALL_PIC
- 		      && allow_rip
- 		      && (CONSTANT_POOL_ADDRESS_P (op1)
- 			  || SYMBOL_REF_FLAG (op1))
- 		      && ! tls_symbolic_operand (op1, GET_MODE (op1))
- 		      && offset < 16*1024*1024
- 		      && offset >= -16*1024*1024
- 		      && trunc_int_for_mode (offset, SImode) == offset)
- 		    return 1;
  		  break;
  		case LABEL_REF:
  		  /* These conditions are similar to SYMBOL_REF ones, just the
  		     constraints for code models differ.  */
! 		  if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM
! 		       || (ix86_cmodel == CM_SMALL_PIC && allow_rip
! 			   && offset >= -16*1024*1024))
  		      && offset < 16*1024*1024
  		      && trunc_int_for_mode (offset, SImode) == offset)
  		    return 1;
--- 4035,4045 ----
  		      && offset > 0
  		      && trunc_int_for_mode (offset, SImode) == offset)
  		    return 1;
  		  break;
  		case LABEL_REF:
  		  /* These conditions are similar to SYMBOL_REF ones, just the
  		     constraints for code models differ.  */
! 		  if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
  		      && offset < 16*1024*1024
  		      && trunc_int_for_mode (offset, SImode) == offset)
  		    return 1;
*************** legitimate_pic_address_disp_p (disp)
*** 5273,5280 ****
  
    /* In 64bit mode we can allow direct addresses of symbols and labels
       when they are not dynamic symbols.  */
!   if (TARGET_64BIT && local_symbolic_operand (disp, Pmode))
!     return 1;
    if (GET_CODE (disp) != CONST)
      return 0;
    disp = XEXP (disp, 0);
--- 5249,5278 ----
  
    /* In 64bit mode we can allow direct addresses of symbols and labels
       when they are not dynamic symbols.  */
!   if (TARGET_64BIT)
!     {
!       /* TLS references should always be enclosed in UNSPEC.  */
!       if (tls_symbolic_operand (disp, GET_MODE (disp)))
! 	return 0;
!       if (GET_CODE (disp) == SYMBOL_REF
! 	  && ix86_cmodel == CM_SMALL_PIC
! 	  && (CONSTANT_POOL_ADDRESS_P (disp)
! 	      || SYMBOL_REF_FLAG (disp)))
! 	return 1;
!       if (GET_CODE (disp) == LABEL_REF)
! 	return 1;
!       if (GET_CODE (disp) == CONST
! 	  && GET_CODE (XEXP (disp, 0)) == PLUS
! 	  && ((GET_CODE (XEXP (XEXP (disp, 0), 0)) == SYMBOL_REF
! 	       && ix86_cmodel == CM_SMALL_PIC
! 	       && (CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (disp, 0), 0))
! 		   || SYMBOL_REF_FLAG (XEXP (XEXP (disp, 0), 0))))
! 	      || GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF)
! 	  && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT
! 	  && INTVAL (XEXP (XEXP (disp, 0), 1)) < 16*1024*1024
! 	  && INTVAL (XEXP (XEXP (disp, 0), 1)) >= -16*1024*1024)
! 	return 1;
!     }
    if (GET_CODE (disp) != CONST)
      return 0;
    disp = XEXP (disp, 0);
*************** legitimate_address_p (mode, addr, strict
*** 5481,5503 ****
      {
        reason_rtx = disp;
  
-       if (TARGET_64BIT)
- 	{
- 	  if (!x86_64_sign_extended_value (disp, !(index || base)))
- 	    {
- 	      reason = "displacement is out of range";
- 	      goto report_error;
- 	    }
- 	}
-       else
- 	{
- 	  if (GET_CODE (disp) == CONST_DOUBLE)
- 	    {
- 	      reason = "displacement is a const_double";
- 	      goto report_error;
- 	    }
- 	}
- 
        if (GET_CODE (disp) == CONST
  	  && GET_CODE (XEXP (disp, 0)) == UNSPEC)
  	switch (XINT (XEXP (disp, 0), 1))
--- 5479,5484 ----
*************** legitimate_address_p (mode, addr, strict
*** 5575,5580 ****
--- 5556,5571 ----
  	  reason = "displacement is not constant";
  	  goto report_error;
  	}
+       else if (TARGET_64BIT && !x86_64_sign_extended_value (disp))
+ 	{
+ 	  reason = "displacement is out of range";
+ 	  goto report_error;
+ 	}
+       else if (!TARGET_64BIT && GET_CODE (disp) == CONST_DOUBLE)
+ 	{
+ 	  reason = "displacement is a const_double";
+ 	  goto report_error;
+ 	}
      }
  
    /* Everything looks valid.  */
*************** legitimize_pic_address (orig, reg)
*** 5636,5663 ****
    return machopic_legitimize_pic_address (orig, GET_MODE (orig), reg);
  #endif
  
!   if (local_symbolic_operand (addr, Pmode))
!     {
!       /* In 64bit mode we can address such objects directly.  */
!       if (TARGET_64BIT)
! 	new = addr;
!       else
! 	{
! 	  /* This symbol may be referenced via a displacement from the PIC
! 	     base address (@GOTOFF).  */
! 
! 	  if (reload_in_progress)
! 	    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
! 	  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
! 	  new = gen_rtx_CONST (Pmode, new);
! 	  new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
  
! 	  if (reg != 0)
! 	    {
! 	      emit_move_insn (reg, new);
! 	      new = reg;
! 	    }
!       	}
      }
    else if (GET_CODE (addr) == SYMBOL_REF)
      {
--- 5627,5650 ----
    return machopic_legitimize_pic_address (orig, GET_MODE (orig), reg);
  #endif
  
!   if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
!     new = addr;
!   else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
!     {
!       /* This symbol may be referenced via a displacement from the PIC
! 	 base address (@GOTOFF).  */
! 
!       if (reload_in_progress)
! 	regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
!       new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
!       new = gen_rtx_CONST (Pmode, new);
!       new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
  
!       if (reg != 0)
! 	{
! 	  emit_move_insn (reg, new);
! 	  new = reg;
! 	}
      }
    else if (GET_CODE (addr) == SYMBOL_REF)
      {
*************** ix86_expand_int_movcc (operands)
*** 9343,9349 ****
  
        if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
  	   || diff == 3 || diff == 5 || diff == 9)
! 	  && (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf), 0)))
  	{
  	  /*
  	   * xorl dest,dest
--- 9330,9336 ----
  
        if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
  	   || diff == 3 || diff == 5 || diff == 9)
! 	  && (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf))))
  	{
  	  /*
  	   * xorl dest,dest
Index: i386.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.h,v
retrieving revision 1.280.4.16
diff -c -3 -p -r1.280.4.16 i386.h
*** i386.h	7 Nov 2002 01:18:00 -0000	1.280.4.16
--- i386.h	11 Nov 2002 22:31:20 -0000
*************** enum reg_class
*** 1442,1448 ****
     constraint, the value returned should be 0 regardless of VALUE.  */
  
  #define EXTRA_CONSTRAINT(VALUE, D)				\
!   ((D) == 'e' ? x86_64_sign_extended_value (VALUE, 0)		\
     : (D) == 'Z' ? x86_64_zero_extended_value (VALUE)		\
     : (D) == 'C' ? standard_sse_constant_p (VALUE)		\
     : 0)
--- 1442,1448 ----
     constraint, the value returned should be 0 regardless of VALUE.  */
  
  #define EXTRA_CONSTRAINT(VALUE, D)				\
!   ((D) == 'e' ? x86_64_sign_extended_value (VALUE)		\
     : (D) == 'Z' ? x86_64_zero_extended_value (VALUE)		\
     : (D) == 'C' ? standard_sse_constant_p (VALUE)		\
     : 0)
*************** do {							\
*** 2565,2571 ****
    case CONST:							\
    case LABEL_REF:						\
    case SYMBOL_REF:						\
!     if (TARGET_64BIT && !x86_64_sign_extended_value (RTX, 0))	\
        return 3;							\
      if (TARGET_64BIT && !x86_64_zero_extended_value (RTX))	\
        return 2;							\
--- 2565,2571 ----
    case CONST:							\
    case LABEL_REF:						\
    case SYMBOL_REF:						\
!     if (TARGET_64BIT && !x86_64_sign_extended_value (RTX))	\
        return 3;							\
      if (TARGET_64BIT && !x86_64_zero_extended_value (RTX))	\
        return 2;							\



More information about the Gcc-patches mailing list