From 122c5bfdad95930de96e191aafb0304fded007b2 Mon Sep 17 00:00:00 2001 From: Zhenhua Luo Date: Fri, 9 Mar 2012 10:57:35 +0000 Subject: 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 --- .../gcc/files/gcc.opt-array-offset.patch | 350 +++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 recipes-devtools/gcc/files/gcc.opt-array-offset.patch (limited to 'recipes-devtools/gcc/files/gcc.opt-array-offset.patch') 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 @@ +Implements a GIMPLE pass to optimize array access by factoring +out expressions that calculate address offset from +multiple array access. Controls with flag -fopt-array-offset + +diff -ruN XLMe500mc/gcc/common.opt XLMe5500/gcc/common.opt +--- XLMe500mc/gcc/common.opt 2011-10-18 14:49:23.026644000 -0500 ++++ XLMe5500/gcc/common.opt 2011-10-05 12:39:26.242644101 -0500 +@@ -1992,6 +1992,10 @@ + Common Report Var(flag_tree_vrp) Init(0) Optimization + Perform Value Range Propagation on trees + ++fopt-array-offset ++Common Report Var(flag_opt_array_offset) ++Expand array offset address calculations ++ + funit-at-a-time + Common Report Var(flag_unit_at_a_time) Init(1) Optimization + Compile whole compilation unit at a time +diff -ruN XLMe500mc/gcc/Makefile.in XLMe5500/gcc/Makefile.in +--- XLMe500mc/gcc/Makefile.in 2011-10-18 14:49:23.028644000 -0500 ++++ XLMe5500/gcc/Makefile.in 2011-10-05 12:08:28.104643898 -0500 +@@ -1306,6 +1306,7 @@ + omp-low.o \ + optabs.o \ + options.o \ ++ opt-array-offset.o \ + opts-common.o \ + opts-global.o \ + opts.o \ +@@ -2629,7 +2630,10 @@ + $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \ + $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \ + $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H) $(REGSET_H) +- ++opt-array-offset.o : opt-array-offset.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ++ $(TM_H) $(FLAGS_H) $(TREE_H) $(TREE_FLOW_H) $(TIMEVAR_H) \ ++ $(TREE_PASS_H) alloc-pool.h $(BASIC_BLOCK_H) $(TARGET_H) \ ++ $(DIAGNOSTIC_H) gimple-pretty-print.h tree-pretty-print.h + widen-types.o : widen-types.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \ + $(DIAGNOSTIC_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h \ + $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \ +diff -ruN XLMe500mc/gcc/opt-array-offset.c XLMe5500/gcc/opt-array-offset.c +--- XLMe500mc/gcc/opt-array-offset.c 1969-12-31 18:00:00.000000000 -0600 ++++ XLMe5500/gcc/opt-array-offset.c 2011-11-01 15:24:21.746039000 -0500 +@@ -0,0 +1,283 @@ ++/* Optimizing array element access ++ Copyright (C) 2011 ++ Free Software Foundation, Inc. ++ ++This file is part of GCC. ++ ++GCC is free software; you can redistribute it and/or modify it ++under the terms of the GNU General Public License as published by the ++Free Software Foundation; either version 3, or (at your option) any ++later version. ++ ++GCC is distributed in the hope that it will be useful, but WITHOUT ++ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++for more details. ++ ++You should have received a copy of the GNU General Public License ++along with GCC; see the file COPYING3. If not see ++. */ ++ ++ ++/* This is a GIMPLE pass over basic block which coverts the stmts: ++ ++ a = b +/- c1; ++ c = a * c2; ++ ++ to: ++ ++ a = b * c2; ++ c = a +/- c1 * c2; ++ ++ in effect expanding the multiplication across addition/substraction. ++ ++ Motivating example: ++ Consider the following simple integer array access: ++ ++ a[i] = c; ++ a[i + 1] = c; ++ ++ The following GIMPLE equivalent will be generated: ++ ++ off_1 = i * 4; ++ a_i = a + off_1; ++ *a_i = c; ++ ++ off_1 = i + 1; ++ off_2 = off_1 * 4; ++ a_i1 = a + off_2; ++ *a_i1 = c; ++ ++ Notice that a_i1 could simply be a_i + 4. But the calcuation of i+1 ++ is preventing CSE to perform. This pass will essentially convert the ++ second expr into: ++ ++ off_1 = i * 4; ++ off_2 = off_1 + 4; ++ a_i1 = a + off_2; ++ .... ++ ++ Thus allowing the previous index i calculation to be reuse. off_1 + 4 ++ would also be combined into a_i if offset addressing mode is available. ++ This also have side effect of avoiding redundant sign extension on ++ i+1 for LP64 model where native integer size is different from pointer size. ++ ++ The algorithm iterates through all the basic blocks looking for ++ the above pattern. Care is taken to make sure off_1 only ++ has the single use otherwise the transformation cannot be perform. ++*/ ++ ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tm.h" ++#include "flags.h" ++#include "tree.h" ++#include "tree-flow.h" ++#include "timevar.h" ++#include "tree-pass.h" ++#include "alloc-pool.h" ++#include "basic-block.h" ++#include "target.h" ++#include "gimple-pretty-print.h" ++#include "tree-pretty-print.h" ++ ++ ++/* ++ We are looking for: ++ a = b +/- c1 ++ c = a * c2 (stmt incoming) ++ d = &arr + c ++*/ ++static bool ++is_candidate (gimple stmt) ++{ ++ tree mul_result = gimple_get_lhs (stmt); ++ tree rhs1, rhs2; ++ gimple rhs1_stmt, use_stmt; ++ use_operand_p use_p; ++ imm_use_iterator imm_iter; ++ ++ /* check for a * c2 */ ++ if (gimple_assign_rhs_code (stmt) != MULT_EXPR) ++ return false; ++ ++ rhs1 = gimple_assign_rhs1 (stmt); ++ rhs2 = gimple_assign_rhs2 (stmt); ++ ++ if (TREE_CODE (rhs2) != INTEGER_CST) ++ return false; ++ ++ /* check for b + c1 */ ++ if (TREE_CODE (rhs1) == SSA_NAME) ++ { ++ rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); ++ if (is_gimple_assign (rhs1_stmt)) ++ { ++ tree rhs1_2; ++ tree plusminus_result; ++ ++ if (gimple_assign_rhs_code (rhs1_stmt) != PLUS_EXPR ++ && gimple_assign_rhs_code (rhs1_stmt) != MINUS_EXPR) ++ return false; ++ ++ rhs1_2 = gimple_assign_rhs2 (rhs1_stmt); ++ if (TREE_CODE (rhs1_2) != INTEGER_CST) ++ return false; ++ ++ /* make sure there are no other uses of a ++ e.g. if a is used as an indcution variable ++ we cannot modified it ++ */ ++ plusminus_result = gimple_get_lhs (rhs1_stmt); ++ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, plusminus_result) ++ { ++ use_stmt = USE_STMT (use_p); ++ ++ /* ignore PHI node */ ++ if (is_gimple_assign (use_stmt) && ++ (gimple_assign_rhs_code (use_stmt) == GIMPLE_PHI)) ++ continue; ++ if (use_stmt != stmt) ++ return false; ++ } ++ ++#if 0 ++ if (gimple_bb(rhs1_stmt) != gimple_bb(stmt)) ++ return false; ++#endif ++ } ++ else ++ return false; ++ } ++ else ++ return false; ++ ++ /* now look for uses of c that is a pointer use */ ++ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, mul_result) ++ { ++ enum tree_code use_code; ++ ++ use_stmt = USE_STMT (use_p); ++ ++ if (is_gimple_debug (use_stmt)) ++ continue; ++ ++ if (gimple_bb (use_stmt) != gimple_bb (stmt)) ++ return false; ++ ++ if (!is_gimple_assign (use_stmt)) ++ return false; ++ ++ use_code = gimple_assign_rhs_code (use_stmt); ++ if (use_code != POINTER_PLUS_EXPR) ++ return false; ++ } ++ ++ if (dump_file) ++ { ++ fprintf (dump_file, "Found candidate:\n"); ++ print_gimple_stmt (dump_file, rhs1_stmt, 0, TDF_SLIM); ++ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); ++ print_gimple_stmt (dump_file, use_stmt, 0, TDF_SLIM); ++ } ++ ++ return true; ++} ++ ++/* Do the actual transformation: ++ a = b + c1 ==> a = b * c2 ++ c = a * c2 ==> c = a + c1*c2 ++*/ ++static bool ++expand_plusminus_mult (gimple stmt) ++{ ++ tree c1, c2, mul_result; ++ gimple rhs1_stmt; ++ ++ /* get c2 */ ++ c2 = gimple_assign_rhs2 (stmt); ++ ++ /* get c1 */ ++ rhs1_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)); ++ c1 = gimple_assign_rhs2 (rhs1_stmt); ++ ++ /* form c1 * c2 */ ++ mul_result = double_int_to_tree (TREE_TYPE(c2), double_int_mul ++ (tree_to_double_int (c1), tree_to_double_int (c2))); ++ ++ /* a = b + c1 ==> a = b * c2 */ ++ gimple_assign_set_rhs2 (rhs1_stmt, c2); ++ gimple_assign_set_rhs_code (rhs1_stmt, MULT_EXPR); ++ update_stmt (rhs1_stmt); ++ ++ /* c = a * c2 ==> c = a + c1*c2 */ ++ gimple_assign_set_rhs2 (stmt, mul_result); ++ /* MINUS_EXPR has already been embedded into c1*c2 */ ++ gimple_assign_set_rhs_code (stmt, PLUS_EXPR); ++ update_stmt (stmt); ++ ++ return true; ++} ++ ++ ++static unsigned int ++execute_opt_array_offset (void) ++{ ++ basic_block bb; ++ tree fndecl; ++ ++ FOR_EACH_BB (bb) ++ { ++ gimple_stmt_iterator gsi; ++ ++ for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next(&gsi)) ++ { ++ gimple stmt = gsi_stmt (gsi); ++ tree lhs,rhs1,rhs2,rhs3; ++ enum tree_code code; ++ ++ /* only interested in assign statement */ ++ if (is_gimple_assign (stmt)) ++ { ++ /* find stmts calculating array offset */ ++ if (is_candidate (stmt)) ++ /* convert stmt */ ++ expand_plusminus_mult(stmt); ++ ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static bool ++gate_opt_array_offset (void) ++{ ++ return flag_opt_array_offset && optimize; ++} ++ ++struct gimple_opt_pass pass_opt_array_offset = ++{ ++ { ++ GIMPLE_PASS, ++ "opt_array_offset", /* name */ ++ gate_opt_array_offset, /* gate */ ++ execute_opt_array_offset, /* execute */ ++ NULL, /* sub */ ++ NULL, /* next */ ++ 0, /* static_pass_number */ ++ TV_NONE, /* tv_id */ ++ PROP_ssa, /* properties_required */ ++ 0, /* properties_provided */ ++ 0, /* properties_destroyed */ ++ 0, /* todo_flags_start */ ++ TODO_verify_ssa ++ | TODO_verify_stmts ++ | TODO_update_ssa ++ | TODO_dump_func /* todo_flags_finish */ ++ } ++}; ++ +diff -ruN XLMe500mc/gcc/passes.c XLMe5500/gcc/passes.c +--- XLMe500mc/gcc/passes.c 2011-10-18 14:49:23.029644000 -0500 ++++ XLMe5500/gcc/passes.c 2011-10-05 11:19:01.168644127 -0500 +@@ -937,6 +937,7 @@ + NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_fold_builtins); + NEXT_PASS (pass_optimize_widening_mul); ++ NEXT_PASS (pass_opt_array_offset); + NEXT_PASS (pass_tail_calls); + NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_uncprop); +diff -ruN XLMe500mc/gcc/tree-pass.h XLMe5500/gcc/tree-pass.h +--- XLMe500mc/gcc/tree-pass.h 2011-10-18 14:49:23.029644000 -0500 ++++ XLMe5500/gcc/tree-pass.h 2011-10-05 11:19:59.665643705 -0500 +@@ -421,6 +421,7 @@ + extern struct gimple_opt_pass pass_cse_sincos; + extern struct gimple_opt_pass pass_optimize_bswap; + extern struct gimple_opt_pass pass_optimize_widening_mul; ++extern struct gimple_opt_pass pass_opt_array_offset; + extern struct gimple_opt_pass pass_warn_function_return; + extern struct gimple_opt_pass pass_warn_function_noreturn; + extern struct gimple_opt_pass pass_cselim; -- cgit v1.2.3-54-g00ecf