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]

S/390: Make literal pool base register explicit to scheduler


Hello,

this fixes a long-standing issue preventing precise scheduling: the fact
that all literal pool accesses implicitly use the base register was not
made explicit to the scheduler.  This made it necessary to add an extra
barrier to the epilog code, and caused other bad scheduling decisions 
in some cases.

However, I also didn't want to change literal pool accesses away from 
simple (symbol_ref ...) too early, because many of the early optimization
passes want to look into the constant actually referenced.

This patch tries to balance this issue by adding an intermediate form
to represent literal pool accesses, which is used between prolog expansion
and machine-dependent reorg.  This form looks like

   (unspec [(symbol_ref ...) (reg base_reg)] UNSPEC_LTREF)

and provides both the explicit reference to the base register to the
scheduler, and keeps the original literal pool symbol.

The prolog expander brings all pool accesses into this form, and the
machine-dependent reorg pass converts this form to the final explicit
(plus (minus (label_ref ...) (label_ref pool_start)) (reg base_reg))
that the assembly output routines want.

Explicit pool-relative accesses (UNSPEC_LTREL_BASE) are brought into
a similar form (variant of UNSPEC_LTREL_BASE with two operands).

Bootstrapped/regtested on s390-ibm-linux and s390x-ibm-linux.
Committed to mainline.

Bye,
Ulrich


ChangeLog:

	* config/s390/s390-protos.h (s390_load_got): Update prototype.
	* config/s390/s390.c (struct machine_function): Add member base_reg.
	(s390_decompose_address): Accept UNSPEC_LTREF.  Simplify logic.
	(s390_split_branches): Annotate late pool references.
	(annotate_constant_pool_refs): New function.
	(find_constant_pool_ref): Work on annotated pool references.
	(replace_constant_pool_ref): Likewise.  Use explicit base.
	(replace_ltrel_base): Use explicit base.
	(s390_mainpool_start): Reflect main_pool pattern change.
	(s390_mainpool_finish): Use base register from main_pool.
	Update calls to replace_ltrel_base and replace_constant_pool_ref.
	(s390_chunkify_start): Use base_reg from struct machine_function.
	(s390_chunkify_finish): Remove base_reg argument.  Update calls
	to replace_ltrel_base and replace_constant_pool_ref.
	(s390_reorg): Don't decide upon base register.  Update calls.
	(s390_load_got): Remove MAYBE_DEAD handling.  Do not emit insns
	but return sequence instead.
	(s390_emit_prologue): Decide upon base register to use.  Annotate
	all literal pool references.  Adapt to main_pool pattern change.
	Update s390_load_got call; move MAYBE_DEAD handling here.
	(s390_emit_epilogue): Annotate late literal pool references.
	Remove barrier before register restore instruction.
	* config/s390/s390.md (UNSPEC_LTREF): New constant.
	("builtin_setjmp_receiver"): Update s390_load_got call.
	("main_pool"): Explicitly reference base register.



Index: gcc/config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.49
diff -c -p -r1.49 s390-protos.h
*** gcc/config/s390/s390-protos.h	24 Jun 2004 00:49:07 -0000	1.49
--- gcc/config/s390/s390-protos.h	26 Jun 2004 01:29:49 -0000
*************** Software Foundation, 59 Temple Place - S
*** 24,30 ****
  extern void optimization_options (int, int);
  extern void override_options (void);
  extern HOST_WIDE_INT s390_arg_frame_offset (void);
- extern void s390_load_got (int);
  extern void s390_emit_prologue (void);
  extern void s390_emit_epilogue (bool);
  extern void s390_function_profiler (FILE *, int);
--- 24,29 ----
*************** extern void s390_initialize_trampoline (
*** 92,97 ****
--- 91,97 ----
  extern rtx s390_gen_rtx_const_DI (int, int);
  extern void s390_output_dwarf_dtprel (FILE*, int, rtx);
  extern int s390_agen_dep_p (rtx, rtx);
+ extern rtx s390_load_got (void);
  
  #endif /* RTX_CODE */
  
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.153
diff -c -p -r1.153 s390.c
*** gcc/config/s390/s390.c	24 Jun 2004 00:49:07 -0000	1.153
--- gcc/config/s390/s390.c	26 Jun 2004 01:29:50 -0000
*************** struct machine_function GTY(())
*** 217,222 ****
--- 217,225 ----
    /* Size of stack frame.  */
    HOST_WIDE_INT frame_size;
  
+   /* Literal pool base register.  */
+   rtx base_reg;
+ 
    /* Some local-dynamic TLS symbol name.  */
    const char *some_ld_name;
  };
*************** static int get_some_local_dynamic_name_1
*** 236,245 ****
  static int reg_used_in_mem_p (int, rtx);
  static int addr_generation_dependency_p (rtx, rtx);
  static int s390_split_branches (void);
  static void find_constant_pool_ref (rtx, rtx *);
  static void replace_constant_pool_ref (rtx *, rtx, rtx);
  static rtx find_ltrel_base (rtx);
! static void replace_ltrel_base (rtx *, rtx);
  static void s390_optimize_prolog (bool);
  static int find_unused_clobbered_reg (void);
  static void s390_frame_info (int, int);
--- 239,249 ----
  static int reg_used_in_mem_p (int, rtx);
  static int addr_generation_dependency_p (rtx, rtx);
  static int s390_split_branches (void);
+ static void annotate_constant_pool_refs (rtx *x);
  static void find_constant_pool_ref (rtx, rtx *);
  static void replace_constant_pool_ref (rtx *, rtx, rtx);
  static rtx find_ltrel_base (rtx);
! static void replace_ltrel_base (rtx *);
  static void s390_optimize_prolog (bool);
  static int find_unused_clobbered_reg (void);
  static void s390_frame_info (int, int);
