annotate gcc/tree-tailcall.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Tail call optimization on trees.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 it under the terms of the GNU General Public License as published by
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 the Free Software Foundation; either version 3, or (at your option)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 any later version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 GNU General Public License for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "coretypes.h"
111
kono
parents: 67
diff changeset
23 #include "backend.h"
kono
parents: 67
diff changeset
24 #include "rtl.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 #include "tree.h"
111
kono
parents: 67
diff changeset
26 #include "gimple.h"
kono
parents: 67
diff changeset
27 #include "cfghooks.h"
kono
parents: 67
diff changeset
28 #include "tree-pass.h"
kono
parents: 67
diff changeset
29 #include "ssa.h"
kono
parents: 67
diff changeset
30 #include "cgraph.h"
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
31 #include "gimple-pretty-print.h"
111
kono
parents: 67
diff changeset
32 #include "fold-const.h"
kono
parents: 67
diff changeset
33 #include "stor-layout.h"
kono
parents: 67
diff changeset
34 #include "gimple-iterator.h"
kono
parents: 67
diff changeset
35 #include "gimplify-me.h"
kono
parents: 67
diff changeset
36 #include "tree-cfg.h"
kono
parents: 67
diff changeset
37 #include "tree-into-ssa.h"
kono
parents: 67
diff changeset
38 #include "tree-dfa.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 #include "except.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
40 #include "tree-eh.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 #include "dbgcnt.h"
111
kono
parents: 67
diff changeset
42 #include "cfgloop.h"
kono
parents: 67
diff changeset
43 #include "common/common-target.h"
kono
parents: 67
diff changeset
44 #include "ipa-utils.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
45 #include "tree-ssa-live.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 /* The file implements the tail recursion elimination. It is also used to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 analyze the tail calls in general, passing the results to the rtl level
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 where they are used for sibcall optimization.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 In addition to the standard tail recursion elimination, we handle the most
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 trivial cases of making the call tail recursive by creating accumulators.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 For example the following function
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 int sum (int n)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 if (n > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 return n + sum (n - 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 is transformed into
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 int sum (int n)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 int acc = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 while (n > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 acc += n--;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 return acc;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
75 To do this, we maintain two accumulators (a_acc and m_acc) that indicate
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 when we reach the return x statement, we should return a_acc + x * m_acc
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 instead. They are initially initialized to 0 and 1, respectively,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 so the semantics of the function is obviously preserved. If we are
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 guaranteed that the value of the accumulator never change, we
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 omit the accumulator.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 There are three cases how the function may exit. The first one is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 handled in adjust_return_value, the other two in adjust_accumulator_values
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 (the second case is actually a special case of the third one and we
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 present it separately just for clarity):
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 1) Just return x, where x is not in any of the remaining special shapes.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 We rewrite this to a gimple equivalent of return m_acc * x + a_acc.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
89
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 2) return f (...), where f is the current function, is rewritten in a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 classical tail-recursion elimination way, into assignment of arguments
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 and jump to the start of the function. Values of the accumulators
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 are unchanged.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
94
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 3) return a + m * f(...), where a and m do not depend on call to f.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 To preserve the semantics described before we want this to be rewritten
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 in such a way that we finally return
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 a_acc + (a + m * f(...)) * m_acc = (a_acc + a * m_acc) + (m * m_acc) * f(...).
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 I.e. we increase a_acc by a * m_acc, multiply m_acc by m and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 eliminate the tail call to f. Special cases when the value is just
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 added or just multiplied are obtained by setting a = 0 or m = 1.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 TODO -- it is possible to do similar tricks for other operations. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 /* A structure that describes the tailcall. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 struct tailcall
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 /* The iterator pointing to the call statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 gimple_stmt_iterator call_gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 /* True if it is a call to the current function. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 bool tail_recursion;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 /* The return value of the caller is mult * f + add, where f is the return
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118 value of the call. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 tree mult, add;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 /* Next tailcall in the chain. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 struct tailcall *next;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 /* The variables holding the value of multiplicative and additive
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 accumulator. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 static tree m_acc, a_acc;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
129 /* Bitmap with a bit for each function parameter which is set to true if we
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
130 have to copy the parameter for conversion of tail-recursive calls. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
131
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
132 static bitmap tailr_arg_needs_copy;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
133
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 static bool optimize_tail_call (struct tailcall *, bool);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 static void eliminate_tail_call (struct tailcall *);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137 /* Returns false when the function is not suitable for tail call optimization
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 from some reason (e.g. if it takes variable number of arguments). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 suitable_for_tail_opt_p (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 if (cfun->stdarg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
148
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 /* Returns false when the function is not suitable for tail call optimization
111
kono
parents: 67
diff changeset
150 for some reason (e.g. if it takes variable number of arguments).
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
151 This test must pass in addition to suitable_for_tail_opt_p in order to make
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 tail call discovery happen. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 suitable_for_tail_call_opt_p (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 tree param;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 /* alloca (until we have stack slot life analysis) inhibits
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 sibling call optimizations, but not tail recursion. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 if (cfun->calls_alloca)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 /* If we are using sjlj exceptions, we may need to add a call to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 _Unwind_SjLj_Unregister at exit of the function. Which means
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 that we cannot do any sibcall transformations. */
111
kono
parents: 67
diff changeset
167 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
168 && current_function_has_exception_handlers ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 /* Any function that calls setjmp might have longjmp called from
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 any called function. ??? We really should represent this
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 properly in the CFG so that this needn't be special cased. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 if (cfun->calls_setjmp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
177 /* Various targets don't handle tail calls correctly in functions
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
178 that call __builtin_eh_return. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
179 if (cfun->calls_eh_return)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
180 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
181
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 /* ??? It is OK if the argument of a function is taken in some cases,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 but not in all cases. See PR15387 and PR19616. Revisit for 4.1. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 for (param = DECL_ARGUMENTS (current_function_decl);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 param;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
186 param = DECL_CHAIN (param))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 if (TREE_ADDRESSABLE (param))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
192
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 /* Checks whether the expression EXPR in stmt AT is independent of the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 statement pointed to by GSI (in a sense that we already know EXPR's value
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 at GSI). We use the fact that we are only called from the chain of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 basic blocks that have only single successor. Returns the expression
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 containing the value of EXPR at GSI. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 static tree
111
kono
parents: 67
diff changeset
200 independent_of_stmt_p (tree expr, gimple *at, gimple_stmt_iterator gsi,
kono
parents: 67
diff changeset
201 bitmap to_move)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 basic_block bb, call_bb, at_bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 if (is_gimple_min_invariant (expr))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 return expr;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 if (TREE_CODE (expr) != SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 return NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212
111
kono
parents: 67
diff changeset
213 if (bitmap_bit_p (to_move, SSA_NAME_VERSION (expr)))
kono
parents: 67
diff changeset
214 return expr;
kono
parents: 67
diff changeset
215
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 /* Mark the blocks in the chain leading to the end. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 at_bb = gimple_bb (at);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 call_bb = gimple_bb (gsi_stmt (gsi));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 for (bb = call_bb; bb != at_bb; bb = single_succ (bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 bb->aux = &bb->aux;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 bb->aux = &bb->aux;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 while (1)
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
224 {
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 at = SSA_NAME_DEF_STMT (expr);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 bb = gimple_bb (at);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 /* The default definition or defined before the chain. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 if (!bb || !bb->aux)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 if (bb == call_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 for (; !gsi_end_p (gsi); gsi_next (&gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 if (gsi_stmt (gsi) == at)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 if (!gsi_end_p (gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 expr = NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 if (gimple_code (at) != GIMPLE_PHI)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 expr = NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 FOR_EACH_EDGE (e, ei, bb->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 if (e->src->aux)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 gcc_assert (e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 expr = PHI_ARG_DEF_FROM_EDGE (at, e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 if (TREE_CODE (expr) != SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 /* The value is a constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 /* Unmark the blocks. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 for (bb = call_bb; bb != at_bb; bb = single_succ (bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 bb->aux = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 bb->aux = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 return expr;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269
111
kono
parents: 67
diff changeset
270 enum par { FAIL, OK, TRY_MOVE };
kono
parents: 67
diff changeset
271
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 /* Simulates the effect of an assignment STMT on the return value of the tail
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 recursive CALL passed in ASS_VAR. M and A are the multiplicative and the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 additive factor for the real return value. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275
111
kono
parents: 67
diff changeset
276 static par
kono
parents: 67
diff changeset
277 process_assignment (gassign *stmt,
kono
parents: 67
diff changeset
278 gimple_stmt_iterator call, tree *m,
kono
parents: 67
diff changeset
279 tree *a, tree *ass_var, bitmap to_move)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 {
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
281 tree op0, op1 = NULL_TREE, non_ass_var = NULL_TREE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 tree dest = gimple_assign_lhs (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 enum tree_code code = gimple_assign_rhs_code (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 enum gimple_rhs_class rhs_class = get_gimple_rhs_class (code);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 tree src_var = gimple_assign_rhs1 (stmt);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
286
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 /* See if this is a simple copy operation of an SSA name to the function
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 result. In that case we may have a simple tail call. Ignore type
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 conversions that can never produce extra code between the function
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 call and the function return. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 if ((rhs_class == GIMPLE_SINGLE_RHS || gimple_assign_cast_p (stmt))
111
kono
parents: 67
diff changeset
292 && src_var == *ass_var)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 /* Reject a tailcall if the type conversion might need
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 additional code. */
111
kono
parents: 67
diff changeset
296 if (gimple_assign_cast_p (stmt))
kono
parents: 67
diff changeset
297 {
kono
parents: 67
diff changeset
298 if (TYPE_MODE (TREE_TYPE (dest)) != TYPE_MODE (TREE_TYPE (src_var)))
kono
parents: 67
diff changeset
299 return FAIL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
300
111
kono
parents: 67
diff changeset
301 /* Even if the type modes are the same, if the precision of the
kono
parents: 67
diff changeset
302 type is smaller than mode's precision,
kono
parents: 67
diff changeset
303 reduce_to_bit_field_precision would generate additional code. */
kono
parents: 67
diff changeset
304 if (INTEGRAL_TYPE_P (TREE_TYPE (dest))
kono
parents: 67
diff changeset
305 && !type_has_mode_precision_p (TREE_TYPE (dest)))
kono
parents: 67
diff changeset
306 return FAIL;
kono
parents: 67
diff changeset
307 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 *ass_var = dest;
111
kono
parents: 67
diff changeset
310 return OK;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
313 switch (rhs_class)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
314 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
315 case GIMPLE_BINARY_RHS:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
316 op1 = gimple_assign_rhs2 (stmt);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
317
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
318 /* Fall through. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
319
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
320 case GIMPLE_UNARY_RHS:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
321 op0 = gimple_assign_rhs1 (stmt);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
322 break;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
323
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
324 default:
111
kono
parents: 67
diff changeset
325 return FAIL;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
326 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
327
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 /* Accumulator optimizations will reverse the order of operations.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 We can only do that for floating-point types if we're assuming
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 that addition and multiplication are associative. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
331 if (!flag_associative_math)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
111
kono
parents: 67
diff changeset
333 return FAIL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334
111
kono
parents: 67
diff changeset
335 if (rhs_class == GIMPLE_UNARY_RHS
kono
parents: 67
diff changeset
336 && op0 == *ass_var)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
337 ;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
338 else if (op0 == *ass_var
111
kono
parents: 67
diff changeset
339 && (non_ass_var = independent_of_stmt_p (op1, stmt, call,
kono
parents: 67
diff changeset
340 to_move)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 ;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
342 else if (op1 == *ass_var
111
kono
parents: 67
diff changeset
343 && (non_ass_var = independent_of_stmt_p (op0, stmt, call,
kono
parents: 67
diff changeset
344 to_move)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 ;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 else
111
kono
parents: 67
diff changeset
347 return TRY_MOVE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 switch (code)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 case PLUS_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 *a = non_ass_var;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 *ass_var = dest;
111
kono
parents: 67
diff changeset
354 return OK;
kono
parents: 67
diff changeset
355
kono
parents: 67
diff changeset
356 case POINTER_PLUS_EXPR:
kono
parents: 67
diff changeset
357 if (op0 != *ass_var)
kono
parents: 67
diff changeset
358 return FAIL;
kono
parents: 67
diff changeset
359 *a = non_ass_var;
kono
parents: 67
diff changeset
360 *ass_var = dest;
kono
parents: 67
diff changeset
361 return OK;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363 case MULT_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
364 *m = non_ass_var;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365 *ass_var = dest;
111
kono
parents: 67
diff changeset
366 return OK;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
368 case NEGATE_EXPR:
111
kono
parents: 67
diff changeset
369 *m = build_minus_one_cst (TREE_TYPE (op0));
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
370 *ass_var = dest;
111
kono
parents: 67
diff changeset
371 return OK;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
372
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
373 case MINUS_EXPR:
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
374 if (*ass_var == op0)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
375 *a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
376 else
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
377 {
111
kono
parents: 67
diff changeset
378 *m = build_minus_one_cst (TREE_TYPE (non_ass_var));
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
379 *a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
380 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
381
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
382 *ass_var = dest;
111
kono
parents: 67
diff changeset
383 return OK;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 default:
111
kono
parents: 67
diff changeset
386 return FAIL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 /* Propagate VAR through phis on edge E. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392 static tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 propagate_through_phis (tree var, edge e)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 basic_block dest = e->dest;
111
kono
parents: 67
diff changeset
396 gphi_iterator gsi;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
397
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398 for (gsi = gsi_start_phis (dest); !gsi_end_p (gsi); gsi_next (&gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 {
111
kono
parents: 67
diff changeset
400 gphi *phi = gsi.phi ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 return PHI_RESULT (phi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
404 return var;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
407 /* Argument for compute_live_vars/live_vars_at_stmt and what compute_live_vars
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
408 returns. Computed lazily, but just once for the function. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
409 static live_vars_map *live_vars;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
410 static vec<bitmap_head> live_vars_vec;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
411
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 /* Finds tailcalls falling into basic block BB. The list of found tailcalls is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 added to the start of RET. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416 find_tail_calls (basic_block bb, struct tailcall **ret)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
417 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
418 tree ass_var = NULL_TREE, ret_var, func, param;
111
kono
parents: 67
diff changeset
419 gimple *stmt;
kono
parents: 67
diff changeset
420 gcall *call = NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
421 gimple_stmt_iterator gsi, agsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
422 bool tail_recursion;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 struct tailcall *nw;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
424 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
425 tree m, a;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
426 basic_block abb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
427 size_t idx;
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
428 tree var;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
429
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
430 if (!single_succ_p (bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
431 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
432
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433 for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
434 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
435 stmt = gsi_stmt (gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436
111
kono
parents: 67
diff changeset
437 /* Ignore labels, returns, nops, clobbers and debug stmts. */
kono
parents: 67
diff changeset
438 if (gimple_code (stmt) == GIMPLE_LABEL
kono
parents: 67
diff changeset
439 || gimple_code (stmt) == GIMPLE_RETURN
kono
parents: 67
diff changeset
440 || gimple_code (stmt) == GIMPLE_NOP
kono
parents: 67
diff changeset
441 || gimple_code (stmt) == GIMPLE_PREDICT
kono
parents: 67
diff changeset
442 || gimple_clobber_p (stmt)
kono
parents: 67
diff changeset
443 || is_gimple_debug (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
444 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
445
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
446 /* Check for a call. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
447 if (is_gimple_call (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
448 {
111
kono
parents: 67
diff changeset
449 call = as_a <gcall *> (stmt);
kono
parents: 67
diff changeset
450 ass_var = gimple_call_lhs (call);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
451 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453
111
kono
parents: 67
diff changeset
454 /* Allow simple copies between local variables, even if they're
kono
parents: 67
diff changeset
455 aggregates. */
kono
parents: 67
diff changeset
456 if (is_gimple_assign (stmt)
kono
parents: 67
diff changeset
457 && auto_var_in_fn_p (gimple_assign_lhs (stmt), cfun->decl)
kono
parents: 67
diff changeset
458 && auto_var_in_fn_p (gimple_assign_rhs1 (stmt), cfun->decl))
kono
parents: 67
diff changeset
459 continue;
kono
parents: 67
diff changeset
460
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
461 /* If the statement references memory or volatile operands, fail. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
462 if (gimple_references_memory_p (stmt)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
463 || gimple_has_volatile_ops (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467 if (gsi_end_p (gsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 /* Recurse to the predecessors. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471 FOR_EACH_EDGE (e, ei, bb->preds)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
472 find_tail_calls (e->src, ret);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
473
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
476
111
kono
parents: 67
diff changeset
477 /* If the LHS of our call is not just a simple register or local
kono
parents: 67
diff changeset
478 variable, we can't transform this into a tail or sibling call.
kono
parents: 67
diff changeset
479 This situation happens, in (e.g.) "*p = foo()" where foo returns a
kono
parents: 67
diff changeset
480 struct. In this case we won't have a temporary here, but we need
kono
parents: 67
diff changeset
481 to carry out the side effect anyway, so tailcall is impossible.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
482
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483 ??? In some situations (when the struct is returned in memory via
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484 invisible argument) we could deal with this, e.g. by passing 'p'
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 itself as that argument to foo, but it's too early to do this here,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 and expand_call() will not handle it anyway. If it ever can, then
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487 we need to revisit this here, to allow that situation. */
111
kono
parents: 67
diff changeset
488 if (ass_var
kono
parents: 67
diff changeset
489 && !is_gimple_reg (ass_var)
kono
parents: 67
diff changeset
490 && !auto_var_in_fn_p (ass_var, cfun->decl))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
493 /* If the call might throw an exception that wouldn't propagate out of
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
494 cfun, we can't transform to a tail or sibling call (82081). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
495 if (stmt_could_throw_p (cfun, stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
496 && !stmt_can_throw_external (cfun, stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
497 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
498
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
499 /* If the function returns a value, then at present, the tail call
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
500 must return the same type of value. There is conceptually a copy
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
501 between the object returned by the tail call candidate and the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
502 object returned by CFUN itself.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
503
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
504 This means that if we have:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
505
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
506 lhs = f (&<retval>); // f reads from <retval>
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
507 // (lhs is usually also <retval>)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
508
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
509 there is a copy between the temporary object returned by f and lhs,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
510 meaning that any use of <retval> in f occurs before the assignment
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
511 to lhs begins. Thus the <retval> that is live on entry to the call
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
512 to f is really an independent local variable V that happens to be
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
513 stored in the RESULT_DECL rather than a local VAR_DECL.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
514
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
515 Turning this into a tail call would remove the copy and make the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
516 lifetimes of the return value and V overlap. The same applies to
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
517 tail recursion, since if f can read from <retval>, we have to assume
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
518 that CFUN might already have written to <retval> before the call.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
519
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
520 The problem doesn't apply when <retval> is passed by value, but that
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
521 isn't a case we handle anyway. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
522 tree result_decl = DECL_RESULT (cfun->decl);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
523 if (result_decl
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
524 && may_be_aliased (result_decl)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
525 && ref_maybe_used_by_stmt_p (call, result_decl))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
526 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
527
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
528 /* We found the call, check whether it is suitable. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
529 tail_recursion = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
530 func = gimple_call_fndecl (call);
111
kono
parents: 67
diff changeset
531 if (func
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
532 && !fndecl_built_in_p (func)
111
kono
parents: 67
diff changeset
533 && recursive_call_p (current_function_decl, func))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
534 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535 tree arg;
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
536
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
537 for (param = DECL_ARGUMENTS (current_function_decl), idx = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 param && idx < gimple_call_num_args (call);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
539 param = DECL_CHAIN (param), idx ++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
541 arg = gimple_call_arg (call, idx);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542 if (param != arg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 /* Make sure there are no problems with copying. The parameter
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 have a copyable type and the two arguments must have reasonably
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
546 equivalent types. The latter requirement could be relaxed if
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 we emitted a suitable type conversion statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548 if (!is_gimple_reg_type (TREE_TYPE (param))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
549 || !useless_type_conversion_p (TREE_TYPE (param),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 TREE_TYPE (arg)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
552
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553 /* The parameter should be a real operand, so that phi node
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
554 created for it at the start of the function has the meaning
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 of copying the value. This test implies is_gimple_reg_type
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556 from the previous condition, however this one could be
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557 relaxed by being more careful with copying the new value
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558 of the parameter (emitting appropriate GIMPLE_ASSIGN and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559 updating the virtual operands). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 if (!is_gimple_reg (param))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
561 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
562 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
563 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564 if (idx == gimple_call_num_args (call) && !param)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
565 tail_recursion = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
567
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
568 /* Compute live vars if not computed yet. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
569 if (live_vars == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
570 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
571 unsigned int cnt = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
572 FOR_EACH_LOCAL_DECL (cfun, idx, var)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
573 if (VAR_P (var)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
574 && auto_var_in_fn_p (var, cfun->decl)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
575 && may_be_aliased (var))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
576 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
577 if (live_vars == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
578 live_vars = new live_vars_map;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
579 live_vars->put (DECL_UID (var), cnt++);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
580 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
581 if (live_vars)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
582 live_vars_vec = compute_live_vars (cfun, live_vars);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
583 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
584
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
585 /* Determine a bitmap of variables which are still in scope after the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
586 call. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
587 bitmap local_live_vars = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
588 if (live_vars)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
589 local_live_vars = live_vars_at_stmt (live_vars_vec, live_vars, call);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
590
111
kono
parents: 67
diff changeset
591 /* Make sure the tail invocation of this function does not indirectly
kono
parents: 67
diff changeset
592 refer to local variables. (Passing variables directly by value
kono
parents: 67
diff changeset
593 is OK.) */
kono
parents: 67
diff changeset
594 FOR_EACH_LOCAL_DECL (cfun, idx, var)
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
595 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
596 if (TREE_CODE (var) != PARM_DECL
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
597 && auto_var_in_fn_p (var, cfun->decl)
111
kono
parents: 67
diff changeset
598 && may_be_aliased (var)
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
599 && (ref_maybe_used_by_stmt_p (call, var)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
600 || call_may_clobber_ref_p (call, var)))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
601 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
602 if (!VAR_P (var))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
603 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
604 if (local_live_vars)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
605 BITMAP_FREE (local_live_vars);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
606 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
607 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
608 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
609 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
610 unsigned int *v = live_vars->get (DECL_UID (var));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
611 if (bitmap_bit_p (local_live_vars, *v))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
612 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
613 BITMAP_FREE (local_live_vars);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
614 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
615 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
616 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
617 }
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
618 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
619
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
620 if (local_live_vars)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
621 BITMAP_FREE (local_live_vars);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
622
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
623 /* Now check the statements after the call. None of them has virtual
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624 operands, so they may only depend on the call through its return
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 value. The return value should also be dependent on each of them,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626 since we are running after dce. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627 m = NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
628 a = NULL_TREE;
111
kono
parents: 67
diff changeset
629 auto_bitmap to_move_defs;
kono
parents: 67
diff changeset
630 auto_vec<gimple *> to_move_stmts;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
631
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 abb = bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 agsi = gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
636 tree tmp_a = NULL_TREE;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
637 tree tmp_m = NULL_TREE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 gsi_next (&agsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
639
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640 while (gsi_end_p (agsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
642 ass_var = propagate_through_phis (ass_var, single_succ_edge (abb));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
643 abb = single_succ (abb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
644 agsi = gsi_start_bb (abb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
647 stmt = gsi_stmt (agsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
648 if (gimple_code (stmt) == GIMPLE_RETURN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650
111
kono
parents: 67
diff changeset
651 if (gimple_code (stmt) == GIMPLE_LABEL
kono
parents: 67
diff changeset
652 || gimple_code (stmt) == GIMPLE_NOP
kono
parents: 67
diff changeset
653 || gimple_code (stmt) == GIMPLE_PREDICT
kono
parents: 67
diff changeset
654 || gimple_clobber_p (stmt)
kono
parents: 67
diff changeset
655 || is_gimple_debug (stmt))
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
656 continue;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
657
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
658 if (gimple_code (stmt) != GIMPLE_ASSIGN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
659 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
660
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
661 /* This is a gimple assign. */
111
kono
parents: 67
diff changeset
662 par ret = process_assignment (as_a <gassign *> (stmt), gsi,
kono
parents: 67
diff changeset
663 &tmp_m, &tmp_a, &ass_var, to_move_defs);
kono
parents: 67
diff changeset
664 if (ret == FAIL)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
665 return;
111
kono
parents: 67
diff changeset
666 else if (ret == TRY_MOVE)
kono
parents: 67
diff changeset
667 {
kono
parents: 67
diff changeset
668 if (! tail_recursion)
kono
parents: 67
diff changeset
669 return;
kono
parents: 67
diff changeset
670 /* Do not deal with checking dominance, the real fix is to
kono
parents: 67
diff changeset
671 do path isolation for the transform phase anyway, removing
kono
parents: 67
diff changeset
672 the need to compute the accumulators with new stmts. */
kono
parents: 67
diff changeset
673 if (abb != bb)
kono
parents: 67
diff changeset
674 return;
kono
parents: 67
diff changeset
675 for (unsigned opno = 1; opno < gimple_num_ops (stmt); ++opno)
kono
parents: 67
diff changeset
676 {
kono
parents: 67
diff changeset
677 tree op = gimple_op (stmt, opno);
kono
parents: 67
diff changeset
678 if (independent_of_stmt_p (op, stmt, gsi, to_move_defs) != op)
kono
parents: 67
diff changeset
679 return;
kono
parents: 67
diff changeset
680 }
kono
parents: 67
diff changeset
681 bitmap_set_bit (to_move_defs,
kono
parents: 67
diff changeset
682 SSA_NAME_VERSION (gimple_assign_lhs (stmt)));
kono
parents: 67
diff changeset
683 to_move_stmts.safe_push (stmt);
kono
parents: 67
diff changeset
684 continue;
kono
parents: 67
diff changeset
685 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
686
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
687 if (tmp_a)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
688 {
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
689 tree type = TREE_TYPE (tmp_a);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
690 if (a)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
691 a = fold_build2 (PLUS_EXPR, type, fold_convert (type, a), tmp_a);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
692 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
693 a = tmp_a;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
694 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
695 if (tmp_m)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
696 {
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
697 tree type = TREE_TYPE (tmp_m);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
698 if (m)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
699 m = fold_build2 (MULT_EXPR, type, fold_convert (type, m), tmp_m);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
700 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
701 m = tmp_m;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
702
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
703 if (a)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
704 a = fold_build2 (MULT_EXPR, type, fold_convert (type, a), tmp_m);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
705 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
706 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
707
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
708 /* See if this is a tail call we can handle. */
111
kono
parents: 67
diff changeset
709 ret_var = gimple_return_retval (as_a <greturn *> (stmt));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
710
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
711 /* We may proceed if there either is no return value, or the return value
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
712 is identical to the call's return. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
713 if (ret_var
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
714 && (ret_var != ass_var))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
715 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
716
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
717 /* If this is not a tail recursive call, we cannot handle addends or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
718 multiplicands. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
719 if (!tail_recursion && (m || a))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
720 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
721
111
kono
parents: 67
diff changeset
722 /* For pointers only allow additions. */
kono
parents: 67
diff changeset
723 if (m && POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
kono
parents: 67
diff changeset
724 return;
kono
parents: 67
diff changeset
725
kono
parents: 67
diff changeset
726 /* Move queued defs. */
kono
parents: 67
diff changeset
727 if (tail_recursion)
kono
parents: 67
diff changeset
728 {
kono
parents: 67
diff changeset
729 unsigned i;
kono
parents: 67
diff changeset
730 FOR_EACH_VEC_ELT (to_move_stmts, i, stmt)
kono
parents: 67
diff changeset
731 {
kono
parents: 67
diff changeset
732 gimple_stmt_iterator mgsi = gsi_for_stmt (stmt);
kono
parents: 67
diff changeset
733 gsi_move_before (&mgsi, &gsi);
kono
parents: 67
diff changeset
734 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
735 if (!tailr_arg_needs_copy)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
736 tailr_arg_needs_copy = BITMAP_ALLOC (NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
737 for (param = DECL_ARGUMENTS (current_function_decl), idx = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
738 param;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
739 param = DECL_CHAIN (param), idx++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
740 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
741 tree ddef, arg = gimple_call_arg (call, idx);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
742 if (is_gimple_reg (param)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
743 && (ddef = ssa_default_def (cfun, param))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
744 && (arg != ddef))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
745 bitmap_set_bit (tailr_arg_needs_copy, idx);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
746 }
111
kono
parents: 67
diff changeset
747 }
kono
parents: 67
diff changeset
748
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
749 nw = XNEW (struct tailcall);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
750
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
751 nw->call_gsi = gsi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
752
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
753 nw->tail_recursion = tail_recursion;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
754
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
755 nw->mult = m;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
756 nw->add = a;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
757
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
758 nw->next = *ret;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
759 *ret = nw;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
760 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
761
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
762 /* Helper to insert PHI_ARGH to the phi of VAR in the destination of edge E. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
763
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
764 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
765 add_successor_phi_arg (edge e, tree var, tree phi_arg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
766 {
111
kono
parents: 67
diff changeset
767 gphi_iterator gsi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
769 for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
111
kono
parents: 67
diff changeset
770 if (PHI_RESULT (gsi.phi ()) == var)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
771 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
772
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
773 gcc_assert (!gsi_end_p (gsi));
111
kono
parents: 67
diff changeset
774 add_phi_arg (gsi.phi (), phi_arg, e, UNKNOWN_LOCATION);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
775 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
776
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
777 /* Creates a GIMPLE statement which computes the operation specified by
111
kono
parents: 67
diff changeset
778 CODE, ACC and OP1 to a new variable with name LABEL and inserts the
kono
parents: 67
diff changeset
779 statement in the position specified by GSI. Returns the
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
780 tree node of the statement's result. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
781
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
782 static tree
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
783 adjust_return_value_with_ops (enum tree_code code, const char *label,
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
784 tree acc, tree op1, gimple_stmt_iterator gsi)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
785 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
786
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
787 tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
111
kono
parents: 67
diff changeset
788 tree result = make_temp_ssa_name (ret_type, NULL, label);
kono
parents: 67
diff changeset
789 gassign *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
790
111
kono
parents: 67
diff changeset
791 if (POINTER_TYPE_P (ret_type))
kono
parents: 67
diff changeset
792 {
kono
parents: 67
diff changeset
793 gcc_assert (code == PLUS_EXPR && TREE_TYPE (acc) == sizetype);
kono
parents: 67
diff changeset
794 code = POINTER_PLUS_EXPR;
kono
parents: 67
diff changeset
795 }
kono
parents: 67
diff changeset
796 if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1))
kono
parents: 67
diff changeset
797 && code != POINTER_PLUS_EXPR)
kono
parents: 67
diff changeset
798 stmt = gimple_build_assign (result, code, acc, op1);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
799 else
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
800 {
111
kono
parents: 67
diff changeset
801 tree tem;
kono
parents: 67
diff changeset
802 if (code == POINTER_PLUS_EXPR)
kono
parents: 67
diff changeset
803 tem = fold_build2 (code, TREE_TYPE (op1), op1, acc);
kono
parents: 67
diff changeset
804 else
kono
parents: 67
diff changeset
805 tem = fold_build2 (code, TREE_TYPE (op1),
kono
parents: 67
diff changeset
806 fold_convert (TREE_TYPE (op1), acc), op1);
kono
parents: 67
diff changeset
807 tree rhs = fold_convert (ret_type, tem);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
808 rhs = force_gimple_operand_gsi (&gsi, rhs,
111
kono
parents: 67
diff changeset
809 false, NULL, true, GSI_SAME_STMT);
kono
parents: 67
diff changeset
810 stmt = gimple_build_assign (result, rhs);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
811 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
812
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
813 gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
814 return result;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
815 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
816
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
817 /* Creates a new GIMPLE statement that adjusts the value of accumulator ACC by
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
818 the computation specified by CODE and OP1 and insert the statement
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
819 at the position specified by GSI as a new statement. Returns new SSA name
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
820 of updated accumulator. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
821
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
822 static tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
823 update_accumulator_with_ops (enum tree_code code, tree acc, tree op1,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
824 gimple_stmt_iterator gsi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
825 {
111
kono
parents: 67
diff changeset
826 gassign *stmt;
kono
parents: 67
diff changeset
827 tree var = copy_ssa_name (acc);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
828 if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
111
kono
parents: 67
diff changeset
829 stmt = gimple_build_assign (var, code, acc, op1);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
830 else
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
831 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
832 tree rhs = fold_convert (TREE_TYPE (acc),
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
833 fold_build2 (code,
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
834 TREE_TYPE (op1),
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
835 fold_convert (TREE_TYPE (op1), acc),
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
836 op1));
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
837 rhs = force_gimple_operand_gsi (&gsi, rhs,
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
838 false, NULL, false, GSI_CONTINUE_LINKING);
111
kono
parents: 67
diff changeset
839 stmt = gimple_build_assign (var, rhs);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
840 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
841 gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
842 return var;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
843 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
844
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
845 /* Adjust the accumulator values according to A and M after GSI, and update
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
846 the phi nodes on edge BACK. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
847
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
848 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
849 adjust_accumulator_values (gimple_stmt_iterator gsi, tree m, tree a, edge back)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
850 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
851 tree var, a_acc_arg, m_acc_arg;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
852
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
853 if (m)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
854 m = force_gimple_operand_gsi (&gsi, m, true, NULL, true, GSI_SAME_STMT);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
855 if (a)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
856 a = force_gimple_operand_gsi (&gsi, a, true, NULL, true, GSI_SAME_STMT);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
857
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
858 a_acc_arg = a_acc;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
859 m_acc_arg = m_acc;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
860 if (a)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
861 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
862 if (m_acc)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
863 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
864 if (integer_onep (a))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
865 var = m_acc;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
866 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
867 var = adjust_return_value_with_ops (MULT_EXPR, "acc_tmp", m_acc,
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
868 a, gsi);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
869 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
870 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
871 var = a;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
872
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
873 a_acc_arg = update_accumulator_with_ops (PLUS_EXPR, a_acc, var, gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
874 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
875
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
876 if (m)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
877 m_acc_arg = update_accumulator_with_ops (MULT_EXPR, m_acc, m, gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
878
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
879 if (a_acc)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
880 add_successor_phi_arg (back, a_acc, a_acc_arg);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
881
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
882 if (m_acc)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
883 add_successor_phi_arg (back, m_acc, m_acc_arg);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
884 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
885
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
886 /* Adjust value of the return at the end of BB according to M and A
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
887 accumulators. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
888
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
889 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
890 adjust_return_value (basic_block bb, tree m, tree a)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
891 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
892 tree retval;
111
kono
parents: 67
diff changeset
893 greturn *ret_stmt = as_a <greturn *> (gimple_seq_last_stmt (bb_seq (bb)));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
894 gimple_stmt_iterator gsi = gsi_last_bb (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
895
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
896 gcc_assert (gimple_code (ret_stmt) == GIMPLE_RETURN);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
897
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
898 retval = gimple_return_retval (ret_stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
899 if (!retval || retval == error_mark_node)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
900 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
901
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
902 if (m)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
903 retval = adjust_return_value_with_ops (MULT_EXPR, "mul_tmp", m_acc, retval,
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
904 gsi);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
905 if (a)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
906 retval = adjust_return_value_with_ops (PLUS_EXPR, "acc_tmp", a_acc, retval,
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
907 gsi);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
908 gimple_return_set_retval (ret_stmt, retval);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
909 update_stmt (ret_stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
910 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
911
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
912 /* Subtract COUNT and FREQUENCY from the basic block and it's
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
913 outgoing edge. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
914 static void
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
915 decrease_profile (basic_block bb, profile_count count)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
916 {
111
kono
parents: 67
diff changeset
917 bb->count = bb->count - count;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
918 if (!single_succ_p (bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
919 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
920 gcc_assert (!EDGE_COUNT (bb->succs));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
921 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
922 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
923 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
924
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
925 /* Eliminates tail call described by T. TMP_VARS is a list of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
926 temporary variables used to copy the function arguments. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
927
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
928 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
929 eliminate_tail_call (struct tailcall *t)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
930 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
931 tree param, rslt;
111
kono
parents: 67
diff changeset
932 gimple *stmt, *call;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
933 tree arg;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
934 size_t idx;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
935 basic_block bb, first;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
936 edge e;
111
kono
parents: 67
diff changeset
937 gphi *phi;
kono
parents: 67
diff changeset
938 gphi_iterator gpi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
939 gimple_stmt_iterator gsi;
111
kono
parents: 67
diff changeset
940 gimple *orig_stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
941
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
942 stmt = orig_stmt = gsi_stmt (t->call_gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
943 bb = gsi_bb (t->call_gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
944
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
945 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
946 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947 fprintf (dump_file, "Eliminated tail recursion in bb %d : ",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948 bb->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
949 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
950 fprintf (dump_file, "\n");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
951 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
952
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
953 gcc_assert (is_gimple_call (stmt));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
954
111
kono
parents: 67
diff changeset
955 first = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
956
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
957 /* Remove the code after call_gsi that will become unreachable. The
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
958 possibly unreachable code in other blocks is removed later in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
959 cfg cleanup. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
960 gsi = t->call_gsi;
111
kono
parents: 67
diff changeset
961 gimple_stmt_iterator gsi2 = gsi_last_bb (gimple_bb (gsi_stmt (gsi)));
kono
parents: 67
diff changeset
962 while (gsi_stmt (gsi2) != gsi_stmt (gsi))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
963 {
111
kono
parents: 67
diff changeset
964 gimple *t = gsi_stmt (gsi2);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
965 /* Do not remove the return statement, so that redirect_edge_and_branch
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
966 sees how the block ends. */
111
kono
parents: 67
diff changeset
967 if (gimple_code (t) != GIMPLE_RETURN)
kono
parents: 67
diff changeset
968 {
kono
parents: 67
diff changeset
969 gimple_stmt_iterator gsi3 = gsi2;
kono
parents: 67
diff changeset
970 gsi_prev (&gsi2);
kono
parents: 67
diff changeset
971 gsi_remove (&gsi3, true);
kono
parents: 67
diff changeset
972 release_defs (t);
kono
parents: 67
diff changeset
973 }
kono
parents: 67
diff changeset
974 else
kono
parents: 67
diff changeset
975 gsi_prev (&gsi2);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
976 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
977
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
978 /* Number of executions of function has reduced by the tailcall. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
979 e = single_succ_edge (gsi_bb (t->call_gsi));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
980
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
981 profile_count count = e->count ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
982
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
983 /* When profile is inconsistent and the recursion edge is more frequent
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
984 than number of executions of functions, scale it down, so we do not end
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
985 up with 0 executions of entry block. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
986 if (count >= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
987 count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count.apply_scale (7, 8);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
988 decrease_profile (EXIT_BLOCK_PTR_FOR_FN (cfun), count);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
989 decrease_profile (ENTRY_BLOCK_PTR_FOR_FN (cfun), count);
111
kono
parents: 67
diff changeset
990 if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
991 decrease_profile (e->dest, count);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
992
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
993 /* Replace the call by a jump to the start of function. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
994 e = redirect_edge_and_branch (single_succ_edge (gsi_bb (t->call_gsi)),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
995 first);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
996 gcc_assert (e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
997 PENDING_STMT (e) = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
998
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
999 /* Add phi node entries for arguments. The ordering of the phi nodes should
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1000 be the same as the ordering of the arguments. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1001 for (param = DECL_ARGUMENTS (current_function_decl),
111
kono
parents: 67
diff changeset
1002 idx = 0, gpi = gsi_start_phis (first);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1003 param;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
1004 param = DECL_CHAIN (param), idx++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1005 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1006 if (!bitmap_bit_p (tailr_arg_needs_copy, idx))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1007 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1008
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1009 arg = gimple_call_arg (stmt, idx);
111
kono
parents: 67
diff changeset
1010 phi = gpi.phi ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1011 gcc_assert (param == SSA_NAME_VAR (PHI_RESULT (phi)));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1012
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1013 add_phi_arg (phi, arg, e, gimple_location (stmt));
111
kono
parents: 67
diff changeset
1014 gsi_next (&gpi);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1015 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1016
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1017 /* Update the values of accumulators. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1018 adjust_accumulator_values (t->call_gsi, t->mult, t->add, e);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1019
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1020 call = gsi_stmt (t->call_gsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1021 rslt = gimple_call_lhs (call);
111
kono
parents: 67
diff changeset
1022 if (rslt != NULL_TREE && TREE_CODE (rslt) == SSA_NAME)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1023 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1024 /* Result of the call will no longer be defined. So adjust the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1025 SSA_NAME_DEF_STMT accordingly. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1026 SSA_NAME_DEF_STMT (rslt) = gimple_build_nop ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1027 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1028
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1029 gsi_remove (&t->call_gsi, true);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1030 release_defs (call);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1031 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1032
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1033 /* Optimizes the tailcall described by T. If OPT_TAILCALLS is true, also
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1034 mark the tailcalls for the sibcall optimization. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1035
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1036 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1037 optimize_tail_call (struct tailcall *t, bool opt_tailcalls)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1038 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1039 if (t->tail_recursion)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1040 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1041 eliminate_tail_call (t);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1042 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1043 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1044
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1045 if (opt_tailcalls)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1046 {
111
kono
parents: 67
diff changeset
1047 gcall *stmt = as_a <gcall *> (gsi_stmt (t->call_gsi));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1048
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1049 gimple_call_set_tail (stmt, true);
111
kono
parents: 67
diff changeset
1050 cfun->tail_call_marked = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1051 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1052 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1053 fprintf (dump_file, "Found tail call ");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1054 print_gimple_stmt (dump_file, stmt, 0, dump_flags);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1055 fprintf (dump_file, " in bb %i\n", (gsi_bb (t->call_gsi))->index);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1056 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1057 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1058
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1059 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1060 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1061
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1062 /* Creates a tail-call accumulator of the same type as the return type of the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1063 current function. LABEL is the name used to creating the temporary
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1064 variable for the accumulator. The accumulator will be inserted in the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1065 phis of a basic block BB with single predecessor with an initial value
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1066 INIT converted to the current function return type. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1067
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1068 static tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1069 create_tailcall_accumulator (const char *label, basic_block bb, tree init)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1070 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1071 tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
111
kono
parents: 67
diff changeset
1072 if (POINTER_TYPE_P (ret_type))
kono
parents: 67
diff changeset
1073 ret_type = sizetype;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1074
111
kono
parents: 67
diff changeset
1075 tree tmp = make_temp_ssa_name (ret_type, NULL, label);
kono
parents: 67
diff changeset
1076 gphi *phi;
kono
parents: 67
diff changeset
1077
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1078 phi = create_phi_node (tmp, bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1079 /* RET_TYPE can be a float when -ffast-maths is enabled. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1080 add_phi_arg (phi, fold_convert (ret_type, init), single_pred_edge (bb),
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1081 UNKNOWN_LOCATION);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1082 return PHI_RESULT (phi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1083 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1084
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1085 /* Optimizes tail calls in the function, turning the tail recursion
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1086 into iteration. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1087
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1088 static unsigned int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1089 tree_optimize_tail_calls_1 (bool opt_tailcalls)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1090 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1091 edge e;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1092 bool phis_constructed = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1093 struct tailcall *tailcalls = NULL, *act, *next;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1094 bool changed = false;
111
kono
parents: 67
diff changeset
1095 basic_block first = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1096 tree param;
111
kono
parents: 67
diff changeset
1097 gimple *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1098 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1099
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1100 if (!suitable_for_tail_opt_p ())
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1101 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1102 if (opt_tailcalls)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1103 opt_tailcalls = suitable_for_tail_call_opt_p ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1104
111
kono
parents: 67
diff changeset
1105 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1106 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1107 /* Only traverse the normal exits, i.e. those that end with return
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1108 statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1109 stmt = last_stmt (e->src);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1110
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1111 if (stmt
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1112 && gimple_code (stmt) == GIMPLE_RETURN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1113 find_tail_calls (e->src, &tailcalls);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1114 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1115
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1116 if (live_vars)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1117 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1118 destroy_live_vars (live_vars_vec);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1119 delete live_vars;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1120 live_vars = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1121 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1122
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1123 /* Construct the phi nodes and accumulators if necessary. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1124 a_acc = m_acc = NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1125 for (act = tailcalls; act; act = act->next)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1126 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1127 if (!act->tail_recursion)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1128 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1129
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1130 if (!phis_constructed)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1131 {
47
3bfb6c00c1e0 update it from 4.4.2 to 4.4.3.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
1132 /* Ensure that there is only one predecessor of the block
3bfb6c00c1e0 update it from 4.4.2 to 4.4.3.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
1133 or if there are existing degenerate PHI nodes. */
3bfb6c00c1e0 update it from 4.4.2 to 4.4.3.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
1134 if (!single_pred_p (first)
3bfb6c00c1e0 update it from 4.4.2 to 4.4.3.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 19
diff changeset
1135 || !gimple_seq_empty_p (phi_nodes (first)))
111
kono
parents: 67
diff changeset
1136 first =
kono
parents: 67
diff changeset
1137 split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1138
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1139 /* Copy the args if needed. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1140 unsigned idx;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1141 for (param = DECL_ARGUMENTS (current_function_decl), idx = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1142 param;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1143 param = DECL_CHAIN (param), idx++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1144 if (bitmap_bit_p (tailr_arg_needs_copy, idx))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1145 {
111
kono
parents: 67
diff changeset
1146 tree name = ssa_default_def (cfun, param);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1147 tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
111
kono
parents: 67
diff changeset
1148 gphi *phi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1149
111
kono
parents: 67
diff changeset
1150 set_ssa_default_def (cfun, param, new_name);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1151 phi = create_phi_node (name, first);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1152 add_phi_arg (phi, new_name, single_pred_edge (first),
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1153 EXPR_LOCATION (param));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1154 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1155 phis_constructed = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1156 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1157
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1158 if (act->add && !a_acc)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1159 a_acc = create_tailcall_accumulator ("add_acc", first,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1160 integer_zero_node);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1161
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1162 if (act->mult && !m_acc)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1163 m_acc = create_tailcall_accumulator ("mult_acc", first,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1164 integer_one_node);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1165 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1166
111
kono
parents: 67
diff changeset
1167 if (a_acc || m_acc)
kono
parents: 67
diff changeset
1168 {
kono
parents: 67
diff changeset
1169 /* When the tail call elimination using accumulators is performed,
kono
parents: 67
diff changeset
1170 statements adding the accumulated value are inserted at all exits.
kono
parents: 67
diff changeset
1171 This turns all other tail calls to non-tail ones. */
kono
parents: 67
diff changeset
1172 opt_tailcalls = false;
kono
parents: 67
diff changeset
1173 }
kono
parents: 67
diff changeset
1174
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1175 for (; tailcalls; tailcalls = next)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1176 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1177 next = tailcalls->next;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1178 changed |= optimize_tail_call (tailcalls, opt_tailcalls);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1179 free (tailcalls);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1180 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1181
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1182 if (a_acc || m_acc)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1183 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1184 /* Modify the remaining return statements. */
111
kono
parents: 67
diff changeset
1185 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1186 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1187 stmt = last_stmt (e->src);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1188
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1189 if (stmt
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1190 && gimple_code (stmt) == GIMPLE_RETURN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1191 adjust_return_value (e->src, m_acc, a_acc);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1192 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1193 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1194
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1195 if (changed)
111
kono
parents: 67
diff changeset
1196 {
kono
parents: 67
diff changeset
1197 /* We may have created new loops. Make them magically appear. */
kono
parents: 67
diff changeset
1198 loops_state_set (LOOPS_NEED_FIXUP);
kono
parents: 67
diff changeset
1199 free_dominance_info (CDI_DOMINATORS);
kono
parents: 67
diff changeset
1200 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1201
111
kono
parents: 67
diff changeset
1202 /* Add phi nodes for the virtual operands defined in the function to the
kono
parents: 67
diff changeset
1203 header of the loop created by tail recursion elimination. Do so
kono
parents: 67
diff changeset
1204 by triggering the SSA renamer. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1205 if (phis_constructed)
111
kono
parents: 67
diff changeset
1206 mark_virtual_operands_for_renaming (cfun);
kono
parents: 67
diff changeset
1207
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1208 if (tailr_arg_needs_copy)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1209 BITMAP_FREE (tailr_arg_needs_copy);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1210
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1211 if (changed)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1212 return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1213 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1214 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1215
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1216 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1217 gate_tail_calls (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1218 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1219 return flag_optimize_sibling_calls != 0 && dbg_cnt (tail_call);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1220 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1221
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1222 static unsigned int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1223 execute_tail_calls (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1224 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1225 return tree_optimize_tail_calls_1 (true);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1226 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1227
111
kono
parents: 67
diff changeset
1228 namespace {
kono
parents: 67
diff changeset
1229
kono
parents: 67
diff changeset
1230 const pass_data pass_data_tail_recursion =
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1231 {
111
kono
parents: 67
diff changeset
1232 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
1233 "tailr", /* name */
kono
parents: 67
diff changeset
1234 OPTGROUP_NONE, /* optinfo_flags */
kono
parents: 67
diff changeset
1235 TV_NONE, /* tv_id */
kono
parents: 67
diff changeset
1236 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents: 67
diff changeset
1237 0, /* properties_provided */
kono
parents: 67
diff changeset
1238 0, /* properties_destroyed */
kono
parents: 67
diff changeset
1239 0, /* todo_flags_start */
kono
parents: 67
diff changeset
1240 0, /* todo_flags_finish */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1241 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1242
111
kono
parents: 67
diff changeset
1243 class pass_tail_recursion : public gimple_opt_pass
kono
parents: 67
diff changeset
1244 {
kono
parents: 67
diff changeset
1245 public:
kono
parents: 67
diff changeset
1246 pass_tail_recursion (gcc::context *ctxt)
kono
parents: 67
diff changeset
1247 : gimple_opt_pass (pass_data_tail_recursion, ctxt)
kono
parents: 67
diff changeset
1248 {}
kono
parents: 67
diff changeset
1249
kono
parents: 67
diff changeset
1250 /* opt_pass methods: */
kono
parents: 67
diff changeset
1251 opt_pass * clone () { return new pass_tail_recursion (m_ctxt); }
kono
parents: 67
diff changeset
1252 virtual bool gate (function *) { return gate_tail_calls (); }
kono
parents: 67
diff changeset
1253 virtual unsigned int execute (function *)
kono
parents: 67
diff changeset
1254 {
kono
parents: 67
diff changeset
1255 return tree_optimize_tail_calls_1 (false);
kono
parents: 67
diff changeset
1256 }
kono
parents: 67
diff changeset
1257
kono
parents: 67
diff changeset
1258 }; // class pass_tail_recursion
kono
parents: 67
diff changeset
1259
kono
parents: 67
diff changeset
1260 } // anon namespace
kono
parents: 67
diff changeset
1261
kono
parents: 67
diff changeset
1262 gimple_opt_pass *
kono
parents: 67
diff changeset
1263 make_pass_tail_recursion (gcc::context *ctxt)
kono
parents: 67
diff changeset
1264 {
kono
parents: 67
diff changeset
1265 return new pass_tail_recursion (ctxt);
kono
parents: 67
diff changeset
1266 }
kono
parents: 67
diff changeset
1267
kono
parents: 67
diff changeset
1268 namespace {
kono
parents: 67
diff changeset
1269
kono
parents: 67
diff changeset
1270 const pass_data pass_data_tail_calls =
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1271 {
111
kono
parents: 67
diff changeset
1272 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
1273 "tailc", /* name */
kono
parents: 67
diff changeset
1274 OPTGROUP_NONE, /* optinfo_flags */
kono
parents: 67
diff changeset
1275 TV_NONE, /* tv_id */
kono
parents: 67
diff changeset
1276 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents: 67
diff changeset
1277 0, /* properties_provided */
kono
parents: 67
diff changeset
1278 0, /* properties_destroyed */
kono
parents: 67
diff changeset
1279 0, /* todo_flags_start */
kono
parents: 67
diff changeset
1280 0, /* todo_flags_finish */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1281 };
111
kono
parents: 67
diff changeset
1282
kono
parents: 67
diff changeset
1283 class pass_tail_calls : public gimple_opt_pass
kono
parents: 67
diff changeset
1284 {
kono
parents: 67
diff changeset
1285 public:
kono
parents: 67
diff changeset
1286 pass_tail_calls (gcc::context *ctxt)
kono
parents: 67
diff changeset
1287 : gimple_opt_pass (pass_data_tail_calls, ctxt)
kono
parents: 67
diff changeset
1288 {}
kono
parents: 67
diff changeset
1289
kono
parents: 67
diff changeset
1290 /* opt_pass methods: */
kono
parents: 67
diff changeset
1291 virtual bool gate (function *) { return gate_tail_calls (); }
kono
parents: 67
diff changeset
1292 virtual unsigned int execute (function *) { return execute_tail_calls (); }
kono
parents: 67
diff changeset
1293
kono
parents: 67
diff changeset
1294 }; // class pass_tail_calls
kono
parents: 67
diff changeset
1295
kono
parents: 67
diff changeset
1296 } // anon namespace
kono
parents: 67
diff changeset
1297
kono
parents: 67
diff changeset
1298 gimple_opt_pass *
kono
parents: 67
diff changeset
1299 make_pass_tail_calls (gcc::context *ctxt)
kono
parents: 67
diff changeset
1300 {
kono
parents: 67
diff changeset
1301 return new pass_tail_calls (ctxt);
kono
parents: 67
diff changeset
1302 }