When the size of record or array is smaller than the target alignment, don't over align them and set DR_TARGET_ALIGNMENT to the reduced target alignment. If the natural alignment isn't lower than the reduced target alignment, set base_misaligned to false.
gcc/ PR middle-end/126410 * tree-vect-data-refs.cc (vect_compute_data_ref_alignment): Don't over align record and array. * tree-vect-stmts.cc (vectorizable_store): No unaligned access dump if DR_TARGET_ALIGNMENT is less than the vector alignment. (vectorizable_load): Likewise. gcc/testsuite/ PR middle-end/126410 * gcc.target/i386/pr126410-1a.c: New test. * gcc.target/i386/pr126410-1b.c: Likewise. * gcc.target/i386/pr126410-1c.c: Likewise. * gcc.target/i386/pr126410-2a.c: Likewise. * gcc.target/i386/pr126410-2b.c: Likewise. * gcc.target/i386/pr126410-2c.c: Likewise. -- H.J.
From 2c6b545a7181ba6a6dfebb7c188b55f6dc57910a Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Sun, 26 Jul 2026 19:21:55 +0800 Subject: [PATCH] vectorizer: Don't over align record and array When the size of record or array is smaller than the target alignment, don't over align them and set DR_TARGET_ALIGNMENT to the reduced target alignment. If the natural alignment isn't lower than the reduced target alignment, set base_misaligned to false. gcc/ PR middle-end/126410 * tree-vect-data-refs.cc (vect_compute_data_ref_alignment): Don't over align record and array. * tree-vect-stmts.cc (vectorizable_store): No unaligned access dump if DR_TARGET_ALIGNMENT is less than the vector alignment. (vectorizable_load): Likewise. gcc/testsuite/ PR middle-end/126410 * gcc.target/i386/pr126410-1a.c: New test. * gcc.target/i386/pr126410-1b.c: Likewise. * gcc.target/i386/pr126410-1c.c: Likewise. * gcc.target/i386/pr126410-2a.c: Likewise. * gcc.target/i386/pr126410-2b.c: Likewise. * gcc.target/i386/pr126410-2c.c: Likewise. Signed-off-by: H.J. Lu <[email protected]> --- gcc/testsuite/gcc.target/i386/pr126410-1a.c | 22 +++++++ gcc/testsuite/gcc.target/i386/pr126410-1b.c | 8 +++ gcc/testsuite/gcc.target/i386/pr126410-1c.c | 7 ++ gcc/testsuite/gcc.target/i386/pr126410-2a.c | 22 +++++++ gcc/testsuite/gcc.target/i386/pr126410-2b.c | 8 +++ gcc/testsuite/gcc.target/i386/pr126410-2c.c | 7 ++ gcc/tree-vect-data-refs.cc | 73 +++++++++++++++++---- gcc/tree-vect-stmts.cc | 23 +++++-- 8 files changed, 152 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr126410-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126410-1b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126410-1c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126410-2a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126410-2b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr126410-2c.c diff --git a/gcc/testsuite/gcc.target/i386/pr126410-1a.c b/gcc/testsuite/gcc.target/i386/pr126410-1a.c new file mode 100644 index 00000000000..489064cda6b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126410-1a.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -march=x86-64-v4 -fomit-frame-pointer" } */ +/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */ + +#ifndef N +#define N 4 +#endif + +typedef float vector[N]; + +extern vector v; + +extern void foo (vector *); + +void +func (vector a, vector b) +{ + vector r; + for (int i = 0; i < N; i++) + r[i] = a[i] * b[i]; + foo (&r); +} diff --git a/gcc/testsuite/gcc.target/i386/pr126410-1b.c b/gcc/testsuite/gcc.target/i386/pr126410-1b.c new file mode 100644 index 00000000000..7e7141eb2e0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126410-1b.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -march=x86-64-v4 -fomit-frame-pointer" } */ +/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]*\\$-32,\[\\t \]*%\[re\]?sp" } } */ +/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */ + +#define N 8 + +#include "pr126410-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126410-1c.c b/gcc/testsuite/gcc.target/i386/pr126410-1c.c new file mode 100644 index 00000000000..8b5fb5bc150 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126410-1c.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -march=x86-64-v4 -fomit-frame-pointer" } */ +/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */ + +#define N 16 + +#include "pr126410-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126410-2a.c b/gcc/testsuite/gcc.target/i386/pr126410-2a.c new file mode 100644 index 00000000000..8bd45573145 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126410-2a.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -march=x86-64-v4 -fomit-frame-pointer" } */ +/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */ + +#ifndef N +#define N 4 +#endif + +typedef struct { float values[N]; } vector; + +extern vector v; + +extern void foo (vector *); + +void +func (vector a, vector b) +{ + vector r; + for (int i = 0; i < N; i++) + r.values[i] = a.values[i] * b.values[i]; + foo (&r); +} diff --git a/gcc/testsuite/gcc.target/i386/pr126410-2b.c b/gcc/testsuite/gcc.target/i386/pr126410-2b.c new file mode 100644 index 00000000000..30743cd73f1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126410-2b.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -march=x86-64-v4 -fomit-frame-pointer" } */ +/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]*\\$-32,\[\\t \]*%\[re\]?sp" } } */ +/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */ + +#define N 8 + +#include "pr126410-2a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr126410-2c.c b/gcc/testsuite/gcc.target/i386/pr126410-2c.c new file mode 100644 index 00000000000..d618b36e15b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126410-2c.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -march=x86-64-v4 -fomit-frame-pointer" } */ +/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */ + +#define N 16 + +#include "pr126410-2a.c" diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc index 0e0754769ae..64080098b64 100644 --- a/gcc/tree-vect-data-refs.cc +++ b/gcc/tree-vect-data-refs.cc @@ -1646,26 +1646,71 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info, { unsigned int max_alignment; tree base = get_base_for_alignment (drb->base_address, &max_alignment); - if (max_alignment < vect_align_c - || (loop_vinfo && LOOP_VINFO_EPILOGUE_P (loop_vinfo)) - || !vect_can_force_dr_alignment_p (base, - vect_align_c * BITS_PER_UNIT)) + bool base_misaligned = true; + + tree type = TREE_TYPE (base); + if (AGGREGATE_TYPE_P (type)) + { + poly_uint64 type_size; + if (poly_int_tree_p (TYPE_SIZE_UNIT (type), &type_size) + && type_size.is_constant ()) + { + unsigned HOST_WIDE_INT size = type_size.to_constant (); + if (size && size < vect_align_c) + { + /* Don't over align record and array if data size is + smaller than the target alignment. */ + + do + { + vect_align_c /= 2; + } + while (size < vect_align_c); + + if (base_alignment >= vect_align_c) + { + /* Set base_misaligned to false if the natural + alignment is higher than the reduced target + alignment. */ + base_misaligned = false; + if (dump_enabled_p ()) + dump_printf_loc + (MSG_NOTE, vect_location, + "no need to force alignment of ref: %T\n", + ref); + } + + /* Set DR_TARGET_ALIGNMENT to the reduced target + alignment. */ + SET_DR_TARGET_ALIGNMENT (dr_info, vect_align_c); + } + } + } + + if (base_misaligned) { + if (max_alignment < vect_align_c + || (loop_vinfo && LOOP_VINFO_EPILOGUE_P (loop_vinfo)) + || !vect_can_force_dr_alignment_p + (base, vect_align_c * BITS_PER_UNIT)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "can't force alignment of ref: %T\n", + ref); + return; + } + + /* Force the alignment of the decl. + NOTE: This is the only change to the code we make during + the analysis phase, before deciding to vectorize the loop. */ if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "can't force alignment of ref: %T\n", ref); - return; + "force alignment of %T\n", ref); } - /* Force the alignment of the decl. - NOTE: This is the only change to the code we make during - the analysis phase, before deciding to vectorize the loop. */ - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "force alignment of %T\n", ref); - dr_info->base_decl = base; - dr_info->base_misaligned = true; + dr_info->base_misaligned = base_misaligned; base_misalignment = 0; } poly_int64 misalignment diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 488b9754bed..54d24c75663 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -8298,8 +8298,15 @@ vectorizable_store (vec_info *vinfo, && memory_access_type != VMAT_STRIDED_SLP && memory_access_type != VMAT_INVARIANT && alignment_support_scheme != dr_aligned) - dump_printf_loc (MSG_NOTE, vect_location, - "Vectorizing an unaligned access.\n"); + { + /* DR_TARGET_ALIGNMENT may be reduced if data size is smaller + than the vector alignment. */ + unsigned int align = TYPE_ALIGN_UNIT (vectype); + poly_uint64 target_align = DR_TARGET_ALIGNMENT (dr_info); + if (known_ge (target_align, align)) + dump_printf_loc (MSG_NOTE, vect_location, + "Vectorizing an unaligned access.\n"); + } } /* Transform. */ @@ -9967,8 +9974,16 @@ vectorizable_load (vec_info *vinfo, && memory_access_type != VMAT_STRIDED_SLP && memory_access_type != VMAT_INVARIANT && alignment_support_scheme != dr_aligned) - dump_printf_loc (MSG_NOTE, vect_location, - "Vectorizing an unaligned access.\n"); + { + /* DR_TARGET_ALIGNMENT may be reduced if data size is smaller + than the vector alignment. */ + dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); + unsigned int align = TYPE_ALIGN_UNIT (vectype); + poly_uint64 target_align = DR_TARGET_ALIGNMENT (dr_info); + if (known_ge (target_align, align)) + dump_printf_loc (MSG_NOTE, vect_location, + "Vectorizing an unaligned access.\n"); + } if (memory_access_type == VMAT_LOAD_STORE_LANES) vinfo->any_known_not_updated_vssa = true; -- 2.55.0
