Hi! If VRP tells us that oprnd is always >= 0 or always < 0, we can generate better code for the divmode vectorization.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2013-10-22 Jakub Jelinek <ja...@redhat.com> * tree-vect-patterns.c (vect_recog_divmod_pattern): Optimize sequence based on get_range_info returned range. --- gcc/tree-vect-patterns.c.jj 2013-09-20 09:42:43.048260891 +0200 +++ gcc/tree-vect-patterns.c 2013-10-22 18:21:21.518563159 +0200 @@ -2226,20 +2226,19 @@ vect_recog_divmod_pattern (vec<gimple> * if (post_shift >= prec) return NULL; - /* t1 = oprnd1 h* ml; */ + /* t1 = oprnd0 h* ml; */ t1 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (MULT_HIGHPART_EXPR, t1, oprnd0, build_int_cst (itype, ml)); - append_pattern_def_seq (stmt_vinfo, def_stmt); if (add) { /* t2 = t1 + oprnd0; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); t2 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (PLUS_EXPR, t2, t1, oprnd0); - append_pattern_def_seq (stmt_vinfo, def_stmt); } else t2 = t1; @@ -2247,27 +2246,57 @@ vect_recog_divmod_pattern (vec<gimple> * if (post_shift) { /* t3 = t2 >> post_shift; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); t3 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (RSHIFT_EXPR, t3, t2, build_int_cst (itype, post_shift)); - append_pattern_def_seq (stmt_vinfo, def_stmt); } else t3 = t2; - /* t4 = oprnd0 >> (prec - 1); */ - t4 = vect_recog_temp_ssa_var (itype, NULL); - def_stmt - = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0, - build_int_cst (itype, prec - 1)); - append_pattern_def_seq (stmt_vinfo, def_stmt); - - /* q = t3 - t4; or q = t4 - t3; */ - q = vect_recog_temp_ssa_var (itype, NULL); - pattern_stmt - = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3, - d < 0 ? t3 : t4); + double_int oprnd0_min, oprnd0_max; + int msb = 1; + if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE) + { + if (!oprnd0_min.is_negative ()) + msb = 0; + else if (oprnd0_max.is_negative ()) + msb = -1; + } + + if (msb == 0 && d >= 0) + { + /* q = t3; */ + q = t3; + pattern_stmt = def_stmt; + } + else + { + /* t4 = oprnd0 >> (prec - 1); + or if we know from VRP that oprnd0 >= 0 + t4 = 0; + or if we know from VRP that oprnd0 < 0 + t4 = -1; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); + t4 = vect_recog_temp_ssa_var (itype, NULL); + if (msb != 1) + def_stmt + = gimple_build_assign_with_ops (INTEGER_CST, + t4, build_int_cst (itype, msb), + NULL_TREE); + else + def_stmt + = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0, + build_int_cst (itype, prec - 1)); + append_pattern_def_seq (stmt_vinfo, def_stmt); + + /* q = t3 - t4; or q = t4 - t3; */ + q = vect_recog_temp_ssa_var (itype, NULL); + pattern_stmt + = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3, + d < 0 ? t3 : t4); + } } if (rhs_code == TRUNC_MOD_EXPR) Jakub