diff options
author | Zhenhua Luo <b19537@freescale.com> | 2012-03-09 10:57:35 +0000 |
---|---|---|
committer | Matthew McClintock <msm@freescale.com> | 2012-03-13 12:41:42 -0500 |
commit | 122c5bfdad95930de96e191aafb0304fded007b2 (patch) | |
tree | ea66cb9147fed9ceacd9eacd5913b10bb64734a1 /recipes-devtools/gcc/files/gcc.opt-array-offset.patch | |
parent | 4f2d99fbb0afd19376e404583700ee31428f7c2e (diff) | |
download | meta-fsl-ppc-122c5bfdad95930de96e191aafb0304fded007b2.tar.gz |
integrate fsl toolchain patches
binutils:
bin.e500mc_nop.patch
bin.e5500.patch
bin.e6500-2.patch
eglibc:
generate-supported.mk
glibc.e500mc_subspecies_of_powerpc_is_not_supported.patch
glibc.fixgcc4.6.patch
glibc.fix_prof.patch
glibc.fix_sqrt.patch
glibc.readv_proto.patch
glibc.undefined_static.patch
gcc:
gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch
gcc.fix_longversionstring.patch
gcc.rm_slow_tests.patch
gcc.fix_mingw32.patch
gcc.fix_cloogstatic2.patch
gcc.fix_build-with-cxx.patch
gcc.e6500-FSF46.patch
gcc.ld_unaligned-460.patch
gcc.local_unaligned_altivec.patch
gcc.soft_float-460.patch
gcc.case_values.patch
gcc.builtin_isel.patch
gcc.experimental_move.patch
gcc.widen_types-46.patch
gcc.extelim-v3.patch
gcc.e5500_mfocr.patch
gcc.opt-array-offset.patch
gcc.load_on_store_bypass-462.patch
gcc.fix_constvector.patch
gcc.fix_MTWX51204-dwarf-vector-reg.patch
gcc.fix_ira-loop-pressure.patch
optional_libstdc.patch
gcc.remove_CCUNSmode_reference.patch
gcc.check_path_validity.patch
gcc.fix_header_issue.patch
gcc.fix_SSIZE_MAX_undefine_issue.patch
gettext:
gettext.fix_testcase.patch
Signed-off-by: Zhenhua Luo <b19537@freescale.com>
Diffstat (limited to 'recipes-devtools/gcc/files/gcc.opt-array-offset.patch')
-rw-r--r-- | recipes-devtools/gcc/files/gcc.opt-array-offset.patch | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/files/gcc.opt-array-offset.patch b/recipes-devtools/gcc/files/gcc.opt-array-offset.patch new file mode 100644 index 0000000..7cdc6f7 --- /dev/null +++ b/recipes-devtools/gcc/files/gcc.opt-array-offset.patch | |||
@@ -0,0 +1,350 @@ | |||
1 | Implements a GIMPLE pass to optimize array access by factoring | ||
2 | out expressions that calculate address offset from | ||
3 | multiple array access. Controls with flag -fopt-array-offset | ||
4 | |||
5 | diff -ruN XLMe500mc/gcc/common.opt XLMe5500/gcc/common.opt | ||
6 | --- XLMe500mc/gcc/common.opt 2011-10-18 14:49:23.026644000 -0500 | ||
7 | +++ XLMe5500/gcc/common.opt 2011-10-05 12:39:26.242644101 -0500 | ||
8 | @@ -1992,6 +1992,10 @@ | ||
9 | Common Report Var(flag_tree_vrp) Init(0) Optimization | ||
10 | Perform Value Range Propagation on trees | ||
11 | |||
12 | +fopt-array-offset | ||
13 | +Common Report Var(flag_opt_array_offset) | ||
14 | +Expand array offset address calculations | ||
15 | + | ||
16 | funit-at-a-time | ||
17 | Common Report Var(flag_unit_at_a_time) Init(1) Optimization | ||
18 | Compile whole compilation unit at a time | ||
19 | diff -ruN XLMe500mc/gcc/Makefile.in XLMe5500/gcc/Makefile.in | ||
20 | --- XLMe500mc/gcc/Makefile.in 2011-10-18 14:49:23.028644000 -0500 | ||
21 | +++ XLMe5500/gcc/Makefile.in 2011-10-05 12:08:28.104643898 -0500 | ||
22 | @@ -1306,6 +1306,7 @@ | ||
23 | omp-low.o \ | ||
24 | optabs.o \ | ||
25 | options.o \ | ||
26 | + opt-array-offset.o \ | ||
27 | opts-common.o \ | ||
28 | opts-global.o \ | ||
29 | opts.o \ | ||
30 | @@ -2629,7 +2630,10 @@ | ||
31 | $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \ | ||
32 | $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \ | ||
33 | $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H) $(REGSET_H) | ||
34 | - | ||
35 | +opt-array-offset.o : opt-array-offset.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ | ||
36 | + $(TM_H) $(FLAGS_H) $(TREE_H) $(TREE_FLOW_H) $(TIMEVAR_H) \ | ||
37 | + $(TREE_PASS_H) alloc-pool.h $(BASIC_BLOCK_H) $(TARGET_H) \ | ||
38 | + $(DIAGNOSTIC_H) gimple-pretty-print.h tree-pretty-print.h | ||
39 | widen-types.o : widen-types.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \ | ||
40 | $(DIAGNOSTIC_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h \ | ||
41 | $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \ | ||
42 | diff -ruN XLMe500mc/gcc/opt-array-offset.c XLMe5500/gcc/opt-array-offset.c | ||
43 | --- XLMe500mc/gcc/opt-array-offset.c 1969-12-31 18:00:00.000000000 -0600 | ||
44 | +++ XLMe5500/gcc/opt-array-offset.c 2011-11-01 15:24:21.746039000 -0500 | ||
45 | @@ -0,0 +1,283 @@ | ||
46 | +/* Optimizing array element access | ||
47 | + Copyright (C) 2011 | ||
48 | + Free Software Foundation, Inc. | ||
49 | + | ||
50 | +This file is part of GCC. | ||
51 | + | ||
52 | +GCC is free software; you can redistribute it and/or modify it | ||
53 | +under the terms of the GNU General Public License as published by the | ||
54 | +Free Software Foundation; either version 3, or (at your option) any | ||
55 | +later version. | ||
56 | + | ||
57 | +GCC is distributed in the hope that it will be useful, but WITHOUT | ||
58 | +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
59 | +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
60 | +for more details. | ||
61 | + | ||
62 | +You should have received a copy of the GNU General Public License | ||
63 | +along with GCC; see the file COPYING3. If not see | ||
64 | +<http://www.gnu.org/licenses/>. */ | ||
65 | + | ||
66 | + | ||
67 | +/* This is a GIMPLE pass over basic block which coverts the stmts: | ||
68 | + | ||
69 | + a = b +/- c1; | ||
70 | + c = a * c2; | ||
71 | + | ||
72 | + to: | ||
73 | + | ||
74 | + a = b * c2; | ||
75 | + c = a +/- c1 * c2; | ||
76 | + | ||
77 | + in effect expanding the multiplication across addition/substraction. | ||
78 | + | ||
79 | + Motivating example: | ||
80 | + Consider the following simple integer array access: | ||
81 | + | ||
82 | + a[i] = c; | ||
83 | + a[i + 1] = c; | ||
84 | + | ||
85 | + The following GIMPLE equivalent will be generated: | ||
86 | + | ||
87 | + off_1 = i * 4; | ||
88 | + a_i = a + off_1; | ||
89 | + *a_i = c; | ||
90 | + | ||
91 | + off_1 = i + 1; | ||
92 | + off_2 = off_1 * 4; | ||
93 | + a_i1 = a + off_2; | ||
94 | + *a_i1 = c; | ||
95 | + | ||
96 | + Notice that a_i1 could simply be a_i + 4. But the calcuation of i+1 | ||
97 | + is preventing CSE to perform. This pass will essentially convert the | ||
98 | + second expr into: | ||
99 | + | ||
100 | + off_1 = i * 4; | ||
101 | + off_2 = off_1 + 4; | ||
102 | + a_i1 = a + off_2; | ||
103 | + .... | ||
104 | + | ||
105 | + Thus allowing the previous index i calculation to be reuse. off_1 + 4 | ||
106 | + would also be combined into a_i if offset addressing mode is available. | ||
107 | + This also have side effect of avoiding redundant sign extension on | ||
108 | + i+1 for LP64 model where native integer size is different from pointer size. | ||
109 | + | ||
110 | + The algorithm iterates through all the basic blocks looking for | ||
111 | + the above pattern. Care is taken to make sure off_1 only | ||
112 | + has the single use otherwise the transformation cannot be perform. | ||
113 | +*/ | ||
114 | + | ||
115 | + | ||
116 | +#include "config.h" | ||
117 | +#include "system.h" | ||
118 | +#include "coretypes.h" | ||
119 | +#include "tm.h" | ||
120 | +#include "flags.h" | ||
121 | +#include "tree.h" | ||
122 | +#include "tree-flow.h" | ||
123 | +#include "timevar.h" | ||
124 | +#include "tree-pass.h" | ||
125 | +#include "alloc-pool.h" | ||
126 | +#include "basic-block.h" | ||
127 | +#include "target.h" | ||
128 | +#include "gimple-pretty-print.h" | ||
129 | +#include "tree-pretty-print.h" | ||
130 | + | ||
131 | + | ||
132 | +/* | ||
133 | + We are looking for: | ||
134 | + a = b +/- c1 | ||
135 | + c = a * c2 (stmt incoming) | ||
136 | + d = &arr + c | ||
137 | +*/ | ||
138 | +static bool | ||
139 | +is_candidate (gimple stmt) | ||
140 | +{ | ||
141 | + tree mul_result = gimple_get_lhs (stmt); | ||
142 | + tree rhs1, rhs2; | ||
143 | + gimple rhs1_stmt, use_stmt; | ||
144 | + use_operand_p use_p; | ||
145 | + imm_use_iterator imm_iter; | ||
146 | + | ||
147 | + /* check for a * c2 */ | ||
148 | + if (gimple_assign_rhs_code (stmt) != MULT_EXPR) | ||
149 | + return false; | ||
150 | + | ||
151 | + rhs1 = gimple_assign_rhs1 (stmt); | ||
152 | + rhs2 = gimple_assign_rhs2 (stmt); | ||
153 | + | ||
154 | + if (TREE_CODE (rhs2) != INTEGER_CST) | ||
155 | + return false; | ||
156 | + | ||
157 | + /* check for b + c1 */ | ||
158 | + if (TREE_CODE (rhs1) == SSA_NAME) | ||
159 | + { | ||
160 | + rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); | ||
161 | + if (is_gimple_assign (rhs1_stmt)) | ||
162 | + { | ||
163 | + tree rhs1_2; | ||
164 | + tree plusminus_result; | ||
165 | + | ||
166 | + if (gimple_assign_rhs_code (rhs1_stmt) != PLUS_EXPR | ||
167 | + && gimple_assign_rhs_code (rhs1_stmt) != MINUS_EXPR) | ||
168 | + return false; | ||
169 | + | ||
170 | + rhs1_2 = gimple_assign_rhs2 (rhs1_stmt); | ||
171 | + if (TREE_CODE (rhs1_2) != INTEGER_CST) | ||
172 | + return false; | ||
173 | + | ||
174 | + /* make sure there are no other uses of a | ||
175 | + e.g. if a is used as an indcution variable | ||
176 | + we cannot modified it | ||
177 | + */ | ||
178 | + plusminus_result = gimple_get_lhs (rhs1_stmt); | ||
179 | + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, plusminus_result) | ||
180 | + { | ||
181 | + use_stmt = USE_STMT (use_p); | ||
182 | + | ||
183 | + /* ignore PHI node */ | ||
184 | + if (is_gimple_assign (use_stmt) && | ||
185 | + (gimple_assign_rhs_code (use_stmt) == GIMPLE_PHI)) | ||
186 | + continue; | ||
187 | + if (use_stmt != stmt) | ||
188 | + return false; | ||
189 | + } | ||
190 | + | ||
191 | +#if 0 | ||
192 | + if (gimple_bb(rhs1_stmt) != gimple_bb(stmt)) | ||
193 | + return false; | ||
194 | +#endif | ||
195 | + } | ||
196 | + else | ||
197 | + return false; | ||
198 | + } | ||
199 | + else | ||
200 | + return false; | ||
201 | + | ||
202 | + /* now look for uses of c that is a pointer use */ | ||
203 | + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, mul_result) | ||
204 | + { | ||
205 | + enum tree_code use_code; | ||
206 | + | ||
207 | + use_stmt = USE_STMT (use_p); | ||
208 | + | ||
209 | + if (is_gimple_debug (use_stmt)) | ||
210 | + continue; | ||
211 | + | ||
212 | + if (gimple_bb (use_stmt) != gimple_bb (stmt)) | ||
213 | + return false; | ||
214 | + | ||
215 | + if (!is_gimple_assign (use_stmt)) | ||
216 | + return false; | ||
217 | + | ||
218 | + use_code = gimple_assign_rhs_code (use_stmt); | ||
219 | + if (use_code != POINTER_PLUS_EXPR) | ||
220 | + return false; | ||
221 | + } | ||
222 | + | ||
223 | + if (dump_file) | ||
224 | + { | ||
225 | + fprintf (dump_file, "Found candidate:\n"); | ||
226 | + print_gimple_stmt (dump_file, rhs1_stmt, 0, TDF_SLIM); | ||
227 | + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); | ||
228 | + print_gimple_stmt (dump_file, use_stmt, 0, TDF_SLIM); | ||
229 | + } | ||
230 | + | ||
231 | + return true; | ||
232 | +} | ||
233 | + | ||
234 | +/* Do the actual transformation: | ||
235 | + a = b + c1 ==> a = b * c2 | ||
236 | + c = a * c2 ==> c = a + c1*c2 | ||
237 | +*/ | ||
238 | +static bool | ||
239 | +expand_plusminus_mult (gimple stmt) | ||
240 | +{ | ||
241 | + tree c1, c2, mul_result; | ||
242 | + gimple rhs1_stmt; | ||
243 | + | ||
244 | + /* get c2 */ | ||
245 | + c2 = gimple_assign_rhs2 (stmt); | ||
246 | + | ||
247 | + /* get c1 */ | ||
248 | + rhs1_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)); | ||
249 | + c1 = gimple_assign_rhs2 (rhs1_stmt); | ||
250 | + | ||
251 | + /* form c1 * c2 */ | ||
252 | + mul_result = double_int_to_tree (TREE_TYPE(c2), double_int_mul | ||
253 | + (tree_to_double_int (c1), tree_to_double_int (c2))); | ||
254 | + | ||
255 | + /* a = b + c1 ==> a = b * c2 */ | ||
256 | + gimple_assign_set_rhs2 (rhs1_stmt, c2); | ||
257 | + gimple_assign_set_rhs_code (rhs1_stmt, MULT_EXPR); | ||
258 | + update_stmt (rhs1_stmt); | ||
259 | + | ||
260 | + /* c = a * c2 ==> c = a + c1*c2 */ | ||
261 | + gimple_assign_set_rhs2 (stmt, mul_result); | ||
262 | + /* MINUS_EXPR has already been embedded into c1*c2 */ | ||
263 | + gimple_assign_set_rhs_code (stmt, PLUS_EXPR); | ||
264 | + update_stmt (stmt); | ||
265 | + | ||
266 | + return true; | ||
267 | +} | ||
268 | + | ||
269 | + | ||
270 | +static unsigned int | ||
271 | +execute_opt_array_offset (void) | ||
272 | +{ | ||
273 | + basic_block bb; | ||
274 | + tree fndecl; | ||
275 | + | ||
276 | + FOR_EACH_BB (bb) | ||
277 | + { | ||
278 | + gimple_stmt_iterator gsi; | ||
279 | + | ||
280 | + for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next(&gsi)) | ||
281 | + { | ||
282 | + gimple stmt = gsi_stmt (gsi); | ||
283 | + tree lhs,rhs1,rhs2,rhs3; | ||
284 | + enum tree_code code; | ||
285 | + | ||
286 | + /* only interested in assign statement */ | ||
287 | + if (is_gimple_assign (stmt)) | ||
288 | + { | ||
289 | + /* find stmts calculating array offset */ | ||
290 | + if (is_candidate (stmt)) | ||
291 | + /* convert stmt */ | ||
292 | + expand_plusminus_mult(stmt); | ||
293 | + | ||
294 | + } | ||
295 | + } | ||
296 | + } | ||
297 | + | ||
298 | + return 0; | ||
299 | +} | ||
300 | + | ||
301 | +static bool | ||
302 | +gate_opt_array_offset (void) | ||
303 | +{ | ||
304 | + return flag_opt_array_offset && optimize; | ||
305 | +} | ||
306 | + | ||
307 | +struct gimple_opt_pass pass_opt_array_offset = | ||
308 | +{ | ||
309 | + { | ||
310 | + GIMPLE_PASS, | ||
311 | + "opt_array_offset", /* name */ | ||
312 | + gate_opt_array_offset, /* gate */ | ||
313 | + execute_opt_array_offset, /* execute */ | ||
314 | + NULL, /* sub */ | ||
315 | + NULL, /* next */ | ||
316 | + 0, /* static_pass_number */ | ||
317 | + TV_NONE, /* tv_id */ | ||
318 | + PROP_ssa, /* properties_required */ | ||
319 | + 0, /* properties_provided */ | ||
320 | + 0, /* properties_destroyed */ | ||
321 | + 0, /* todo_flags_start */ | ||
322 | + TODO_verify_ssa | ||
323 | + | TODO_verify_stmts | ||
324 | + | TODO_update_ssa | ||
325 | + | TODO_dump_func /* todo_flags_finish */ | ||
326 | + } | ||
327 | +}; | ||
328 | + | ||
329 | diff -ruN XLMe500mc/gcc/passes.c XLMe5500/gcc/passes.c | ||
330 | --- XLMe500mc/gcc/passes.c 2011-10-18 14:49:23.029644000 -0500 | ||
331 | +++ XLMe5500/gcc/passes.c 2011-10-05 11:19:01.168644127 -0500 | ||
332 | @@ -937,6 +937,7 @@ | ||
333 | NEXT_PASS (pass_phiopt); | ||
334 | NEXT_PASS (pass_fold_builtins); | ||
335 | NEXT_PASS (pass_optimize_widening_mul); | ||
336 | + NEXT_PASS (pass_opt_array_offset); | ||
337 | NEXT_PASS (pass_tail_calls); | ||
338 | NEXT_PASS (pass_rename_ssa_copies); | ||
339 | NEXT_PASS (pass_uncprop); | ||
340 | diff -ruN XLMe500mc/gcc/tree-pass.h XLMe5500/gcc/tree-pass.h | ||
341 | --- XLMe500mc/gcc/tree-pass.h 2011-10-18 14:49:23.029644000 -0500 | ||
342 | +++ XLMe5500/gcc/tree-pass.h 2011-10-05 11:19:59.665643705 -0500 | ||
343 | @@ -421,6 +421,7 @@ | ||
344 | extern struct gimple_opt_pass pass_cse_sincos; | ||
345 | extern struct gimple_opt_pass pass_optimize_bswap; | ||
346 | extern struct gimple_opt_pass pass_optimize_widening_mul; | ||
347 | +extern struct gimple_opt_pass pass_opt_array_offset; | ||
348 | extern struct gimple_opt_pass pass_warn_function_return; | ||
349 | extern struct gimple_opt_pass pass_warn_function_noreturn; | ||
350 | extern struct gimple_opt_pass pass_cselim; | ||