https://gcc.gnu.org/g:64af1a600f6bd57d47a5926f2328682bba88be90
commit r13-9028-g64af1a600f6bd57d47a5926f2328682bba88be90 Author: H.J. Lu <hjl.to...@gmail.com> Date: Fri Sep 6 05:24:07 2024 -0700 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.to...@gmail.com> (cherry picked from commit fa7bbb065c63aa802e0bbb04d605407dad58cf94) Diff: --- gcc/config/i386/i386.cc | 22 ++++++++++++++-- gcc/testsuite/gcc.target/i386/pr116621.c | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 85aa68175aa3..e4d3ce1acc87 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -4814,13 +4814,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 000000000000..704266458a85 --- /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); +}