Message ID | alpine.DEB.2.02.1209222258440.14384@stedding.saclay.inria.fr |
---|---|
State | New |
Headers | show |
On Sat, Sep 22, 2012 at 11:17 PM, Marc Glisse <marc.glisse@inria.fr> wrote: > 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). Ok. Thanks, Richard. > 2012-09-24 Marc Glisse <marc.glisse@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 > >
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" } } */