Copy EH phi args for throwing hardened compares

Alexandre Oliva oliva@adacore.com
Wed Feb 23 22:43:34 GMT 2022


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.

Regstrapped on x86_64-linux-gnu.  Ok to install?


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.
---
 gcc/gimple-harden-conditionals.cc |   31 ++++++++++++++++++++++++++++---
 gcc/testsuite/g++.dg/pr103856.C   |   17 +++++++++++++++++
 2 files changed, 45 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pr103856.C

diff --git a/gcc/gimple-harden-conditionals.cc b/gcc/gimple-harden-conditionals.cc
index 9418194cb20c2..6a5fc3fb9e1a2 100644
--- a/gcc/gimple-harden-conditionals.cc
+++ b/gcc/gimple-harden-conditionals.cc
@@ -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)));
diff --git a/gcc/testsuite/g++.dg/pr103856.C b/gcc/testsuite/g++.dg/pr103856.C
new file mode 100644
index 0000000000000..26c7d8750255a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103856.C
@@ -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)
+    ;
+}


-- 
Alexandre Oliva, happy hacker                https://FSFLA.org/blogs/lxo/
   Free Software Activist                       GNU Toolchain Engineer
Disinformation flourishes because many people care deeply about injustice
but very few check the facts.  Ask me about <https://stallmansupport.org>


More information about the Gcc-patches mailing list