S/390: Simplify literal pool overflow case further

Ulrich Weigand weigand@i1.informatik.uni-erlangen.de
Sat Aug 23 00:23:00 GMT 2003


Hello,

this further simplifies the literal pool overflow case by removing
the s390_fixup_clobbered_return_reg hack; this can be done by always
loading the return address from its save area slot even for
__builtin_return_address (0).

The patch also merges the various consttable_ insns into a single
one, and removes a now superfluous special case in literal_pool_31.

Bootstrapped/regtested (both as-is and with artifically reduced
literal pool size) on s390-ibm-linux and s390x-ibm-linux.

Bye,
Ulrich

ChangeLog:

	* config/s390/s390-protos.h (s390_output_pool_entry): Declare.
	* config/s390/s390.c (gen_consttable): Remove.
	(s390_dump_pool): Use UNSPECV_POOL_ENTRY for pool entry insns.
	(s390_output_pool_entry): New function.
	* config/s390/s390.md (UNSPECV_POOL_QI, UNSPECV_POOL_HI, 
	UNSPECV_POOL_SI, UNSPECV_POOL_DI, UNSPECV_POOL_TI, 
	UNSPECV_POOL_SF, UNSPECV_POOL_DF): Remove, replace by ...
	(UNSPECV_POOL_ENTRY): ... this new constant.
	("consttable_qi", "consttable_hi", "consttable_si", "consttable_di",
	"consttable_ti", "consttable_sf", "consttable_df"): Remove ...
	("*pool_entry"): ... and replace by this new insn.
	("literal_pool_31"): Do not emit anchor label if pool empty.

	* config/s390/s390.c (struct machine_function): Add save_return_addr_p.
	(s390_optimize_prolog): Save RETURN_REGNUM if save_return_addr_p.
	(s390_fixup_clobbered_return_reg): Remove.
	(s390_reorg): Don't call s390_fixup_clobbered_return_reg.
	(s390_return_addr_rtx): Always retrieve return address from save area
	slot.  Use save_return_addr_p to force slot to be filled.
	(s390_emit_prologue): Remove has_hard_reg_initial_val test.



