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"  } */
5 
6 extern void abort (void);
7 
8 struct S
9 {
10   int i;
11   void (*f)(struct S *);
12   int j,k,l;
13 };
14 
15 struct Z
16 {
17   unsigned u;
18   void (*f)(struct Z *, int);
19   struct Z *next;
20 };
21 
22 static struct Z *gz;
23 static struct S *gs;
24 static int gr = 111;
25 char gc[1024];
26 
27 static __attribute__ ((noinline, noclone)) struct S *
get_s(void)28 get_s (void)
29 {
30   return (struct S *) &gc;
31 }
32 
33 
wrong_target_1(struct S * s)34 static void wrong_target_1 (struct S *s)
35 {
36   abort ();
37 }
38 
wrong_target_2(struct S * s)39 static void wrong_target_2 (struct S *s)
40 {
41   abort ();
42 }
43 
wrong_target_3(struct S * s)44 static void wrong_target_3 (struct S *s)
45 {
46   abort ();
47 }
48 
good_target(struct Z * z,int i)49 static void good_target (struct Z *z, int i)
50 {
51   gr = 0;
52 }
53 
good_target_3(struct S * s)54 static void good_target_3 (struct S *s)
55 {
56   gr = 0;
57 }
58 
g1(struct S * s)59 static void g1 (struct S *s)
60 {
61   struct Z *z = (struct Z*) s;
62   z->f (z, 8);
63 }
64 
f1(struct S * s)65 static void f1 (struct S *s)
66 {
67   gz->f = good_target;
68   g1 (s);
69 }
70 
g2(struct Z * z)71 static void g2 (struct Z *z)
72 {
73   z->f (z, 8);
74 }
75 
f2(struct S * s)76 static void f2 (struct S *s)
77 {
78   gz->f = good_target;
79   g2 ((struct Z*) s);
80 }
81 
g3(struct S * s)82 static void g3 (struct S *s)
83 {
84   s->f (s);
85 }
86 
h3(struct Z * z)87 static void h3 (struct Z *z)
88 {
89   gs->f = good_target_3;
90   g3 ((struct S *) z);
91 }
92 
f3(struct S * s)93 static void f3 (struct S *s)
94 {
95   h3 ((struct Z*) s);
96 }
97 
main(int argc,char ** argv)98 int main (int argc, char **argv)
99 {
100   struct S *s = get_s();
101   s->i = 5678;
102   s->f = wrong_target_1;
103   s->j = 1234;
104   gz = (struct Z *) s;
105   f1 (s);
106 
107   s = get_s();
108   gz = (struct Z *) s;
109   s->i = 9999;
110   s->f = wrong_target_1;
111   f2 (s);
112 
113   s = get_s();
114   gs = s;
115   s->i = 9999;
116   s->f = wrong_target_3;
117   f3 (s);
118 
119   return gr;
120 }
121 
122 
123 /* { dg-final { scan-ipa-dump-not "wrong_target\[^\\n\]*inline copy in" "inline"  } } */
124 /* { dg-final { cleanup-ipa-dump "inline" } } */
125