*************** s390_expand_plus_operand (register rtx t
*** 2069,2077 ****
--- 2073,2083 ----
  static int
  s390_decompose_address (register rtx addr, struct s390_address *out)
  {
+   HOST_WIDE_INT offset = 0;
    rtx base = NULL_RTX;
    rtx indx = NULL_RTX;
    rtx disp = NULL_RTX;
+   rtx orig_disp;
    int pointer = FALSE;
    int base_ptr = FALSE;
    int indx_ptr = FALSE;
*************** s390_decompose_address (register rtx add
*** 2119,2134 ****
    else
      disp = addr;		/* displacement */
  
  
    /* Validate base register.  */
    if (base)
      {
        if (GET_CODE (base) == UNSPEC)
!         {
!           if (XVECLEN (base, 0) != 1 || XINT (base, 1) != UNSPEC_LTREL_BASE)
  	    return FALSE;
! 	  base = gen_rtx_REG (Pmode, BASE_REGISTER);
! 	}
  
        if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
  	return FALSE;
--- 2125,2193 ----
    else
      disp = addr;		/* displacement */
  
+   /* Extract integer part of displacement.  */
+   orig_disp = disp;
+   if (disp)
+     {
+       if (GET_CODE (disp) == CONST_INT)
+ 	{
+ 	  offset = INTVAL (disp);
+ 	  disp = NULL_RTX;
+ 	}
+       else if (GET_CODE (disp) == CONST
+ 	       && GET_CODE (XEXP (disp, 0)) == PLUS
+ 	       && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
+ 	{
+ 	  offset = INTVAL (XEXP (XEXP (disp, 0), 1));
+ 	  disp = XEXP (XEXP (disp, 0), 0);
+ 	}
+     }
+ 
+   /* Strip off CONST here to avoid special case tests later.  */
+   if (disp && GET_CODE (disp) == CONST)
+     disp = XEXP (disp, 0);
+ 
+   /* We can convert literal pool addresses to
+      displacements by basing them off the base register.  */
+   if (disp && GET_CODE (disp) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (disp))
+     {
+       /* Either base or index must be free to hold the base register.  */
+       if (!base)
+         base = gen_rtx_REG (Pmode, BASE_REGISTER);
+       else if (!indx)
+         indx = gen_rtx_REG (Pmode, BASE_REGISTER);
+       else
+         return FALSE;
+ 
+       /* Mark up the displacement.  */
+       disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),
+ 			     UNSPEC_LTREL_OFFSET);
+     }
  
    /* Validate base register.  */
    if (base)
      {
        if (GET_CODE (base) == UNSPEC)
! 	switch (XINT (base, 1))
! 	  {
! 	  case UNSPEC_LTREF:
! 	    if (!disp)
! 	      disp = gen_rtx_UNSPEC (Pmode, 
! 				     gen_rtvec (1, XVECEXP (base, 0, 0)),
! 				     UNSPEC_LTREL_OFFSET);
! 	    else
! 	      return FALSE;
! 
! 	    base = gen_rtx_REG (Pmode, BASE_REGISTER);
! 	    break;
! 
! 	  case UNSPEC_LTREL_BASE:
! 	    base = gen_rtx_REG (Pmode, BASE_REGISTER);
! 	    break;
! 
! 	  default:
  	    return FALSE;
! 	  }
  
        if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
  	return FALSE;
*************** s390_decompose_address (register rtx add
*** 2149,2159 ****
    if (indx)
      {
        if (GET_CODE (indx) == UNSPEC)
!         {
!           if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != UNSPEC_LTREL_BASE)
  	    return FALSE;
! 	  indx = gen_rtx_REG (Pmode, BASE_REGISTER);
! 	}
  
        if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
  	return FALSE;
--- 2208,2233 ----
    if (indx)
      {
        if (GET_CODE (indx) == UNSPEC)
! 	switch (XINT (indx, 1))
! 	  {
! 	  case UNSPEC_LTREF:
! 	    if (!disp)
! 	      disp = gen_rtx_UNSPEC (Pmode, 
! 				     gen_rtvec (1, XVECEXP (indx, 0, 0)),
! 				     UNSPEC_LTREL_OFFSET);
! 	    else
! 	      return FALSE;
! 
! 	    indx = gen_rtx_REG (Pmode, BASE_REGISTER);
! 	    break;
! 
! 	  case UNSPEC_LTREL_BASE:
! 	    indx = gen_rtx_REG (Pmode, BASE_REGISTER);
! 	    break;
! 
! 	  default:
  	    return FALSE;
! 	  }
  
        if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
  	return FALSE;
*************** s390_decompose_address (register rtx add
*** 2180,2285 ****
      }
  
    /* Validate displacement.  */
!   if (disp)
      {
!       /* Allow integer constant in range.  */
!       if (GET_CODE (disp) == CONST_INT)
!         {
! 	  /* If the argument pointer is involved, the displacement will change
! 	     later anyway as the argument pointer gets eliminated.  This could
! 	     make a valid displacement invalid, but it is more likely to make
! 	     an invalid displacement valid, because we sometimes access the
! 	     register save area via negative offsets to the arg pointer.
! 	     Thus we don't check the displacement for validity here.  If after
! 	     elimination the displacement turns out to be invalid after all,
! 	     this is fixed up by reload in any case.  */
! 	  if (base != arg_pointer_rtx && indx != arg_pointer_rtx)
! 	    {
! 	      if (!DISP_IN_RANGE (INTVAL (disp)))
! 	        return FALSE;
! 	    }
!         }
  
        /* In the small-PIC case, the linker converts @GOT
           and @GOTNTPOFF offsets to possible displacements.  */
!       else if (GET_CODE (disp) == CONST
!                && GET_CODE (XEXP (disp, 0)) == UNSPEC
!                && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT
! 		   || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
          {
!           if (flag_pic != 1)
!             return FALSE;
! 
! 	  pointer = TRUE;
          }
  
!       /* Accept chunkfied literal pool symbol references.  */
!       else if (GET_CODE (disp) == CONST
!                && GET_CODE (XEXP (disp, 0)) == MINUS
!                && GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF
!                && GET_CODE (XEXP (XEXP (disp, 0), 1)) == LABEL_REF)
          {
! 	  pointer = TRUE;
          }
  
!       /* Likewise if a constant offset is present.  */
!       else if (GET_CODE (disp) == CONST
!                && GET_CODE (XEXP (disp, 0)) == PLUS
!                && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT
!                && GET_CODE (XEXP (XEXP (disp, 0), 0)) == MINUS
!                && GET_CODE (XEXP (XEXP (XEXP (disp, 0), 0), 0)) == LABEL_REF
!                && GET_CODE (XEXP (XEXP (XEXP (disp, 0), 0), 1)) == LABEL_REF)
          {
! 	  pointer = TRUE;
          }
  
-       /* We can convert literal pool addresses to
-          displacements by basing them off the base register.  */
        else
!         {
!           /* In some cases, we can accept an additional
!              small constant offset.  Split these off here.  */
! 
!           unsigned int offset = 0;
! 
!           if (GET_CODE (disp) == CONST
!               && GET_CODE (XEXP (disp, 0)) == PLUS
!               && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
!             {
!               offset = INTVAL (XEXP (XEXP (disp, 0), 1));
!               disp = XEXP (XEXP (disp, 0), 0);
!             }
! 
!           /* Now we must have a literal pool address.  */
!           if (GET_CODE (disp) != SYMBOL_REF
!               || !CONSTANT_POOL_ADDRESS_P (disp))
!             return FALSE;
! 
!           /* If we have an offset, make sure it does not
!              exceed the size of the constant pool entry.  */
!           if (offset && offset >= GET_MODE_SIZE (get_pool_mode (disp)))
!             return FALSE;
! 
!           /* Either base or index must be free to
!              hold the base register.  */
!           if (base && indx)
!             return FALSE;
! 
!           /* Convert the address.  */
!           if (base)
!             indx = gen_rtx_REG (Pmode, BASE_REGISTER);
!           else
!             base = gen_rtx_REG (Pmode, BASE_REGISTER);
! 
!           disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),
! 				 UNSPEC_LTREL_OFFSET);
!           disp = gen_rtx_CONST (Pmode, disp);
! 
!           if (offset)
!             disp = plus_constant (disp, offset);
! 
! 	  pointer = TRUE;
!         }
      }
  
    if (!base && !indx)
--- 2254,2316 ----
      }
  
    /* Validate displacement.  */
!   if (!disp)
      {
!       /* If the argument pointer is involved, the displacement will change
! 	 later anyway as the argument pointer gets eliminated.  This could
! 	 make a valid displacement invalid, but it is more likely to make
! 	 an invalid displacement valid, because we sometimes access the
! 	 register save area via negative offsets to the arg pointer.
! 	 Thus we don't check the displacement for validity here.  If after
! 	 elimination the displacement turns out to be invalid after all,
! 	 this is fixed up by reload in any case.  */
!       if (base != arg_pointer_rtx && indx != arg_pointer_rtx)
! 	if (!DISP_IN_RANGE (offset))
! 	  return FALSE;
!     }
!   else
!     {
!       /* All the special cases are pointers.  */
!       pointer = TRUE;
  
        /* In the small-PIC case, the linker converts @GOT
           and @GOTNTPOFF offsets to possible displacements.  */
!       if (GET_CODE (disp) == UNSPEC
!           && (XINT (disp, 1) == UNSPEC_GOT
! 	      || XINT (disp, 1) == UNSPEC_GOTNTPOFF)
! 	  && offset == 0
! 	  && flag_pic == 1)
          {
! 	  ;
          }
  
!       /* Accept chunkified literal pool symbol references.  */
!       else if (GET_CODE (disp) == MINUS
!                && GET_CODE (XEXP (disp, 0)) == LABEL_REF
!                && GET_CODE (XEXP (disp, 1)) == LABEL_REF)
          {
! 	  ;
          }
  
!       /* Accept literal pool references.  */
!       else if (GET_CODE (disp) == UNSPEC
! 	       && XINT (disp, 1) == UNSPEC_LTREL_OFFSET)
          {
! 	  orig_disp = gen_rtx_CONST (Pmode, disp);
! 	  if (offset)
! 	    {
! 	      /* If we have an offset, make sure it does not
! 		 exceed the size of the constant pool entry.  */
! 	      rtx sym = XVECEXP (disp, 0, 0);
! 	      if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))
! 		return FALSE;
! 
!               orig_disp = plus_constant (orig_disp, offset);
! 	    }
          }
  
        else
! 	return FALSE;
      }
  
    if (!base && !indx)
*************** s390_decompose_address (register rtx add
*** 2289,2295 ****
      {
        out->base = base;
        out->indx = indx;
!       out->disp = disp;
        out->pointer = pointer;
      }
  
--- 2320,2326 ----
      {
        out->base = base;
        out->indx = indx;
!       out->disp = orig_disp;
        out->pointer = pointer;
      }
  
*************** s390_split_branches (void)
*** 4058,4063 ****
--- 4089,4095 ----
  	  tmp = force_const_mem (Pmode, *label);
  	  tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
  	  INSN_ADDRESSES_NEW (tmp, -1);
+ 	  annotate_constant_pool_refs (&PATTERN (tmp));
  
  	  target = temp_reg;
  	}
*************** s390_split_branches (void)
*** 4070,4077 ****
  	  target = force_const_mem (Pmode, target);
  	  tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
  	  INSN_ADDRESSES_NEW (tmp, -1);
  
!           target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (target, 0)),
  				   UNSPEC_LTREL_BASE);
  	  target = gen_rtx_PLUS (Pmode, temp_reg, target);
  	}