Index: gcc/config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.35
diff -c -p -r1.35 s390-protos.h
*** gcc/config/s390/s390-protos.h	17 Aug 2003 10:00:03 -0000	1.35
--- gcc/config/s390/s390-protos.h	22 Aug 2003 17:54:19 -0000
*************** extern void s390_output_symbolic_const (
*** 80,85 ****
--- 80,87 ----
  extern void print_operand_address (FILE *, rtx);
  extern void print_operand (FILE *, rtx, int);
  extern void s390_output_constant_pool (rtx, rtx);
+ extern void s390_output_pool_entry (FILE *, rtx, enum machine_mode, 
+ 				    unsigned int);
  extern void s390_trampoline_template (FILE *);
  extern void s390_initialize_trampoline (rtx, rtx, rtx);
  extern rtx s390_gen_rtx_const_DI (int, int);
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.107
diff -c -p -r1.107 s390.c
*** gcc/config/s390/s390.c	17 Aug 2003 10:00:03 -0000	1.107
--- gcc/config/s390/s390.c	22 Aug 2003 17:54:21 -0000
*************** struct machine_function GTY(())
*** 189,194 ****
--- 189,198 ----
    /* Set, if some of the fprs 8-15 need to be saved (64 bit abi).  */
    int save_fprs_p;
  
+   /* Set if return address needs to be saved because the current
+      function uses __builtin_return_addr (0).  */
+   bool save_return_addr_p;
+ 
    /* Number of first and last gpr to be saved, restored.  */
    int first_save_gpr;
    int first_restore_gpr;
*************** static void replace_constant_pool_ref (r
*** 220,226 ****
  static rtx find_ltrel_base (rtx);
  static void replace_ltrel_base (rtx *, rtx);
  static void s390_optimize_prolog (int);
- static bool s390_fixup_clobbered_return_reg (rtx);
  static int find_unused_clobbered_reg (void);
  static void s390_frame_info (void);
  static rtx save_fpr (rtx, int, int);
--- 224,229 ----
*************** enum machine_mode constant_modes[NR_C_MO
*** 4049,4059 ****
    QImode
  };
  
- rtx (*gen_consttable[NR_C_MODES])(rtx) =
- {
-   gen_consttable_ti, gen_consttable_df, gen_consttable_di, gen_consttable_sf, gen_consttable_si, gen_consttable_hi, gen_consttable_qi
- };
- 
  struct constant
  {
    struct constant *next;
--- 4052,4057 ----
*************** s390_dump_pool (struct constant_pool *po
*** 4249,4255 ****
  
  	insn = emit_label_after (c->label, insn);
  	INSN_ADDRESSES_NEW (insn, -1);
! 	insn = emit_insn_after (gen_consttable[i] (value), insn);
  	INSN_ADDRESSES_NEW (insn, -1);
        }
  
--- 4247,4257 ----
  
  	insn = emit_label_after (c->label, insn);
  	INSN_ADDRESSES_NEW (insn, -1);
! 
! 	value = gen_rtx_UNSPEC_VOLATILE (constant_modes[i], 
! 					 gen_rtvec (1, value),
! 					 UNSPECV_POOL_ENTRY);
! 	insn = emit_insn_after (value, insn);
  	INSN_ADDRESSES_NEW (insn, -1);
        }
  
*************** s390_output_constant_pool (rtx start_lab
*** 4717,4722 ****
--- 4719,4764 ----
      }
  }
  
+ /* Output to FILE the constant pool entry EXP in mode MODE
+    with alignment ALIGN.  */
+ 
+ void
+ s390_output_pool_entry (FILE *file, rtx exp, enum machine_mode mode, 
+ 			unsigned int align)
+ {
+   REAL_VALUE_TYPE r;
+ 
+   switch (GET_MODE_CLASS (mode))
+     {
+     case MODE_FLOAT:
+       if (GET_CODE (exp) != CONST_DOUBLE)
+ 	abort ();
+ 
+       REAL_VALUE_FROM_CONST_DOUBLE (r, exp);
+       assemble_real (r, mode, align);
+       break;
+ 
+     case MODE_INT:
+       if (GET_CODE (exp) == CONST
+ 	  || GET_CODE (exp) == SYMBOL_REF
+ 	  || GET_CODE (exp) == LABEL_REF)
+ 	{
+ 	  fputs (integer_asm_op (GET_MODE_SIZE (mode), TRUE), file);
+ 	  s390_output_symbolic_const (file, exp);
+ 	  fputc ('\n', file);
+ 	}
+       else
+ 	{
+ 	  assemble_integer (exp, GET_MODE_SIZE (mode), align, 1);
+ 	}
+       break;
+ 
+     default:
+       abort ();
+     }
+ }
+ 
+ 
  /* Rework the prolog/epilog to avoid saving/restoring
     registers unnecessarily.  If TEMP_REGNO is nonnegative,
     it specifies the number of a caller-saved register used
*************** s390_optimize_prolog (int temp_regno)
*** 4742,4749 ****
      regs_ever_live[BASE_REGISTER] = 1;
  
    /* In non-leaf functions, the prolog/epilog code relies
!      on RETURN_REGNUM being saved in any case.  */
!   if (!current_function_is_leaf)
      regs_ever_live[RETURN_REGNUM] = 1;
  
    /* We need to save/restore the temporary register.  */
--- 4784,4794 ----
      regs_ever_live[BASE_REGISTER] = 1;
  
    /* In non-leaf functions, the prolog/epilog code relies
!      on RETURN_REGNUM being saved in any case.  We also need
!      to save the return register if __builtin_return_address (0)
!      was used in the current function.  */
!   if (!current_function_is_leaf 
!       || cfun->machine->save_return_addr_p)
      regs_ever_live[RETURN_REGNUM] = 1;
  
    /* We need to save/restore the temporary register.  */
*************** s390_optimize_prolog (int temp_regno)
*** 4868,4935 ****
      }
  }
  
