commit e754b70fe5470b975d31887fa5647f1c92d6522d
Author: H.J. Lu <[email protected]>
Date: Tue Apr 7 23:16:38 2026 +0800
x86: Rewrite ix86_find_max_used_stack_alignment
doesn't handle
(insn 13 12 14 2 (set (reg:DI 0 ax [orig:112 _35 ] [112])
(sign_extend:DI (mem/c:SI (symbol_ref:DI
("vpx_quantize_b_avx_index") [flags 0x2] <var_decl 0x7fffe941f000
vpx_quantize_b_avx_index>) [2 vpx_quantize_b_avx_index+0 S4 A32])))
"z.c":14:56 188 {*extendsidi2_rex64}
(nil))
...
(insn 21 20 35 4 (set (mem:V4DI (reg/f:DI 0 ax [orig:104 _38 ] [104])
[1 MEM[(__m256i *)_38]+0 S32 A256])
(reg:V4DI 20 xmm0 [116])) "z.c":5:59 2459 {movv4di_internal}
(nil))
correctly since it assumes that
(mem:V4DI (reg/f:DI 0 ax [orig:104 _38 ] [104]) [1 MEM[(__m256i
*)_38]+0 S32 A256])
is on stack. Add ix86_not_on_stack_p and call it on base and index
registers to check if they point to stack. If false, don't update
stack alignment.
gcc/
PR target/126202
* config/i386/i386.cc (register_info_data): New.
(ix86_get_register_info): Likewise.
(ix86_not_on_stack_p): Likewise.
(ix86_update_stack_alignment_2): Add a basic_block argument.
Call ix86_not_on_stack_p to check if base or index registers
point to stack and don't update alignment if false.
(ix86_update_stack_alignment_1): Add a basic_block argument and
pass it to ix86_update_stack_alignment_2.
(ix86_update_stack_alignment): Pass the basic_block of INSN
to ix86_update_stack_alignment_1.
(ix86_find_max_used_stack_alignment): Call calculate_dominance_info
before calling ix86_update_stack_alignment and call
free_dominance_info after.
gcc/testsuite/
PR target/126202
* g++.target/i386/pr126202-1.C: New test.
* gcc.target/i386/pr126202-1.c: Likewise.
--
H.J.
From e795a50b3eab48a21fa6254044a6e16a728d6d02 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Sat, 11 Jul 2026 06:30:28 +0800
Subject: [PATCH] x86: Check if a register points to stack
commit e754b70fe5470b975d31887fa5647f1c92d6522d
Author: H.J. Lu <[email protected]>
Date: Tue Apr 7 23:16:38 2026 +0800
x86: Rewrite ix86_find_max_used_stack_alignment
doesn't handle
(insn 13 12 14 2 (set (reg:DI 0 ax [orig:112 _35 ] [112])
(sign_extend:DI (mem/c:SI (symbol_ref:DI ("vpx_quantize_b_avx_index") [flags 0x2] <var_decl 0x7fffe941f000 vpx_quantize_b_avx_index>) [2 vpx_quantize_b_avx_index+0 S4 A32]))) "z.c":14:56 188 {*extendsidi2_rex64}
(nil))
...
(insn 21 20 35 4 (set (mem:V4DI (reg/f:DI 0 ax [orig:104 _38 ] [104]) [1 MEM[(__m256i *)_38]+0 S32 A256])
(reg:V4DI 20 xmm0 [116])) "z.c":5:59 2459 {movv4di_internal}
(nil))
correctly since it assumes that
(mem:V4DI (reg/f:DI 0 ax [orig:104 _38 ] [104]) [1 MEM[(__m256i *)_38]+0 S32 A256])
is on stack. Add ix86_not_on_stack_p and call it on base and index
registers to check if they point to stack. If false, don't update
stack alignment.
gcc/
PR target/126202
* config/i386/i386.cc (register_info_data): New.
(ix86_get_register_info): Likewise.
(ix86_not_on_stack_p): Likewise.
(ix86_update_stack_alignment_2): Add a basic_block argument.
Call ix86_not_on_stack_p to check if base or index registers
point to stack and don't update alignment if false.
(ix86_update_stack_alignment_1): Add a basic_block argument and
pass it to ix86_update_stack_alignment_2.
(ix86_update_stack_alignment): Pass the basic_block of INSN
to ix86_update_stack_alignment_1.
(ix86_find_max_used_stack_alignment): Call calculate_dominance_info
before calling ix86_update_stack_alignment and call
free_dominance_info after.
gcc/testsuite/
PR target/126202
* g++.target/i386/pr126202-1.C: New test.
* gcc.target/i386/pr126202-1.c: Likewise.
Signed-off-by: H.J. Lu <[email protected]>
---
gcc/config/i386/i386.cc | 104 +++++++++++++++++++--
gcc/testsuite/g++.target/i386/pr126202-1.C | 71 ++++++++++++++
gcc/testsuite/gcc.target/i386/pr126202-1.c | 29 ++++++
3 files changed, 198 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/g++.target/i386/pr126202-1.C
create mode 100644 gcc/testsuite/gcc.target/i386/pr126202-1.c
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 1e778c4a2a7..a1f3d8322b5 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8617,11 +8617,86 @@ output_probe_stack_range (rtx reg, rtx end)
return "";
}
+/* Data passed to and from ix86_get_register_info. */
+struct register_info_data
+{
+ /* The destination register number to check. */
+ unsigned int regno;
+ /* Set to true if the destination register is in Pmode. */
+ bool pmode;
+ /* Set to true if the destination register doesn't point to stack. */
+ bool not_stack;
+};
+
+/* Return the pointer info in *DATA for the destination register, DEST,
+ in PAT if DEST matches the destination register. */
+
+static void
+ix86_get_register_info (rtx dest, const_rtx pat, void *data)
+{
+ register_info_data *p = (register_info_data *) data;
+ if (GET_MODE (dest) != Pmode
+ || !REG_P (dest)
+ || REGNO (dest) != p->regno)
+ return;
+
+ p->pmode = true;
+
+ if (GET_CODE (pat) != SET)
+ return;
+
+ rtx src = SET_SRC (pat);
+ if (GET_CODE (src) == SIGN_EXTEND || GET_CODE (src) == ZERO_EXTEND)
+ src = XEXP (src, 0);
+ if (MEM_P (src))
+ src = XEXP (src, 0);
+ if (CONST_INT_P (src)
+ || SYMBOLIC_CONST (src)
+ || reg_mentioned_p (dest, src))
+ p->not_stack = true;
+}
+
+/* Return true if OP in BB isn't on stack. */
+
+static bool
+ix86_not_on_stack_p (const_rtx op, basic_block bb)
+{
+ bool not_on_stack = false;
+
+ unsigned int regno = REGNO (op);
+ for (df_ref def = DF_REG_DEF_CHAIN (regno);
+ def;
+ def = DF_REF_NEXT_REG (def))
+ {
+ if (DF_REF_IS_ARTIFICIAL (def)
+ || DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER)
+ || DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER))
+ continue;
+
+ basic_block set_bb = DF_REF_BB (def);
+ if (dominated_by_p (CDI_DOMINATORS, bb, set_bb))
+ {
+ rtx_insn *insn = DF_REF_INSN (def);
+ register_info_data data = { regno, false, false };
+ note_stores (insn, ix86_get_register_info, &data);
+ if (!data.pmode)
+ continue;
+ if (data.not_stack)
+ not_on_stack = true;
+ else
+ return false;
+ }
+ }
+
+ return not_on_stack;
+}
+
/* Update the maximum stack slot alignment from memory alignment if
OP is stack memory. */
static void
-ix86_update_stack_alignment_2 (const_rtx op, unsigned int &alignment)
+ix86_update_stack_alignment_2 (const_rtx op, basic_block bb,
+ unsigned int &alignment)
{
unsigned int mem_align = MEM_ALIGN (op);
if (mem_align <= alignment)
@@ -8733,6 +8808,16 @@ ix86_update_stack_alignment_2 (const_rtx op, unsigned int &alignment)
return;
}
+ if (parts.base
+ && REG_P (parts.base)
+ && ix86_not_on_stack_p (parts.base, bb))
+ return;
+
+ if (parts.index
+ && REG_P (parts.index)
+ && ix86_not_on_stack_p (parts.index, bb))
+ return;
+
alignment = mem_align;
}
@@ -8740,12 +8825,13 @@ ix86_update_stack_alignment_2 (const_rtx op, unsigned int &alignment)
SET references stack memory. */
static void
-ix86_update_stack_alignment_1 (rtx set, unsigned int &alignment)
+ix86_update_stack_alignment_1 (rtx set, basic_block bb,
+ unsigned int &alignment)
{
rtx dest = SET_DEST (set);
if (MEM_P (dest))
- return ix86_update_stack_alignment_2 (dest, alignment);
+ return ix86_update_stack_alignment_2 (dest, bb, alignment);
const_rtx src = SET_SRC (set);
@@ -8755,7 +8841,7 @@ ix86_update_stack_alignment_1 (rtx set, unsigned int &alignment)
auto op = *iter;
if (MEM_P (op))
- return ix86_update_stack_alignment_2 (op, alignment);
+ return ix86_update_stack_alignment_2 (op, bb, alignment);
}
}
@@ -8767,7 +8853,8 @@ ix86_update_stack_alignment (rtx_insn *insn, unsigned int &alignment)
{
rtx set = single_set (insn);
if (set)
- return ix86_update_stack_alignment_1 (set, alignment);
+ return ix86_update_stack_alignment_1 (set, BLOCK_FOR_INSN (insn),
+ alignment);
rtx pat = PATTERN (insn);
if (GET_CODE (pat) != PARALLEL)
@@ -8778,7 +8865,8 @@ ix86_update_stack_alignment (rtx_insn *insn, unsigned int &alignment)
rtx exp = XVECEXP (pat, 0, i);
if (GET_CODE (exp) == SET)
- ix86_update_stack_alignment_1 (exp, alignment);
+ ix86_update_stack_alignment_1 (exp, BLOCK_FOR_INSN (insn),
+ alignment);
}
}
@@ -8807,6 +8895,8 @@ ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
&& stack_alignment > crtl->preferred_stack_boundary)
stack_alignment = crtl->preferred_stack_boundary;
+ calculate_dominance_info (CDI_DOMINATORS);
+
FOR_EACH_BB_FN (bb, cfun)
{
rtx_insn *insn;
@@ -8832,6 +8922,8 @@ ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
ix86_update_stack_alignment (insn, stack_alignment);
}
}
+
+ free_dominance_info (CDI_DOMINATORS);
}
/* Finalize stack_realign_needed and frame_pointer_needed flags, which
diff --git a/gcc/testsuite/g++.target/i386/pr126202-1.C b/gcc/testsuite/g++.target/i386/pr126202-1.C
new file mode 100644
index 00000000000..95d463bf017
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr126202-1.C
@@ -0,0 +1,71 @@
+/* { dg-do compile { target pie } } */
+/* { dg-options "-O3 -std=gnu++20 -march=znver5 -fPIE" } */
+
+typedef int fixed16_16;
+struct vec2_fixed
+{
+ fixed16_16 x, z;
+} s_polygonUv[32];
+struct vec3_fixed
+{
+ fixed16_16 x, y, z;
+};
+template <typename> struct allocator_traits;
+template <typename> class allocator;
+template <typename _Tp> struct allocator_traits<allocator<_Tp>>
+{
+ using value_type = _Tp;
+ using pointer = _Tp *;
+ template <typename _Up> using rebind_alloc = allocator<_Up>;
+};
+template <typename _Alloc> struct __alloc_traits : allocator_traits<_Alloc>
+{
+ typedef allocator_traits<_Alloc> _Base_type;
+ typedef _Base_type::value_type reference;
+ template <typename _Tp> struct rebind
+ {
+ typedef typename _Base_type::rebind_alloc<_Tp> other;
+ };
+};
+template <typename _Tp, typename _Alloc> struct _Vector_base
+{
+ typedef __alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type;
+ struct
+ {
+ __alloc_traits<_Tp_alloc_type>::pointer _M_start;
+ } _M_impl;
+};
+template <typename _Tp, typename _Alloc = allocator<_Tp>>
+struct vector : _Vector_base<_Tp, _Alloc>
+{
+ __alloc_traits<typename _Vector_base<_Tp, _Alloc>::_Tp_alloc_type>::reference
+ operator[] (int __n)
+ {
+ return *(this->_M_impl._M_start + __n);
+ }
+};
+extern int vertexCount, s_polygonIntensity_0;
+struct JmPolygon
+{
+ int *indices;
+};
+extern vector<vec3_fixed> s_verticesVS;
+extern vector<fixed16_16> s_vertexIntensity;
+extern vec3_fixed s_polygonVerticesVS[2];
+extern JmPolygon *robj3d_setupPolygon_polygon;
+void
+robj3d_setupPolygon ()
+{
+ for (int v = 0; v < vertexCount; v++)
+ s_polygonVerticesVS[v]
+ = s_verticesVS[robj3d_setupPolygon_polygon->indices[v]];
+ vec2_fixed *uv = (vec2_fixed *)robj3d_setupPolygon_polygon;
+ vec2_fixed zero{};
+ for (int v = 0; v < vertexCount; v++)
+ s_polygonUv[v] = uv[v];
+ for (int v = 0; v < vertexCount; v++)
+ s_polygonUv[v] = zero;
+ for (int v;;)
+ s_polygonIntensity_0
+ = s_vertexIntensity[robj3d_setupPolygon_polygon->indices[v]];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126202-1.c b/gcc/testsuite/gcc.target/i386/pr126202-1.c
new file mode 100644
index 00000000000..7a2b5b7be15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126202-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=x86-64 -mavx -O2 -fno-strict-overflow" } */
+
+typedef long __m128i __attribute__ ((__vector_size__ (16)));
+__m128i _mm_store_si128___B;
+typedef long __m256i __attribute__ ((__vector_size__ (32)));
+int vpx_quantize_b_avx___trans_tmp_6, vpx_quantize_b_avx_index;
+void
+_mm256_store_si256 (__m256i *__P, __m256i __A)
+{
+ *__P = __A;
+}
+void
+store_tran_low (int *b)
+{
+ *(__m128i *)b = _mm_store_si128___B;
+}
+void
+vpx_quantize_b_avx (int, long, int, int *qcoeff_ptr, int, short,
+ short *eob_ptr)
+{
+ __m256i __trans_tmp_5 = {};
+ if (vpx_quantize_b_avx___trans_tmp_6)
+ _mm256_store_si256 ((__m256i *)(qcoeff_ptr
+ + vpx_quantize_b_avx_index + 8),
+ __trans_tmp_5);
+ store_tran_low (qcoeff_ptr + vpx_quantize_b_avx_index + 8);
+ *eob_ptr = 0;
+}
--
2.55.0