[PATCH] Fix PR90020

Richard Biener rguenther@suse.de
Tue Apr 9 15:05:00 GMT 2019


This fixes issues in GIMPLE and RTL code-hoisting which ignore
const/pure calls when determining whether it is safe to hoist
a possibly trapping memory reference across it.

The GIMPLE side of the fix handles this similar to regular
operations where we avoid hoisting possibly trapping ones
over a call that might not return.

The RTL side of the fix makes sure to not handle
RTL_LOOPING_CONST_OR_PURE_CALL_P like pure or const calls
but mark blocks with such calls in block_with_calls.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2019-04-09  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/90020
	* tree-ssa-sccvn.c (vn_reference_may_trap): New function.
	* tree-ssa-sccvn.h (vn_reference_may_trap): Declare.
	* tree-ssa-pre.c (compute_avail): Use it to not put
	possibly trapping references after a call that might not
	return into EXP_GEN.
	* gcse.c (compute_hash_table_work): Do not elide
	marking a block containing a call if the call might not
	return.

	* gcc.dg/torture/pr90020.c: New testcase.

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c	(revision 270223)
+++ gcc/tree-ssa-sccvn.c	(working copy)
@@ -4766,6 +4766,57 @@ vn_nary_may_trap (vn_nary_op_t nary)
   return false;
 }
 
+/* Return true if the reference operation REF may trap.  */
+
+bool
+vn_reference_may_trap (vn_reference_t ref)
+{
+  switch (ref->operands[0].opcode)
+    {
+    case MODIFY_EXPR:
+    case CALL_EXPR:
+      /* We do not handle calls.  */
+    case ADDR_EXPR:
+      /* And toplevel address computations never trap.  */
+      return false;
+    default:;
+    }
+
+  vn_reference_op_t op;
+  unsigned i;
+  FOR_EACH_VEC_ELT (ref->operands, i, op)
+    {
+      switch (op->opcode)
+	{
+	case WITH_SIZE_EXPR:
+	case TARGET_MEM_REF:
+	  /* Always variable.  */
+	  return true;
+	case COMPONENT_REF:
+	  if (op->op1 && TREE_CODE (op->op1) == SSA_NAME)
+	    return true;
+	  break;
+	case ARRAY_RANGE_REF:
+	case ARRAY_REF:
+	  if (TREE_CODE (op->op0) == SSA_NAME)
+	    return true;
+	  break;
+	case MEM_REF:
+	  /* Nothing interesting in itself, the base is separate.  */
+	  break;
+	/* The following are the address bases.  */
+	case SSA_NAME:
+	  return true;
+	case ADDR_EXPR:
+	  if (op->op0)
+	    return tree_could_trap_p (TREE_OPERAND (op->op0, 0));
+	  return false;
+	default:;
+	}
+    }
+  return false;
+}
+
 eliminate_dom_walker::eliminate_dom_walker (cdi_direction direction,
 					    bitmap inserted_exprs_)
   : dom_walker (direction), do_pre (inserted_exprs_ != NULL),
Index: gcc/tree-ssa-sccvn.h
===================================================================
--- gcc/tree-ssa-sccvn.h	(revision 270223)
+++ gcc/tree-ssa-sccvn.h	(working copy)
@@ -243,6 +243,7 @@ vn_reference_t vn_reference_insert_piece
 bool vn_nary_op_eq (const_vn_nary_op_t const vno1,
 		    const_vn_nary_op_t const vno2);
 bool vn_nary_may_trap (vn_nary_op_t);
+bool vn_reference_may_trap (vn_reference_t);
 bool vn_reference_eq (const_vn_reference_t const, const_vn_reference_t const);
 unsigned int get_max_value_id (void);
 unsigned int get_next_value_id (void);
Index: gcc/tree-ssa-pre.c
===================================================================
--- gcc/tree-ssa-pre.c	(revision 270223)
+++ gcc/tree-ssa-pre.c	(working copy)
@@ -3931,6 +3931,13 @@ compute_avail (void)
 			  continue;
 			}
 
+		      /* If the REFERENCE traps and there was a preceding
+		         point in the block that might not return avoid
+			 adding the reference to EXP_GEN.  */
+		      if (BB_MAY_NOTRETURN (block)
+			  && vn_reference_may_trap (ref))
+			continue;
+
 		      /* If the value of the reference is not invalidated in
 			 this block until it is computed, add the expression
 			 to EXP_GEN.  */
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c	(revision 270223)
+++ gcc/gcse.c	(working copy)
@@ -1532,7 +1532,8 @@ compute_hash_table_work (struct gcse_has
 					      0, regno, hrsi)
 		record_last_reg_set_info (insn, regno);
 
-	      if (! RTL_CONST_OR_PURE_CALL_P (insn))
+	      if (! RTL_CONST_OR_PURE_CALL_P (insn)
+		  || RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))
 		record_last_mem_set_info (insn);
 	    }
 
Index: gcc/testsuite/gcc.dg/torture/pr90020.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr90020.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr90020.c	(working copy)
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-require-weak "" } */
+
+void __attribute__((noinline,noclone))
+check (int i)
+{
+  if (i == 0)
+    __builtin_exit (0);
+}
+
+int i;
+extern int x __attribute__((weak));
+
+int main(int argc, char **argv)
+{
+  if (argc)
+    {
+      check (i);
+      return x;
+    }
+  else
+    {
+      check (i);
+      return x-1;
+    }
+  return 0;
+}



More information about the Gcc-patches mailing list