- /* Check whether any insn in the function makes use of the original
-    value of RETURN_REG (e.g. for __builtin_return_address).
-    If so, insert an insn reloading that value.
- 
-    Return true if any such insn was found.  */
- 
- static bool
- s390_fixup_clobbered_return_reg (rtx return_reg)
- {
-   bool replacement_done = 0;
-   rtx insn;
- 
-   /* If we never called __builtin_return_address, register 14
-      might have been used as temp during the prolog; we do
-      not want to touch those uses.  */
-   if (!has_hard_reg_initial_val (Pmode, REGNO (return_reg)))
-     return false;
- 
-   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-     {
-       rtx reg, off, new_insn;
- 
-       if (GET_CODE (insn) != INSN)
- 	continue;
-       if (!reg_referenced_p (return_reg, PATTERN (insn)))
- 	continue;
-       if (GET_CODE (PATTERN (insn)) == PARALLEL
- 	  && store_multiple_operation (PATTERN (insn), VOIDmode))
- 	continue;
- 
-       if (frame_pointer_needed)
- 	reg = hard_frame_pointer_rtx;
-       else
- 	reg = stack_pointer_rtx;
- 
-       off = GEN_INT (cfun->machine->frame_size + REGNO (return_reg) * UNITS_PER_WORD);
-       if (!DISP_IN_RANGE (INTVAL (off)))
- 	{
- 	  off = force_const_mem (Pmode, off);
- 	  new_insn = gen_rtx_SET (Pmode, return_reg, off);
- 	  new_insn = emit_insn_before (new_insn, insn);
- 	  INSN_ADDRESSES_NEW (new_insn, -1);
- 	  off = return_reg;
- 	}
- 
-       new_insn = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, reg, off));
-       new_insn = gen_rtx_SET (Pmode, return_reg, new_insn);
-       new_insn = emit_insn_before (new_insn, insn);
-       INSN_ADDRESSES_NEW (new_insn, -1);
- 
-       replacement_done = 1;
-     }
- 
-   return replacement_done;
- }
- 
  /* Perform machine-dependent processing.  */
  
  static void
  s390_reorg (void)
  {
-   bool fixed_up_clobbered_return_reg = 0;
    rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
    bool temp_used = 0;
  
--- 4913,4923 ----
*************** s390_reorg (void)
*** 4985,5005 ****
            continue;
          }
  
-       /* Check whether we have clobbered a use of the return
- 	 register (e.g. for __builtin_return_address).  If so,
- 	 add insns reloading the register where necessary.  */
-       if (temp_used && !fixed_up_clobbered_return_reg
- 	  && s390_fixup_clobbered_return_reg (temp_reg))
- 	{
- 	  fixed_up_clobbered_return_reg = 1;
- 
- 	  /* The fixup insns might have caused a jump to overflow.  */
- 	  if (pool_list)
- 	    s390_chunkify_cancel (pool_list);
- 
- 	  continue;
- 	}
- 
        /* If we made it up to here, both conditions are satisfied.
  	 Finish up pool chunkification if required.  */
        if (pool_list)
