aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2004-05-10 14:26:50 +0000
committerAlan Modra <amodra@gcc.gnu.org>2004-05-10 23:56:50 +0930
commitb2d04ecff8d793aab12249005576f4b36bc263df (patch)
treeb91c0a516954519112bdd143f83a329712f73857 /gcc
parentb6685939515a82257ce895032e981c34b3b71b39 (diff)
downloadgcc-b2d04ecff8d793aab12249005576f4b36bc263df.zip
gcc-b2d04ecff8d793aab12249005576f4b36bc263df.tar.gz
gcc-b2d04ecff8d793aab12249005576f4b36bc263df.tar.bz2
rs6000.c (function_arg_boundary): Always align AltiVec vectors.
* config/rs6000/rs6000.c (function_arg_boundary): Always align AltiVec vectors. (function_arg_advance): Pass TARGET_32BIT -mabi=no-altivec AltiVec vectors by refererence. Align the same for TARGET_64BIT to a 16 byte boundary. Remove useless code. Add function comment. (function_arg): Similarly. Move gpr rs6000_mixed_function_arg call to where it belongs. (function_arg_partial_nregs): Return true for all TARGET_32BIT -mabi=no-altivec AltiVec vectors. Fix debug output. (rs6000_va_arg): Adjust for AltiVec change. From-SVN: r81666
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/rs6000/rs6000.c94
2 files changed, 61 insertions, 46 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 27177b2..294337f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2004-05-10 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (function_arg_boundary): Always align
+ AltiVec vectors.
+ (function_arg_advance): Pass TARGET_32BIT -mabi=no-altivec AltiVec
+ vectors by refererence. Align the same for TARGET_64BIT to a 16
+ byte boundary. Remove useless code. Add function comment.
+ (function_arg): Similarly. Move gpr rs6000_mixed_function_arg
+ call to where it belongs.
+ (function_arg_partial_nregs): Return true for all TARGET_32BIT
+ -mabi=no-altivec AltiVec vectors. Fix debug output.
+ (rs6000_va_arg): Adjust for AltiVec change.
+
2004-05-10 Paul Brook <paul@codesourcery.com>
* config/arm/arm.c (arm_promote_prototypes): Use TARGET_AAPCS_BASED.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 7ee32b1..e1a55e4 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4192,7 +4192,7 @@ function_arg_boundary (enum machine_mode mode, tree type ATTRIBUTE_UNUSED)
return 64;
else if (SPE_VECTOR_MODE (mode))
return 64;
- else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ else if (ALTIVEC_VECTOR_MODE (mode))
return 128;
else
return PARM_BOUNDARY;
@@ -4218,7 +4218,11 @@ rs6000_arg_size (enum machine_mode mode, tree type)
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
+ (TYPE is null for libcalls where that information may not be available.)
+
+ Note that for args passed by reference, function_arg will be called
+ with MODE and TYPE set to that of the pointer to the arg, not the arg
+ itself. */
void
function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
@@ -4295,18 +4299,9 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
else
{
- int n_words;
+ int n_words = rs6000_arg_size (mode, type);
int gregno = cum->sysv_gregno;
- /* Aggregates, IEEE quad, and AltiVec vectors get passed by
- reference. */
- if ((type && AGGREGATE_TYPE_P (type))
- || mode == TFmode
- || ALTIVEC_VECTOR_MODE (mode))
- n_words = 1;
- else
- n_words = rs6000_arg_size (mode, type);
-
/* Long long and SPE vectors are put in (r3,r4), (r5,r6),
(r7,r8) or (r9,r10). As does any other 2 word item such
as complex int due to a historical mistake. */
@@ -4342,10 +4337,16 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
else
{
- int align = (TARGET_32BIT && (cum->words & 1) != 0
- && function_arg_boundary (mode, type) == 64) ? 1 : 0;
+ int n_words = rs6000_arg_size (mode, type);
+ int align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
- cum->words += align + rs6000_arg_size (mode, type);
+ /* The simple alignment calculation here works because
+ function_arg_boundary / PARM_BOUNDARY will only be 1 or 2.
+ If we ever want to handle alignments larger than 8 bytes for
+ 32-bit or 16 bytes for 64-bit, then we'll need to take into
+ account the offset to the start of the parm save area. */
+ align &= cum->words;
+ cum->words += align + n_words;
if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& TARGET_HARD_FLOAT && TARGET_FPRS)
@@ -4544,7 +4545,11 @@ rs6000_mixed_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
both an FP and integer register (or possibly FP reg and stack). Library
functions (when CALL_LIBCALL is set) always have the proper types for args,
so we can pass the FP value just in one register. emit_library_function
- doesn't support PARALLEL anyway. */
+ doesn't support PARALLEL anyway.
+
+ Note that for args passed by reference, function_arg will be called
+ with MODE and TYPE set to that of the pointer to the arg, not the arg
+ itself. */
struct rtx_def *
function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
@@ -4658,18 +4663,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
else
{
- int n_words;
+ int n_words = rs6000_arg_size (mode, type);
int gregno = cum->sysv_gregno;
- /* Aggregates, IEEE quad, and AltiVec vectors get passed by
- reference. */
- if ((type && AGGREGATE_TYPE_P (type))
- || mode == TFmode
- || ALTIVEC_VECTOR_MODE (mode))
- n_words = 1;
- else
- n_words = rs6000_arg_size (mode, type);
-
/* Long long and SPE vectors are put in (r3,r4), (r5,r6),
(r7,r8) or (r9,r10). As does any other 2 word item such
as complex int due to a historical mistake. */
@@ -4685,16 +4681,8 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
else
{
- int align = (TARGET_32BIT && (cum->words & 1) != 0
- && function_arg_boundary (mode, type) == 64) ? 1 : 0;
- int align_words = cum->words + align;
-
- if (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
- return NULL_RTX;
-
- if (TARGET_32BIT && TARGET_POWERPC64
- && (mode == DImode || mode == BLKmode))
- return rs6000_mixed_function_arg (cum, mode, type, align_words);
+ int align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
+ int align_words = cum->words + (cum->words & align);
if (USE_FP_FOR_ARG_P (cum, mode, type))
{
@@ -4763,7 +4751,13 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return gen_rtx_PARALLEL (mode, gen_rtvec_v (n, r));
}
else if (align_words < GP_ARG_NUM_REG)
- return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
+ {
+ if (TARGET_32BIT && TARGET_POWERPC64
+ && (mode == DImode || mode == BLKmode))
+ return rs6000_mixed_function_arg (cum, mode, type, align_words);
+
+ return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
+ }
else
return NULL_RTX;
}
@@ -4810,7 +4804,10 @@ function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
the argument itself. The pointer is passed in whatever way is
appropriate for passing a pointer to that type.
- Under V.4, structures and unions are passed by reference.
+ Under V.4, aggregates and long double are passed by reference.
+
+ As an extension to all 32-bit ABIs, AltiVec vectors are passed by
+ reference unless the AltiVec vector extension ABI is in force.
As an extension to all ABIs, variable sized types are passed by
reference. */
@@ -4820,17 +4817,18 @@ function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED,
tree type, int named ATTRIBUTE_UNUSED)
{
- if (DEFAULT_ABI == ABI_V4
- && ((type && AGGREGATE_TYPE_P (type))
- || mode == TFmode
- || (!TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))))
+ if ((DEFAULT_ABI == ABI_V4
+ && ((type && AGGREGATE_TYPE_P (type))
+ || mode == TFmode))
+ || (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ || (type && int_size_in_bytes (type) < 0))
{
if (TARGET_DEBUG_ARG)
- fprintf (stderr, "function_arg_pass_by_reference: aggregate\n");
+ fprintf (stderr, "function_arg_pass_by_reference\n");
return 1;
}
- return type && int_size_in_bytes (type) < 0;
+ return 0;
}
static void
@@ -5081,8 +5079,12 @@ rs6000_va_arg (tree valist, tree type)
if (DEFAULT_ABI != ABI_V4)
{
- /* Variable sized types are passed by reference. */
- if (int_size_in_bytes (type) < 0)
+ /* Variable sized types are passed by reference, as are AltiVec
+ vectors when 32-bit and not using the AltiVec ABI extension. */
+ if (int_size_in_bytes (type) < 0
+ || (TARGET_32BIT
+ && !TARGET_ALTIVEC_ABI
+ && ALTIVEC_VECTOR_MODE (TYPE_MODE (type))))
{
u = build_pointer_type (type);