Mercurial > hg > CbC > CbC_gcc
annotate gcc/combine-stack-adj.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | f6334be47118 |
rev | line source |
---|---|
0 | 1 /* Combine stack adjustments. |
2 Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
0 | 4 Free Software Foundation, Inc. |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
22 /* Track stack adjustments and stack memory references. Attempt to | |
23 reduce the number of stack adjustments by back-propagating across | |
24 the memory references. | |
25 | |
26 This is intended primarily for use with targets that do not define | |
27 ACCUMULATE_OUTGOING_ARGS. It is of significantly more value to | |
28 targets that define PREFERRED_STACK_BOUNDARY more aligned than | |
29 STACK_BOUNDARY (e.g. x86), or if not all registers can be pushed | |
30 (e.g. x86 fp regs) which would ordinarily have to be implemented | |
31 as a sub/mov pair due to restrictions in calls.c. | |
32 | |
33 Propagation stops when any of the insns that need adjusting are | |
34 (a) no longer valid because we've exceeded their range, (b) a | |
35 non-trivial push instruction, or (c) a call instruction. | |
36 | |
37 Restriction B is based on the assumption that push instructions | |
38 are smaller or faster. If a port really wants to remove all | |
39 pushes, it should have defined ACCUMULATE_OUTGOING_ARGS. The | |
40 one exception that is made is for an add immediately followed | |
41 by a push. */ | |
42 | |
43 #include "config.h" | |
44 #include "system.h" | |
45 #include "coretypes.h" | |
46 #include "tm.h" | |
47 #include "rtl.h" | |
48 #include "tm_p.h" | |
49 #include "insn-config.h" | |
50 #include "recog.h" | |
51 #include "output.h" | |
52 #include "regs.h" | |
53 #include "hard-reg-set.h" | |
54 #include "flags.h" | |
55 #include "function.h" | |
56 #include "expr.h" | |
57 #include "basic-block.h" | |
58 #include "df.h" | |
59 #include "except.h" | |
60 #include "toplev.h" | |
61 #include "reload.h" | |
62 #include "timevar.h" | |
63 #include "tree-pass.h" | |
64 | |
65 | |
66 /* Turn STACK_GROWS_DOWNWARD into a boolean. */ | |
67 #ifdef STACK_GROWS_DOWNWARD | |
68 #undef STACK_GROWS_DOWNWARD | |
69 #define STACK_GROWS_DOWNWARD 1 | |
70 #else | |
71 #define STACK_GROWS_DOWNWARD 0 | |
72 #endif | |
73 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
74 /* This structure records two kinds of stack references between stack |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
75 adjusting instructions: stack references in memory addresses for |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
76 regular insns and all stack references for debug insns. */ |
0 | 77 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
78 struct csa_reflist |
0 | 79 { |
80 HOST_WIDE_INT sp_offset; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
81 rtx insn, *ref; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
82 struct csa_reflist *next; |
0 | 83 }; |
84 | |
85 static int stack_memref_p (rtx); | |
86 static rtx single_set_for_csa (rtx); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
87 static void free_csa_reflist (struct csa_reflist *); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
88 static struct csa_reflist *record_one_stack_ref (rtx, rtx *, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
89 struct csa_reflist *); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
90 static int try_apply_stack_adjustment (rtx, struct csa_reflist *, |
0 | 91 HOST_WIDE_INT, HOST_WIDE_INT); |
92 static void combine_stack_adjustments_for_block (basic_block); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
93 static int record_stack_refs (rtx *, void *); |
0 | 94 |
95 | |
96 /* Main entry point for stack adjustment combination. */ | |
97 | |
98 static void | |
99 combine_stack_adjustments (void) | |
100 { | |
101 basic_block bb; | |
102 | |
103 FOR_EACH_BB (bb) | |
104 combine_stack_adjustments_for_block (bb); | |
105 } | |
106 | |
107 /* Recognize a MEM of the form (sp) or (plus sp const). */ | |
108 | |
109 static int | |
110 stack_memref_p (rtx x) | |
111 { | |
112 if (!MEM_P (x)) | |
113 return 0; | |
114 x = XEXP (x, 0); | |
115 | |
116 if (x == stack_pointer_rtx) | |
117 return 1; | |
118 if (GET_CODE (x) == PLUS | |
119 && XEXP (x, 0) == stack_pointer_rtx | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
120 && CONST_INT_P (XEXP (x, 1))) |
0 | 121 return 1; |
122 | |
123 return 0; | |
124 } | |
125 | |
126 /* Recognize either normal single_set or the hack in i386.md for | |
127 tying fp and sp adjustments. */ | |
128 | |
129 static rtx | |
130 single_set_for_csa (rtx insn) | |
131 { | |
132 int i; | |
133 rtx tmp = single_set (insn); | |
134 if (tmp) | |
135 return tmp; | |
136 | |
137 if (!NONJUMP_INSN_P (insn) | |
138 || GET_CODE (PATTERN (insn)) != PARALLEL) | |
139 return NULL_RTX; | |
140 | |
141 tmp = PATTERN (insn); | |
142 if (GET_CODE (XVECEXP (tmp, 0, 0)) != SET) | |
143 return NULL_RTX; | |
144 | |
145 for (i = 1; i < XVECLEN (tmp, 0); ++i) | |
146 { | |
147 rtx this_rtx = XVECEXP (tmp, 0, i); | |
148 | |
149 /* The special case is allowing a no-op set. */ | |
150 if (GET_CODE (this_rtx) == SET | |
151 && SET_SRC (this_rtx) == SET_DEST (this_rtx)) | |
152 ; | |
153 else if (GET_CODE (this_rtx) != CLOBBER | |
154 && GET_CODE (this_rtx) != USE) | |
155 return NULL_RTX; | |
156 } | |
157 | |
158 return XVECEXP (tmp, 0, 0); | |
159 } | |
160 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
161 /* Free the list of csa_reflist nodes. */ |
0 | 162 |
163 static void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
164 free_csa_reflist (struct csa_reflist *reflist) |
0 | 165 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
166 struct csa_reflist *next; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
167 for (; reflist ; reflist = next) |
0 | 168 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
169 next = reflist->next; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
170 free (reflist); |
0 | 171 } |
172 } | |
173 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
174 /* Create a new csa_reflist node from the given stack reference. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
175 It is already known that the reference is either a MEM satisfying the |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
176 predicate stack_memref_p or a REG representing the stack pointer. */ |
0 | 177 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
178 static struct csa_reflist * |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
179 record_one_stack_ref (rtx insn, rtx *ref, struct csa_reflist *next_reflist) |
0 | 180 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
181 struct csa_reflist *ml; |
0 | 182 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
183 ml = XNEW (struct csa_reflist); |
0 | 184 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
185 if (REG_P (*ref) || XEXP (*ref, 0) == stack_pointer_rtx) |
0 | 186 ml->sp_offset = 0; |
187 else | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
188 ml->sp_offset = INTVAL (XEXP (XEXP (*ref, 0), 1)); |
0 | 189 |
190 ml->insn = insn; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
191 ml->ref = ref; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
192 ml->next = next_reflist; |
0 | 193 |
194 return ml; | |
195 } | |
196 | |
197 /* Attempt to apply ADJUST to the stack adjusting insn INSN, as well | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
198 as each of the memories and stack references in REFLIST. Return true |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
199 on success. */ |
0 | 200 |
201 static int | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
202 try_apply_stack_adjustment (rtx insn, struct csa_reflist *reflist, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
203 HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta) |
0 | 204 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
205 struct csa_reflist *ml; |
0 | 206 rtx set; |
207 | |
208 set = single_set_for_csa (insn); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
209 if (MEM_P (SET_DEST (set))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
210 validate_change (insn, &SET_DEST (set), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
211 replace_equiv_address (SET_DEST (set), stack_pointer_rtx), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
212 1); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
213 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
214 validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1); |
0 | 215 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
216 for (ml = reflist; ml ; ml = ml->next) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
217 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
218 rtx new_addr = plus_constant (stack_pointer_rtx, ml->sp_offset - delta); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
219 rtx new_val; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
220 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
221 if (MEM_P (*ml->ref)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
222 new_val = replace_equiv_address_nv (*ml->ref, new_addr); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
223 else if (GET_MODE (*ml->ref) == GET_MODE (stack_pointer_rtx)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
224 new_val = new_addr; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
225 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
226 new_val = lowpart_subreg (GET_MODE (*ml->ref), new_addr, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
227 GET_MODE (new_addr)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
228 validate_change (ml->insn, ml->ref, new_val, 1); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
229 } |
0 | 230 |
231 if (apply_change_group ()) | |
232 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
233 /* Succeeded. Update our knowledge of the stack references. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
234 for (ml = reflist; ml ; ml = ml->next) |
0 | 235 ml->sp_offset -= delta; |
236 | |
237 return 1; | |
238 } | |
239 else | |
240 return 0; | |
241 } | |
242 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
243 /* Called via for_each_rtx and used to record all stack memory and other |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
244 references in the insn and discard all other stack pointer references. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
245 struct record_stack_refs_data |
0 | 246 { |
247 rtx insn; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
248 struct csa_reflist *reflist; |
0 | 249 }; |
250 | |
251 static int | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
252 record_stack_refs (rtx *xp, void *data) |
0 | 253 { |
254 rtx x = *xp; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
255 struct record_stack_refs_data *d = |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
256 (struct record_stack_refs_data *) data; |
0 | 257 if (!x) |
258 return 0; | |
259 switch (GET_CODE (x)) | |
260 { | |
261 case MEM: | |
262 if (!reg_mentioned_p (stack_pointer_rtx, x)) | |
263 return -1; | |
264 /* We are not able to handle correctly all possible memrefs containing | |
265 stack pointer, so this check is necessary. */ | |
266 if (stack_memref_p (x)) | |
267 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
268 d->reflist = record_one_stack_ref (d->insn, xp, d->reflist); |
0 | 269 return -1; |
270 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
271 /* Try harder for DEBUG_INSNs, handle e.g. (mem (mem (sp + 16) + 4). */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
272 return !DEBUG_INSN_P (d->insn); |
0 | 273 case REG: |
274 /* ??? We want be able to handle non-memory stack pointer | |
275 references later. For now just discard all insns referring to | |
276 stack pointer outside mem expressions. We would probably | |
277 want to teach validate_replace to simplify expressions first. | |
278 | |
279 We can't just compare with STACK_POINTER_RTX because the | |
280 reference to the stack pointer might be in some other mode. | |
281 In particular, an explicit clobber in an asm statement will | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
282 result in a QImode clobber. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
283 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
284 In DEBUG_INSNs, we want to replace all occurrences, otherwise |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
285 they will cause -fcompare-debug failures. */ |
0 | 286 if (REGNO (x) == STACK_POINTER_REGNUM) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
287 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
288 if (!DEBUG_INSN_P (d->insn)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
289 return 1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
290 d->reflist = record_one_stack_ref (d->insn, xp, d->reflist); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
291 return -1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
292 } |
0 | 293 break; |
294 default: | |
295 break; | |
296 } | |
297 return 0; | |
298 } | |
299 | |
300 /* Adjust or create REG_FRAME_RELATED_EXPR note when merging a stack | |
301 adjustment into a frame related insn. */ | |
302 | |
303 static void | |
304 adjust_frame_related_expr (rtx last_sp_set, rtx insn, | |
305 HOST_WIDE_INT this_adjust) | |
306 { | |
307 rtx note = find_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, NULL_RTX); | |
308 rtx new_expr = NULL_RTX; | |
309 | |
310 if (note == NULL_RTX && RTX_FRAME_RELATED_P (insn)) | |
311 return; | |
312 | |
313 if (note | |
314 && GET_CODE (XEXP (note, 0)) == SEQUENCE | |
315 && XVECLEN (XEXP (note, 0), 0) >= 2) | |
316 { | |
317 rtx expr = XEXP (note, 0); | |
318 rtx last = XVECEXP (expr, 0, XVECLEN (expr, 0) - 1); | |
319 int i; | |
320 | |
321 if (GET_CODE (last) == SET | |
322 && RTX_FRAME_RELATED_P (last) == RTX_FRAME_RELATED_P (insn) | |
323 && SET_DEST (last) == stack_pointer_rtx | |
324 && GET_CODE (SET_SRC (last)) == PLUS | |
325 && XEXP (SET_SRC (last), 0) == stack_pointer_rtx | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
326 && CONST_INT_P (XEXP (SET_SRC (last), 1))) |
0 | 327 { |
328 XEXP (SET_SRC (last), 1) | |
329 = GEN_INT (INTVAL (XEXP (SET_SRC (last), 1)) + this_adjust); | |
330 return; | |
331 } | |
332 | |
333 new_expr = gen_rtx_SEQUENCE (VOIDmode, | |
334 rtvec_alloc (XVECLEN (expr, 0) + 1)); | |
335 for (i = 0; i < XVECLEN (expr, 0); i++) | |
336 XVECEXP (new_expr, 0, i) = XVECEXP (expr, 0, i); | |
337 } | |
338 else | |
339 { | |
340 new_expr = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2)); | |
341 if (note) | |
342 XVECEXP (new_expr, 0, 0) = XEXP (note, 0); | |
343 else | |
344 { | |
345 rtx expr = copy_rtx (single_set_for_csa (last_sp_set)); | |
346 | |
347 XEXP (SET_SRC (expr), 1) | |
348 = GEN_INT (INTVAL (XEXP (SET_SRC (expr), 1)) - this_adjust); | |
349 RTX_FRAME_RELATED_P (expr) = 1; | |
350 XVECEXP (new_expr, 0, 0) = expr; | |
351 } | |
352 } | |
353 | |
354 XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1) | |
355 = copy_rtx (single_set_for_csa (insn)); | |
356 RTX_FRAME_RELATED_P (XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1)) | |
357 = RTX_FRAME_RELATED_P (insn); | |
358 if (note) | |
359 XEXP (note, 0) = new_expr; | |
360 else | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
361 add_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, new_expr); |
0 | 362 } |
363 | |
364 /* Subroutine of combine_stack_adjustments, called for each basic block. */ | |
365 | |
366 static void | |
367 combine_stack_adjustments_for_block (basic_block bb) | |
368 { | |
369 HOST_WIDE_INT last_sp_adjust = 0; | |
370 rtx last_sp_set = NULL_RTX; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
371 struct csa_reflist *reflist = NULL; |
0 | 372 rtx insn, next, set; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
373 struct record_stack_refs_data data; |
0 | 374 bool end_of_block = false; |
375 | |
376 for (insn = BB_HEAD (bb); !end_of_block ; insn = next) | |
377 { | |
378 end_of_block = insn == BB_END (bb); | |
379 next = NEXT_INSN (insn); | |
380 | |
381 if (! INSN_P (insn)) | |
382 continue; | |
383 | |
384 set = single_set_for_csa (insn); | |
385 if (set) | |
386 { | |
387 rtx dest = SET_DEST (set); | |
388 rtx src = SET_SRC (set); | |
389 | |
390 /* Find constant additions to the stack pointer. */ | |
391 if (dest == stack_pointer_rtx | |
392 && GET_CODE (src) == PLUS | |
393 && XEXP (src, 0) == stack_pointer_rtx | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
394 && CONST_INT_P (XEXP (src, 1))) |
0 | 395 { |
396 HOST_WIDE_INT this_adjust = INTVAL (XEXP (src, 1)); | |
397 | |
398 /* If we've not seen an adjustment previously, record | |
399 it now and continue. */ | |
400 if (! last_sp_set) | |
401 { | |
402 last_sp_set = insn; | |
403 last_sp_adjust = this_adjust; | |
404 continue; | |
405 } | |
406 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
407 /* If not all recorded refs can be adjusted, or the |
0 | 408 adjustment is now too large for a constant addition, |
409 we cannot merge the two stack adjustments. | |
410 | |
411 Also we need to be careful to not move stack pointer | |
412 such that we create stack accesses outside the allocated | |
413 area. We can combine an allocation into the first insn, | |
414 or a deallocation into the second insn. We can not | |
415 combine an allocation followed by a deallocation. | |
416 | |
417 The only somewhat frequent occurrence of the later is when | |
418 a function allocates a stack frame but does not use it. | |
419 For this case, we would need to analyze rtl stream to be | |
420 sure that allocated area is really unused. This means not | |
421 only checking the memory references, but also all registers | |
422 or global memory references possibly containing a stack | |
423 frame address. | |
424 | |
425 Perhaps the best way to address this problem is to teach | |
426 gcc not to allocate stack for objects never used. */ | |
427 | |
428 /* Combine an allocation into the first instruction. */ | |
429 if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0) | |
430 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
431 if (try_apply_stack_adjustment (last_sp_set, reflist, |
0 | 432 last_sp_adjust + this_adjust, |
433 this_adjust)) | |
434 { | |
435 if (RTX_FRAME_RELATED_P (last_sp_set)) | |
436 adjust_frame_related_expr (last_sp_set, insn, | |
437 this_adjust); | |
438 /* It worked! */ | |
439 delete_insn (insn); | |
440 last_sp_adjust += this_adjust; | |
441 continue; | |
442 } | |
443 } | |
444 | |
445 /* Otherwise we have a deallocation. Do not combine with | |
446 a previous allocation. Combine into the second insn. */ | |
447 else if (STACK_GROWS_DOWNWARD | |
448 ? last_sp_adjust >= 0 : last_sp_adjust <= 0) | |
449 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
450 if (try_apply_stack_adjustment (insn, reflist, |
0 | 451 last_sp_adjust + this_adjust, |
452 -last_sp_adjust)) | |
453 { | |
454 /* It worked! */ | |
455 delete_insn (last_sp_set); | |
456 last_sp_set = insn; | |
457 last_sp_adjust += this_adjust; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
458 free_csa_reflist (reflist); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
459 reflist = NULL; |
0 | 460 continue; |
461 } | |
462 } | |
463 | |
464 /* Combination failed. Restart processing from here. If | |
465 deallocation+allocation conspired to cancel, we can | |
466 delete the old deallocation insn. */ | |
467 if (last_sp_set && last_sp_adjust == 0) | |
468 delete_insn (last_sp_set); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
469 free_csa_reflist (reflist); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
470 reflist = NULL; |
0 | 471 last_sp_set = insn; |
472 last_sp_adjust = this_adjust; | |
473 continue; | |
474 } | |
475 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
476 /* Find a store with pre-(dec|inc)rement or pre-modify of exactly |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
477 the previous adjustment and turn it into a simple store. This |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
478 is equivalent to anticipating the stack adjustment so this must |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
479 be an allocation. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
480 if (MEM_P (dest) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
481 && ((STACK_GROWS_DOWNWARD |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
482 ? (GET_CODE (XEXP (dest, 0)) == PRE_DEC |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
483 && last_sp_adjust |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
484 == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
485 : (GET_CODE (XEXP (dest, 0)) == PRE_INC |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
486 && last_sp_adjust |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
487 == -(HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest)))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
488 || ((STACK_GROWS_DOWNWARD |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
489 ? last_sp_adjust >= 0 : last_sp_adjust <= 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
490 && GET_CODE (XEXP (dest, 0)) == PRE_MODIFY |
0 | 491 && GET_CODE (XEXP (XEXP (dest, 0), 1)) == PLUS |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
492 && XEXP (XEXP (XEXP (dest, 0), 1), 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
493 == stack_pointer_rtx |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
494 && GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
495 == CONST_INT |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
496 && INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
497 == -last_sp_adjust)) |
0 | 498 && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
499 && !reg_mentioned_p (stack_pointer_rtx, src) |
0 | 500 && memory_address_p (GET_MODE (dest), stack_pointer_rtx) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
501 && try_apply_stack_adjustment (insn, reflist, 0, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
502 -last_sp_adjust)) |
0 | 503 { |
504 delete_insn (last_sp_set); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
505 free_csa_reflist (reflist); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
506 reflist = NULL; |
0 | 507 last_sp_set = NULL_RTX; |
508 last_sp_adjust = 0; | |
509 continue; | |
510 } | |
511 } | |
512 | |
513 data.insn = insn; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
514 data.reflist = reflist; |
0 | 515 if (!CALL_P (insn) && last_sp_set |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
516 && !for_each_rtx (&PATTERN (insn), record_stack_refs, &data)) |
0 | 517 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
518 reflist = data.reflist; |
0 | 519 continue; |
520 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
521 reflist = data.reflist; |
0 | 522 |
523 /* Otherwise, we were not able to process the instruction. | |
524 Do not continue collecting data across such a one. */ | |
525 if (last_sp_set | |
526 && (CALL_P (insn) | |
527 || reg_mentioned_p (stack_pointer_rtx, PATTERN (insn)))) | |
528 { | |
529 if (last_sp_set && last_sp_adjust == 0) | |
530 delete_insn (last_sp_set); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
531 free_csa_reflist (reflist); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
532 reflist = NULL; |
0 | 533 last_sp_set = NULL_RTX; |
534 last_sp_adjust = 0; | |
535 } | |
536 } | |
537 | |
538 if (last_sp_set && last_sp_adjust == 0) | |
539 delete_insn (last_sp_set); | |
540 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
541 if (reflist) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
542 free_csa_reflist (reflist); |
0 | 543 } |
544 | |
545 | |
546 static bool | |
547 gate_handle_stack_adjustments (void) | |
548 { | |
549 return (optimize > 0); | |
550 } | |
551 | |
552 static unsigned int | |
553 rest_of_handle_stack_adjustments (void) | |
554 { | |
555 cleanup_cfg (flag_crossjumping ? CLEANUP_CROSSJUMP : 0); | |
556 | |
557 /* This is kind of a heuristic. We need to run combine_stack_adjustments | |
558 even for machines with possibly nonzero RETURN_POPS_ARGS | |
559 and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having | |
560 push instructions will have popping returns. */ | |
561 #ifndef PUSH_ROUNDING | |
562 if (!ACCUMULATE_OUTGOING_ARGS) | |
563 #endif | |
564 { | |
565 df_note_add_problem (); | |
566 df_analyze (); | |
567 combine_stack_adjustments (); | |
568 } | |
569 return 0; | |
570 } | |
571 | |
572 struct rtl_opt_pass pass_stack_adjustments = | |
573 { | |
574 { | |
575 RTL_PASS, | |
576 "csa", /* name */ | |
577 gate_handle_stack_adjustments, /* gate */ | |
578 rest_of_handle_stack_adjustments, /* execute */ | |
579 NULL, /* sub */ | |
580 NULL, /* next */ | |
581 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
582 TV_COMBINE_STACK_ADJUST, /* tv_id */ |
0 | 583 0, /* properties_required */ |
584 0, /* properties_provided */ | |
585 0, /* properties_destroyed */ | |
586 0, /* todo_flags_start */ | |
587 TODO_df_finish | TODO_verify_rtl_sharing | | |
588 TODO_dump_func | | |
589 TODO_ggc_collect, /* todo_flags_finish */ | |
590 } | |
591 }; |