aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2024-09-06 05:24:07 -0700
committerH.J. Lu <hjl.tools@gmail.com>2024-09-08 16:01:32 -0700
commitfa7bbb065c63aa802e0bbb04d605407dad58cf94 (patch)
tree809b44dc206b915f45c165ac2c2098b74335c854 /gcc
parent1e17a11171dae2bc5d60380bf48c12ef49f59c7f (diff)
downloadgcc-fa7bbb065c63aa802e0bbb04d605407dad58cf94.zip
gcc-fa7bbb065c63aa802e0bbb04d605407dad58cf94.tar.gz
gcc-fa7bbb065c63aa802e0bbb04d605407dad58cf94.tar.bz2
x86-64: Don't use temp for argument in a TImode register
Don't use temp for a PARALLEL BLKmode argument of an EXPR_LIST expression in a TImode register. Otherwise, the TImode variable will be put in the GPR save area which guarantees only 8-byte alignment. gcc/ PR target/116621 * config/i386/i386.cc (ix86_gimplify_va_arg): Don't use temp for a PARALLEL BLKmode container of an EXPR_LIST expression in a TImode register. gcc/testsuite/ PR target/116621 * gcc.target/i386/pr116621.c: New test. Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.cc22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr116621.c43
2 files changed, 63 insertions, 2 deletions
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 707b75a..4532012 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -4908,13 +4908,31 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
examine_argument (nat_mode, type, 0, &needed_intregs, &needed_sseregs);
- need_temp = (!REG_P (container)
+ bool container_in_reg = false;
+ if (REG_P (container))
+ container_in_reg = true;
+ else if (GET_CODE (container) == PARALLEL
+ && GET_MODE (container) == BLKmode
+ && XVECLEN (container, 0) == 1)
+ {
+ /* Check if it is a PARALLEL BLKmode container of an EXPR_LIST
+ expression in a TImode register. In this case, temp isn't
+ needed. Otherwise, the TImode variable will be put in the
+ GPR save area which guarantees only 8-byte alignment. */
+ rtx x = XVECEXP (container, 0, 0);
+ if (GET_CODE (x) == EXPR_LIST
+ && REG_P (XEXP (x, 0))
+ && XEXP (x, 1) == const0_rtx)
+ container_in_reg = true;
+ }
+
+ need_temp = (!container_in_reg
&& ((needed_intregs && TYPE_ALIGN (type) > 64)
|| TYPE_ALIGN (type) > 128));
/* In case we are passing structure, verify that it is consecutive block
on the register save area. If not we need to do moves. */
- if (!need_temp && !REG_P (container))
+ if (!need_temp && !container_in_reg)
{
/* Verify that all registers are strictly consecutive */
if (SSE_REGNO_P (REGNO (XEXP (XVECEXP (container, 0, 0), 0))))
diff --git a/gcc/testsuite/gcc.target/i386/pr116621.c b/gcc/testsuite/gcc.target/i386/pr116621.c
new file mode 100644
index 0000000..7042664
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr116621.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+#include <string.h>
+
+union S8302
+{
+ union
+ {
+ double b;
+ int c;
+ } a;
+ long double d;
+ unsigned short int f[5];
+};
+
+union S8302 s8302;
+extern void check8302va (int i, ...);
+
+int
+main (void)
+{
+ memset (&s8302, '\0', sizeof (s8302));
+ s8302.a.b = -221438.250000;
+ check8302va (1, s8302);
+ return 0;
+}
+
+__attribute__((noinline, noclone))
+void
+check8302va (int z, ...)
+{
+ union S8302 arg, *p;
+ va_list ap;
+
+ __builtin_va_start (ap, z);
+ p = &s8302;
+ arg = __builtin_va_arg (ap, union S8302);
+ if (p->a.b != arg.a.b)
+ __builtin_abort ();
+ __builtin_va_end (ap);
+}