On Tue, Dec 13, 2016 at 03:08:17PM +0530, Prathamesh Kulkarni wrote: > Thanks for the suggestions. It didn't occur to me to check for gimple_cond. > I have tried to do the changes in the attached version. > I am not sure if I have handled cond_expr correctly. > IIUC, if gimple_assign has code cond_expr, then the condition is > stored in gimple_assign_rhs1, > however it's not a single operand but a tree of the form "op1 cond_code op2". > Is that correct ?
Yes. gimple_assign_rhs1 will be in what you are looking for EQ_EXPR or NE_EXPR tree, its TREE_CODE will be this code you want to check, and TREE_OPERAND (exp, 0) and TREE_OPERAND (exp, 1) the rhs1 and rhs2 you use elsewhere. > However I am not able to write a test-case that generates cond_expr in the IL. > I tried: > t1 = strstr (s, t); > (t1 == s) ? foo() : bar (); > and other such variants but it seems the ?: operator is getting > lowered to gimple_cond instead. It is, but in some cases tree-if-conv.c turns them back into COND_EXPRs. I guess you need -ftree-loop-if-convert now, and it has to be in some loop where the addition of cond_expr would likely turn it into a single bb loop. You probably want constants or vars, not function calls in the ? : expressions though. > +/* Try to fold strstr (s, t) == s to memcmp (s, t, strlen (t)) == 0. */ > + > +static void > +fold_strstr_to_memcmp(enum tree_code code, tree rhs1, tree rhs2, gimple > *stmt) Formatting, space before (. > +{ > + gimple *call_stmt = NULL; > + for (int pass = 0; pass < 2; pass++) > + { > + gimple *g = SSA_NAME_DEF_STMT (rhs1); > + if (g I think g should be always non-NULL (except for invalid IL), so probably no need to check it. > + && gimple_call_builtin_p (g, BUILT_IN_STRSTR) > + && has_single_use (rhs1) > + && gimple_call_arg (as_a<gcall *> (g), 0) == rhs2) I think gimple_call_arg works fine even with just gimple * argument. So you can avoid the as_a<gcall *> (g) uglification and just use g. > + if (is_gimple_assign (stmt)) > + { > + if (gimple_assign_rhs_code (stmt) == COND_EXPR) > + { > + tree cond = gimple_assign_rhs1 (stmt); > + TREE_SET_CODE (cond, EQ_EXPR); This looks weird. You are hardcoding EQ_EXPR, while for the other case below you use code. So, do you handle properly both EQ_EXPR and NE_EXPR for this and gimple_cond cases? Also, for non-COND_EXPR assign you build a new stmt instead of reusing the existing one, why? > + TREE_OPERAND (cond, 0) = memcmp_lhs; > + TREE_OPERAND (cond, 1) = zero; > + update_stmt (stmt); > + } > + else > + { > + gsi = gsi_for_stmt (stmt); > + tree lhs = gimple_assign_lhs (stmt); > + gassign *ga = gimple_build_assign (lhs, code, memcmp_lhs, > + zero); > + gsi_replace (&gsi, ga, false); > + } > + } > + else > + { > + gcond *cond = as_a<gcond *> (stmt); > + gimple_cond_set_lhs (cond, memcmp_lhs); > + gimple_cond_set_rhs (cond, zero); > + gimple_cond_set_code (cond, EQ_EXPR); Likewise here. Jakub