Copy EH phi args for throwing hardened compares

When we duplicate a throwing compare for hardening, the EH edge from
the original compare gets duplicated for the inverted compare, but we
failed to adjust any PHI nodes in the EH block.  This patch adds the
needed adjustment, copying the PHI args from those of the preexisting
edge.


for  gcc/ChangeLog

	PR tree-optimization/103856
	* gimple-harden-conditionals.cc (non_eh_succ_edge): Enable the
	eh edge to be requested through an extra parameter.
	(pass_harden_compares::execute): Copy PHI args in the EH dest
	block for the new EH edge added for the inverted compare.

for  gcc/testsuite/ChangeLog

	PR tree-optimization/103856
	* g++.dg/pr103856.C: New.
This commit is contained in:
Alexandre Oliva 2022-02-24 22:03:32 -03:00 committed by Alexandre Oliva
parent 756a61851c
commit e53bb1965d
2 changed files with 45 additions and 3 deletions

View File

@ -361,9 +361,9 @@ make_pass_harden_conditional_branches (gcc::context *ctxt)
}
/* Return the fallthru edge of a block whose other edge is an EH
edge. */
edge. If EHP is not NULL, store the EH edge in it. */
static inline edge
non_eh_succ_edge (basic_block bb)
non_eh_succ_edge (basic_block bb, edge *ehp = NULL)
{
gcc_checking_assert (EDGE_COUNT (bb->succs) == 2);
@ -375,6 +375,9 @@ non_eh_succ_edge (basic_block bb)
gcc_checking_assert (!(ret->flags & EDGE_EH)
&& (eh->flags & EDGE_EH));
if (ehp)
*ehp = eh;
return ret;
}
@ -538,8 +541,9 @@ pass_harden_compares::execute (function *fun)
add_stmt_to_eh_lp (asgnck, lookup_stmt_eh_lp (asgn));
make_eh_edges (asgnck);
edge ckeh;
basic_block nbb = split_edge (non_eh_succ_edge
(gimple_bb (asgnck)));
(gimple_bb (asgnck), &ckeh));
gsi_split = gsi_start_bb (nbb);
if (dump_file)
@ -547,6 +551,27 @@ pass_harden_compares::execute (function *fun)
"Splitting non-EH edge from block %i into %i after"
" the newly-inserted reversed throwing compare\n",
gimple_bb (asgnck)->index, nbb->index);
if (!gimple_seq_empty_p (phi_nodes (ckeh->dest)))
{
edge aseh;
non_eh_succ_edge (gimple_bb (asgn), &aseh);
gcc_checking_assert (aseh->dest == ckeh->dest);
for (gphi_iterator psi = gsi_start_phis (ckeh->dest);
!gsi_end_p (psi); gsi_next (&psi))
{
gphi *phi = psi.phi ();
add_phi_arg (phi, PHI_ARG_DEF_FROM_EDGE (phi, aseh), ckeh,
gimple_phi_arg_location_from_edge (phi, aseh));
}
if (dump_file)
fprintf (dump_file,
"Copying PHI args in EH block %i from %i to %i\n",
aseh->dest->index, aseh->src->index, ckeh->src->index);
}
}
gcc_checking_assert (single_succ_p (gsi_bb (gsi_split)));

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-Og -fnon-call-exceptions -fsignaling-nans -fharden-compares" } */
struct S {
S(float);
S();
operator float();
~S() {}
};
int
main() {
S s_arr[] = {2};
S var1;
if (var1)
;
}