This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR85627 (and more)


The following fixes PR85627 and more generally complex lowering not
preserving EH information with -fnon-call-exceptions when replacing
complex multiplication or division with a libcall.

This requires changing BUILT_IN_COMPLEX_{MUL,DIV} to be no longer
declared nothrow - complex lowering (which looks like the only consumer)
properly will set the nothrow flag on the individual call based on
the context.

Test coverage of -fnon-call-exceptions is notoriously bad and I'm not
sure whether Ada uses GCCs complex types.  Eric?

Otherwise does this look sane?  I'm waiting for Kyrylos patch to come
in and then will refresh and re-test.

Bootstrap / regtest running on x86_64-unknown-linux-gnu.

Richard.

2018-05-03  Richard Biener  <rguenther@suse.de>

	PR middle-end/85627
	* tree-complex.c (update_complex_assignment): We are always in SSA form.
	(expand_complex_div_wide): Likewise.
	(expand_complex_operations_1): Likewise.
	(expand_complex_libcall): Preserve EH info of the original stmt.
	(tree_lower_complex): Handle removed blocks.
	* tree.c (build_common_builtin_nodes): Do not set ECF_NOTRHOW
	on complex multiplication and division libcall builtins.

	* g++.dg/torture/pr85627.C: New testcase.

Index: gcc/tree-complex.c
===================================================================
--- gcc/tree-complex.c	(revision 259879)
+++ gcc/tree-complex.c	(working copy)
@@ -703,8 +703,7 @@ update_complex_assignment (gimple_stmt_i
   if (maybe_clean_eh_stmt (stmt))
     gimple_purge_dead_eh_edges (gimple_bb (stmt));
 
-  if (gimple_in_ssa_p (cfun))
-    update_complex_components (gsi, gsi_stmt (*gsi), r, i);
+  update_complex_components (gsi, gsi_stmt (*gsi), r, i);
 }
 
 
@@ -1009,20 +1008,29 @@ expand_complex_libcall (gimple_stmt_iter
 
   stmt = gimple_build_call (fn, 4, ar, ai, br, bi);
   gimple_call_set_lhs (stmt, lhs);
+  gimple_call_set_nothrow (stmt, !stmt_could_throw_p (old_stmt));
   update_stmt (stmt);
-  gsi_replace (gsi, stmt, false);
+  gsi_replace (gsi, stmt, true);
 
-  if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
-    gimple_purge_dead_eh_edges (gsi_bb (*gsi));
-
-  if (gimple_in_ssa_p (cfun))
+  type = TREE_TYPE (type);
+  if (stmt_can_throw_internal (stmt))
     {
-      type = TREE_TYPE (type);
-      update_complex_components (gsi, stmt,
+      edge_iterator ei;
+      edge e;
+      FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
+	if (!(e->flags & EDGE_EH))
+	  break;
+      basic_block bb = split_edge (e);
+      gimple_stmt_iterator gsi2 = gsi_start_bb (bb);
+      update_complex_components (&gsi2, stmt,
 				 build1 (REALPART_EXPR, type, lhs),
 				 build1 (IMAGPART_EXPR, type, lhs));
-      SSA_NAME_DEF_STMT (lhs) = stmt;
     }
+  else
+    update_complex_components (gsi, stmt,
+			       build1 (REALPART_EXPR, type, lhs),
+			       build1 (IMAGPART_EXPR, type, lhs));
+  SSA_NAME_DEF_STMT (lhs) = stmt;
 }
 
 /* Expand complex multiplication to scalars:
@@ -1170,14 +1178,8 @@ expand_complex_div_wide (gimple_stmt_ite
       gimple *stmt;
       tree cond, tmp;
 
-      tmp = create_tmp_var (boolean_type_node);
+      tmp = make_ssa_name (boolean_type_node);
       stmt = gimple_build_assign (tmp, compare);
-      if (gimple_in_ssa_p (cfun))
-	{
-	  tmp = make_ssa_name (tmp, stmt);
-	  gimple_assign_set_lhs (stmt, tmp);
-	}
-
       gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
 
       cond = fold_build2_loc (gimple_location (stmt),
@@ -1602,25 +1604,20 @@ expand_complex_operations_1 (gimple_stmt
   else
     br = bi = NULL_TREE;
 
-  if (gimple_in_ssa_p (cfun))
+  al = find_lattice_value (ac);
+  if (al == UNINITIALIZED)
+    al = VARYING;
+
+  if (TREE_CODE_CLASS (code) == tcc_unary)
+    bl = UNINITIALIZED;
+  else if (ac == bc)
+    bl = al;
+  else
     {
-      al = find_lattice_value (ac);
-      if (al == UNINITIALIZED)
-	al = VARYING;
-
-      if (TREE_CODE_CLASS (code) == tcc_unary)
-	bl = UNINITIALIZED;
-      else if (ac == bc)
-	bl = al;
-      else
-	{
-	  bl = find_lattice_value (bc);
-	  if (bl == UNINITIALIZED)
-	    bl = VARYING;
-	}
+      bl = find_lattice_value (bc);
+      if (bl == UNINITIALIZED)
+	bl = VARYING;
     }
-  else
-    al = bl = VARYING;
 
   switch (code)
     {
@@ -1692,6 +1689,8 @@ tree_lower_complex (void)
   for (i = 0; i < n_bbs; i++)
     {
       bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
+      if (!bb)
+	continue;
       update_phi_components (bb);
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	expand_complex_operations_1 (&gsi);
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 259879)
+++ gcc/tree.c	(working copy)
@@ -10386,17 +10386,19 @@ build_common_builtin_nodes (void)
 	  *q = TOLOWER (*p);
 	*q = '\0';
 
+	/* For -ftrapping-math these should throw from a former
+	   -fnon-call-exception stmt.  */
 	built_in_names[mcode] = concat (prefix, "mul", mode_name_buf, "3",
 					NULL);
         local_define_builtin (built_in_names[mcode], ftype, mcode,
 			      built_in_names[mcode],
-			      ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+			      ECF_CONST | ECF_LEAF);
 
 	built_in_names[dcode] = concat (prefix, "div", mode_name_buf, "3",
 					NULL);
         local_define_builtin (built_in_names[dcode], ftype, dcode,
 			      built_in_names[dcode],
-			      ECF_CONST | ECF_NOTHROW | ECF_LEAF);
+			      ECF_CONST | ECF_LEAF);
       }
   }
 
Index: gcc/testsuite/g++.dg/torture/pr85627.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr85627.C	(nonexistent)
+++ gcc/testsuite/g++.dg/torture/pr85627.C	(working copy)
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+/* { dg-additional-options "-fnon-call-exceptions -fdump-tree-optimized" } */
+
+__complex double
+foo (__complex double a, __complex double b)
+{
+  __complex res = a;
+  try {
+      res = a * b;
+  }
+  catch (...) {
+      res = b;
+  }
+  return res;
+}
+
+__complex double
+bar (__complex double a, __complex double b)
+{
+  __complex res = a;
+  try {
+      res = a / b;
+  }
+  catch (...) {
+      res = b;
+  }
+  return res;
+}
+
+/* Verify EH is preserved by complex lowering.  */
+
+/* { dg-final { scan-tree-dump-times "__cxa_begin_catch" 2 "optimized" } } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]