lower-bitint: Fix up additions of EH edges [PR113818]
Checks
Commit Message
Hi!
Due to -fnon-call-exceptions the bitint lowering adds new EH edges
in various places, so that the EH edge points from handling (e.g. load or
store) of each of the limbs. The problem is that the EH edge destination
as shown in the testcase can have some PHIs. If it is just a virtual
PHI, no big deal, the pass uses TODO_update_ssa_only_virtuals, but if
it has other PHIs, I think we need to copy the values from the preexisting
corresponding EH edge (which is from the original stmt to the EH pad)
to the newly added EH edge, so that the PHI arguments are the same rather
than missing (which ICEs during checking at the end of the pass).
This patch adds a function to do that and uses it whenever adding EH edges.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2024-02-09 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/113818
* gimple-lower-bitint.cc (add_eh_edge): New function.
(bitint_large_huge::handle_load,
bitint_large_huge::lower_mergeable_stmt,
bitint_large_huge::lower_muldiv_stmt): Use it.
* gcc.dg/bitint-89.c: New test.
Jakub
Comments
On Fri, 9 Feb 2024, Jakub Jelinek wrote:
> Hi!
>
> Due to -fnon-call-exceptions the bitint lowering adds new EH edges
> in various places, so that the EH edge points from handling (e.g. load or
> store) of each of the limbs. The problem is that the EH edge destination
> as shown in the testcase can have some PHIs. If it is just a virtual
> PHI, no big deal, the pass uses TODO_update_ssa_only_virtuals, but if
> it has other PHIs, I think we need to copy the values from the preexisting
> corresponding EH edge (which is from the original stmt to the EH pad)
> to the newly added EH edge, so that the PHI arguments are the same rather
> than missing (which ICEs during checking at the end of the pass).
>
> This patch adds a function to do that and uses it whenever adding EH edges.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
Thanks,
Richard.
> 2024-02-09 Jakub Jelinek <jakub@redhat.com>
>
> PR tree-optimization/113818
> * gimple-lower-bitint.cc (add_eh_edge): New function.
> (bitint_large_huge::handle_load,
> bitint_large_huge::lower_mergeable_stmt,
> bitint_large_huge::lower_muldiv_stmt): Use it.
>
> * gcc.dg/bitint-89.c: New test.
>
> --- gcc/gimple-lower-bitint.cc.jj 2024-02-08 14:33:36.033220098 +0100
> +++ gcc/gimple-lower-bitint.cc 2024-02-08 17:29:38.182386934 +0100
> @@ -1681,6 +1681,27 @@ bitint_large_huge::handle_cast (tree lhs
> return NULL_TREE;
> }
>
> +/* Add a new EH edge from SRC to EH_EDGE->dest, where EH_EDGE
> + is an older EH edge, and except for virtual PHIs duplicate the
> + PHI argument from the EH_EDGE to the new EH edge. */
> +
> +static void
> +add_eh_edge (basic_block src, edge eh_edge)
> +{
> + edge e = make_edge (src, eh_edge->dest, EDGE_EH);
> + e->probability = profile_probability::very_unlikely ();
> + for (gphi_iterator gsi = gsi_start_phis (eh_edge->dest);
> + !gsi_end_p (gsi); gsi_next (&gsi))
> + {
> + gphi *phi = gsi.phi ();
> + tree lhs = gimple_phi_result (phi);
> + if (virtual_operand_p (lhs))
> + continue;
> + const phi_arg_d *arg = gimple_phi_arg (phi, eh_edge->dest_idx);
> + add_phi_arg (phi, arg->def, e, arg->locus);
> + }
> +}
> +
> /* Helper function for handle_stmt method, handle a load from memory. */
>
> tree
> @@ -1756,8 +1777,7 @@ bitint_large_huge::handle_load (gimple *
> if (eh_edge)
> {
> edge e = split_block (gsi_bb (m_gsi), g);
> - make_edge (e->src, eh_edge->dest, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e->src, eh_edge);
> m_gsi = gsi_after_labels (e->dest);
> if (gsi_bb (save_gsi) == e->src)
> {
> @@ -1876,8 +1896,7 @@ bitint_large_huge::handle_load (gimple *
> {
> edge e = split_block (gsi_bb (m_gsi), g);
> m_gsi = gsi_after_labels (e->dest);
> - make_edge (e->src, eh_edge->dest, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e->src, eh_edge);
> }
> }
> if (conditional)
> @@ -1934,8 +1953,7 @@ normal_load:
> {
> edge e = split_block (gsi_bb (m_gsi), g);
> m_gsi = gsi_after_labels (e->dest);
> - make_edge (e->src, eh_edge->dest, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e->src, eh_edge);
> }
> if (tree_fits_uhwi_p (idx))
> {
> @@ -2554,8 +2572,8 @@ bitint_large_huge::lower_mergeable_stmt
> {
> edge e = split_block (gsi_bb (m_gsi), g);
> m_gsi = gsi_after_labels (e->dest);
> - make_edge (e->src, eh_pad, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e->src,
> + find_edge (gimple_bb (stmt), eh_pad));
> }
> }
> if (kind == bitint_prec_large)
> @@ -2633,8 +2651,8 @@ bitint_large_huge::lower_mergeable_stmt
> {
> edge e = split_block (gsi_bb (m_gsi), g);
> m_gsi = gsi_after_labels (e->dest);
> - make_edge (e->src, eh_pad, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e->src,
> + find_edge (gimple_bb (stmt), eh_pad));
> }
> }
> if (new_bb)
> @@ -2777,8 +2795,7 @@ bitint_large_huge::lower_mergeable_stmt
> {
> edge e = split_block (gsi_bb (m_gsi), g);
> m_gsi = gsi_after_labels (e->dest);
> - make_edge (e->src, eh_pad, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e->src, find_edge (gimple_bb (stmt), eh_pad));
> }
> }
> if (kind == bitint_prec_huge && i == (bo_bit != 0))
> @@ -2822,8 +2839,7 @@ bitint_large_huge::lower_mergeable_stmt
> {
> edge e = split_block (gsi_bb (m_gsi), g);
> m_gsi = gsi_after_labels (e->dest);
> - make_edge (e->src, eh_pad, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e->src, find_edge (gimple_bb (stmt), eh_pad));
> }
> }
> }
> @@ -3479,8 +3495,7 @@ bitint_large_huge::lower_muldiv_stmt (tr
> {
> edge e2 = split_block (gsi_bb (m_gsi), g);
> m_gsi = gsi_after_labels (e2->dest);
> - make_edge (e2->src, e1->dest, EDGE_EH)->probability
> - = profile_probability::very_unlikely ();
> + add_eh_edge (e2->src, e1);
> }
> }
> }
> --- gcc/testsuite/gcc.dg/bitint-89.c.jj 2024-02-08 17:35:01.693881442 +0100
> +++ gcc/testsuite/gcc.dg/bitint-89.c 2024-02-08 17:34:39.555189760 +0100
> @@ -0,0 +1,22 @@
> +/* PR tree-optimization/113818 */
> +/* { dg-do compile { target bitint } } */
> +/* { dg-options "-Os -fnon-call-exceptions -finstrument-functions-once" } */
> +
> +int c, i;
> +void bar (int *);
> +
> +#if __BITINT_MAXWIDTH__ >= 129
> +_BitInt(129) *a;
> +#else
> +_BitInt(63) *a;
> +#endif
> +
> +void
> +foo (void)
> +{
> + if (c)
> + return;
> + int q;
> + a[i] = 0;
> + bar (&q);
> +}
>
> Jakub
>
>
@@ -1681,6 +1681,27 @@ bitint_large_huge::handle_cast (tree lhs
return NULL_TREE;
}
+/* Add a new EH edge from SRC to EH_EDGE->dest, where EH_EDGE
+ is an older EH edge, and except for virtual PHIs duplicate the
+ PHI argument from the EH_EDGE to the new EH edge. */
+
+static void
+add_eh_edge (basic_block src, edge eh_edge)
+{
+ edge e = make_edge (src, eh_edge->dest, EDGE_EH);
+ e->probability = profile_probability::very_unlikely ();
+ for (gphi_iterator gsi = gsi_start_phis (eh_edge->dest);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gphi *phi = gsi.phi ();
+ tree lhs = gimple_phi_result (phi);
+ if (virtual_operand_p (lhs))
+ continue;
+ const phi_arg_d *arg = gimple_phi_arg (phi, eh_edge->dest_idx);
+ add_phi_arg (phi, arg->def, e, arg->locus);
+ }
+}
+
/* Helper function for handle_stmt method, handle a load from memory. */
tree
@@ -1756,8 +1777,7 @@ bitint_large_huge::handle_load (gimple *
if (eh_edge)
{
edge e = split_block (gsi_bb (m_gsi), g);
- make_edge (e->src, eh_edge->dest, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e->src, eh_edge);
m_gsi = gsi_after_labels (e->dest);
if (gsi_bb (save_gsi) == e->src)
{
@@ -1876,8 +1896,7 @@ bitint_large_huge::handle_load (gimple *
{
edge e = split_block (gsi_bb (m_gsi), g);
m_gsi = gsi_after_labels (e->dest);
- make_edge (e->src, eh_edge->dest, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e->src, eh_edge);
}
}
if (conditional)
@@ -1934,8 +1953,7 @@ normal_load:
{
edge e = split_block (gsi_bb (m_gsi), g);
m_gsi = gsi_after_labels (e->dest);
- make_edge (e->src, eh_edge->dest, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e->src, eh_edge);
}
if (tree_fits_uhwi_p (idx))
{
@@ -2554,8 +2572,8 @@ bitint_large_huge::lower_mergeable_stmt
{
edge e = split_block (gsi_bb (m_gsi), g);
m_gsi = gsi_after_labels (e->dest);
- make_edge (e->src, eh_pad, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e->src,
+ find_edge (gimple_bb (stmt), eh_pad));
}
}
if (kind == bitint_prec_large)
@@ -2633,8 +2651,8 @@ bitint_large_huge::lower_mergeable_stmt
{
edge e = split_block (gsi_bb (m_gsi), g);
m_gsi = gsi_after_labels (e->dest);
- make_edge (e->src, eh_pad, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e->src,
+ find_edge (gimple_bb (stmt), eh_pad));
}
}
if (new_bb)
@@ -2777,8 +2795,7 @@ bitint_large_huge::lower_mergeable_stmt
{
edge e = split_block (gsi_bb (m_gsi), g);
m_gsi = gsi_after_labels (e->dest);
- make_edge (e->src, eh_pad, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e->src, find_edge (gimple_bb (stmt), eh_pad));
}
}
if (kind == bitint_prec_huge && i == (bo_bit != 0))
@@ -2822,8 +2839,7 @@ bitint_large_huge::lower_mergeable_stmt
{
edge e = split_block (gsi_bb (m_gsi), g);
m_gsi = gsi_after_labels (e->dest);
- make_edge (e->src, eh_pad, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e->src, find_edge (gimple_bb (stmt), eh_pad));
}
}
}
@@ -3479,8 +3495,7 @@ bitint_large_huge::lower_muldiv_stmt (tr
{
edge e2 = split_block (gsi_bb (m_gsi), g);
m_gsi = gsi_after_labels (e2->dest);
- make_edge (e2->src, e1->dest, EDGE_EH)->probability
- = profile_probability::very_unlikely ();
+ add_eh_edge (e2->src, e1);
}
}
}
@@ -0,0 +1,22 @@
+/* PR tree-optimization/113818 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-Os -fnon-call-exceptions -finstrument-functions-once" } */
+
+int c, i;
+void bar (int *);
+
+#if __BITINT_MAXWIDTH__ >= 129
+_BitInt(129) *a;
+#else
+_BitInt(63) *a;
+#endif
+
+void
+foo (void)
+{
+ if (c)
+ return;
+ int q;
+ a[i] = 0;
+ bar (&q);
+}