--- 4102,4111 ----
  	  target = force_const_mem (Pmode, target);
  	  tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
  	  INSN_ADDRESSES_NEW (tmp, -1);
+ 	  annotate_constant_pool_refs (&PATTERN (tmp));
  
!           target = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XEXP (target, 0),
! 							cfun->machine->base_reg),
  				   UNSPEC_LTREL_BASE);
  	  target = gen_rtx_PLUS (Pmode, temp_reg, target);
  	}
*************** s390_split_branches (void)
*** 4083,4093 ****
    return new_literal;
  }
  
  
! /* Find a literal pool symbol referenced in RTX X, and store
!    it at REF.  Will abort if X contains references to more than
!    one such pool symbol; multiple references to the same symbol
!    are allowed, however.
  
     The rtx pointed to by REF must be initialized to NULL_RTX
     by the caller before calling this routine.  */
--- 4117,4231 ----
    return new_literal;
  }
  
+ /* Annotate every literal pool reference in X by an UNSPEC_LTREF expression.
+    Fix up MEMs as required.  */
+ 
+ static void
+ annotate_constant_pool_refs (rtx *x)
+ {
+   int i, j;
+   const char *fmt;
+ 
+   if (GET_CODE (*x) == SYMBOL_REF
+       && CONSTANT_POOL_ADDRESS_P (*x))
+     abort ();
+ 
+   /* Literal pool references can only occur inside a MEM ...  */
+   if (GET_CODE (*x) == MEM)
+     {
+       rtx memref = XEXP (*x, 0);
+ 
+       if (GET_CODE (memref) == SYMBOL_REF
+ 	  && CONSTANT_POOL_ADDRESS_P (memref))
+ 	{
+ 	  rtx base = cfun->machine->base_reg;
+ 	  rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, memref, base),
+ 				     UNSPEC_LTREF);
+ 
+ 	  *x = replace_equiv_address (*x, addr);
+ 	  return;
+ 	}
+ 
+       if (GET_CODE (memref) == CONST
+ 	  && GET_CODE (XEXP (memref, 0)) == PLUS
+ 	  && GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
+ 	  && GET_CODE (XEXP (XEXP (memref, 0), 0)) == SYMBOL_REF
+ 	  && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (memref, 0), 0)))
+ 	{
+ 	  HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
+ 	  rtx sym = XEXP (XEXP (memref, 0), 0);
+ 	  rtx base = cfun->machine->base_reg;
+ 	  rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
+ 				     UNSPEC_LTREF);
+ 
+ 	  *x = replace_equiv_address (*x, plus_constant (addr, off));
+ 	  return;
+ 	}
+     }
+ 
+   /* ... or a load-address type pattern.  */
+   if (GET_CODE (*x) == SET)
+     {
+       rtx addrref = SET_SRC (*x);
+ 
+       if (GET_CODE (addrref) == SYMBOL_REF
+ 	  && CONSTANT_POOL_ADDRESS_P (addrref))
+ 	{
+ 	  rtx base = cfun->machine->base_reg;
+ 	  rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, addrref, base),
+ 				     UNSPEC_LTREF);
+ 
+ 	  SET_SRC (*x) = addr;
+ 	  return;
+ 	}
+ 
+       if (GET_CODE (addrref) == CONST
+ 	  && GET_CODE (XEXP (addrref, 0)) == PLUS
+ 	  && GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
+ 	  && GET_CODE (XEXP (XEXP (addrref, 0), 0)) == SYMBOL_REF
+ 	  && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (addrref, 0), 0)))
+ 	{
+ 	  HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
+ 	  rtx sym = XEXP (XEXP (addrref, 0), 0);
+ 	  rtx base = cfun->machine->base_reg;
+ 	  rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
+ 				     UNSPEC_LTREF);
+ 
+ 	  SET_SRC (*x) = plus_constant (addr, off);
+ 	  return;
+ 	}
+     }
+ 
+   /* Annotate LTREL_BASE as well.  */
+   if (GET_CODE (*x) == UNSPEC
+       && XINT (*x, 1) == UNSPEC_LTREL_BASE)
+     {
+       rtx base = cfun->machine->base_reg;
+       *x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XVECEXP (*x, 0, 0), base),
+ 				  UNSPEC_LTREL_BASE);
+       return;
+     }
+ 
+   fmt = GET_RTX_FORMAT (GET_CODE (*x));
+   for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
+     {
+       if (fmt[i] == 'e')
+         {
+           annotate_constant_pool_refs (&XEXP (*x, i));
+         }
+       else if (fmt[i] == 'E')
+         {
+           for (j = 0; j < XVECLEN (*x, i); j++)
+             annotate_constant_pool_refs (&XVECEXP (*x, i, j));
+         }
+     }
+ }
+ 
  
