On Mon, 21 Mar 2011, Diego Novillo wrote: > On 03/18/2011 10:11 AM, Richard Guenther wrote: > > > > This tries to extend the previously posted CCP folding patch by > > introducing a generic interface for non-tree-building, GIMPLE SSA > > aware folding. The low-level interface for folding regular > > operations is > > > > /* Fold the expression composed by *CODEP, TYPE and valueized operands > > *OP0P, > > *OP1P and *OP2P (as required), using the VALUEIZE callback to valueize > > SSA names that turn up during statement lookup and producing a result > > of at most KIND. The folding result will be stored in the operands. > > GF_KIND_FAIL is returned if no folding was done. > > If GF_KIND_CONST or GF_KIND_VAL is returned the folding result is > > stored in *OP0P and is a is_gimple_min_invariant or a is_gimple_val. > > If GF_KIND_STMT is returned the folding result is stored in *CODEP, > > *OP0P, *OP1P and *OP2P (as required) and will compose a valid set of > > operands for a gimple assignment. > > If GF_KIND_COMPLEX is returned the folding result is stored in *OP0P > > and will be an arbitrarily complex tree. */ > > > > enum gf_kind > > gimple_fold (enum tree_code *codep, tree type, > > tree *op0p, tree *op1p, tree *op2p, > > tree (*valueize)(tree), enum gf_kind kind) > > > > which would allow existing gimple-level foldings to build ontop of this > > (including fold_stmt and friends and the special CCP foldings). > > > > The current implementation is quite lame, just dispatching to fold, > > but I plan to integrate it with the CCP and fold_stmt foldings before > > considering to merge it (eventually producing some sort of statistics > > of what the fold path catches that the gimple path does not). > > > > The low-level interface needs to be amended by one for builtin calls > > where I'm not sure if it is going to take decomposed operands > > or just a gimple statement (I think we have at most 3 operands to > > any builtin we can fold in some way). > > > > This again is just a RFC (even though the patch "works" as far as > > plugging into the SCCVN binary operation simplification). > > > > I like this. In terms of the interface, what do you think about this always > returning an SSA name or (may be) the statement that defines it. Although, if > this is just the low-level interface, then we can build a wrapper that calls > it and returns a statement.
Right, my plan was to wrap existing interfaces around this low-level implementation. > Some questions and nits below: > > > + enum gf_kind { > > + GF_KIND_FAIL = 0, > > + GF_KIND_CONST, > > + GF_KIND_VAL, > > + GF_KIND_STMT, > > + GF_KIND_COMPLEX > > + }; > > These will need documentation. The values are also sorted by level of > complexity, right? Yes. > Should we not bother with GF_KIND_COMPLEX? If we are going to return an > arbitrarily complex tree, we might as well return GF_KIND_FAIL, I think. Are > you implementing GF_KIND_COMPLEX as a workaround or is this the expected > behaviour? I simply put it in place as a possibility, I currently don't plan to implement any GF_KIND_COMPLEX folders (the caller would need to re-gimplify them which doesn't sound too useful). Maybe I should simply drop it. > For instance, if folding ends up producing a complex tree, would it need to be > gimplified? Maybe we could generate the gimplified statement and return the > SSA name on the LHS? Though I'm not sure I like even this. Hm, I tried to avoid making the folder rewrite existing or emit new stmts - the idea was to make the interface cheap, not allocating GC memory for expressions or statements. Thanks, Richard. > > + > > + > > + static tree > > + build_valueized_tree_from_def (tree name, tree (*valueize)(tree)) > > + { > > Needs comment. > > > + gimple def_stmt = SSA_NAME_DEF_STMT (name); > > + tree op0, op1, op2; > > + > > + if (!is_gimple_assign (def_stmt) > > + || gimple_vuse (def_stmt)) > > + return name; > > + > > + switch (gimple_assign_rhs_class (def_stmt)) > > + { > > + case GIMPLE_SINGLE_RHS: > > + return gimple_assign_rhs1 (def_stmt); > > + > > + case GIMPLE_TERNARY_RHS: > > + op2 = gimple_assign_rhs3 (def_stmt); > > + if (TREE_CODE (op2) == SSA_NAME > > + && valueize) > > + op2 = (*valueize) (op2); > > + > > + case GIMPLE_BINARY_RHS: > > + op1 = gimple_assign_rhs2 (def_stmt); > > + if (TREE_CODE (op1) == SSA_NAME > > + && valueize) > > + op1 = (*valueize) (op1); > > + > > /* Fallthru */ > > > + case GIMPLE_UNARY_RHS: > > + op0 = gimple_assign_rhs1 (def_stmt); > > + if (TREE_CODE (op0) == SSA_NAME > > + && valueize) > > + op0 = (*valueize) (op0); > > + break; > > + > > + default:; > > + } > > + > > + switch (gimple_assign_rhs_class (def_stmt)) > > + { > > + case GIMPLE_UNARY_RHS: > > + return fold_build1 (gimple_assign_rhs_code (def_stmt), > > + TREE_TYPE (name), op0); > > + case GIMPLE_BINARY_RHS: > > + return fold_build2 (gimple_assign_rhs_code (def_stmt), > > + TREE_TYPE (name), op0, op1); > > + case GIMPLE_TERNARY_RHS: > > + return fold_build3 (gimple_assign_rhs_code (def_stmt), > > + TREE_TYPE (name), op0, op1, op2); > > + default:; > > + } > > + > > + return name; > > + } > > + > > + static enum gf_kind > > + const_or_val (tree res, enum gf_kind kind) > > + { > > Needs comment. > > > Diego. > >