If the required stack alignment > ASAN alignment, round up the ASAN red
zone size so that variables on stack are properly aligned.

gcc/

PR tree-optimization/120201
* cfgexpand.cc (expand_used_vars): Round up the ASAN red zone
size for stack alignment.

gcc/testsuite/

PR tree-optimization/120201
* g++.dg/asan/pr120201.C: New test.


-- 
H.J.
From 0de2c51995e6cf6e1390e50d061a09e9c8c3ff2c Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Sun, 10 May 2026 10:01:58 +0800
Subject: [PATCH] Round up the ASAN red zone size for stack alignment

If the required stack alignment > ASAN alignment, round up the ASAN red
zone size so that variables on stack are properly aligned.

gcc/

	PR tree-optimization/120201
	* cfgexpand.cc (expand_used_vars): Round up the ASAN red zone
	size for stack alignment.

gcc/testsuite/

	PR tree-optimization/120201
	* g++.dg/asan/pr120201.C: New test.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/cfgexpand.cc                     |  7 +++++
 gcc/testsuite/g++.dg/asan/pr120201.C | 40 ++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/asan/pr120201.C

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 7517e8d5788..3878b3b52ec 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -2681,6 +2681,13 @@ expand_used_vars (bitmap forced_stack_vars)
 	      && sz + ASAN_RED_ZONE_SIZE >= (int) data.asan_alignb)
 	    redzonesz = ((sz + ASAN_RED_ZONE_SIZE + data.asan_alignb - 1)
 			 & ~(data.asan_alignb - HOST_WIDE_INT_1)) - sz;
+	  unsigned int alignment_needed
+	    = crtl->stack_alignment_needed / BITS_PER_UNIT;
+	  /* If the required stack alignment > ASAN alignment, round
+	     up the ASAN red zone size so that variables on stack are
+	     properly aligned.  */
+	  if (alignment_needed > data.asan_alignb)
+	    redzonesz = ROUND_UP (redzonesz, alignment_needed);
 	  /* Allocating a constant amount of space from a constant
 	     starting offset must give a constant result.  */
 	  offset = (alloc_stack_frame_space (redzonesz, ASAN_RED_ZONE_SIZE)
diff --git a/gcc/testsuite/g++.dg/asan/pr120201.C b/gcc/testsuite/g++.dg/asan/pr120201.C
new file mode 100644
index 00000000000..0817ce56263
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr120201.C
@@ -0,0 +1,40 @@
+// { dg-do run }
+// { dg-options "-O3 -std=c++23 -fsanitize=address" }
+// { dg-additional-options "-march=x86-64-v4" { target { i?86-*-* x86_64-*-* } } }
+
+#include <cstring>
+
+float* shaderLightData;
+
+using ShaderShadowTransform = float[4z * 4z * 6z];
+using Transform = float[4 * 4];
+
+__attribute__ ((noipa))
+static void
+do_test (void)
+{
+  int lightCount = 3;
+  ShaderShadowTransform* shaderShadowData = new ShaderShadowTransform[lightCount];
+  for (int index = 0; index < lightCount; index++)
+    {
+      Transform transforms[6];
+
+      const std::size_t matSize = 4z * 4z;
+      float* transformBlockStart = shaderShadowData[index];
+      for (int face = 0; face < 6; face++)
+	std::memcpy(transformBlockStart + (matSize * face),
+		    &transforms[face][0], matSize * sizeof(float));
+  }
+
+  delete [] shaderShadowData;
+}
+
+int
+main (void)
+{
+#if defined(__i386__) || defined(__x86_64__)
+  if (__builtin_cpu_supports ("x86-64-v4"))
+#endif
+    do_test ();
+  return 0;
+}
-- 
2.54.0

Reply via email to