public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] x86: Properly find the maximum stack slot alignment
@ 2023-07-05 23:27 H.J. Lu
  2023-07-06  6:38 ` Richard Biener
  0 siblings, 1 reply; 2+ messages in thread
From: H.J. Lu @ 2023-07-05 23:27 UTC (permalink / raw)
  To: gcc-patches

Don't assume that stack slots can only be accessed by stack or frame
registers.  Also check memory accesses from registers defined by
stack or frame registers.

gcc/

	PR target/109780
	* config/i386/i386.cc (ix86_set_with_register_source): New.
	(ix86_find_all_stack_access): Likewise.
	(ix86_find_max_used_stack_alignment): Also check memory accesses
	from registers defined by stack or frame registers.

gcc/testsuite/

	PR target/109780
	* g++.target/i386/pr109780-1.C: New test.
	* gcc.target/i386/pr109780-1.c: Likewise.
	* gcc.target/i386/pr109780-2.c: Likewise.
---
 gcc/config/i386/i386.cc                    | 145 ++++++++++++++++++---
 gcc/testsuite/g++.target/i386/pr109780-1.C |  72 ++++++++++
 gcc/testsuite/gcc.target/i386/pr109780-1.c |  14 ++
 gcc/testsuite/gcc.target/i386/pr109780-2.c |  21 +++
 4 files changed, 233 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/i386/pr109780-1.C
 create mode 100644 gcc/testsuite/gcc.target/i386/pr109780-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr109780-2.c

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index caca74d6dec..85dd8cb0581 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -8084,6 +8084,72 @@ output_probe_stack_range (rtx reg, rtx end)
   return "";
 }
 
+/* Check if PAT is a SET with register source.  */
+
+static void
+ix86_set_with_register_source (rtx, const_rtx pat, void *data)
+{
+  if (GET_CODE (pat) != SET)
+    return;
+
+  rtx src = SET_SRC (pat);
+  if (MEM_P (src) || CONST_INT_P (src))
+    return;
+
+  bool *may_use_register = (bool *) data;
+  *may_use_register = true;
+}
+
+/* Find all register access registers.  */
+
+static bool
+ix86_find_all_stack_access (HARD_REG_SET &stack_slot_access)
+{
+  bool repeat = false;
+
+  for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (GENERAL_REGNO_P (i)
+	&& !TEST_HARD_REG_BIT (stack_slot_access, i))
+      for (df_ref def = DF_REG_DEF_CHAIN (i);
+	   def != NULL;
+	   def = DF_REF_NEXT_REG (def))
+	{
+	  if (DF_REF_IS_ARTIFICIAL (def))
+	    continue;
+
+	  rtx_insn *insn = DF_REF_INSN (def);
+
+	  bool may_use_register = false;
+	  note_stores (insn, ix86_set_with_register_source,
+		       &may_use_register);
+
+	  if (!may_use_register)
+	    continue;
+
+	  df_ref use;
+	  FOR_EACH_INSN_USE (use, insn)
+	    {
+	      rtx reg = DF_REF_REG (use);
+
+	      if (!REG_P (reg))
+		continue;
+
+	      /* Skip if stack slot access register isn't used.  */
+	      if (!TEST_HARD_REG_BIT (stack_slot_access,
+				      REGNO (reg)))
+		continue;
+
+	      /* Add this register to stack_slot_access.  */
+	      add_to_hard_reg_set (&stack_slot_access, Pmode, i);
+
+	      /* Repeat if a register is added to stack_slot_access.  */
+	      repeat = true;
+	    }
+	}
+
+  return repeat;
+}
+
 /* Set stack_frame_required to false if stack frame isn't required.
    Update STACK_ALIGNMENT to the largest alignment, in bits, of stack
    slot used if stack frame is required and CHECK_STACK_SLOT is true.  */
@@ -8092,15 +8158,23 @@ static void
 ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
 				    bool check_stack_slot)
 {
-  HARD_REG_SET set_up_by_prologue, prologue_used;
+  HARD_REG_SET set_up_by_prologue, prologue_used, stack_slot_access;
   basic_block bb;
 
   CLEAR_HARD_REG_SET (prologue_used);
   CLEAR_HARD_REG_SET (set_up_by_prologue);
+  CLEAR_HARD_REG_SET (stack_slot_access);
   add_to_hard_reg_set (&set_up_by_prologue, Pmode, STACK_POINTER_REGNUM);
   add_to_hard_reg_set (&set_up_by_prologue, Pmode, ARG_POINTER_REGNUM);
   add_to_hard_reg_set (&set_up_by_prologue, Pmode,
 		       HARD_FRAME_POINTER_REGNUM);
+  /* Stack slot can be accessed by stack pointer, frame pointer or
+     registers defined by stack pointer or frame pointer.  */
+  add_to_hard_reg_set (&stack_slot_access, Pmode,
+		       STACK_POINTER_REGNUM);
+  if (frame_pointer_needed)
+    add_to_hard_reg_set (&stack_slot_access, Pmode,
+			 HARD_FRAME_POINTER_REGNUM);
 
   /* The preferred stack alignment is the minimum stack alignment.  */
   if (stack_alignment > crtl->preferred_stack_boundary)
@@ -8108,32 +8182,65 @@ ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
 
   bool require_stack_frame = false;
 
+  /* Find all register access registers.  */
+  while (ix86_find_all_stack_access (stack_slot_access))
+    ;
+
   FOR_EACH_BB_FN (bb, cfun)
     {
       rtx_insn *insn;
       FOR_BB_INSNS (bb, insn)
-	if (NONDEBUG_INSN_P (insn)
-	    && requires_stack_frame_p (insn, prologue_used,
-				       set_up_by_prologue))
+	if (NONDEBUG_INSN_P (insn))
 	  {
-	    require_stack_frame = true;
+	    if (!require_stack_frame)
+	      {
+		if (requires_stack_frame_p (insn, prologue_used,
+					    set_up_by_prologue))
+		  require_stack_frame = true;
+		else
+		  /* Skip if stack frame isn't required.  */
+		  continue;
+	      }
 
-	    if (check_stack_slot)
+	    /* Stop if stack frame is required, but we don't need to
+	       check stack slot.  */
+	    if (!check_stack_slot)
+	      break;
+
+	    /* Find stack slot access register use.  */
+	    bool stack_slot_register_p = false;
+	    df_ref use;
+	    FOR_EACH_INSN_USE (use, insn)
 	      {
-		/* Find the maximum stack alignment.  */
-		subrtx_iterator::array_type array;
-		FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL)
-		  if (MEM_P (*iter)
-		      && (reg_mentioned_p (stack_pointer_rtx,
-					   *iter)
-			  || reg_mentioned_p (frame_pointer_rtx,
-					      *iter)))
-		    {
-		      unsigned int alignment = MEM_ALIGN (*iter);
-		      if (alignment > stack_alignment)
-			stack_alignment = alignment;
-		    }
+		rtx reg = DF_REF_REG (use);
+
+		if (!REG_P (reg))
+		  continue;
+
+		/* Stop if stack slot access register is used.  */
+		if (TEST_HARD_REG_BIT (stack_slot_access,
+				       REGNO (reg)))
+		  {
+		    stack_slot_register_p = true;
+		    break;
+		  }
 	      }
+
+	    /* Skip if stack slot access registers are unused.  */
+	    if (!stack_slot_register_p)
+	      continue;
+
+	    /* This insn may reference stack slot.  Find the maximum
+	       stack slot alignment.  */
+	    subrtx_iterator::array_type array;
+	    FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL)
+	      if (MEM_P (*iter))
+		{
+		  unsigned int alignment = MEM_ALIGN (*iter);
+		  if (alignment > stack_alignment)
+		    stack_alignment = alignment;
+		  break;
+		}
 	  }
     }
 
diff --git a/gcc/testsuite/g++.target/i386/pr109780-1.C b/gcc/testsuite/g++.target/i386/pr109780-1.C
new file mode 100644
index 00000000000..7e3eabdec94
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr109780-1.C
@@ -0,0 +1,72 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target c++17 } */
+/* { dg-options "-O2 -mavx2 -mtune=haswell" } */
+
+template <typename _Tp> struct remove_reference {
+  using type = __remove_reference(_Tp);
+};
+template <typename T> struct MaybeStorageBase {
+  T val;
+  struct Union {
+    ~Union();
+  } mStorage;
+};
+template <typename T> struct MaybeStorage : MaybeStorageBase<T> {
+  char mIsSome;
+};
+template <typename T, typename U = typename remove_reference<T>::type>
+constexpr MaybeStorage<U> Some(T &&);
+template <typename T, typename U> constexpr MaybeStorage<U> Some(T &&aValue) {
+  return {aValue};
+}
+template <class> struct Span {
+  int operator[](long idx) {
+    int *__trans_tmp_4;
+    if (__builtin_expect(idx, 0))
+      *(int *)__null = false;
+    __trans_tmp_4 = storage_.data();
+    return __trans_tmp_4[idx];
+  }
+  struct {
+    int *data() { return data_; }
+    int *data_;
+  } storage_;
+};
+struct Variant {
+  template <typename RefT> Variant(RefT) {}
+};
+long from_i, from___trans_tmp_9;
+namespace js::intl {
+struct DecimalNumber {
+  Variant string_;
+  unsigned long significandStart_;
+  unsigned long significandEnd_;
+  bool zero_ = false;
+  bool negative_;
+  template <typename CharT> DecimalNumber(CharT string) : string_(string) {}
+  template <typename CharT>
+  static MaybeStorage<DecimalNumber> from(Span<const CharT>);
+  void from();
+};
+} // namespace js::intl
+void js::intl::DecimalNumber::from() {
+  Span<const char16_t> __trans_tmp_3;
+  from(__trans_tmp_3);
+}
+template <typename CharT>
+MaybeStorage<js::intl::DecimalNumber>
+js::intl::DecimalNumber::from(Span<const CharT> chars) {
+  DecimalNumber number(chars);
+  if (auto ch = chars[from_i]) {
+    from_i++;
+    number.negative_ = ch == '-';
+  }
+  while (from___trans_tmp_9 && chars[from_i])
+    ;
+  if (chars[from_i])
+    while (chars[from_i - 1])
+      number.zero_ = true;
+  return Some(number);
+}
+
+/* { dg-final { scan-assembler-not "and\[lq\]?\[^\\n\]*-32,\[^\\n\]*sp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr109780-1.c b/gcc/testsuite/gcc.target/i386/pr109780-1.c
new file mode 100644
index 00000000000..6b06947f2a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr109780-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=skylake" } */
+
+char perm[64];
+
+void
+__attribute__((noipa))
+foo (int n)
+{
+  for (int i = 0; i < n; ++i)
+    perm[i] = i;
+}
+
+/* { dg-final { scan-assembler-not "and\[lq\]?\[^\\n\]*-32,\[^\\n\]*sp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr109780-2.c b/gcc/testsuite/gcc.target/i386/pr109780-2.c
new file mode 100644
index 00000000000..152da06c6ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr109780-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=skylake" } */
+
+#define N 9
+
+void
+f (double x, double y, double *res)
+{
+  y = -y;
+  for (int i = 0; i < N; ++i)
+    {
+      double tmp = y;
+      y = x;
+      x = tmp;
+      res[i] = i;
+    }
+  res[N] = y * y;
+  res[N + 1] = x;
+}
+
+/* { dg-final { scan-assembler-not "and\[lq\]?\[^\\n\]*-32,\[^\\n\]*sp" } } */
-- 
2.41.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-07-06  6:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-05 23:27 [PATCH] x86: Properly find the maximum stack slot alignment H.J. Lu
2023-07-06  6:38 ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).