! /* Find an annotated literal pool symbol referenced in RTX X, 
!    and store it at REF.  Will abort if X contains references to 
!    more than one such pool symbol; multiple references to the same
!    symbol are allowed, however.
  
     The rtx pointed to by REF must be initialized to NULL_RTX
     by the caller before calling this routine.  */
*************** find_constant_pool_ref (rtx x, rtx *ref)
*** 4109,4119 ****
  
    if (GET_CODE (x) == SYMBOL_REF
        && CONSTANT_POOL_ADDRESS_P (x))
      {
        if (*ref == NULL_RTX)
!         *ref = x;
!       else if (*ref != x)
!         abort();
      }
  
    fmt = GET_RTX_FORMAT (GET_CODE (x));
--- 4247,4267 ----
  
    if (GET_CODE (x) == SYMBOL_REF
        && CONSTANT_POOL_ADDRESS_P (x))
+     abort ();
+ 
+   if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_LTREF)
      {
+       rtx sym = XVECEXP (x, 0, 0);
+       if (GET_CODE (sym) != SYMBOL_REF
+ 	  || !CONSTANT_POOL_ADDRESS_P (sym))
+ 	abort ();
+ 
        if (*ref == NULL_RTX)
! 	*ref = sym;
!       else if (*ref != sym)
! 	abort ();
! 
!       return;
      }
  
    fmt = GET_RTX_FORMAT (GET_CODE (x));
