138fd1498Szrj /* Combining of if-expressions on trees.
238fd1498Szrj Copyright (C) 2007-2018 Free Software Foundation, Inc.
338fd1498Szrj Contributed by Richard Guenther <rguenther@suse.de>
438fd1498Szrj
538fd1498Szrj This file is part of GCC.
638fd1498Szrj
738fd1498Szrj GCC is free software; you can redistribute it and/or modify
838fd1498Szrj it under the terms of the GNU General Public License as published by
938fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
1038fd1498Szrj any later version.
1138fd1498Szrj
1238fd1498Szrj GCC is distributed in the hope that it will be useful,
1338fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1438fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1538fd1498Szrj GNU General Public License for more details.
1638fd1498Szrj
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3. If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>. */
2038fd1498Szrj
2138fd1498Szrj #include "config.h"
2238fd1498Szrj #include "system.h"
2338fd1498Szrj #include "coretypes.h"
2438fd1498Szrj #include "backend.h"
2538fd1498Szrj #include "rtl.h"
2638fd1498Szrj #include "tree.h"
2738fd1498Szrj #include "gimple.h"
2838fd1498Szrj #include "cfghooks.h"
2938fd1498Szrj #include "tree-pass.h"
3038fd1498Szrj #include "memmodel.h"
3138fd1498Szrj #include "tm_p.h"
3238fd1498Szrj #include "ssa.h"
3338fd1498Szrj #include "tree-pretty-print.h"
3438fd1498Szrj /* rtl is needed only because arm back-end requires it for
3538fd1498Szrj BRANCH_COST. */
3638fd1498Szrj #include "fold-const.h"
3738fd1498Szrj #include "cfganal.h"
3838fd1498Szrj #include "gimple-fold.h"
3938fd1498Szrj #include "gimple-iterator.h"
4038fd1498Szrj #include "gimplify-me.h"
4138fd1498Szrj #include "tree-cfg.h"
4238fd1498Szrj #include "tree-ssa.h"
43*e215fc28Szrj #include "params.h"
4438fd1498Szrj
4538fd1498Szrj #ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
4638fd1498Szrj #define LOGICAL_OP_NON_SHORT_CIRCUIT \
4738fd1498Szrj (BRANCH_COST (optimize_function_for_speed_p (cfun), \
4838fd1498Szrj false) >= 2)
4938fd1498Szrj #endif
5038fd1498Szrj
5138fd1498Szrj /* This pass combines COND_EXPRs to simplify control flow. It
5238fd1498Szrj currently recognizes bit tests and comparisons in chains that
5338fd1498Szrj represent logical and or logical or of two COND_EXPRs.
5438fd1498Szrj
5538fd1498Szrj It does so by walking basic blocks in a approximate reverse
5638fd1498Szrj post-dominator order and trying to match CFG patterns that
5738fd1498Szrj represent logical and or logical or of two COND_EXPRs.
5838fd1498Szrj Transformations are done if the COND_EXPR conditions match
5938fd1498Szrj either
6038fd1498Szrj
6138fd1498Szrj 1. two single bit tests X & (1 << Yn) (for logical and)
6238fd1498Szrj
6338fd1498Szrj 2. two bit tests X & Yn (for logical or)
6438fd1498Szrj
6538fd1498Szrj 3. two comparisons X OPn Y (for logical or)
6638fd1498Szrj
6738fd1498Szrj To simplify this pass, removing basic blocks and dead code
6838fd1498Szrj is left to CFG cleanup and DCE. */
6938fd1498Szrj
7038fd1498Szrj
7138fd1498Szrj /* Recognize a if-then-else CFG pattern starting to match with the
7238fd1498Szrj COND_BB basic-block containing the COND_EXPR. The recognized
7338fd1498Szrj then end else blocks are stored to *THEN_BB and *ELSE_BB. If
7438fd1498Szrj *THEN_BB and/or *ELSE_BB are already set, they are required to
7538fd1498Szrj match the then and else basic-blocks to make the pattern match.
7638fd1498Szrj Returns true if the pattern matched, false otherwise. */
7738fd1498Szrj
7838fd1498Szrj static bool
recognize_if_then_else(basic_block cond_bb,basic_block * then_bb,basic_block * else_bb)7938fd1498Szrj recognize_if_then_else (basic_block cond_bb,
8038fd1498Szrj basic_block *then_bb, basic_block *else_bb)
8138fd1498Szrj {
8238fd1498Szrj edge t, e;
8338fd1498Szrj
8438fd1498Szrj if (EDGE_COUNT (cond_bb->succs) != 2)
8538fd1498Szrj return false;
8638fd1498Szrj
8738fd1498Szrj /* Find the then/else edges. */
8838fd1498Szrj t = EDGE_SUCC (cond_bb, 0);
8938fd1498Szrj e = EDGE_SUCC (cond_bb, 1);
9038fd1498Szrj if (!(t->flags & EDGE_TRUE_VALUE))
9138fd1498Szrj std::swap (t, e);
9238fd1498Szrj if (!(t->flags & EDGE_TRUE_VALUE)
9338fd1498Szrj || !(e->flags & EDGE_FALSE_VALUE))
9438fd1498Szrj return false;
9538fd1498Szrj
9638fd1498Szrj /* Check if the edge destinations point to the required block. */
9738fd1498Szrj if (*then_bb
9838fd1498Szrj && t->dest != *then_bb)
9938fd1498Szrj return false;
10038fd1498Szrj if (*else_bb
10138fd1498Szrj && e->dest != *else_bb)
10238fd1498Szrj return false;
10338fd1498Szrj
10438fd1498Szrj if (!*then_bb)
10538fd1498Szrj *then_bb = t->dest;
10638fd1498Szrj if (!*else_bb)
10738fd1498Szrj *else_bb = e->dest;
10838fd1498Szrj
10938fd1498Szrj return true;
11038fd1498Szrj }
11138fd1498Szrj
11238fd1498Szrj /* Verify if the basic block BB does not have side-effects. Return
11338fd1498Szrj true in this case, else false. */
11438fd1498Szrj
11538fd1498Szrj static bool
bb_no_side_effects_p(basic_block bb)11638fd1498Szrj bb_no_side_effects_p (basic_block bb)
11738fd1498Szrj {
11838fd1498Szrj gimple_stmt_iterator gsi;
11938fd1498Szrj
12038fd1498Szrj for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
12138fd1498Szrj {
12238fd1498Szrj gimple *stmt = gsi_stmt (gsi);
12338fd1498Szrj
12438fd1498Szrj if (is_gimple_debug (stmt))
12538fd1498Szrj continue;
12638fd1498Szrj
12738fd1498Szrj if (gimple_has_side_effects (stmt)
12838fd1498Szrj || gimple_uses_undefined_value_p (stmt)
12938fd1498Szrj || gimple_could_trap_p (stmt)
13038fd1498Szrj || gimple_vuse (stmt)
13138fd1498Szrj /* const calls don't match any of the above, yet they could
13238fd1498Szrj still have some side-effects - they could contain
13338fd1498Szrj gimple_could_trap_p statements, like floating point
13438fd1498Szrj exceptions or integer division by zero. See PR70586.
13538fd1498Szrj FIXME: perhaps gimple_has_side_effects or gimple_could_trap_p
13638fd1498Szrj should handle this. */
13738fd1498Szrj || is_gimple_call (stmt))
13838fd1498Szrj return false;
13938fd1498Szrj }
14038fd1498Szrj
14138fd1498Szrj return true;
14238fd1498Szrj }
14338fd1498Szrj
14438fd1498Szrj /* Return true if BB is an empty forwarder block to TO_BB. */
14538fd1498Szrj
14638fd1498Szrj static bool
forwarder_block_to(basic_block bb,basic_block to_bb)14738fd1498Szrj forwarder_block_to (basic_block bb, basic_block to_bb)
14838fd1498Szrj {
14938fd1498Szrj return empty_block_p (bb)
15038fd1498Szrj && single_succ_p (bb)
15138fd1498Szrj && single_succ (bb) == to_bb;
15238fd1498Szrj }
15338fd1498Szrj
15438fd1498Szrj /* Verify if all PHI node arguments in DEST for edges from BB1 or
15538fd1498Szrj BB2 to DEST are the same. This makes the CFG merge point
15638fd1498Szrj free from side-effects. Return true in this case, else false. */
15738fd1498Szrj
15838fd1498Szrj static bool
same_phi_args_p(basic_block bb1,basic_block bb2,basic_block dest)15938fd1498Szrj same_phi_args_p (basic_block bb1, basic_block bb2, basic_block dest)
16038fd1498Szrj {
16138fd1498Szrj edge e1 = find_edge (bb1, dest);
16238fd1498Szrj edge e2 = find_edge (bb2, dest);
16338fd1498Szrj gphi_iterator gsi;
16438fd1498Szrj gphi *phi;
16538fd1498Szrj
16638fd1498Szrj for (gsi = gsi_start_phis (dest); !gsi_end_p (gsi); gsi_next (&gsi))
16738fd1498Szrj {
16838fd1498Szrj phi = gsi.phi ();
16938fd1498Szrj if (!operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, e1),
17038fd1498Szrj PHI_ARG_DEF_FROM_EDGE (phi, e2), 0))
17138fd1498Szrj return false;
17238fd1498Szrj }
17338fd1498Szrj
17438fd1498Szrj return true;
17538fd1498Szrj }
17638fd1498Szrj
17738fd1498Szrj /* Return the best representative SSA name for CANDIDATE which is used
17838fd1498Szrj in a bit test. */
17938fd1498Szrj
18038fd1498Szrj static tree
get_name_for_bit_test(tree candidate)18138fd1498Szrj get_name_for_bit_test (tree candidate)
18238fd1498Szrj {
18338fd1498Szrj /* Skip single-use names in favor of using the name from a
18438fd1498Szrj non-widening conversion definition. */
18538fd1498Szrj if (TREE_CODE (candidate) == SSA_NAME
18638fd1498Szrj && has_single_use (candidate))
18738fd1498Szrj {
18838fd1498Szrj gimple *def_stmt = SSA_NAME_DEF_STMT (candidate);
18938fd1498Szrj if (is_gimple_assign (def_stmt)
19038fd1498Szrj && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
19138fd1498Szrj {
19238fd1498Szrj if (TYPE_PRECISION (TREE_TYPE (candidate))
19338fd1498Szrj <= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
19438fd1498Szrj return gimple_assign_rhs1 (def_stmt);
19538fd1498Szrj }
19638fd1498Szrj }
19738fd1498Szrj
19838fd1498Szrj return candidate;
19938fd1498Szrj }
20038fd1498Szrj
20138fd1498Szrj /* Recognize a single bit test pattern in GIMPLE_COND and its defining
20238fd1498Szrj statements. Store the name being tested in *NAME and the bit
20338fd1498Szrj in *BIT. The GIMPLE_COND computes *NAME & (1 << *BIT).
20438fd1498Szrj Returns true if the pattern matched, false otherwise. */
20538fd1498Szrj
20638fd1498Szrj static bool
recognize_single_bit_test(gcond * cond,tree * name,tree * bit,bool inv)20738fd1498Szrj recognize_single_bit_test (gcond *cond, tree *name, tree *bit, bool inv)
20838fd1498Szrj {
20938fd1498Szrj gimple *stmt;
21038fd1498Szrj
21138fd1498Szrj /* Get at the definition of the result of the bit test. */
21238fd1498Szrj if (gimple_cond_code (cond) != (inv ? EQ_EXPR : NE_EXPR)
21338fd1498Szrj || TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME
21438fd1498Szrj || !integer_zerop (gimple_cond_rhs (cond)))
21538fd1498Szrj return false;
21638fd1498Szrj stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (cond));
21738fd1498Szrj if (!is_gimple_assign (stmt))
21838fd1498Szrj return false;
21938fd1498Szrj
22038fd1498Szrj /* Look at which bit is tested. One form to recognize is
22138fd1498Szrj D.1985_5 = state_3(D) >> control1_4(D);
22238fd1498Szrj D.1986_6 = (int) D.1985_5;
22338fd1498Szrj D.1987_7 = op0 & 1;
22438fd1498Szrj if (D.1987_7 != 0) */
22538fd1498Szrj if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
22638fd1498Szrj && integer_onep (gimple_assign_rhs2 (stmt))
22738fd1498Szrj && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
22838fd1498Szrj {
22938fd1498Szrj tree orig_name = gimple_assign_rhs1 (stmt);
23038fd1498Szrj
23138fd1498Szrj /* Look through copies and conversions to eventually
23238fd1498Szrj find the stmt that computes the shift. */
23338fd1498Szrj stmt = SSA_NAME_DEF_STMT (orig_name);
23438fd1498Szrj
23538fd1498Szrj while (is_gimple_assign (stmt)
23638fd1498Szrj && ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
23738fd1498Szrj && (TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (stmt)))
23838fd1498Szrj <= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt))))
23938fd1498Szrj && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
24038fd1498Szrj || gimple_assign_ssa_name_copy_p (stmt)))
24138fd1498Szrj stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
24238fd1498Szrj
24338fd1498Szrj /* If we found such, decompose it. */
24438fd1498Szrj if (is_gimple_assign (stmt)
24538fd1498Szrj && gimple_assign_rhs_code (stmt) == RSHIFT_EXPR)
24638fd1498Szrj {
24738fd1498Szrj /* op0 & (1 << op1) */
24838fd1498Szrj *bit = gimple_assign_rhs2 (stmt);
24938fd1498Szrj *name = gimple_assign_rhs1 (stmt);
25038fd1498Szrj }
25138fd1498Szrj else
25238fd1498Szrj {
25338fd1498Szrj /* t & 1 */
25438fd1498Szrj *bit = integer_zero_node;
25538fd1498Szrj *name = get_name_for_bit_test (orig_name);
25638fd1498Szrj }
25738fd1498Szrj
25838fd1498Szrj return true;
25938fd1498Szrj }
26038fd1498Szrj
26138fd1498Szrj /* Another form is
26238fd1498Szrj D.1987_7 = op0 & (1 << CST)
26338fd1498Szrj if (D.1987_7 != 0) */
26438fd1498Szrj if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
26538fd1498Szrj && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
26638fd1498Szrj && integer_pow2p (gimple_assign_rhs2 (stmt)))
26738fd1498Szrj {
26838fd1498Szrj *name = gimple_assign_rhs1 (stmt);
26938fd1498Szrj *bit = build_int_cst (integer_type_node,
27038fd1498Szrj tree_log2 (gimple_assign_rhs2 (stmt)));
27138fd1498Szrj return true;
27238fd1498Szrj }
27338fd1498Szrj
27438fd1498Szrj /* Another form is
27538fd1498Szrj D.1986_6 = 1 << control1_4(D)
27638fd1498Szrj D.1987_7 = op0 & D.1986_6
27738fd1498Szrj if (D.1987_7 != 0) */
27838fd1498Szrj if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
27938fd1498Szrj && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
28038fd1498Szrj && TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
28138fd1498Szrj {
28238fd1498Szrj gimple *tmp;
28338fd1498Szrj
28438fd1498Szrj /* Both arguments of the BIT_AND_EXPR can be the single-bit
28538fd1498Szrj specifying expression. */
28638fd1498Szrj tmp = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
28738fd1498Szrj if (is_gimple_assign (tmp)
28838fd1498Szrj && gimple_assign_rhs_code (tmp) == LSHIFT_EXPR
28938fd1498Szrj && integer_onep (gimple_assign_rhs1 (tmp)))
29038fd1498Szrj {
29138fd1498Szrj *name = gimple_assign_rhs2 (stmt);
29238fd1498Szrj *bit = gimple_assign_rhs2 (tmp);
29338fd1498Szrj return true;
29438fd1498Szrj }
29538fd1498Szrj
29638fd1498Szrj tmp = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
29738fd1498Szrj if (is_gimple_assign (tmp)
29838fd1498Szrj && gimple_assign_rhs_code (tmp) == LSHIFT_EXPR
29938fd1498Szrj && integer_onep (gimple_assign_rhs1 (tmp)))
30038fd1498Szrj {
30138fd1498Szrj *name = gimple_assign_rhs1 (stmt);
30238fd1498Szrj *bit = gimple_assign_rhs2 (tmp);
30338fd1498Szrj return true;
30438fd1498Szrj }
30538fd1498Szrj }
30638fd1498Szrj
30738fd1498Szrj return false;
30838fd1498Szrj }
30938fd1498Szrj
31038fd1498Szrj /* Recognize a bit test pattern in a GIMPLE_COND and its defining
31138fd1498Szrj statements. Store the name being tested in *NAME and the bits
31238fd1498Szrj in *BITS. The COND_EXPR computes *NAME & *BITS.
31338fd1498Szrj Returns true if the pattern matched, false otherwise. */
31438fd1498Szrj
31538fd1498Szrj static bool
recognize_bits_test(gcond * cond,tree * name,tree * bits,bool inv)31638fd1498Szrj recognize_bits_test (gcond *cond, tree *name, tree *bits, bool inv)
31738fd1498Szrj {
31838fd1498Szrj gimple *stmt;
31938fd1498Szrj
32038fd1498Szrj /* Get at the definition of the result of the bit test. */
32138fd1498Szrj if (gimple_cond_code (cond) != (inv ? EQ_EXPR : NE_EXPR)
32238fd1498Szrj || TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME
32338fd1498Szrj || !integer_zerop (gimple_cond_rhs (cond)))
32438fd1498Szrj return false;
32538fd1498Szrj stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (cond));
32638fd1498Szrj if (!is_gimple_assign (stmt)
32738fd1498Szrj || gimple_assign_rhs_code (stmt) != BIT_AND_EXPR)
32838fd1498Szrj return false;
32938fd1498Szrj
33038fd1498Szrj *name = get_name_for_bit_test (gimple_assign_rhs1 (stmt));
33138fd1498Szrj *bits = gimple_assign_rhs2 (stmt);
33238fd1498Szrj
33338fd1498Szrj return true;
33438fd1498Szrj }
33538fd1498Szrj
33638fd1498Szrj
33738fd1498Szrj /* Update profile after code in outer_cond_bb was adjusted so
33838fd1498Szrj outer_cond_bb has no condition. */
33938fd1498Szrj
34038fd1498Szrj static void
update_profile_after_ifcombine(basic_block inner_cond_bb,basic_block outer_cond_bb)34138fd1498Szrj update_profile_after_ifcombine (basic_block inner_cond_bb,
34238fd1498Szrj basic_block outer_cond_bb)
34338fd1498Szrj {
34438fd1498Szrj edge outer_to_inner = find_edge (outer_cond_bb, inner_cond_bb);
34538fd1498Szrj edge outer2 = (EDGE_SUCC (outer_cond_bb, 0) == outer_to_inner
34638fd1498Szrj ? EDGE_SUCC (outer_cond_bb, 1)
34738fd1498Szrj : EDGE_SUCC (outer_cond_bb, 0));
34838fd1498Szrj edge inner_taken = EDGE_SUCC (inner_cond_bb, 0);
34938fd1498Szrj edge inner_not_taken = EDGE_SUCC (inner_cond_bb, 1);
35038fd1498Szrj
35138fd1498Szrj if (inner_taken->dest != outer2->dest)
35238fd1498Szrj std::swap (inner_taken, inner_not_taken);
35338fd1498Szrj gcc_assert (inner_taken->dest == outer2->dest);
35438fd1498Szrj
35538fd1498Szrj /* In the following we assume that inner_cond_bb has single predecessor. */
35638fd1498Szrj gcc_assert (single_pred_p (inner_cond_bb));
35738fd1498Szrj
35838fd1498Szrj /* Path outer_cond_bb->(outer2) needs to be merged into path
35938fd1498Szrj outer_cond_bb->(outer_to_inner)->inner_cond_bb->(inner_taken)
36038fd1498Szrj and probability of inner_not_taken updated. */
36138fd1498Szrj
36238fd1498Szrj inner_cond_bb->count = outer_cond_bb->count;
36338fd1498Szrj
36438fd1498Szrj inner_taken->probability = outer2->probability + outer_to_inner->probability
36538fd1498Szrj * inner_taken->probability;
36638fd1498Szrj inner_not_taken->probability = profile_probability::always ()
36738fd1498Szrj - inner_taken->probability;
36838fd1498Szrj
36938fd1498Szrj outer_to_inner->probability = profile_probability::always ();
37038fd1498Szrj outer2->probability = profile_probability::never ();
37138fd1498Szrj }
37238fd1498Szrj
37338fd1498Szrj /* If-convert on a and pattern with a common else block. The inner
37438fd1498Szrj if is specified by its INNER_COND_BB, the outer by OUTER_COND_BB.
37538fd1498Szrj inner_inv, outer_inv and result_inv indicate whether the conditions
37638fd1498Szrj are inverted.
37738fd1498Szrj Returns true if the edges to the common else basic-block were merged. */
37838fd1498Szrj
37938fd1498Szrj static bool
ifcombine_ifandif(basic_block inner_cond_bb,bool inner_inv,basic_block outer_cond_bb,bool outer_inv,bool result_inv)38038fd1498Szrj ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
38138fd1498Szrj basic_block outer_cond_bb, bool outer_inv, bool result_inv)
38238fd1498Szrj {
38338fd1498Szrj gimple_stmt_iterator gsi;
38438fd1498Szrj gimple *inner_stmt, *outer_stmt;
38538fd1498Szrj gcond *inner_cond, *outer_cond;
38638fd1498Szrj tree name1, name2, bit1, bit2, bits1, bits2;
38738fd1498Szrj
38838fd1498Szrj inner_stmt = last_stmt (inner_cond_bb);
38938fd1498Szrj if (!inner_stmt
39038fd1498Szrj || gimple_code (inner_stmt) != GIMPLE_COND)
39138fd1498Szrj return false;
39238fd1498Szrj inner_cond = as_a <gcond *> (inner_stmt);
39338fd1498Szrj
39438fd1498Szrj outer_stmt = last_stmt (outer_cond_bb);
39538fd1498Szrj if (!outer_stmt
39638fd1498Szrj || gimple_code (outer_stmt) != GIMPLE_COND)
39738fd1498Szrj return false;
39838fd1498Szrj outer_cond = as_a <gcond *> (outer_stmt);
39938fd1498Szrj
40038fd1498Szrj /* See if we test a single bit of the same name in both tests. In
40138fd1498Szrj that case remove the outer test, merging both else edges,
40238fd1498Szrj and change the inner one to test for
40338fd1498Szrj name & (bit1 | bit2) == (bit1 | bit2). */
40438fd1498Szrj if (recognize_single_bit_test (inner_cond, &name1, &bit1, inner_inv)
40538fd1498Szrj && recognize_single_bit_test (outer_cond, &name2, &bit2, outer_inv)
40638fd1498Szrj && name1 == name2)
40738fd1498Szrj {
40838fd1498Szrj tree t, t2;
40938fd1498Szrj
41038fd1498Szrj /* Do it. */
41138fd1498Szrj gsi = gsi_for_stmt (inner_cond);
41238fd1498Szrj t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
41338fd1498Szrj build_int_cst (TREE_TYPE (name1), 1), bit1);
41438fd1498Szrj t2 = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
41538fd1498Szrj build_int_cst (TREE_TYPE (name1), 1), bit2);
41638fd1498Szrj t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), t, t2);
41738fd1498Szrj t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
41838fd1498Szrj true, GSI_SAME_STMT);
41938fd1498Szrj t2 = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
42038fd1498Szrj t2 = force_gimple_operand_gsi (&gsi, t2, true, NULL_TREE,
42138fd1498Szrj true, GSI_SAME_STMT);
42238fd1498Szrj t = fold_build2 (result_inv ? NE_EXPR : EQ_EXPR,
42338fd1498Szrj boolean_type_node, t2, t);
42438fd1498Szrj t = canonicalize_cond_expr_cond (t);
42538fd1498Szrj if (!t)
42638fd1498Szrj return false;
42738fd1498Szrj gimple_cond_set_condition_from_tree (inner_cond, t);
42838fd1498Szrj update_stmt (inner_cond);
42938fd1498Szrj
43038fd1498Szrj /* Leave CFG optimization to cfg_cleanup. */
43138fd1498Szrj gimple_cond_set_condition_from_tree (outer_cond,
43238fd1498Szrj outer_inv ? boolean_false_node : boolean_true_node);
43338fd1498Szrj update_stmt (outer_cond);
43438fd1498Szrj
43538fd1498Szrj update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb);
43638fd1498Szrj
43738fd1498Szrj if (dump_file)
43838fd1498Szrj {
43938fd1498Szrj fprintf (dump_file, "optimizing double bit test to ");
44038fd1498Szrj print_generic_expr (dump_file, name1);
44138fd1498Szrj fprintf (dump_file, " & T == T\nwith temporary T = (1 << ");
44238fd1498Szrj print_generic_expr (dump_file, bit1);
44338fd1498Szrj fprintf (dump_file, ") | (1 << ");
44438fd1498Szrj print_generic_expr (dump_file, bit2);
44538fd1498Szrj fprintf (dump_file, ")\n");
44638fd1498Szrj }
44738fd1498Szrj
44838fd1498Szrj return true;
44938fd1498Szrj }
45038fd1498Szrj
45138fd1498Szrj /* See if we have two bit tests of the same name in both tests.
45238fd1498Szrj In that case remove the outer test and change the inner one to
45338fd1498Szrj test for name & (bits1 | bits2) != 0. */
45438fd1498Szrj else if (recognize_bits_test (inner_cond, &name1, &bits1, !inner_inv)
45538fd1498Szrj && recognize_bits_test (outer_cond, &name2, &bits2, !outer_inv))
45638fd1498Szrj {
45738fd1498Szrj gimple_stmt_iterator gsi;
45838fd1498Szrj tree t;
45938fd1498Szrj
46038fd1498Szrj /* Find the common name which is bit-tested. */
46138fd1498Szrj if (name1 == name2)
46238fd1498Szrj ;
46338fd1498Szrj else if (bits1 == bits2)
46438fd1498Szrj {
46538fd1498Szrj std::swap (name2, bits2);
46638fd1498Szrj std::swap (name1, bits1);
46738fd1498Szrj }
46838fd1498Szrj else if (name1 == bits2)
46938fd1498Szrj std::swap (name2, bits2);
47038fd1498Szrj else if (bits1 == name2)
47138fd1498Szrj std::swap (name1, bits1);
47238fd1498Szrj else
47338fd1498Szrj return false;
47438fd1498Szrj
47538fd1498Szrj /* As we strip non-widening conversions in finding a common
47638fd1498Szrj name that is tested make sure to end up with an integral
47738fd1498Szrj type for building the bit operations. */
47838fd1498Szrj if (TYPE_PRECISION (TREE_TYPE (bits1))
47938fd1498Szrj >= TYPE_PRECISION (TREE_TYPE (bits2)))
48038fd1498Szrj {
48138fd1498Szrj bits1 = fold_convert (unsigned_type_for (TREE_TYPE (bits1)), bits1);
48238fd1498Szrj name1 = fold_convert (TREE_TYPE (bits1), name1);
48338fd1498Szrj bits2 = fold_convert (unsigned_type_for (TREE_TYPE (bits2)), bits2);
48438fd1498Szrj bits2 = fold_convert (TREE_TYPE (bits1), bits2);
48538fd1498Szrj }
48638fd1498Szrj else
48738fd1498Szrj {
48838fd1498Szrj bits2 = fold_convert (unsigned_type_for (TREE_TYPE (bits2)), bits2);
48938fd1498Szrj name1 = fold_convert (TREE_TYPE (bits2), name1);
49038fd1498Szrj bits1 = fold_convert (unsigned_type_for (TREE_TYPE (bits1)), bits1);
49138fd1498Szrj bits1 = fold_convert (TREE_TYPE (bits2), bits1);
49238fd1498Szrj }
49338fd1498Szrj
49438fd1498Szrj /* Do it. */
49538fd1498Szrj gsi = gsi_for_stmt (inner_cond);
49638fd1498Szrj t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), bits1, bits2);
49738fd1498Szrj t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
49838fd1498Szrj true, GSI_SAME_STMT);
49938fd1498Szrj t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
50038fd1498Szrj t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
50138fd1498Szrj true, GSI_SAME_STMT);
50238fd1498Szrj t = fold_build2 (result_inv ? NE_EXPR : EQ_EXPR, boolean_type_node, t,
50338fd1498Szrj build_int_cst (TREE_TYPE (t), 0));
50438fd1498Szrj t = canonicalize_cond_expr_cond (t);
50538fd1498Szrj if (!t)
50638fd1498Szrj return false;
50738fd1498Szrj gimple_cond_set_condition_from_tree (inner_cond, t);
50838fd1498Szrj update_stmt (inner_cond);
50938fd1498Szrj
51038fd1498Szrj /* Leave CFG optimization to cfg_cleanup. */
51138fd1498Szrj gimple_cond_set_condition_from_tree (outer_cond,
51238fd1498Szrj outer_inv ? boolean_false_node : boolean_true_node);
51338fd1498Szrj update_stmt (outer_cond);
51438fd1498Szrj update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb);
51538fd1498Szrj
51638fd1498Szrj if (dump_file)
51738fd1498Szrj {
51838fd1498Szrj fprintf (dump_file, "optimizing bits or bits test to ");
51938fd1498Szrj print_generic_expr (dump_file, name1);
52038fd1498Szrj fprintf (dump_file, " & T != 0\nwith temporary T = ");
52138fd1498Szrj print_generic_expr (dump_file, bits1);
52238fd1498Szrj fprintf (dump_file, " | ");
52338fd1498Szrj print_generic_expr (dump_file, bits2);
52438fd1498Szrj fprintf (dump_file, "\n");
52538fd1498Szrj }
52638fd1498Szrj
52738fd1498Szrj return true;
52838fd1498Szrj }
52938fd1498Szrj
53038fd1498Szrj /* See if we have two comparisons that we can merge into one. */
53138fd1498Szrj else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison
53238fd1498Szrj && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison)
53338fd1498Szrj {
53438fd1498Szrj tree t;
53538fd1498Szrj enum tree_code inner_cond_code = gimple_cond_code (inner_cond);
53638fd1498Szrj enum tree_code outer_cond_code = gimple_cond_code (outer_cond);
53738fd1498Szrj
53838fd1498Szrj /* Invert comparisons if necessary (and possible). */
53938fd1498Szrj if (inner_inv)
54038fd1498Szrj inner_cond_code = invert_tree_comparison (inner_cond_code,
54138fd1498Szrj HONOR_NANS (gimple_cond_lhs (inner_cond)));
54238fd1498Szrj if (inner_cond_code == ERROR_MARK)
54338fd1498Szrj return false;
54438fd1498Szrj if (outer_inv)
54538fd1498Szrj outer_cond_code = invert_tree_comparison (outer_cond_code,
54638fd1498Szrj HONOR_NANS (gimple_cond_lhs (outer_cond)));
54738fd1498Szrj if (outer_cond_code == ERROR_MARK)
54838fd1498Szrj return false;
54938fd1498Szrj /* Don't return false so fast, try maybe_fold_or_comparisons? */
55038fd1498Szrj
55138fd1498Szrj if (!(t = maybe_fold_and_comparisons (inner_cond_code,
55238fd1498Szrj gimple_cond_lhs (inner_cond),
55338fd1498Szrj gimple_cond_rhs (inner_cond),
55438fd1498Szrj outer_cond_code,
55538fd1498Szrj gimple_cond_lhs (outer_cond),
55638fd1498Szrj gimple_cond_rhs (outer_cond))))
55738fd1498Szrj {
55838fd1498Szrj tree t1, t2;
55938fd1498Szrj gimple_stmt_iterator gsi;
560*e215fc28Szrj bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
561*e215fc28Szrj if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
562*e215fc28Szrj logical_op_non_short_circuit
563*e215fc28Szrj = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
564*e215fc28Szrj if (!logical_op_non_short_circuit || flag_sanitize_coverage)
56538fd1498Szrj return false;
56638fd1498Szrj /* Only do this optimization if the inner bb contains only the conditional. */
56738fd1498Szrj if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (inner_cond_bb)))
56838fd1498Szrj return false;
56938fd1498Szrj t1 = fold_build2_loc (gimple_location (inner_cond),
57038fd1498Szrj inner_cond_code,
57138fd1498Szrj boolean_type_node,
57238fd1498Szrj gimple_cond_lhs (inner_cond),
57338fd1498Szrj gimple_cond_rhs (inner_cond));
57438fd1498Szrj t2 = fold_build2_loc (gimple_location (outer_cond),
57538fd1498Szrj outer_cond_code,
57638fd1498Szrj boolean_type_node,
57738fd1498Szrj gimple_cond_lhs (outer_cond),
57838fd1498Szrj gimple_cond_rhs (outer_cond));
57938fd1498Szrj t = fold_build2_loc (gimple_location (inner_cond),
58038fd1498Szrj TRUTH_AND_EXPR, boolean_type_node, t1, t2);
58138fd1498Szrj if (result_inv)
58238fd1498Szrj {
58338fd1498Szrj t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
58438fd1498Szrj result_inv = false;
58538fd1498Szrj }
58638fd1498Szrj gsi = gsi_for_stmt (inner_cond);
58738fd1498Szrj t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr, NULL, true,
58838fd1498Szrj GSI_SAME_STMT);
58938fd1498Szrj }
59038fd1498Szrj if (result_inv)
59138fd1498Szrj t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
59238fd1498Szrj t = canonicalize_cond_expr_cond (t);
59338fd1498Szrj if (!t)
59438fd1498Szrj return false;
59538fd1498Szrj gimple_cond_set_condition_from_tree (inner_cond, t);
59638fd1498Szrj update_stmt (inner_cond);
59738fd1498Szrj
59838fd1498Szrj /* Leave CFG optimization to cfg_cleanup. */
59938fd1498Szrj gimple_cond_set_condition_from_tree (outer_cond,
60038fd1498Szrj outer_inv ? boolean_false_node : boolean_true_node);
60138fd1498Szrj update_stmt (outer_cond);
60238fd1498Szrj update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb);
60338fd1498Szrj
60438fd1498Szrj if (dump_file)
60538fd1498Szrj {
60638fd1498Szrj fprintf (dump_file, "optimizing two comparisons to ");
60738fd1498Szrj print_generic_expr (dump_file, t);
60838fd1498Szrj fprintf (dump_file, "\n");
60938fd1498Szrj }
61038fd1498Szrj
61138fd1498Szrj return true;
61238fd1498Szrj }
61338fd1498Szrj
61438fd1498Szrj return false;
61538fd1498Szrj }
61638fd1498Szrj
61738fd1498Szrj /* Helper function for tree_ssa_ifcombine_bb. Recognize a CFG pattern and
61838fd1498Szrj dispatch to the appropriate if-conversion helper for a particular
61938fd1498Szrj set of INNER_COND_BB, OUTER_COND_BB, THEN_BB and ELSE_BB.
62038fd1498Szrj PHI_PRED_BB should be one of INNER_COND_BB, THEN_BB or ELSE_BB. */
62138fd1498Szrj
62238fd1498Szrj static bool
tree_ssa_ifcombine_bb_1(basic_block inner_cond_bb,basic_block outer_cond_bb,basic_block then_bb,basic_block else_bb,basic_block phi_pred_bb)62338fd1498Szrj tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, basic_block outer_cond_bb,
62438fd1498Szrj basic_block then_bb, basic_block else_bb,
62538fd1498Szrj basic_block phi_pred_bb)
62638fd1498Szrj {
62738fd1498Szrj /* The && form is characterized by a common else_bb with
62838fd1498Szrj the two edges leading to it mergable. The latter is
62938fd1498Szrj guaranteed by matching PHI arguments in the else_bb and
63038fd1498Szrj the inner cond_bb having no side-effects. */
63138fd1498Szrj if (phi_pred_bb != else_bb
63238fd1498Szrj && recognize_if_then_else (outer_cond_bb, &inner_cond_bb, &else_bb)
63338fd1498Szrj && same_phi_args_p (outer_cond_bb, phi_pred_bb, else_bb))
63438fd1498Szrj {
63538fd1498Szrj /* We have
63638fd1498Szrj <outer_cond_bb>
63738fd1498Szrj if (q) goto inner_cond_bb; else goto else_bb;
63838fd1498Szrj <inner_cond_bb>
63938fd1498Szrj if (p) goto ...; else goto else_bb;
64038fd1498Szrj ...
64138fd1498Szrj <else_bb>
64238fd1498Szrj ...
64338fd1498Szrj */
64438fd1498Szrj return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, false,
64538fd1498Szrj false);
64638fd1498Szrj }
64738fd1498Szrj
64838fd1498Szrj /* And a version where the outer condition is negated. */
64938fd1498Szrj if (phi_pred_bb != else_bb
65038fd1498Szrj && recognize_if_then_else (outer_cond_bb, &else_bb, &inner_cond_bb)
65138fd1498Szrj && same_phi_args_p (outer_cond_bb, phi_pred_bb, else_bb))
65238fd1498Szrj {
65338fd1498Szrj /* We have
65438fd1498Szrj <outer_cond_bb>
65538fd1498Szrj if (q) goto else_bb; else goto inner_cond_bb;
65638fd1498Szrj <inner_cond_bb>
65738fd1498Szrj if (p) goto ...; else goto else_bb;
65838fd1498Szrj ...
65938fd1498Szrj <else_bb>
66038fd1498Szrj ...
66138fd1498Szrj */
66238fd1498Szrj return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, true,
66338fd1498Szrj false);
66438fd1498Szrj }
66538fd1498Szrj
66638fd1498Szrj /* The || form is characterized by a common then_bb with the
66738fd1498Szrj two edges leading to it mergable. The latter is guaranteed
66838fd1498Szrj by matching PHI arguments in the then_bb and the inner cond_bb
66938fd1498Szrj having no side-effects. */
67038fd1498Szrj if (phi_pred_bb != then_bb
67138fd1498Szrj && recognize_if_then_else (outer_cond_bb, &then_bb, &inner_cond_bb)
67238fd1498Szrj && same_phi_args_p (outer_cond_bb, phi_pred_bb, then_bb))
67338fd1498Szrj {
67438fd1498Szrj /* We have
67538fd1498Szrj <outer_cond_bb>
67638fd1498Szrj if (q) goto then_bb; else goto inner_cond_bb;
67738fd1498Szrj <inner_cond_bb>
67838fd1498Szrj if (q) goto then_bb; else goto ...;
67938fd1498Szrj <then_bb>
68038fd1498Szrj ...
68138fd1498Szrj */
68238fd1498Szrj return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, true,
68338fd1498Szrj true);
68438fd1498Szrj }
68538fd1498Szrj
68638fd1498Szrj /* And a version where the outer condition is negated. */
68738fd1498Szrj if (phi_pred_bb != then_bb
68838fd1498Szrj && recognize_if_then_else (outer_cond_bb, &inner_cond_bb, &then_bb)
68938fd1498Szrj && same_phi_args_p (outer_cond_bb, phi_pred_bb, then_bb))
69038fd1498Szrj {
69138fd1498Szrj /* We have
69238fd1498Szrj <outer_cond_bb>
69338fd1498Szrj if (q) goto inner_cond_bb; else goto then_bb;
69438fd1498Szrj <inner_cond_bb>
69538fd1498Szrj if (q) goto then_bb; else goto ...;
69638fd1498Szrj <then_bb>
69738fd1498Szrj ...
69838fd1498Szrj */
69938fd1498Szrj return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, false,
70038fd1498Szrj true);
70138fd1498Szrj }
70238fd1498Szrj
70338fd1498Szrj return false;
70438fd1498Szrj }
70538fd1498Szrj
70638fd1498Szrj /* Recognize a CFG pattern and dispatch to the appropriate
70738fd1498Szrj if-conversion helper. We start with BB as the innermost
70838fd1498Szrj worker basic-block. Returns true if a transformation was done. */
70938fd1498Szrj
71038fd1498Szrj static bool
tree_ssa_ifcombine_bb(basic_block inner_cond_bb)71138fd1498Szrj tree_ssa_ifcombine_bb (basic_block inner_cond_bb)
71238fd1498Szrj {
71338fd1498Szrj basic_block then_bb = NULL, else_bb = NULL;
71438fd1498Szrj
71538fd1498Szrj if (!recognize_if_then_else (inner_cond_bb, &then_bb, &else_bb))
71638fd1498Szrj return false;
71738fd1498Szrj
71838fd1498Szrj /* Recognize && and || of two conditions with a common
71938fd1498Szrj then/else block which entry edges we can merge. That is:
72038fd1498Szrj if (a || b)
72138fd1498Szrj ;
72238fd1498Szrj and
72338fd1498Szrj if (a && b)
72438fd1498Szrj ;
72538fd1498Szrj This requires a single predecessor of the inner cond_bb. */
72638fd1498Szrj if (single_pred_p (inner_cond_bb)
72738fd1498Szrj && bb_no_side_effects_p (inner_cond_bb))
72838fd1498Szrj {
72938fd1498Szrj basic_block outer_cond_bb = single_pred (inner_cond_bb);
73038fd1498Szrj
73138fd1498Szrj if (tree_ssa_ifcombine_bb_1 (inner_cond_bb, outer_cond_bb,
73238fd1498Szrj then_bb, else_bb, inner_cond_bb))
73338fd1498Szrj return true;
73438fd1498Szrj
73538fd1498Szrj if (forwarder_block_to (else_bb, then_bb))
73638fd1498Szrj {
73738fd1498Szrj /* Other possibilities for the && form, if else_bb is
73838fd1498Szrj empty forwarder block to then_bb. Compared to the above simpler
73938fd1498Szrj forms this can be treated as if then_bb and else_bb were swapped,
74038fd1498Szrj and the corresponding inner_cond_bb not inverted because of that.
74138fd1498Szrj For same_phi_args_p we look at equality of arguments between
74238fd1498Szrj edge from outer_cond_bb and the forwarder block. */
74338fd1498Szrj if (tree_ssa_ifcombine_bb_1 (inner_cond_bb, outer_cond_bb, else_bb,
74438fd1498Szrj then_bb, else_bb))
74538fd1498Szrj return true;
74638fd1498Szrj }
74738fd1498Szrj else if (forwarder_block_to (then_bb, else_bb))
74838fd1498Szrj {
74938fd1498Szrj /* Other possibilities for the || form, if then_bb is
75038fd1498Szrj empty forwarder block to else_bb. Compared to the above simpler
75138fd1498Szrj forms this can be treated as if then_bb and else_bb were swapped,
75238fd1498Szrj and the corresponding inner_cond_bb not inverted because of that.
75338fd1498Szrj For same_phi_args_p we look at equality of arguments between
75438fd1498Szrj edge from outer_cond_bb and the forwarder block. */
75538fd1498Szrj if (tree_ssa_ifcombine_bb_1 (inner_cond_bb, outer_cond_bb, else_bb,
75638fd1498Szrj then_bb, then_bb))
75738fd1498Szrj return true;
75838fd1498Szrj }
75938fd1498Szrj }
76038fd1498Szrj
76138fd1498Szrj return false;
76238fd1498Szrj }
76338fd1498Szrj
76438fd1498Szrj /* Main entry for the tree if-conversion pass. */
76538fd1498Szrj
76638fd1498Szrj namespace {
76738fd1498Szrj
76838fd1498Szrj const pass_data pass_data_tree_ifcombine =
76938fd1498Szrj {
77038fd1498Szrj GIMPLE_PASS, /* type */
77138fd1498Szrj "ifcombine", /* name */
77238fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */
77338fd1498Szrj TV_TREE_IFCOMBINE, /* tv_id */
77438fd1498Szrj ( PROP_cfg | PROP_ssa ), /* properties_required */
77538fd1498Szrj 0, /* properties_provided */
77638fd1498Szrj 0, /* properties_destroyed */
77738fd1498Szrj 0, /* todo_flags_start */
77838fd1498Szrj TODO_update_ssa, /* todo_flags_finish */
77938fd1498Szrj };
78038fd1498Szrj
78138fd1498Szrj class pass_tree_ifcombine : public gimple_opt_pass
78238fd1498Szrj {
78338fd1498Szrj public:
pass_tree_ifcombine(gcc::context * ctxt)78438fd1498Szrj pass_tree_ifcombine (gcc::context *ctxt)
78538fd1498Szrj : gimple_opt_pass (pass_data_tree_ifcombine, ctxt)
78638fd1498Szrj {}
78738fd1498Szrj
78838fd1498Szrj /* opt_pass methods: */
78938fd1498Szrj virtual unsigned int execute (function *);
79038fd1498Szrj
79138fd1498Szrj }; // class pass_tree_ifcombine
79238fd1498Szrj
79338fd1498Szrj unsigned int
execute(function * fun)79438fd1498Szrj pass_tree_ifcombine::execute (function *fun)
79538fd1498Szrj {
79638fd1498Szrj basic_block *bbs;
79738fd1498Szrj bool cfg_changed = false;
79838fd1498Szrj int i;
79938fd1498Szrj
80038fd1498Szrj bbs = single_pred_before_succ_order ();
80138fd1498Szrj calculate_dominance_info (CDI_DOMINATORS);
80238fd1498Szrj
80338fd1498Szrj /* Search every basic block for COND_EXPR we may be able to optimize.
80438fd1498Szrj
80538fd1498Szrj We walk the blocks in order that guarantees that a block with
80638fd1498Szrj a single predecessor is processed after the predecessor.
80738fd1498Szrj This ensures that we collapse outter ifs before visiting the
80838fd1498Szrj inner ones, and also that we do not try to visit a removed
80938fd1498Szrj block. This is opposite of PHI-OPT, because we cascade the
81038fd1498Szrj combining rather than cascading PHIs. */
81138fd1498Szrj for (i = n_basic_blocks_for_fn (fun) - NUM_FIXED_BLOCKS - 1; i >= 0; i--)
81238fd1498Szrj {
81338fd1498Szrj basic_block bb = bbs[i];
81438fd1498Szrj gimple *stmt = last_stmt (bb);
81538fd1498Szrj
81638fd1498Szrj if (stmt
81738fd1498Szrj && gimple_code (stmt) == GIMPLE_COND)
81838fd1498Szrj if (tree_ssa_ifcombine_bb (bb))
81938fd1498Szrj {
82038fd1498Szrj /* Clear range info from all stmts in BB which is now executed
82138fd1498Szrj conditional on a always true/false condition. */
82238fd1498Szrj reset_flow_sensitive_info_in_bb (bb);
82338fd1498Szrj cfg_changed |= true;
82438fd1498Szrj }
82538fd1498Szrj }
82638fd1498Szrj
82738fd1498Szrj free (bbs);
82838fd1498Szrj
82938fd1498Szrj return cfg_changed ? TODO_cleanup_cfg : 0;
83038fd1498Szrj }
83138fd1498Szrj
83238fd1498Szrj } // anon namespace
83338fd1498Szrj
83438fd1498Szrj gimple_opt_pass *
make_pass_tree_ifcombine(gcc::context * ctxt)83538fd1498Szrj make_pass_tree_ifcombine (gcc::context *ctxt)
83638fd1498Szrj {
83738fd1498Szrj return new pass_tree_ifcombine (ctxt);
83838fd1498Szrj }
839