--- /dev/null
+/* { dg-do run } */
+/* fre1 is disable because it can figure out that the if return value is just `a` */
+/* { dg-options "-O1 -fdisable-tree-fre1" } */
+
+/* This code is done this way to have the false edge as 1st
+ successor edge of BB2. Normally the true edge would be
+ the first and you would not hit the bug. Also the way PHIs is
+ done needs to be such that 0 is first. */
+[[gnu::noipa]]
+_Bool f3(_Bool a)
+{
+ if (a==0)
+ return 0;
+ else
+ return a;
+}
+
+int main()
+{
+ if (f3(0))
+ __builtin_abort();
+ if (!f3(1))
+ __builtin_abort();
+}
--- /dev/null
+/* { dg-do run } */
+/* We need to disable passes which might cause cfg cleanup */
+/* { dg-options "-O1 -fgimple -fdisable-tree-ethread -fdisable-tree-fre1" } */
+
+/* This code is done this way to have the false edge as 1st
+ successor edge of BB2. Normally the true edge would be
+ the first and you would not hit the bug. */
+[[gnu::noipa]]
+_Bool __GIMPLE (ssa, startwith("forwprop1"))
+f3 (_Bool a)
+{
+ _Bool i;
+ _Bool tt;
+
+ __BB(2):
+ tt_4 = a_1(D) == _Literal (_Bool)0;
+ if (tt_4 != _Literal (_Bool)0)
+ goto __BB3;
+ else
+ goto __BB4;
+
+ __BB(3):
+ goto __BB5;
+
+ __BB(4):
+ goto __BB5;
+
+ __BB(5):
+ i_2 = __PHI (__BB4: a_1(D), __BB3: _Literal (_Bool)0);
+
+ return i_2;
+}
+
+int main()
+{
+ if (f3(0))
+ __builtin_abort();
+ if (!f3(1))
+ __builtin_abort();
+}
gimple *stmt_to_move = NULL;
gimple *stmt_to_move_alt = NULL;
auto_bitmap inserted_exprs;
+ tree arg_true, arg_false;
/* Special case A ? B : B as this will always simplify to B. */
if (operand_equal_for_phi_arg_p (arg0, arg1))
/* We need to know which is the true edge and which is the false
edge so that we know when to invert the condition below. */
extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
- if (e1 == true_edge || e0 == false_edge)
- std::swap (arg0, arg1);
+
+ /* Forward the edges over the middle basic block. */
+ if (true_edge->dest == middle_bb)
+ true_edge = EDGE_SUCC (true_edge->dest, 0);
+ if (false_edge->dest == middle_bb)
+ false_edge = EDGE_SUCC (false_edge->dest, 0);
+
+ /* When THREEWAY_P then e1 will point to the edge of the final transition
+ from middle-bb to end. */
+ if (true_edge == e0)
+ {
+ if (!threeway_p)
+ gcc_assert (false_edge == e1);
+ arg_true = arg0;
+ arg_false = arg1;
+ }
+ else
+ {
+ gcc_assert (false_edge == e0);
+ if (!threeway_p)
+ gcc_assert (true_edge == e1);
+ arg_true = arg1;
+ arg_false = arg0;
+ }
tree type = TREE_TYPE (gimple_phi_result (phi));
result = gimple_simplify_phiopt (early_p, type, stmt,
- arg0, arg1,
+ arg_true, arg_false,
&seq);
if (!result)
return false;