*************** find_constant_pool_ref (rtx x, rtx *ref)
*** 4131,4141 ****
      }
  }
  
! /* Replace every reference to the literal pool symbol REF
!    in X by the address ADDR.  Fix up MEMs as required.  */
  
  static void
! replace_constant_pool_ref (rtx *x, rtx ref, rtx addr)
  {
    int i, j;
    const char *fmt;
--- 4279,4289 ----
      }
  }
  
! /* Replace every reference to the annotated literal pool 
!    symbol REF in X by its base plus OFFSET.  */
  
  static void
! replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
  {
    int i, j;
    const char *fmt;
*************** replace_constant_pool_ref (rtx *x, rtx r
*** 4143,4190 ****
    if (*x == ref)
      abort ();
  
!   /* Literal pool references can only occur inside a MEM ...  */
!   if (GET_CODE (*x) == MEM)
      {
!       rtx memref = XEXP (*x, 0);
! 
!       if (memref == ref)
! 	{
! 	  *x = replace_equiv_address (*x, addr);
! 	  return;
! 	}
! 
!       if (GET_CODE (memref) == CONST
! 	  && GET_CODE (XEXP (memref, 0)) == PLUS
! 	  && GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
! 	  && XEXP (XEXP (memref, 0), 0) == ref)
! 	{
! 	  HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
! 	  *x = replace_equiv_address (*x, plus_constant (addr, off));
! 	  return;
! 	}
      }
  
!   /* ... or a load-address type pattern.  */
!   if (GET_CODE (*x) == SET)
      {
!       rtx addrref = SET_SRC (*x);
! 
!       if (addrref == ref)
! 	{
! 	  SET_SRC (*x) = addr;
! 	  return;
! 	}
! 
!       if (GET_CODE (addrref) == CONST
! 	  && GET_CODE (XEXP (addrref, 0)) == PLUS
! 	  && GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
! 	  && XEXP (XEXP (addrref, 0), 0) == ref)
! 	{
! 	  HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
! 	  SET_SRC (*x) = plus_constant (addr, off);
! 	  return;
! 	}
      }
  
    fmt = GET_RTX_FORMAT (GET_CODE (*x));
--- 4291,4313 ----
    if (*x == ref)
      abort ();
  
!   if (GET_CODE (*x) == UNSPEC
!       && XINT (*x, 1) == UNSPEC_LTREF
!       && XVECEXP (*x, 0, 0) == ref)
      {
!       *x = gen_rtx_PLUS (Pmode, XVECEXP (*x, 0, 1), offset);
!       return;
      }
  
!   if (GET_CODE (*x) == PLUS
!       && GET_CODE (XEXP (*x, 1)) == CONST_INT
!       && GET_CODE (XEXP (*x, 0)) == UNSPEC
!       && XINT (XEXP (*x, 0), 1) == UNSPEC_LTREF
!       && XVECEXP (XEXP (*x, 0), 0, 0) == ref)
      {
!       rtx addr = gen_rtx_PLUS (Pmode, XVECEXP (XEXP (*x, 0), 0, 1), offset);
!       *x = plus_constant (addr, INTVAL (XEXP (*x, 1)));
!       return;
      }
  
    fmt = GET_RTX_FORMAT (GET_CODE (*x));
*************** replace_constant_pool_ref (rtx *x, rtx r
*** 4192,4203 ****
      {
        if (fmt[i] == 'e')
          {
!           replace_constant_pool_ref (&XEXP (*x, i), ref, addr);
          }
        else if (fmt[i] == 'E')
          {
            for (j = 0; j < XVECLEN (*x, i); j++)
!             replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, addr);
          }
      }
  }
--- 4315,4326 ----
      {
        if (fmt[i] == 'e')
          {
!           replace_constant_pool_ref (&XEXP (*x, i), ref, offset);
          }
        else if (fmt[i] == 'E')
          {
            for (j = 0; j < XVECLEN (*x, i); j++)
!             replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
          }
      }
  }
*************** find_ltrel_base (rtx x)
*** 4238,4247 ****
    return NULL_RTX;
  }
  
! /* Replace any occurrence of UNSPEC_LTREL_BASE in X with BASE.  */
  
  static void
! replace_ltrel_base (rtx *x, rtx base)
  {
    int i, j;
    const char *fmt;
--- 4361,4370 ----
    return NULL_RTX;
  }
  
! /* Replace any occurrence of UNSPEC_LTREL_BASE in X with its base.  */
  
  static void
! replace_ltrel_base (rtx *x)
  {
    int i, j;
    const char *fmt;
*************** replace_ltrel_base (rtx *x, rtx base)
*** 4249,4255 ****
    if (GET_CODE (*x) == UNSPEC
        && XINT (*x, 1) == UNSPEC_LTREL_BASE)
      {
!       *x = base;
        return;
      }
  
--- 4372,4378 ----
    if (GET_CODE (*x) == UNSPEC
        && XINT (*x, 1) == UNSPEC_LTREL_BASE)
      {
!       *x = XVECEXP (*x, 0, 1);
        return;
      }
  
*************** replace_ltrel_base (rtx *x, rtx base)
*** 4258,4269 ****
      {
        if (fmt[i] == 'e')
          {
!           replace_ltrel_base (&XEXP (*x, i), base);
          }
        else if (fmt[i] == 'E')
          {
            for (j = 0; j < XVECLEN (*x, i); j++)
!             replace_ltrel_base (&XVECEXP (*x, i, j), base);
          }
      }
  }
