Hello,this patch lets forwprop fold bit_field_refs of constructors. It is particularly useful in forwprop4, which happens after the pass that lowers unsupported vector operations. Indeed, that pass keeps breaking vectors into pieces and reconstructing them for each operation, which is a waste when there are several operations in a row. This happens fairly late though, and dead constructors are left lying around (no dead code elimination after forwprop4) for the rtl layer to remove, so we are probably missing possible optimizations.
Bootstrap+testsuite ok (well, still about a thousand FAILs, but it doesn't increase with my patch).
2012-09-24 Marc Glisse <marc.gli...@inria.fr> gcc/ * tree-ssa-forwprop.c: Include tree-ssa-propagate.h. (simplify_bitfield_ref): Handle constructors. * Makefile.in (tree-ssa-forwprop.o): Depend on tree-ssa-propagate.h. gcc/testsuite/ * gcc.dg/tree-ssa/forwprop-23.c: New testcase. -- Marc Glisse
Index: Makefile.in =================================================================== --- Makefile.in (revision 191644) +++ Makefile.in (working copy) @@ -2239,21 +2239,21 @@ tree-outof-ssa.o : tree-outof-ssa.c $(TR $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) $(BITMAP_H) $(GGC_H) \ $(EXPR_H) $(SSAEXPAND_H) $(GIMPLE_PRETTY_PRINT_H) tree-ssa-dse.o : tree-ssa-dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(GGC_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \ $(TREE_FLOW_H) $(TREE_PASS_H) domwalk.h $(FLAGS_H) \ $(GIMPLE_PRETTY_PRINT_H) langhooks.h tree-ssa-forwprop.o : tree-ssa-forwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) $(CFGLOOP_H) \ $(TREE_FLOW_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \ langhooks.h $(FLAGS_H) $(GIMPLE_H) $(GIMPLE_PRETTY_PRINT_H) $(EXPR_H) \ - $(OPTABS_H) + $(OPTABS_H) tree-ssa-propagate.h tree-ssa-phiprop.o : tree-ssa-phiprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \ $(TREE_FLOW_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \ langhooks.h $(FLAGS_H) $(GIMPLE_PRETTY_PRINT_H) tree-ssa-ifcombine.o : tree-ssa-ifcombine.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) $(TREE_H) $(BASIC_BLOCK_H) \ $(TREE_FLOW_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \ $(TREE_PRETTY_PRINT_H) tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(GGC_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \ Index: tree-ssa-forwprop.c =================================================================== --- tree-ssa-forwprop.c (revision 191644) +++ tree-ssa-forwprop.c (working copy) @@ -27,20 +27,21 @@ along with GCC; see the file COPYING3. #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-flow.h" #include "tree-pass.h" #include "langhooks.h" #include "flags.h" #include "gimple.h" #include "expr.h" #include "cfgloop.h" #include "optabs.h" +#include "tree-ssa-propagate.h" /* This pass propagates the RHS of assignment statements into use sites of the LHS of the assignment. It's basically a specialized form of tree combination. It is hoped all of this can disappear when we have a generalized tree combiner. One class of common cases we handle is forward propagating a single use variable into a COND_EXPR. bb0: @@ -2575,39 +2576,49 @@ simplify_bitfield_ref (gimple_stmt_itera enum tree_code code; op = gimple_assign_rhs1 (stmt); gcc_checking_assert (TREE_CODE (op) == BIT_FIELD_REF); op0 = TREE_OPERAND (op, 0); if (TREE_CODE (op0) != SSA_NAME || TREE_CODE (TREE_TYPE (op0)) != VECTOR_TYPE) return false; + def_stmt = get_prop_source_stmt (op0, false, NULL); + if (!def_stmt || !can_propagate_from (def_stmt)) + return false; + + op1 = TREE_OPERAND (op, 1); + op2 = TREE_OPERAND (op, 2); + code = gimple_assign_rhs_code (def_stmt); + + if (code == CONSTRUCTOR) + { + tree tem = fold_ternary (BIT_FIELD_REF, TREE_TYPE (op), + gimple_assign_rhs1 (def_stmt), op1, op2); + if (!tem || !valid_gimple_rhs_p (tem)) + return false; + gimple_assign_set_rhs_from_tree (gsi, tem); + update_stmt (gsi_stmt (*gsi)); + return true; + } + elem_type = TREE_TYPE (TREE_TYPE (op0)); if (TREE_TYPE (op) != elem_type) return false; size = TREE_INT_CST_LOW (TYPE_SIZE (elem_type)); - op1 = TREE_OPERAND (op, 1); n = TREE_INT_CST_LOW (op1) / size; if (n != 1) return false; - - def_stmt = get_prop_source_stmt (op0, false, NULL); - if (!def_stmt || !can_propagate_from (def_stmt)) - return false; - - op2 = TREE_OPERAND (op, 2); idx = TREE_INT_CST_LOW (op2) / size; - code = gimple_assign_rhs_code (def_stmt); - if (code == VEC_PERM_EXPR) { tree p, m, index, tem; unsigned nelts; m = gimple_assign_rhs3 (def_stmt); if (TREE_CODE (m) != VECTOR_CST) return false; nelts = VECTOR_CST_NELTS (m); idx = TREE_INT_CST_LOW (VECTOR_CST_ELT (m, idx)); idx %= 2 * nelts; Index: testsuite/gcc.dg/tree-ssa/forwprop-23.c =================================================================== --- testsuite/gcc.dg/tree-ssa/forwprop-23.c (revision 0) +++ testsuite/gcc.dg/tree-ssa/forwprop-23.c (revision 0) @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +typedef long vec __attribute__ ((vector_size (2 * sizeof (long)))); + +long f (long d, long e) +{ + vec x = { d, e }; + vec m = { 1, 0 }; + return __builtin_shuffle (x, m) [1]; +} + + +/* { dg-final { scan-tree-dump-not "BIT_FIELD_REF" "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ Property changes on: testsuite/gcc.dg/tree-ssa/forwprop-23.c ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision URL Added: svn:eol-style + native