/* { dg-do compile } */
|
/* { dg-do compile } */
|
/* { dg-options "-O2 -fno-early-inlining" } */
|
/* { dg-options "-O2 -fno-early-inlining" } */
|
|
|
extern void do_something_usefull();
|
extern void do_something_usefull();
|
/* Check that we finish compiling even if instructed to
|
/* Check that we finish compiling even if instructed to
|
flatten a cyclic callgraph. Verify we correctly
|
flatten a cyclic callgraph. Verify we correctly
|
flatten with another function marked flatten in the
|
flatten with another function marked flatten in the
|
callgraph.
|
callgraph.
|
|
|
Main inline is cureful about indirect calls giving
|
Main inline is cureful about indirect calls giving
|
precedence to breaking cycle at indirect call sites.
|
precedence to breaking cycle at indirect call sites.
|
Early inliner can't do similar analysis, so we need
|
Early inliner can't do similar analysis, so we need
|
to disable it if we want cycles to be broken consistently. */
|
to disable it if we want cycles to be broken consistently. */
|
|
|
void __attribute__((flatten)) direct(void)
|
void __attribute__((flatten)) direct(void)
|
{
|
{
|
direct();
|
direct();
|
}
|
}
|
|
|
|
|
void __attribute__((flatten)) indirect(void);
|
void __attribute__((flatten)) indirect(void);
|
static void indirect1(void)
|
static void indirect1(void)
|
{
|
{
|
indirect();
|
indirect();
|
}
|
}
|
void __attribute__((flatten)) indirect(void)
|
void __attribute__((flatten)) indirect(void)
|
{
|
{
|
indirect1();
|
indirect1();
|
}
|
}
|
|
|
|
|
void __attribute__((flatten)) doubleindirect(void);
|
void __attribute__((flatten)) doubleindirect(void);
|
static void doubleindirect2(void)
|
static void doubleindirect2(void)
|
{
|
{
|
doubleindirect();
|
doubleindirect();
|
do_something_usefull ();
|
do_something_usefull ();
|
}
|
}
|
static void doubleindirect1(void)
|
static void doubleindirect1(void)
|
{
|
{
|
doubleindirect2();
|
doubleindirect2();
|
}
|
}
|
void __attribute__((flatten)) doubleindirect(void)
|
void __attribute__((flatten)) doubleindirect(void)
|
{
|
{
|
doubleindirect1();
|
doubleindirect1();
|
}
|
}
|
|
|
|
|
static void subcycle1(void);
|
static void subcycle1(void);
|
static void subcycle2(void)
|
static void subcycle2(void)
|
{
|
{
|
subcycle1();
|
subcycle1();
|
do_something_usefull ();
|
do_something_usefull ();
|
}
|
}
|
static void subcycle1(void)
|
static void subcycle1(void)
|
{
|
{
|
subcycle2();
|
subcycle2();
|
}
|
}
|
void __attribute__((flatten)) subcycle(void)
|
void __attribute__((flatten)) subcycle(void)
|
{
|
{
|
subcycle1();
|
subcycle1();
|
}
|
}
|
|
|
|
|
static void doublesubcycle1(void);
|
static void doublesubcycle1(void);
|
static void doublesubcycle2(void);
|
static void doublesubcycle2(void);
|
static void doublesubcycle3(void)
|
static void doublesubcycle3(void)
|
{
|
{
|
doublesubcycle1();
|
doublesubcycle1();
|
do_something_usefull ();
|
do_something_usefull ();
|
}
|
}
|
static void doublesubcycle2(void)
|
static void doublesubcycle2(void)
|
{
|
{
|
doublesubcycle3();
|
doublesubcycle3();
|
}
|
}
|
static void doublesubcycle1(void)
|
static void doublesubcycle1(void)
|
{
|
{
|
doublesubcycle2();
|
doublesubcycle2();
|
}
|
}
|
void __attribute__((flatten)) doublesubcycle(void)
|
void __attribute__((flatten)) doublesubcycle(void)
|
{
|
{
|
doublesubcycle1();
|
doublesubcycle1();
|
}
|
}
|
|
|
/* { dg-final { scan-assembler "cycle\[123\]\[: \t\n\]" } } */
|
/* { dg-final { scan-assembler "cycle\[123\]\[: \t\n\]" } } */
|
/* { dg-final { scan-assembler-not "indirect\[12\]\[: \t\n\]" } } */
|
/* { dg-final { scan-assembler-not "indirect\[12\]\[: \t\n\]" } } */
|
|
|