On 24/07/15 05:05, Jeff Law wrote: > On 07/15/2015 11:52 PM, Kugan wrote: >> >>>> >>>> diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c >>>> index 932c83a..3058eb5 100644 >>>> --- a/gcc/tree-ssa-reassoc.c >>>> +++ b/gcc/tree-ssa-reassoc.c >>> >>>> return false; >>>> bb = gimple_bb (stmt); >>>> if (!single_succ_p (bb)) >>>> @@ -2729,9 +2743,8 @@ final_range_test_p (gimple stmt) >>>> >>>> lhs = gimple_assign_lhs (stmt); >>>> rhs = gimple_assign_rhs1 (stmt); >>>> - if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)) >>>> - || TREE_CODE (rhs) != SSA_NAME >>>> - || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE) >>>> + if (TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE >>>> + && TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE) >>>> return false; >>> So you're ensuring that one of the two is a boolean... Note that >>> previously we ensured that the rhs was a boolean and the lhs was an >>> integral type (which I believe is true for booleans). >>> >>> Thus if we had >>> bool x; >>> int y; >>> >>> x = (bool) y; >>> >>> The old code would have rejected that case. But I think it gets through >>> now, right? >>> >>> I think once that issue is addressed, this will be good for the trunk. >>> >> >> Thanks for the review. How about: >> >> - if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)) >> - || TREE_CODE (rhs) != SSA_NAME >> - || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE) >> + if (gimple_assign_cast_p (stmt) >> + && (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)) >> + || TREE_CODE (rhs) != SSA_NAME >> + || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE)) > But then I think you need to verify that for the _234 = a_2(D) == 2; > case that type of the RHS is a boolean. > > ie, each case has requirements for the types. I don't think they can be > reasonably unified. So something like this: > > if (gimple_assign_cast_p (stmt) > && ! (correct types for cast) > return false; > > if (!gimple_assign_cast_p (stmt) > && ! (correct types for tcc_comparison case)) > return false; > > > This works because we've already verified that it's either a type > conversion or a comparison on the RHS. > I thought that when !gimple_assign_cast_p (stmt), RHS will always boolean. I have now added this check in the attached patch.
I also noticed that in maybe_optimize_range_tests, GIMPLE_COND can have non compatible types when new_op is updated (boolean types coming from tcc_compare results) and hence need to be converted. Changed that as well. Bootstrapped and regression tested on x86-64-none-linux-gnu with no new regressions. Is this OK for trunk? Thanks, Kugan
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index efb813c..cc215b6 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -2707,18 +2707,32 @@ optimize_range_tests (enum tree_code opcode, # _345 = PHI <_123(N), 1(...), 1(...)> where _234 has bool type, _123 has single use and bb N has a single successor M. This is commonly used in - the last block of a range test. */ + the last block of a range test. + + Also Return true if STMT is tcc_compare like: + <bb N>: + ... + _234 = a_2(D) == 2; + <bb M>: + # _345 = PHI <_234(N), 1(...), 1(...)> + _346 = (int) _345; + where _234 has booltype, single use and + bb N has a single successor M. This is commonly used in + the last block of a range test. */ static bool final_range_test_p (gimple stmt) { - basic_block bb, rhs_bb; + basic_block bb, rhs_bb, lhs_bb; edge e; tree lhs, rhs; use_operand_p use_p; gimple use_stmt; - if (!gimple_assign_cast_p (stmt)) + if (!gimple_assign_cast_p (stmt) + && (!is_gimple_assign (stmt) + || (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) + != tcc_comparison))) return false; bb = gimple_bb (stmt); if (!single_succ_p (bb)) @@ -2729,11 +2743,16 @@ final_range_test_p (gimple stmt) lhs = gimple_assign_lhs (stmt); rhs = gimple_assign_rhs1 (stmt); - if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)) - || TREE_CODE (rhs) != SSA_NAME - || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE) + if (gimple_assign_cast_p (stmt) + && (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + || TREE_CODE (rhs) != SSA_NAME + || TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE)) return false; + if (!gimple_assign_cast_p (stmt) + && (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE)) + return false; + /* Test whether lhs is consumed only by a PHI in the only successor bb. */ if (!single_imm_use (lhs, &use_p, &use_stmt)) return false; @@ -2743,10 +2762,20 @@ final_range_test_p (gimple stmt) return false; /* And that the rhs is defined in the same loop. */ - rhs_bb = gimple_bb (SSA_NAME_DEF_STMT (rhs)); - if (rhs_bb == NULL - || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), rhs_bb)) - return false; + if (gimple_assign_cast_p (stmt)) + { + if (TREE_CODE (rhs) != SSA_NAME + || !(rhs_bb = gimple_bb (SSA_NAME_DEF_STMT (rhs))) + || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), rhs_bb)) + return false; + } + else + { + if (TREE_CODE (lhs) != SSA_NAME + || !(lhs_bb = gimple_bb (SSA_NAME_DEF_STMT (lhs))) + || !flow_bb_inside_loop_p (loop_containing_stmt (stmt), lhs_bb)) + return false; + } return true; } @@ -3132,6 +3161,8 @@ maybe_optimize_range_tests (gimple stmt) /* stmt is _123 = (int) _234; + OR + _234 = a_2(D) == 2; followed by: <bb M>: @@ -3161,6 +3192,8 @@ maybe_optimize_range_tests (gimple stmt) of the bitwise or resp. and, recursively. */ if (!get_ops (rhs, code, &ops, loop_containing_stmt (stmt)) + && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) + != tcc_comparison) && has_single_use (rhs)) { /* Otherwise, push the _234 range test itself. */ @@ -3173,6 +3206,23 @@ maybe_optimize_range_tests (gimple stmt) ops.safe_push (oe); bb_ent.last_idx++; } + else if (!get_ops (lhs, code, &ops, + loop_containing_stmt (stmt)) + && TREE_CODE (lhs) == SSA_NAME + && INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + && is_gimple_assign (stmt) + && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) + == tcc_comparison) + && has_single_use (lhs)) + { + operand_entry_t oe = operand_entry_pool.allocate (); + oe->op = lhs; + oe->rank = code; + oe->id = 0; + oe->count = 1; + ops.safe_push (oe); + bb_ent.last_idx++; + } else bb_ent.last_idx = ops.length (); bb_ent.op = rhs; @@ -3258,16 +3308,46 @@ maybe_optimize_range_tests (gimple stmt) gimple use_stmt, cast_stmt = NULL; FOR_EACH_IMM_USE_STMT (use_stmt, iter, bbinfo[idx].op) - if (is_gimple_debug (use_stmt)) + if (is_gimple_debug (use_stmt) + || (TREE_CODE (new_op) == SSA_NAME + && !reassoc_stmt_dominates_stmt_p + (SSA_NAME_DEF_STMT (new_op), use_stmt))) continue; - else if (gimple_code (use_stmt) == GIMPLE_COND - || gimple_code (use_stmt) == GIMPLE_PHI) - FOR_EACH_IMM_USE_ON_STMT (use_p, iter) - SET_USE (use_p, new_op); + else if (gimple_code (use_stmt) == GIMPLE_PHI) + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, new_op); + else if (gimple_code (use_stmt) == GIMPLE_COND) + { + tree new_type, new_lhs; + gassign *g; + gcond *cond_stmt = as_a <gcond *> (use_stmt); + new_type = TREE_TYPE (gimple_cond_lhs (cond_stmt)); + if (!types_compatible_p (new_type, TREE_TYPE (new_op))) + { + new_lhs = make_ssa_name (new_type); + if (is_gimple_min_invariant (new_op)) + { + new_op = fold_convert (new_type, new_op); + g = gimple_build_assign (new_lhs, new_op); + } + else + g = gimple_build_assign (new_lhs, + CONVERT_EXPR, new_op); + gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); + gimple_set_uid (g, gimple_uid (use_stmt)); + gimple_set_visited (g, true); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + } + else + new_lhs = new_op; + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, new_lhs); + } else if (gimple_assign_cast_p (use_stmt)) cast_stmt = use_stmt; else - gcc_unreachable (); + cast_stmt = NULL; + if (cast_stmt) { gcc_assert (bb == last_bb); @@ -3291,7 +3371,8 @@ maybe_optimize_range_tests (gimple stmt) if (is_gimple_debug (use_stmt)) continue; else if (gimple_code (use_stmt) == GIMPLE_COND - || gimple_code (use_stmt) == GIMPLE_PHI) + || gimple_code (use_stmt) == GIMPLE_PHI + || is_gimple_assign (use_stmt)) FOR_EACH_IMM_USE_ON_STMT (use_p, iter) SET_USE (use_p, new_lhs); else