1/* Verify that simple indirect calls are inlined even without early
2   inlining..  */
3/* { dg-do run } */
4/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-icf"  } */
5
6extern void abort (void);
7
8struct S
9{
10  int i;
11  void (*f)(struct S *);
12  int j,k,l;
13};
14
15struct U
16{
17  struct U *next;
18  struct S s;
19  short a[8];
20};
21
22struct Z
23{
24  unsigned u;
25  void (*f)(struct Z *, int);
26  struct Z *next;
27};
28
29static struct Z *gz;
30static struct U *gu;
31static int gr = 111;
32char gc[1024];
33
34static __attribute__ ((noinline, noclone)) struct U *
35get_u (void)
36{
37  return (struct U *) &gc;
38}
39
40static void wrong_target_1 (struct S *s)
41{
42  abort ();
43}
44
45static void wrong_target_2 (struct S *s)
46{
47  abort ();
48}
49
50static void wrong_target_3 (struct S *s)
51{
52  abort ();
53}
54
55static void wrong_target_4 (struct S *s)
56{
57  abort ();
58}
59
60static void good_target (struct Z *z, int i)
61{
62  gr = 0;
63}
64
65static void good_target_4 (struct S *s)
66{
67  gr = 0;
68}
69
70static void g1 (struct S *s)
71{
72  struct Z *z = (struct Z*) s;
73  z->f (z, 8);
74}
75
76static void f1 (struct U *u)
77{
78  gz->f = good_target;
79  g1 (&u->s);
80}
81
82static void g2 (struct Z *z)
83{
84  z->f (z, 8);
85}
86
87static void f2 (struct U *u)
88{
89  gz->f = good_target;
90  g2 ((struct Z*) &u->s);
91}
92
93static void h3 (struct Z *z)
94{
95  z->f (z, 8);
96}
97
98static void g3 (struct S *s)
99{
100  h3 ((struct Z*) s);
101}
102
103static void f3 (struct U *u)
104{
105  gz->f = good_target;
106  g3 (&u->s);
107}
108
109static void h4 (struct S *s)
110{
111  s->f (s);
112}
113
114static void g4 (struct U *u)
115{
116  h4 (&u->s);
117}
118
119static inline __attribute__ ((flatten)) void f4 (struct Z *z)
120{
121  gu->s.f = good_target_4;
122  g4 ((struct U *) z);
123}
124
125int main (int argc, char **argv)
126{
127  struct U *u = get_u ();
128  u->next = u;
129  u->s.i = 5678;
130  u->s.f = wrong_target_1;
131  u->s.j = 1234;
132  gz = (struct Z *) &u->s;
133  f1 (u);
134
135  u = get_u();
136  u->s.i = 9999;
137  u->s.f = wrong_target_2;
138  gz = (struct Z *) &u->s;
139  f2 (u);
140
141  u = get_u();
142  u->s.i = 9998;
143  u->s.f = wrong_target_3;
144  gz = (struct Z *) &u->s;
145  f3 (u);
146
147  u = get_u();
148  u->s.i = 9998;
149  u->s.f = wrong_target_4;
150  gu = u;
151  f4 ((struct Z *) u);
152  return gr;
153}
154
155
156/* { dg-final { scan-ipa-dump-not "wrong_target\[^\\n\]*inline copy in" "inline"  } } */
157/* { dg-final { cleanup-ipa-dump "inline" } } */
158