aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2005-05-25 20:39:31 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2005-05-25 20:39:31 +0000
commit29a79fcf4e9d44888aade5c3e19e2b8925c20ab0 (patch)
treee4be1bc753b666b714ba6acf1e4ebca138322cb5 /gcc/config
parent24597146d4d08526bc0a2032e44f5523f6399db3 (diff)
downloadgcc-29a79fcf4e9d44888aade5c3e19e2b8925c20ab0.zip
gcc-29a79fcf4e9d44888aade5c3e19e2b8925c20ab0.tar.gz
gcc-29a79fcf4e9d44888aade5c3e19e2b8925c20ab0.tar.bz2
s390.c (GP_ARG_NUM_REG, [...]): New defines.
ChangeLog: * config/s390/s390.c (GP_ARG_NUM_REG, FP_ARG_NUM_REG): New defines. (s390_function_arg, s390_gimplify_va_arg): Use them. (s390_register_info): Save only required subset of argument registers into save area for va_list. (s390_va_start): Initialize only required elements of va_list struct. (s390_build_builtin_va_list): Set va_list_[gf]pr_counter_field. testsuite/ChangeLog: * gcc.dg/tree-ssa/stdarg-2.c: Add tests for s390*-*-linux* targets. * gcc.dg/tree-ssa/stdarg-3.c: Likewise. * gcc.dg/tree-ssa/stdarg-4.c: Likewise. * gcc.dg/tree-ssa/stdarg-5.c: Likewise. From-SVN: r100164
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/s390/s390.c126
1 files changed, 83 insertions, 43 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 6bbaaf3..2c860e7 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -255,6 +255,11 @@ struct machine_function GTY(())
#define cfun_fpr_bit_p(BITNUM) (!!(cfun->machine->frame_layout.fpr_bitmap & \
(1 << (BITNUM))))
+/* Number of GPRs and FPRs used for argument passing. */
+#define GP_ARG_NUM_REG 5
+#define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2)
+
+
/* Return true if SET either doesn't set the CC register, or else
the source and destination have matching CC modes and that
CC mode is at least as constrained as REQ_MODE. */
@@ -5659,18 +5664,40 @@ s390_register_info (int live_regs[])
if (current_function_stdarg)
{
/* Varargs functions need to save gprs 2 to 6. */
- if (cfun_frame_layout.first_save_gpr == -1
- || cfun_frame_layout.first_save_gpr > 2)
- cfun_frame_layout.first_save_gpr = 2;
-
- if (cfun_frame_layout.last_save_gpr == -1
- || cfun_frame_layout.last_save_gpr < 6)
- cfun_frame_layout.last_save_gpr = 6;
+ if (cfun->va_list_gpr_size
+ && current_function_args_info.gprs < GP_ARG_NUM_REG)
+ {
+ int min_gpr = current_function_args_info.gprs;
+ int max_gpr = min_gpr + cfun->va_list_gpr_size;
+ if (max_gpr > GP_ARG_NUM_REG)
+ max_gpr = GP_ARG_NUM_REG;
+
+ if (cfun_frame_layout.first_save_gpr == -1
+ || cfun_frame_layout.first_save_gpr > 2 + min_gpr)
+ cfun_frame_layout.first_save_gpr = 2 + min_gpr;
+
+ if (cfun_frame_layout.last_save_gpr == -1
+ || cfun_frame_layout.last_save_gpr < 2 + max_gpr - 1)
+ cfun_frame_layout.last_save_gpr = 2 + max_gpr - 1;
+ }
/* Mark f0, f2 for 31 bit and f0-f4 for 64 bit to be saved. */
- if (TARGET_HARD_FLOAT)
- for (i = 0; i < (TARGET_64BIT ? 4 : 2); i++)
- cfun_set_fpr_bit (i);
+ if (TARGET_HARD_FLOAT && cfun->va_list_fpr_size
+ && current_function_args_info.fprs < FP_ARG_NUM_REG)
+ {
+ int min_fpr = current_function_args_info.fprs;
+ int max_fpr = min_fpr + cfun->va_list_fpr_size;
+ if (max_fpr > FP_ARG_NUM_REG)
+ max_fpr = FP_ARG_NUM_REG;
+
+ /* ??? This is currently required to ensure proper location
+ of the fpr save slots within the va_list save area. */
+ if (TARGET_PACKED_STACK)
+ min_fpr = 0;
+
+ for (i = min_fpr; i < max_fpr; i++)
+ cfun_set_fpr_bit (i);
+ }
}
if (!TARGET_64BIT)
@@ -6714,7 +6741,7 @@ s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
{
if (s390_function_arg_float (mode, type))
{
- if (cum->fprs + 1 > (TARGET_64BIT? 4 : 2))
+ if (cum->fprs + 1 > FP_ARG_NUM_REG)
return 0;
else
return gen_rtx_REG (mode, cum->fprs + 16);
@@ -6724,7 +6751,7 @@ s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
int size = s390_function_arg_size (mode, type);
int n_gprs = (size + UNITS_PER_WORD-1) / UNITS_PER_WORD;
- if (cum->gprs + n_gprs > 5)
+ if (cum->gprs + n_gprs > GP_ARG_NUM_REG)
return 0;
else
return gen_rtx_REG (mode, cum->gprs + 2);
@@ -6832,6 +6859,9 @@ s390_build_builtin_va_list (void)
f_sav = build_decl (FIELD_DECL, get_identifier ("__reg_save_area"),
ptr_type_node);
+ va_list_gpr_counter_field = f_gpr;
+ va_list_fpr_counter_field = f_fpr;
+
DECL_FIELD_CONTEXT (f_gpr) = record;
DECL_FIELD_CONTEXT (f_fpr) = record;
DECL_FIELD_CONTEXT (f_ovf) = record;
@@ -6887,39 +6917,53 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
n_gpr = current_function_args_info.gprs;
n_fpr = current_function_args_info.fprs;
- t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
- build_int_cst (NULL_TREE, n_gpr));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ if (cfun->va_list_gpr_size)
+ {
+ t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
+ build_int_cst (NULL_TREE, n_gpr));
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
- t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
- build_int_cst (NULL_TREE, n_fpr));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ if (cfun->va_list_fpr_size)
+ {
+ t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
+ build_int_cst (NULL_TREE, n_fpr));
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
/* Find the overflow area. */
- t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
+ if (n_gpr + cfun->va_list_gpr_size > GP_ARG_NUM_REG
+ || n_fpr + cfun->va_list_fpr_size > FP_ARG_NUM_REG)
+ {
+ t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
- off = INTVAL (current_function_arg_offset_rtx);
- off = off < 0 ? 0 : off;
- if (TARGET_DEBUG_ARG)
- fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
- (int)n_gpr, (int)n_fpr, off);
+ off = INTVAL (current_function_arg_offset_rtx);
+ off = off < 0 ? 0 : off;
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
+ (int)n_gpr, (int)n_fpr, off);
- t = build (PLUS_EXPR, TREE_TYPE (ovf), t, build_int_cst (NULL_TREE, off));
+ t = build (PLUS_EXPR, TREE_TYPE (ovf), t, build_int_cst (NULL_TREE, off));
- t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
/* Find the register save area. */
- t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
- t = build (PLUS_EXPR, TREE_TYPE (sav), t,
- build_int_cst (NULL_TREE, -RETURN_REGNUM * UNITS_PER_WORD));
+ if ((cfun->va_list_gpr_size && n_gpr < GP_ARG_NUM_REG)
+ || (cfun->va_list_fpr_size && n_fpr < FP_ARG_NUM_REG))
+ {
+ t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
+ t = build (PLUS_EXPR, TREE_TYPE (sav), t,
+ build_int_cst (NULL_TREE, -RETURN_REGNUM * UNITS_PER_WORD));
- t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
}
/* Implement va_arg by updating the va_list structure
@@ -6987,7 +7031,7 @@ s390_gimplify_va_arg (tree valist, tree type, tree *pre_p,
sav_ofs = 2 * UNITS_PER_WORD;
sav_scale = UNITS_PER_WORD;
size = UNITS_PER_WORD;
- max_reg = 4;
+ max_reg = GP_ARG_NUM_REG - n_reg;
}
else if (s390_function_arg_float (TYPE_MODE (type), type))
{
@@ -7003,8 +7047,7 @@ s390_gimplify_va_arg (tree valist, tree type, tree *pre_p,
n_reg = 1;
sav_ofs = 16 * UNITS_PER_WORD;
sav_scale = 8;
- /* TARGET_64BIT has up to 4 parameter in fprs */
- max_reg = TARGET_64BIT ? 3 : 1;
+ max_reg = FP_ARG_NUM_REG - n_reg;
}
else
{
@@ -7028,10 +7071,7 @@ s390_gimplify_va_arg (tree valist, tree type, tree *pre_p,
sav_ofs += UNITS_PER_WORD - size;
sav_scale = UNITS_PER_WORD;
- if (n_reg > 1)
- max_reg = 3;
- else
- max_reg = 4;
+ max_reg = GP_ARG_NUM_REG - n_reg;
}
/* Pull the value out of the saved registers ... */