/* Test the noipa attribute.  */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-require-effective-target alloca } */

static inline int __attribute__((noipa))
fn1 (void) /* { dg-warning "inline function \[^\n\]* given attribute 'noinline'" "" } */
{
  return 1;
}

/* Verify the function is not inlined into its caller.  */

static __attribute__((noipa)) int
fn2 (int x, int y)
{
  return x + y;
}

int
fn3 (int x)
{
  return fn2 (x, 0);
}

/* { dg-final { scan-tree-dump "= fn2 \\(" "optimized" } } */

void fn4 (char *);

/* Verify the function is not cloned.  */

__attribute__((__noipa__)) static int
fn5 (int x, int y)
{
  char *p = __builtin_alloca (x + y);
  fn4 (p);
  return x + y;
}

int
fn6 (int x)
{
  return fn5 (x, 2);
}

/* { dg-final { scan-tree-dump "= fn5 \\(" "optimized" } } */
/* { dg-final { scan-tree-dump-not "fn5\\.constprop" "optimized" } } */

/* Verify we still remove unused function calls, even if they have
   noipa attribute.  */

static void fn7 (void) __attribute__((noipa));
static void
fn7 (void)
{
}

/* { dg-final { scan-tree-dump-not "fn7 \\(" "optimized" } } */

/* Verify noipa functions are not ICF optimized.  */

static __attribute__((noipa)) int
fn8 (int x)
{
  return x + 12;
}

static __attribute__((noipa)) int
fn9 (int x)
{
  return x + 12;
}

int
fn10 (int x)
{
  return fn8 (x) + fn9 (x);
}

/* { dg-final { scan-tree-dump "fn8 \\(int" "optimized" } } */
/* { dg-final { scan-tree-dump "fn9 \\(int" "optimized" } } */

/* Verify IPA-VRP is not performed.  */

void fn11 (void);

static int __attribute__((noipa))
fn12 (int x)
{
  if (x < 6 || x >= 29)
    fn11 ();
}

void
fn13 (int x)
{
  fn12 (6 + (x & 15));
}

/* { dg-final { scan-tree-dump "fn11 \\(\\)" "optimized" } } */

void fn14 (void);

__attribute__((noipa)) static int
fn15 (int x)
{
  return x & 7;
}

int
fn16 (int x)
{
  x = fn15 (x);
  if (x < 0 || x >= 7)
    fn14 ();
}

/* { dg-final { scan-tree-dump "fn14 \\(\\)" "optimized" } } */

/* Verify IPA BIT CP is not performed.  */

void fn17 (void);

__attribute__((noipa)) static int
fn18 (int x)
{
  if (x & 8)
    fn17 ();
}

void
fn19 (void)
{
  fn18 (1);
  fn18 (2);
  fn18 (4);
  fn18 (16);
  fn18 (32);
  fn18 (64);
}

/* { dg-final { scan-tree-dump "fn17 \\(\\)" "optimized" } } */

/* Ensure pure/const discovery is not performed.  */

int var1;
void fn20 (void);

__attribute__((noipa)) static int
fn21 (int x, int y)
{
  return x * y;
}

int
fn22 (void)
{
  var1 = 7;
  asm volatile ("" : "+g" (var1) : : "memory");
  int a = var1;
  int b = fn21 (a, a);
  if (a != var1)
    fn20 ();
  return b;
}

/* { dg-final { scan-tree-dump "fn20 \\(\\)" "optimized" } } */

/* Verify IPA alignment propagation is not performed.  */

static __attribute__ ((aligned(16))) char var2[32];
void fn23 (void);

__attribute__((noipa)) static void
fn24 (char *p)
{
  if ((((__UINTPTR_TYPE__) p) & 15) != 0)
    fn23 ();
  asm ("");
}

void
fn25 (void)
{
  fn24 (var2);
  fn24 (var2 + 16);
}

/* { dg-final { scan-tree-dump "fn20 \\(\\)" "optimized" } } */