--- 4381,4392 ----
      {
        if (fmt[i] == 'e')
          {
!           replace_ltrel_base (&XEXP (*x, i));
          }
        else if (fmt[i] == 'E')
          {
            for (j = 0; j < XVECLEN (*x, i); j++)
!             replace_ltrel_base (&XVECEXP (*x, i, j));
          }
      }
  }
*************** struct constant_pool
*** 4302,4312 ****
  };
  
  static struct constant_pool * s390_mainpool_start (void);
! static void s390_mainpool_finish (struct constant_pool *, rtx base_reg);
  static void s390_mainpool_cancel (struct constant_pool *);
  
! static struct constant_pool * s390_chunkify_start (rtx base_reg);
! static void s390_chunkify_finish (struct constant_pool *, rtx base_reg);
  static void s390_chunkify_cancel (struct constant_pool *);
  
  static struct constant_pool *s390_start_pool (struct constant_pool **, rtx);
--- 4425,4435 ----
  };
  
  static struct constant_pool * s390_mainpool_start (void);
! static void s390_mainpool_finish (struct constant_pool *);
  static void s390_mainpool_cancel (struct constant_pool *);
  
! static struct constant_pool * s390_chunkify_start (void);
! static void s390_chunkify_finish (struct constant_pool *);
  static void s390_chunkify_cancel (struct constant_pool *);
  
  static struct constant_pool *s390_start_pool (struct constant_pool **, rtx);
