[PATCH] Fix PR38819, PREing of trapping expressions

Richard Guenther rguenther@suse.de
Fri Jan 16 23:56:00 GMT 2009


This tries to fix PREing of trapping expressions to a place where
they could be executed when they are not necessarily executed in
their original place.  I didn't try to cleverly find out if they
are always executed on the path to the original location but instead
only tried to preserve that phi-translation could make them
non-trapping or that they could be available on all paths.

Any more obvious improvements possible?  Can someone SPEC-test this
for me?

Bootstrapped and tested on x86_64-unknown-linux-gnu, Danny, does this
look ok?

Thanks,
Richard.

2009-01-16  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/38819
	* tree-flow.h (operation_could_trap_helper_p): Declare.
	* tree-eh.c (operation_could_trap_helper_p): Export.
	* tree-ssa-pre.c (insert_into_preds_of_block): Check if we
	are about to insert a possibly trapping instruction and fail
	in this case.

Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h	(revision 143442)
--- gcc/tree-flow.h	(working copy)
*************** static inline bool unmodifiable_var_p (c
*** 1071,1076 ****
--- 1071,1078 ----
  /* In tree-eh.c  */
  extern void make_eh_edges (gimple);
  extern bool tree_could_trap_p (tree);
+ extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
+ 					   bool, tree, bool *);
  extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
  extern bool stmt_could_throw_p (gimple);
  extern bool tree_could_throw_p (tree);
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c	(revision 143442)
--- gcc/tree-eh.c	(working copy)
*************** verify_eh_edges (gimple stmt)
*** 2067,2073 ****
  
  /* Helper function for operation_could_trap_p and stmt_could_throw_p.  */
  
! static bool
  operation_could_trap_helper_p (enum tree_code op,
  			       bool fp_operation,
  			       bool honor_trapv,
--- 2067,2073 ----
  
  /* Helper function for operation_could_trap_p and stmt_could_throw_p.  */
  
! bool
  operation_could_trap_helper_p (enum tree_code op,
  			       bool fp_operation,
  			       bool honor_trapv,
Index: gcc/testsuite/gcc.c-torture/execute/pr38819.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr38819.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr38819.c	(revision 0)
***************
*** 0 ****
--- 1,29 ----
+ extern void exit (int);
+ extern void abort (void);
+ 
+ volatile int a = 1;
+ volatile int b = 0;
+ volatile int x = 2;
+ volatile signed int r = 8;
+ 
+ void __attribute__((noinline))
+ foo (void)
+ {
+   exit (0);
+ }
+ 
+ int
+ main (void)
+ {
+   int si1 = a;
+   int si2 = b;
+   int i;
+ 
+   for (i = 0; i < 100; ++i) {
+       foo ();
+       if (x == 8)
+ 	i++;
+       r += i + si1 % si2;
+   }
+   abort ();
+ }
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c	(revision 143442)
--- gcc/tree-ssa-pre.c	(working copy)
*************** insert_into_preds_of_block (basic_block 
*** 3004,3009 ****
--- 3004,3059 ----
  	}
      }
  
+   /* Make sure we are not inserting trapping expressions.  This is a copy
+      of stmt_could_throw_1_p adjusted to the SCCVN IL.  */
+   FOR_EACH_EDGE (pred, ei, block->preds)
+     {
+       vn_nary_op_t nary;
+       tree type;
+       tree rhs2;
+       bool honor_nans = false;
+       bool honor_snans = false;
+       bool fp_operation = false;
+       bool honor_trapv = false;
+       bool handled, ret;
+       unsigned i;
+ 
+       bprime = pred->src;
+       eprime = avail[bprime->index];
+       if (eprime->kind == NAME
+ 	  || eprime->kind == CONSTANT
+ 	  || eprime->kind == REFERENCE)
+ 	continue;
+ 
+       nary = PRE_EXPR_NARY (eprime);
+       if (TREE_CODE_CLASS (nary->opcode) == tcc_comparison
+ 	  || TREE_CODE_CLASS (nary->opcode) == tcc_unary
+ 	  || TREE_CODE_CLASS (nary->opcode) == tcc_binary)
+ 	{
+ 	  type = nary->type;
+ 	  fp_operation = FLOAT_TYPE_P (type);
+ 	  if (fp_operation)
+ 	    {
+ 	      honor_nans = flag_trapping_math && !flag_finite_math_only;
+ 	      honor_snans = flag_signaling_nans != 0;
+ 	    }
+ 	  else if (INTEGRAL_TYPE_P (type)
+ 		   && TYPE_OVERFLOW_TRAPS (type))
+ 	    honor_trapv = true;
+ 	}
+       rhs2 = nary->op[1];
+       ret = operation_could_trap_helper_p (nary->opcode, fp_operation,
+ 					   honor_trapv,
+ 					   honor_nans, honor_snans, rhs2,
+ 					   &handled);
+       if (handled
+ 	  && ret)
+ 	return false;
+ 
+       for (i = 0; i < nary->length; ++i)
+ 	if (tree_could_trap_p (nary->op[i]))
+ 	  return false;
+     }
  
    /* Make the necessary insertions.  */
    FOR_EACH_EDGE (pred, ei, block->preds)



More information about the Gcc-patches mailing list