diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 5032ba137799..f77db74af6de 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9690,10 +9690,6 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, if (DECL_NAME (x) || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))) saw_named_field = true; - - if (AGGREGATE_TYPE_P (TREE_TYPE (x)) - && TYPE_TYPELESS_STORAGE (TREE_TYPE (x))) - TYPE_TYPELESS_STORAGE (t) = true; } detect_field_duplicates (fieldlist); @@ -9905,7 +9901,6 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, TYPE_FIELDS (x) = TYPE_FIELDS (t); TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t); TYPE_TRANSPARENT_AGGR (x) = TYPE_TRANSPARENT_AGGR (t); - TYPE_TYPELESS_STORAGE (x) = TYPE_TYPELESS_STORAGE (t); C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t); C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t); C_TYPE_FIELDS_NON_CONSTEXPR (x) = C_TYPE_FIELDS_NON_CONSTEXPR (t); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index b007c8ffe766..50a112e65df8 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -464,21 +464,13 @@ c_build_function_type (tree type, tree args, bool no) return c_set_type_bits (ret, type); } -/* Build an array type. This sets typeless storage as required - by C2Y and C_TYPE_VARIABLY_MODIFIED and C_TYPE_VARIABLE_SIZE - based on the element type and domain. */ +/* Build an array type. This sets C_TYPE_VARIABLY_MODIFIED and + C_TYPE_VARIABLE_SIZE based on the element type and domain. */ tree c_build_array_type (tree type, tree domain) { - int type_quals = TYPE_QUALS (type); - - /* Identify typeless storage as introduced in C2Y - and supported also in earlier language modes. */ - bool typeless = (char_type_p (type) && !(type_quals & TYPE_QUAL_ATOMIC)) - || (AGGREGATE_TYPE_P (type) && TYPE_TYPELESS_STORAGE (type)); - - tree ret = build_array_type (type, domain, typeless); + tree ret = build_array_type (type, domain); if (domain && TYPE_MAX_VALUE (domain) && TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST) diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 33d9acd67710..34bd0a02e2b7 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -996,6 +996,8 @@ extern enum riscv_cc get_riscv_cc (const rtx use); #define TARGET_VECTOR_MISALIGN_SUPPORTED \ riscv_vector_unaligned_access_p +#define LOGICAL_OP_NON_SHORT_CIRCUIT 0 + /* Control the assembler format that we output. */ /* Output to assembler file text saying following lines diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1309e602628e..d20d9b8bc0d8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -15901,10 +15901,6 @@ In each case, the @var{value} is an integer. The following choices of @var{name} are recognized for all targets: @table @gcctabopt -@item phiopt-factor-max-stmts-live -When factoring statements out of if/then/else, this is the max # of statements -after the defining statement to be allow to extend the lifetime of a name - @item predictable-branch-outcome When branch is predicted to be taken with probability lower than this threshold (in percent), then it is considered well predictable. diff --git a/gcc/params.opt b/gcc/params.opt index 64e453d29b74..0d4d56783d15 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -904,10 +904,6 @@ Enum(parloops_schedule_type) String(runtime) Value(PARLOOPS_SCHEDULE_RUNTIME) Common Joined UInteger Var(param_partial_inlining_entry_probability) Init(70) Optimization IntegerRange(0, 100) Param Maximum probability of the entry BB of split region (in percent relative to entry BB of the function) to make partial inlining happen. --param=phiopt-factor-max-stmts-live= -Common Joined UInteger Var(param_phiopt_factor_max_stmts_live) Init(5) Optimization IntegerRange(0, 100) Param -Maximum number of statements allowed inbetween the statement and the end to considered not extending the liferange. - -param=predictable-branch-outcome= Common Joined UInteger Var(param_predictable_branch_outcome) Init(2) IntegerRange(0, 50) Param Optimization Maximal estimated outcome of branch considered predictable. diff --git a/gcc/testsuite/gcc.dg/c2y-byte-alias-1.c b/gcc/testsuite/gcc.dg/c2y-byte-alias-1.c deleted file mode 100644 index 30bc2c09c2f8..000000000000 --- a/gcc/testsuite/gcc.dg/c2y-byte-alias-1.c +++ /dev/null @@ -1,46 +0,0 @@ -/* { dg-do run } */ -/* { dg-options "-std=c2y -O2" } */ - -struct f { _Alignas(int) char buf[sizeof(int)]; }; -struct f2 { struct f x; }; -union g { _Alignas(int) char buf[sizeof(int)]; }; - -[[gnu::noinline]] -int foo(struct f *p, int *q) -{ - *q = 1; - *p = (struct f){ }; - return *q; -} - -[[gnu::noinline]] -int foo2(struct f2 *p, int *q) -{ - *q = 1; - *p = (struct f2){ }; - return *q; -} - -[[gnu::noinline]] -int bar(union g *p, int *q) -{ - *q = 1; - *p = (union g){ }; - return *q; -} - - -int main() -{ - struct f p; - if (0 != foo(&p, (void*)&p.buf)) - __builtin_abort(); - - struct f2 p2; - if (0 != foo2(&p2, (void*)&p2.x.buf)) - __builtin_abort(); - - union g q; - if (0 != bar(&q, (void*)&q.buf)) - __builtin_abort(); -} diff --git a/gcc/testsuite/gcc.dg/c2y-byte-alias-2.c b/gcc/testsuite/gcc.dg/c2y-byte-alias-2.c deleted file mode 100644 index 9bd2d18b3864..000000000000 --- a/gcc/testsuite/gcc.dg/c2y-byte-alias-2.c +++ /dev/null @@ -1,43 +0,0 @@ -/* { dg-do run } */ -/* { dg-options "-std=c2y -O2" } */ - -struct f2 { - struct f { - _Alignas(int) char buf[sizeof(int)]; - } x[2]; - int i; -}; - -[[gnu::noinline]] -int foo2(struct f2 *p, int *q) -{ - *q = 1; - *p = (struct f2){ }; - return *q; -} - -struct g2 { - union g { - _Alignas(int) char buf[sizeof(int)]; - } x[2]; - int i; -}; - -[[gnu::noinline]] -int bar2(struct g2 *p, int *q) -{ - *q = 1; - *p = (struct g2){ }; - return *q; -} - -int main() -{ - struct f2 p2; - if (0 != foo2(&p2, (void*)&p2.x[0].buf)) - __builtin_abort(); - - struct g2 q2; - if (0 != bar2(&q2, (void*)&q2.x[0].buf)) - __builtin_abort(); -} diff --git a/gcc/testsuite/gcc.dg/c2y-byte-alias-3.c b/gcc/testsuite/gcc.dg/c2y-byte-alias-3.c deleted file mode 100644 index f88eab2e92f3..000000000000 --- a/gcc/testsuite/gcc.dg/c2y-byte-alias-3.c +++ /dev/null @@ -1,47 +0,0 @@ -/* { dg-do run } */ -/* { dg-options "-std=c2y -O2" } */ - -struct f { _Alignas(int) typeof(volatile char) buf[sizeof(int)]; }; -struct f2 { struct f x; }; -union g { _Alignas(int) volatile char buf[sizeof(int)]; }; - - -[[gnu::noinline]] -int foo(struct f *p, int *q) -{ - *q = 1; - *p = (struct f){ }; - return *q; -} - -[[gnu::noinline]] -int foo2(struct f2 *p, int *q) -{ - *q = 1; - *p = (struct f2){ }; - return *q; -} - -[[gnu::noinline]] -int bar(union g *p, int *q) -{ - *q = 1; - *p = (union g){ }; - return *q; -} - - -int main() -{ - struct f p; - if (0 != foo(&p, (void*)&p.buf)) - __builtin_abort(); - - struct f2 p2; - if (0 != foo2(&p2, (void*)&p2.x.buf)) - __builtin_abort(); - - union g q; - if (0 != bar(&q, (void*)&q.buf)) - __builtin_abort(); -} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-1.c b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-1.c deleted file mode 100644 index 6c0971ff8014..000000000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-1.c +++ /dev/null @@ -1,27 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt1-details -fdump-tree-optimized" } */ - -/* PR tree-optimization/112418 */ - -int f(int a, int b, int d) -{ - int c; - if (a < 0) - { - a = -a; - c = d > 0 ? d : -d; - } - else - { - a = a; - c = d > 0 ? d : -d; - } - return a + c; -} - -/* ABS should be able to pull out of the if statement early on in phiopt1. */ -/* { dg-final { scan-tree-dump "changed to factor operation out from " "phiopt1" } } */ -/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 2 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-not "if " "optimized" } } */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-2.c b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-2.c deleted file mode 100644 index 93e2eb3a051c..000000000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-2.c +++ /dev/null @@ -1,29 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt1-details -fdump-tree-optimized" } */ - -/* PR tree-optimization/112418 */ - -/* This is factor_op_phi-1.c but with statements swapped in the inner if. */ - -int f(int a, int b, int d) -{ - int c; - if (a < 0) - { - c = d > 0 ? d : -d; - a = -a; - } - else - { - c = d > 0 ? d : -d; - a = a; - } - return a + c; -} - -/* ABS should be able to pull out of the if statement early on in phiopt1. */ -/* { dg-final { scan-tree-dump "changed to factor operation out from " "phiopt1" } } */ -/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 2 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-not "if " "optimized" } } */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-3.c b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-3.c deleted file mode 100644 index 0aca877fa362..000000000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-3.c +++ /dev/null @@ -1,33 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O1 -fdump-tree-phiopt1-details -fdump-tree-optimized" } */ - -int h(void); -int h1(void); - -int f(int a, int b, int d) -{ - int c; - if (a < 0) - { - a = h(); - c = d > 0 ? d : -d; - a += h(); - } - else - { - a = h1(); - c = d > 0 ? d : -d; - a += h1(); - } - return a + c; -} - -/* ABS should be not to pulled out of the if statement early on in phiopt1 as it lengthes d's - live range over a call. - Note pre can lift the */ -/* { dg-final { scan-tree-dump-not "changed to factor operation out from " "phiopt1" } } */ -/* { dg-final { scan-tree-dump "if " "phiopt1" } } */ -/* { dg-final { scan-tree-dump "if " "optimized" } } */ -/* There will be 2 ABS due to the need for it in the inner if. */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 2 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-4.c b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-4.c deleted file mode 100644 index 482c39b203b7..000000000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-4.c +++ /dev/null @@ -1,29 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt1-details -fdump-tree-optimized" } */ - -/* PR tree-optimization/112418 */ - -/* This is factor_op_phi-1.c but with statements swapped in the inner if. */ - -int f(int a, int b, int d, int e) -{ - int c; - if (a < 0) - { - c = d > 0 ? d : -d; - a = -a; - } - else - { - c = e > 0 ? e : -e; - a = a; - } - return a + c; -} - -/* ABS should be able to pull out of the if statement early on in phiopt1. */ -/* { dg-final { scan-tree-dump "changed to factor operation out from " "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "if " 1 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 1 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "if " 1 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "ABS_EXPR " 1 "optimized" } } */ diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index aaebae6b38c0..47c85a02a3d2 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -223,90 +223,14 @@ replace_phi_edge_with_variable (basic_block cond_block, bb->index); } -/* Returns true if the ARG used from DEF_STMT is profitable to move - to a PHI node of the basic block MERGE where the new statement - will be located. */ -static bool -is_factor_profitable (gimple *def_stmt, basic_block merge, tree arg) -{ - /* The defining statement should be conditional. */ - if (dominated_by_p (CDI_DOMINATORS, merge, - gimple_bb (def_stmt))) - return false; - - /* If the arg is invariant, then there is - no extending of the live range. */ - if (is_gimple_min_invariant (arg)) - return true; - - /* Otherwise, the arg needs to be a ssa name. */ - if (TREE_CODE (arg) != SSA_NAME) - return false; - - /* We should not increase the live range of arg - across too many statements or calls. */ - gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt); - gsi_next_nondebug (&gsi); - - /* Skip past nops and predicates. */ - while (!gsi_end_p (gsi) - && (gimple_code (gsi_stmt (gsi)) == GIMPLE_NOP - || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT)) - gsi_next_nondebug (&gsi); - - /* If the defining statement is at the end of the bb, then it is - always profitable to be to move. */ - if (gsi_end_p (gsi)) - return true; - - /* Check if the uses of arg is dominated by merge block, this is a quick and - rough estimate if arg is still alive at the merge bb. */ - /* FIXME: extend to a more complete live range detection. */ - use_operand_p use_p; - imm_use_iterator iter; - FOR_EACH_IMM_USE_FAST (use_p, iter, arg) - { - gimple *use_stmt = USE_STMT (use_p); - basic_block use_bb = gimple_bb (use_stmt); - if (dominated_by_p (CDI_DOMINATORS, merge, use_bb)) - return true; - } - - /* If there are a few (non-call/asm) statements between - the old defining statement and end of the bb, then - the live range of new arg does not increase enough. */ - int max_statements = param_phiopt_factor_max_stmts_live; - - while (!gsi_end_p (gsi)) - { - gimple *stmt = gsi_stmt (gsi); - auto gcode = gimple_code (stmt); - /* Skip over NOPs and predicts. */ - if (gcode == GIMPLE_NOP - || gcode == GIMPLE_PREDICT) - { - gsi_next_nondebug (&gsi); - continue; - } - /* Non-assigns will extend the live range too much. */ - if (gcode != GIMPLE_ASSIGN) - return false; - max_statements --; - if (max_statements == 0) - return false; - gsi_next_nondebug (&gsi); - } - return true; -} - /* PR66726: Factor operations out of COND_EXPR. If the arguments of the PHI stmt are Unary operator, factor out the operation and perform the operation to the result of PHI stmt. COND_STMT is the controlling predicate. - Return true if the operation was factored out; false otherwise. */ + Return the newly-created PHI, if any. */ -static bool -factor_out_conditional_operation (edge e0, edge e1, basic_block merge, - gphi *phi, gimple *cond_stmt) +static gphi * +factor_out_conditional_operation (edge e0, edge e1, gphi *phi, + tree arg0, tree arg1, gimple *cond_stmt) { gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL; tree temp, result; @@ -315,21 +239,12 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, location_t locus = gimple_location (phi); gimple_match_op arg0_op, arg1_op; - /* We should only get here if the phi had two arguments. */ - gcc_assert (gimple_phi_num_args (phi) == 2); - - /* Virtual operands are never handled. */ - if (virtual_operand_p (gimple_phi_result (phi))) - return false; - - tree arg0 = gimple_phi_arg_def (phi, e0->dest_idx); - tree arg1 = gimple_phi_arg_def (phi, e1->dest_idx); - gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); - - /* Arugments that are the same don't have anything to be - done to them. */ - if (operand_equal_for_phi_arg_p (arg0, arg1)) - return false; + /* Handle only PHI statements with two arguments. TODO: If all + other arguments to PHI are INTEGER_CST or if their defining + statement have the same unary operation, we can handle more + than two arguments too. */ + if (gimple_phi_num_args (phi) != 2) + return NULL; /* First canonicalize to simplify tests. */ if (TREE_CODE (arg0) != SSA_NAME) @@ -341,21 +256,21 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, if (TREE_CODE (arg0) != SSA_NAME || (TREE_CODE (arg1) != SSA_NAME && TREE_CODE (arg1) != INTEGER_CST)) - return false; + return NULL; /* Check if arg0 is an SSA_NAME and the stmt which defines arg0 is an unary operation. */ arg0_def_stmt = SSA_NAME_DEF_STMT (arg0); if (!gimple_extract_op (arg0_def_stmt, &arg0_op)) - return false; + return NULL; /* Check to make sure none of the operands are in abnormal phis. */ if (arg0_op.operands_occurs_in_abnormal_phi ()) - return false; + return NULL; /* Currently just support one operand expressions. */ if (arg0_op.num_ops != 1) - return false; + return NULL; tree new_arg0 = arg0_op.ops[0]; tree new_arg1; @@ -363,45 +278,42 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, /* If arg0 have > 1 use, then this transformation actually increases the number of expressions evaluated at runtime. */ if (!has_single_use (arg0)) - return false; - if (!is_factor_profitable (arg0_def_stmt, merge, new_arg0)) - return false; + return NULL; if (TREE_CODE (arg1) == SSA_NAME) { /* Check if arg1 is an SSA_NAME. */ arg1_def_stmt = SSA_NAME_DEF_STMT (arg1); if (!gimple_extract_op (arg1_def_stmt, &arg1_op)) - return false; + return NULL; if (arg1_op.code != arg0_op.code) - return false; + return NULL; if (arg1_op.num_ops != arg0_op.num_ops) - return false; + return NULL; if (arg1_op.operands_occurs_in_abnormal_phi ()) - return false; + return NULL; /* If arg1 have > 1 use, then this transformation actually increases the number of expressions evaluated at runtime. */ if (!has_single_use (arg1)) - return false; + return NULL; + /* Either arg1_def_stmt or arg0_def_stmt should be conditional. */ + if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb (arg0_def_stmt)) + && dominated_by_p (CDI_DOMINATORS, + gimple_bb (phi), gimple_bb (arg1_def_stmt))) + return NULL; new_arg1 = arg1_op.ops[0]; - - if (!is_factor_profitable (arg1_def_stmt, merge, new_arg1)) - return false; } else { - /* For constants only handle if the phi was the only one. */ - if (single_non_singleton_phi_for_edges (phi_nodes (merge), e0, e1) == NULL) - return false; /* TODO: handle more than just casts here. */ if (!gimple_assign_cast_p (arg0_def_stmt)) - return false; + return NULL; /* arg0_def_stmt should be conditional. */ if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb (arg0_def_stmt))) - return false; + return NULL; /* If arg1 is an INTEGER_CST, fold it to new type if it fits, or else if the bits will not be modified during the conversion, except for @@ -412,7 +324,7 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, == TYPE_PRECISION (TREE_TYPE (arg1)) && (TREE_CODE (TREE_TYPE (new_arg0)) != BOOLEAN_TYPE || TYPE_PRECISION (TREE_TYPE (new_arg0)) == 1)))) - return false; + return NULL; /* For the INTEGER_CST case, we are just moving the conversion from one place to another, which can often @@ -457,16 +369,26 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, && !(INTEGRAL_TYPE_P (lhst) && TYPE_UNSIGNED (lhst) && TYPE_PRECISION (lhst) == 1)) - return false; + return NULL; if (lhs != gimple_assign_rhs1 (arg0_def_stmt)) - return false; + return NULL; gsi_prev_nondebug (&gsi); if (!gsi_end_p (gsi)) - return false; + return NULL; } else - return false; + return NULL; } + gsi = gsi_for_stmt (arg0_def_stmt); + gsi_next_nondebug (&gsi); + /* Skip past nops and predicates. */ + while (!gsi_end_p (gsi) + && (gimple_code (gsi_stmt (gsi)) == GIMPLE_NOP + || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT)) + gsi_next_nondebug (&gsi); + /* Reject if the statement was not at the end of the block. */ + if (!gsi_end_p (gsi)) + return NULL; } new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1); @@ -477,7 +399,7 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, /* If types of new_arg0 and new_arg1 are different bailout. */ if (!types_compatible_p (TREE_TYPE (new_arg0), TREE_TYPE (new_arg1))) - return false; + return NULL; /* Create a new PHI stmt. */ result = gimple_phi_result (phi); @@ -495,7 +417,7 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, if (!result) { release_ssa_name (temp); - return false; + return NULL; } gsi = gsi_after_labels (gimple_bb (phi)); @@ -535,7 +457,7 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, statistics_counter_event (cfun, "factored out operation", 1); - return true; + return newphi; } @@ -4504,29 +4426,6 @@ pass_phiopt::execute (function *) basic_block merge = diamond_p ? EDGE_SUCC (bb2, 0)->dest : bb2; gimple_seq phis = phi_nodes (merge); - if (gimple_seq_empty_p (phis)) - return; - - /* Factor out operations from the phi if possible. */ - if (single_pred_p (bb1) - && EDGE_COUNT (merge->preds) == 2) - { - for (gsi = gsi_start (phis); !gsi_end_p (gsi); ) - { - gphi *phi = as_a (gsi_stmt (gsi)); - - if (factor_out_conditional_operation (e1, e2, merge, phi, - cond_stmt)) - { - /* Start over if there was an operation that was factored out because the new phi might have another opportunity. */ - phis = phi_nodes (merge); - gsi = gsi_start (phis); - } - else - gsi_next (&gsi); - } - } - /* Value replacement can work with more than one PHI so try that first. */ if (!early_p && !diamond_p) @@ -4553,6 +4452,24 @@ pass_phiopt::execute (function *) node. */ gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); + if (single_pred_p (bb1) + && EDGE_COUNT (merge->preds) == 2) + { + gphi *newphi = phi; + while (newphi) + { + phi = newphi; + /* factor_out_conditional_operation may create a new PHI in + BB2 and eliminate an existing PHI in BB2. Recompute values + that may be affected by that change. */ + arg0 = gimple_phi_arg_def (phi, e1->dest_idx); + arg1 = gimple_phi_arg_def (phi, e2->dest_idx); + gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); + newphi = factor_out_conditional_operation (e1, e2, phi, + arg0, arg1, + cond_stmt); + } + } /* Do the replacement of conditional if it can be done. */ if (match_simplify_replacement (bb, bb1, bb2, e1, e2, phi,