--- 4973,4978 ----
*************** s390_return_addr_rtx (int count, rtx fra
*** 5021,5033 ****
  {
    rtx addr;
  
!   /* For the current frame, we use the initial value of RETURN_REGNUM.
!      This works both in leaf and non-leaf functions.  */
  
    if (count == 0)
!     return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
  
!   /* For frames farther back, we read the stack slot where the
       corresponding RETURN_REGNUM value was saved.  */
  
    addr = plus_constant (frame, RETURN_REGNUM * UNITS_PER_WORD);
--- 4994,5006 ----
  {
    rtx addr;
  
!   /* For the current frame, we need to make sure the initial
!      value of RETURN_REGNUM is actually saved.  */
  
    if (count == 0)
!     cfun->machine->save_return_addr_p = true;
  
!   /* To retrieve the return address we read the stack slot where the
       corresponding RETURN_REGNUM value was saved.  */
  
    addr = plus_constant (frame, RETURN_REGNUM * UNITS_PER_WORD);
*************** s390_emit_prologue (void)
*** 5343,5349 ****
       See below for why TPF must use the register 1.  */
  
    if (!current_function_is_leaf
-       && !has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
        && get_pool_size () < S390_POOL_CHUNK_MAX / 2
        && !TARGET_TPF)
      temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
--- 5316,5321 ----
Index: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.67
diff -c -p -r1.67 s390.md
*** gcc/config/s390/s390.md	7 Aug 2003 11:05:54 -0000	1.67
--- gcc/config/s390/s390.md	22 Aug 2003 17:54:24 -0000
***************
*** 92,104 ****
     (UNSPECV_POOL		200)
     (UNSPECV_POOL_START		201)
     (UNSPECV_POOL_END		202)
!    (UNSPECV_POOL_QI		203)
!    (UNSPECV_POOL_HI		204)
!    (UNSPECV_POOL_SI		205)
!    (UNSPECV_POOL_DI		206)
!    (UNSPECV_POOL_TI		207)
!    (UNSPECV_POOL_SF		208)
!    (UNSPECV_POOL_DF		209)
     (UNSPECV_MAIN_POOL		300)
  
     ; TLS support
--- 92,98 ----
     (UNSPECV_POOL		200)
     (UNSPECV_POOL_START		201)
     (UNSPECV_POOL_END		202)
!    (UNSPECV_POOL_ENTRY		203)
     (UNSPECV_MAIN_POOL		300)
  
     ; TLS support
***************
*** 7058,7145 ****
  ; Special literal pool access instruction pattern(s).
  ;
  
! (define_insn "consttable_qi"
!   [(unspec_volatile [(match_operand:QI 0 "consttable_operand" "X")]
! 		    UNSPECV_POOL_QI)]
    ""
  {
!   assemble_integer (operands[0], 1, BITS_PER_UNIT, 1);
    return "";
  }
!   [(set_attr "op_type"  "NN")
!    (set_attr "length"   "1")])
! 
! (define_insn "consttable_hi"
!   [(unspec_volatile [(match_operand:HI 0 "consttable_operand" "X")]
! 		    UNSPECV_POOL_HI)]
!   ""
! {
!   assemble_integer (operands[0], 2, 2*BITS_PER_UNIT, 1);
!   return "";
! }
!   [(set_attr "op_type"  "NN")
!    (set_attr "length"   "2")])
! 
! (define_insn "consttable_si"
!   [(unspec_volatile [(match_operand:SI 0 "consttable_operand" "X")]
! 		    UNSPECV_POOL_SI)]
!   ""
!   ".long\t%0"
!   [(set_attr "op_type"  "NN")
!    (set_attr "length"   "4")])
! 
! (define_insn "consttable_di"
!   [(unspec_volatile [(match_operand:DI 0 "consttable_operand" "X")]
! 		    UNSPECV_POOL_DI)]
!   ""
!   ".quad\t%0"
!   [(set_attr "op_type"  "NN")
!    (set_attr "length"   "8")])
! 
! (define_insn "consttable_ti"
!   [(unspec_volatile [(match_operand:TI 0 "consttable_operand" "X")]
! 		    UNSPECV_POOL_TI)]
!   ""
! {
!   assemble_integer (operands[0], 16, 16*BITS_PER_UNIT, 1);
!   return "";
! }
!   [(set_attr "op_type"  "NN")
!    (set_attr "length"   "16")])
! 
! (define_insn "consttable_sf"
!   [(unspec_volatile [(match_operand:SF 0 "consttable_operand" "X")]
! 		    UNSPECV_POOL_SF)]
!   ""
! {
!   REAL_VALUE_TYPE r;
! 
!   if (GET_CODE (operands[0]) != CONST_DOUBLE)
!     abort ();
! 
!   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
!   assemble_real (r, SFmode, 4*BITS_PER_UNIT);
!   return "";
! }
!   [(set_attr "op_type"  "NN")
!    (set_attr "length"   "4")])
! 
! (define_insn "consttable_df"
!   [(unspec_volatile [(match_operand:DF 0 "consttable_operand" "X")]
! 		    UNSPECV_POOL_DF)]
!   ""
! {
!   REAL_VALUE_TYPE r;
! 
!   if (GET_CODE (operands[0]) != CONST_DOUBLE)
!     abort ();
! 
!   REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
!   assemble_real (r, DFmode, 8*BITS_PER_UNIT);
!   return "";
! }
!   [(set_attr "op_type"  "NN")
!    (set_attr "length"   "8")])
  
  (define_insn "pool_start_31"
    [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
--- 7052,7070 ----
  ; Special literal pool access instruction pattern(s).
  ;
  
! (define_insn "*pool_entry"
!   [(unspec_volatile [(match_operand 0 "consttable_operand" "X")]
!                     UNSPECV_POOL_ENTRY)]
    ""
  {
!   enum machine_mode mode = GET_MODE (PATTERN (insn));
!   unsigned int align = GET_MODE_BITSIZE (mode);
!   s390_output_pool_entry (asm_out_file, operands[0], mode, align);
    return "";
  }
!   [(set_attr "op_type" "NN")
!    (set (attr "length") 
!         (symbol_ref "GET_MODE_SIZE (GET_MODE (PATTERN (insn)))"))])
  
  (define_insn "pool_start_31"
    [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
***************
*** 7238,7249 ****
       {
         output_asm_insn ("bras\t%0,%2", operands);
         s390_output_constant_pool (operands[1], operands[2]);
-      }
-    else if (flag_pic)
-      {
-         /* We need the anchor label in any case.  */
-         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                            CODE_LABEL_NUMBER (operands[1]));
       }
  
     return "";
--- 7163,7168 ----
-- 
  Dr. Ulrich Weigand
  weigand@informatik.uni-erlangen.de



More information about the Gcc-patches mailing list