*************** s390_mainpool_start (void)
*** 4560,4567 ****
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        if (GET_CODE (insn) == INSN
! 	  && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
! 	  && XINT (PATTERN (insn), 1) == UNSPECV_MAIN_POOL)
  	{
  	  if (pool->pool_insn)
  	    abort ();
--- 4683,4691 ----
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        if (GET_CODE (insn) == INSN
! 	  && GET_CODE (PATTERN (insn)) == SET
! 	  && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE
! 	  && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL)
  	{
  	  if (pool->pool_insn)
  	    abort ();
*************** s390_mainpool_start (void)
*** 4599,4610 ****
  
  /* POOL holds the main literal pool as collected by s390_mainpool_start.
     Modify the current function to output the pool constants as well as
!    the pool register setup instruction.  BASE_REG is the register to
!    be used as pool base register.  */
  
  static void
! s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
  {
    rtx insn;
  
    /* If the pool is empty, we're done.  */
--- 4723,4734 ----
  
  /* POOL holds the main literal pool as collected by s390_mainpool_start.
     Modify the current function to output the pool constants as well as
!    the pool register setup instruction.  */
  
  static void
! s390_mainpool_finish (struct constant_pool *pool)
  {
+   rtx base_reg = SET_DEST (PATTERN (pool->pool_insn));
    rtx insn;
  
    /* If the pool is empty, we're done.  */
*************** s390_mainpool_finish (struct constant_po
*** 4684,4690 ****
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        if (INSN_P (insn))
! 	replace_ltrel_base (&PATTERN (insn), base_reg);
  
        if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
          {
--- 4808,4814 ----
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        if (INSN_P (insn))
! 	replace_ltrel_base (&PATTERN (insn));
  
        if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
          {
*************** s390_mainpool_finish (struct constant_po
*** 4694,4700 ****
              {
                addr = s390_find_constant (pool, get_pool_constant (pool_ref),
                                                 get_pool_mode (pool_ref));
-               addr = gen_rtx_PLUS (Pmode, base_reg, addr);
                replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
                INSN_CODE (insn) = -1;
              }
--- 4818,4823 ----
*************** s390_mainpool_cancel (struct constant_po
*** 4718,4731 ****
  }
  
  
! /* Chunkify the literal pool.  BASE_REG is to be used as pool
!    register.  */
  
  #define S390_POOL_CHUNK_MIN	0xc00
  #define S390_POOL_CHUNK_MAX	0xe00
  
  static struct constant_pool *
! s390_chunkify_start (rtx base_reg)
  {
    struct constant_pool *curr_pool = NULL, *pool_list = NULL;
    int extra_size = 0;
--- 4841,4853 ----
  }
  
  
! /* Chunkify the literal pool.  */
  
  #define S390_POOL_CHUNK_MIN	0xc00
  #define S390_POOL_CHUNK_MAX	0xe00
  
  static struct constant_pool *
! s390_chunkify_start (void)
  {
    struct constant_pool *curr_pool = NULL, *pool_list = NULL;
    int extra_size = 0;
*************** s390_chunkify_start (rtx base_reg)
*** 4952,4958 ****
  
    for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
      {
!       rtx new_insn = gen_reload_base (base_reg, curr_pool->label);
        rtx insn = curr_pool->first_insn;
        INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
      }
--- 5074,5081 ----
  
    for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
      {
!       rtx new_insn = gen_reload_base (cfun->machine->base_reg, 
! 				      curr_pool->label);
        rtx insn = curr_pool->first_insn;
        INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
      }
*************** s390_chunkify_start (rtx base_reg)
*** 4966,4972 ****
  	struct constant_pool *pool = s390_find_pool (pool_list, insn);
  	if (pool)
  	  {
! 	    rtx new_insn = gen_reload_base (base_reg, pool->label);
  	    INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
  	  }
        }
--- 5089,5096 ----
  	struct constant_pool *pool = s390_find_pool (pool_list, insn);
  	if (pool)
  	  {
! 	    rtx new_insn = gen_reload_base (cfun->machine->base_reg, 
! 					    pool->label);
  	    INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
  	  }
        }
*************** s390_chunkify_start (rtx base_reg)
*** 4985,4995 ****
  
  /* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
     After we have decided to use this list, finish implementing
!    all changes to the current function as required.  BASE_REG is
!    to be used as pool base register.  */
  
  static void
! s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg)
  {
    struct constant_pool *curr_pool = NULL;
    rtx insn;
--- 5109,5118 ----
  
  /* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
     After we have decided to use this list, finish implementing
!    all changes to the current function as required.  */
  
  static void
! s390_chunkify_finish (struct constant_pool *pool_list)
  {
    struct constant_pool *curr_pool = NULL;
    rtx insn;
*************** s390_chunkify_finish (struct constant_po
*** 5000,5006 ****
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        if (INSN_P (insn))
! 	replace_ltrel_base (&PATTERN (insn), base_reg);
  
        curr_pool = s390_find_pool (pool_list, insn);
        if (!curr_pool)
--- 5123,5129 ----
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        if (INSN_P (insn))
! 	replace_ltrel_base (&PATTERN (insn));
  
        curr_pool = s390_find_pool (pool_list, insn);
        if (!curr_pool)
*************** s390_chunkify_finish (struct constant_po
*** 5014,5020 ****
              {
                addr = s390_find_constant (curr_pool, get_pool_constant (pool_ref),
                                                      get_pool_mode (pool_ref));
-               addr = gen_rtx_PLUS (Pmode, base_reg, addr);
                replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
                INSN_CODE (insn) = -1;
              }
--- 5137,5142 ----
*************** s390_optimize_prolog (bool base_used)
*** 5273,5279 ****
  static void
  s390_reorg (void)
  {
-   rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER);
    bool base_used = false;
    bool pool_overflow = false;
  
--- 5395,5400 ----
*************** s390_reorg (void)
*** 5282,5293 ****
    split_all_insns_noflow ();
  
  
-   /* In small leaf functions, try to use an unused call-clobbered
-      register as base register to avoid save/restore overhead.  */
-   if (current_function_is_leaf && !regs_ever_live[5])
-     base_reg = gen_rtx_REG (Pmode, 5);
- 
- 
    /* Install the main literal pool and the associated base
       register load insns.
  
--- 5403,5408 ----
*************** s390_reorg (void)
*** 5335,5341 ****
  
        /* If literal pool overflowed, start to chunkify it.  */
        if (pool_overflow)
!         pool = s390_chunkify_start (base_reg);
  
        /* Split out-of-range branches.  If this has created new
  	 literal pool entries, cancel current chunk list and
--- 5450,5456 ----
  
        /* If literal pool overflowed, start to chunkify it.  */
        if (pool_overflow)
!         pool = s390_chunkify_start ();
  
        /* Split out-of-range branches.  If this has created new
  	 literal pool entries, cancel current chunk list and
*************** s390_reorg (void)
*** 5354,5366 ****
        /* If we made it up to here, both conditions are satisfied.
  	 Finish up literal pool related changes.  */
        if ((pool_overflow || pool->size > 0)
! 	   && REGNO (base_reg) == BASE_REGISTER)
  	base_used = true;
  
        if (pool_overflow)
! 	s390_chunkify_finish (pool, base_reg);
        else
! 	s390_mainpool_finish (pool, base_reg);
  
        break;
      }
--- 5469,5481 ----
        /* If we made it up to here, both conditions are satisfied.
  	 Finish up literal pool related changes.  */
        if ((pool_overflow || pool->size > 0)
! 	   && REGNO (cfun->machine->base_reg) == BASE_REGISTER)
  	base_used = true;
  
        if (pool_overflow)
! 	s390_chunkify_finish (pool);
        else
! 	s390_mainpool_finish (pool);
  
        break;
      }
*************** restore_gprs (rtx base, int offset, int 
*** 5649,5697 ****
    return insn;
  }
  
! /* Emit code to load the GOT register.  If MAYBE_DEAD is true,
!    annotate generated insns with REG_MAYBE_DEAD notes.  */
  
  static GTY(()) rtx got_symbol;
! void
! s390_load_got (int maybe_dead)
  {
    if (!got_symbol)
      {
        got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
        SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
      }
  
    if (TARGET_CPU_ZARCH)
      {
!       rtx insn = emit_move_insn (pic_offset_table_rtx, got_symbol);
!       if (maybe_dead)
!         REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
!                                              REG_NOTES (insn));
      }
    else
      {
!       rtx offset, insn;
  
        offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
  			       UNSPEC_LTREL_OFFSET);
        offset = gen_rtx_CONST (Pmode, offset);
        offset = force_const_mem (Pmode, offset);
  
!       insn = emit_move_insn (pic_offset_table_rtx, offset);
!       if (maybe_dead)
! 	REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
! 					     REG_NOTES (insn));
  
        offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)),
  			       UNSPEC_LTREL_BASE);
        offset = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
  
!       insn = emit_move_insn (pic_offset_table_rtx, offset);
!       if (maybe_dead)
! 	REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
! 					     REG_NOTES (insn));
      }
  }
  
  /* Expand the prologue into a bunch of separate insns.  */
--- 5764,5810 ----
    return insn;
  }
  
! /* Return insn sequence to load the GOT register.  */
  
  static GTY(()) rtx got_symbol;
