/* The goal here is to ensure that dynamic allocations via vlas or
   alloca calls receive probing.

   Scanning the RTL or assembly code seems like insanity here as does
   checking for particular allocation sizes and probe offsets.  For
   now we just verify that there's an allocation + probe loop and
   residual allocation + probe for f?.  */

/* { dg-do compile } */
/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-expand -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */
/* { dg-require-effective-target supports_stack_clash_protection } */

__attribute__((noinline, noclone)) void
foo (char *p)
{
  asm volatile ("" : : "r" (p) : "memory");
}

/* Simple VLA, no other locals. */
__attribute__((noinline, noclone)) void
f0 (int x)
{
  char vla[x];
  foo (vla);
}

/* Simple VLA, small local frame.  */
__attribute__((noinline, noclone)) void
f1 (int x)
{
  char locals[128];
  char vla[x];
  foo (vla);
}

/* Small constant alloca, no other locals. */
__attribute__((noinline, noclone)) void
f2 (int x)
{
  char *vla = __builtin_alloca (128);
  foo (vla);
}

/* Big constant alloca, small local frame.  */
__attribute__((noinline, noclone)) void
f3 (int x)
{
  char locals[128];
  char *vla = __builtin_alloca (16384);
  foo (vla);
}

/* Big constant alloca, small local frame.  */
__attribute__((noinline, noclone)) void
f3a (int x)
{
  char locals[128];
  char *vla = __builtin_alloca (32768);
  foo (vla);
}

/* Nonconstant alloca, no other locals. */
__attribute__((noinline, noclone)) void
f4 (int x)
{
  char *vla = __builtin_alloca (x);
  foo (vla);
}

/* Nonconstant alloca, small local frame.  */
__attribute__((noinline, noclone)) void
f5 (int x)
{
  char locals[128];
  char *vla = __builtin_alloca (x);
  foo (vla);
}

/* { dg-final { scan-rtl-dump-times "allocation and probing residuals" 7 "expand" } } */


/* { dg-final { scan-rtl-dump-times "allocation and probing in loop" 7 "expand" { target callee_realigns_stack } } } */
/* { dg-final { scan-rtl-dump-times "allocation and probing in loop" 4 "expand" { target { ! callee_realigns_stack } } } } */
/* { dg-final { scan-rtl-dump-times "allocation and probing in rotated loop" 1 "expand" { target { ! callee_realigns_stack } } } } */
/* { dg-final { scan-rtl-dump-times "allocation and probing inline" 1 "expand" { target { ! callee_realigns_stack } } } } */
/* { dg-final { scan-rtl-dump-times "skipped dynamic allocation and probing loop" 1 "expand" { target { ! callee_realigns_stack } } } } */
