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 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 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 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 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 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 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 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 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 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 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 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: 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 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 * 83538fd1498Szrj make_pass_tree_ifcombine (gcc::context *ctxt) 83638fd1498Szrj { 83738fd1498Szrj return new pass_tree_ifcombine (ctxt); 83838fd1498Szrj } 839