! rtx
! s390_load_got (void)
  {
+   rtx insns;
+ 
    if (!got_symbol)
      {
        got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
        SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
      }
  
+   start_sequence ();
+ 
    if (TARGET_CPU_ZARCH)
      {
!       emit_move_insn (pic_offset_table_rtx, got_symbol);
      }
    else
      {
!       rtx offset;
  
        offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
  			       UNSPEC_LTREL_OFFSET);
        offset = gen_rtx_CONST (Pmode, offset);
        offset = force_const_mem (Pmode, offset);
  
!       emit_move_insn (pic_offset_table_rtx, offset);
  
        offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)),
  			       UNSPEC_LTREL_BASE);
        offset = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
  
!       emit_move_insn (pic_offset_table_rtx, offset);
      }
+ 
+   insns = get_insns ();
+   end_sequence ();
+   return insns;
  }
  
  /* Expand the prologue into a bunch of separate insns.  */
*************** s390_emit_prologue (void)
*** 5712,5717 ****
--- 5825,5841 ----
        || regs_ever_live[RETURN_REGNUM])
      cfun->machine->save_return_addr_p = 1;
  
+   /* Decide which register to use as literal pool base.  In small leaf 
+      functions, try to use an unused call-clobbered register as base 
+      register to avoid save/restore overhead.  */
+ 
+   if (current_function_is_leaf && !regs_ever_live[5])
+     cfun->machine->base_reg = gen_rtx_REG (Pmode, 5);
+   else
+     cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGISTER);
+ 
+   regs_ever_live[REGNO (cfun->machine->base_reg)] = 1;
+ 
    /* Compute frame info.  Note that at this point, we assume the base 
       register and -on S/390- the return register always need to be saved.
       This is done because the usage of these registers might change even 
*************** s390_emit_prologue (void)
*** 5727,5732 ****
--- 5851,5867 ----
  				  || cfun->machine->save_return_addr_p;
    regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
  
+   /* Annotate all constant pool references to let the scheduler know
+      they implicitly use the base register.  */
+ 
+   push_topmost_sequence ();
+ 
+   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+     if (INSN_P (insn))
+       annotate_constant_pool_refs (&PATTERN (insn));
+ 
+   pop_topmost_sequence ();
+ 
    /* Choose best register to use for temp use within prologue.
       See below for why TPF must use the register 1.  */
  
*************** s390_emit_prologue (void)
*** 5744,5750 ****
  
    /* Dummy insn to mark literal pool slot.  */
  
!   emit_insn (gen_main_pool ());
  
    /* Save fprs for variable args.  */
  
--- 5879,5885 ----
  
    /* Dummy insn to mark literal pool slot.  */
  
!   emit_insn (gen_main_pool (cfun->machine->base_reg));
  
    /* Save fprs for variable args.  */
  
*************** s390_emit_prologue (void)
*** 5790,5795 ****
--- 5925,5931 ----
  	    frame_off = force_const_mem (Pmode, frame_off);
  
            insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
+ 	  annotate_constant_pool_refs (&PATTERN (insn));
  	}
  
        RTX_FRAME_RELATED_P (insn) = 1;
*************** s390_emit_prologue (void)
*** 5854,5860 ****
    /* Set up got pointer, if needed.  */
  
    if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
!     s390_load_got(true);
  
    if (TARGET_TPF_PROFILING)
      {
--- 5990,6008 ----
    /* Set up got pointer, if needed.  */
  
    if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
!     {
!       rtx insns = s390_load_got ();
! 
!       for (insn = insns; insn; insn = NEXT_INSN (insn))
! 	{
! 	  annotate_constant_pool_refs (&PATTERN (insn));
! 
! 	  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
! 						REG_NOTES (insn));
! 	}
! 
!       emit_insn (insns);
!     }
  
    if (TARGET_TPF_PROFILING)
      {
*************** s390_emit_epilogue (bool sibcall)
*** 5965,5970 ****
--- 6113,6119 ----
  	    frame_off = force_const_mem (Pmode, frame_off);
  
  	  insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
+ 	  annotate_constant_pool_refs (&PATTERN (insn));
  	}
      }
  
*************** s390_emit_epilogue (bool sibcall)
*** 6044,6055 ****
  	    }
  	}
  
-       /* ??? As references to the base register are not made
- 	 explicit in insn RTX code, we have to add a barrier here
- 	 to prevent incorrect scheduling.  */
- 
-       emit_insn (gen_blockage());
- 
        insn = restore_gprs (frame_pointer, offset,
  			   cfun->machine->first_restore_gpr,
  			   cfun->machine->last_restore_gpr);
--- 6193,6198 ----
Index: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.113
diff -c -p -r1.113 s390.md
*** gcc/config/s390/s390.md	24 Jun 2004 00:49:07 -0000	1.113
--- gcc/config/s390/s390.md	26 Jun 2004 01:29:51 -0000
***************
*** 92,97 ****
--- 92,98 ----
     ; Literal pool
     (UNSPEC_RELOAD_BASE		210)
     (UNSPEC_MAIN_BASE		211)
+    (UNSPEC_LTREF		212)
  
     ; TLS relocation specifiers
     (UNSPEC_TLSGD		500)
***************
*** 7394,7400 ****
    [(match_operand 0 "" "")]
    "flag_pic"
  {
!   s390_load_got (false);
    emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
    DONE;
  })
--- 7395,7401 ----
    [(match_operand 0 "" "")]
    "flag_pic"
  {
!   emit_insn (s390_load_got ());
    emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
    DONE;
  })
***************
*** 7561,7568 ****
     (set_attr "type"    "larl")])
  
  (define_insn "main_pool"
!   [(unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL)]
!   ""
    "* abort ();"
    [(set_attr "op_type" "NN")])
  
--- 7562,7570 ----
     (set_attr "type"    "larl")])
  
  (define_insn "main_pool"
!   [(set (match_operand 0 "register_operand" "=a")
!         (unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL))]
!   "GET_MODE (operands[0]) == Pmode"
    "* abort ();"
    [(set_attr "op_type" "NN")])
  
-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de


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