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

Reply via email to