Patchwork couple of small optimization tweaks

login
register
mail settings
Submitter Eric Botcazou
Date Sept. 24, 2011, 4:41 p.m.
Message ID <201109241841.53569.ebotcazou@adacore.com>
Download mbox | patch
Permalink /patch/116229/
State New
Headers show

Comments

Eric Botcazou - Sept. 24, 2011, 4:41 p.m.
Hi,

this is a couple of small tweaks to the GIMPLE optimizers aimed at helping 
vectorization in Ada.  More changes will be needed, so no testcases yet.


  1. pass_fold_builtins knows how to delete a call to __builtin_stack_restore 
that is the only real statement in a cleanup, i.e. to turn

<L101>:
  .builtin_stack_restore (saved_stack.116_22);
  resx 1

into

<L101>:
  GIMPLE_NOP
  resx 1

This is valid when the block has no outgoing edge.  Then ehcleanup can in turn 
delete the cleanup as empty.  The problem is that pass_fold_builtins runs very 
late in the game, so most of the optimizations, e.g. vectorization, are 
constrained by the EH structure, all the more so if -fnon-call-exceptions is 
enabled like in Ada.  This happens as soon as you do dynamic stack allocation, 
because then you have a call to __builtin_stack_restore in the FINALLY part of 
a TRY-FINALLY structure, hence the cleanup.

The first change enhances ehcleanup so as to remove this kind of cleanups on 
its own, without the need to wait for pass_fold_builtins.


  2. The introduction of MEM_REF has disabled vectorization for parameters 
passed by reference in Ada.  This used to work because dr_analyze_innermost 
was always building a pointer via build_fold_addr_expr; now, if the base is a 
MEM_REF, it can just take the first operand, which is a reference and not a 
pointer for a parameter passed by reference in Ada.  And simple_iv, unlike 
other functions in tree-scalar-evolution.c, accepts only pointer types:

  type = TREE_TYPE (op);
  if (TREE_CODE (type) != INTEGER_TYPE
      && TREE_CODE (type) != POINTER_TYPE)
    return false;

The second change makes simple_iv use the same test as the other functions in 
tree-scalar-evolution.c.


Bootstrapped/regtested on x86_64-suse-linux, OK for mainline?


2011-09-24  Eric Botcazou  <ebotcazou@adacore.com>

	* tree-eh.c (is_gimple_stack_restore): New predicate.
	(cleanup_empty_eh): Allow a call to __builtin_stack_restore if there
	is no outgoing edge.

	* tree-scalar-evolution.c (simple_iv): Accept all pointer and integral
	types.
Richard Guenther - Sept. 25, 2011, 8:27 a.m.
On Sat, Sep 24, 2011 at 6:41 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> Hi,
>
> this is a couple of small tweaks to the GIMPLE optimizers aimed at helping
> vectorization in Ada.  More changes will be needed, so no testcases yet.
>
>
>  1. pass_fold_builtins knows how to delete a call to __builtin_stack_restore
> that is the only real statement in a cleanup, i.e. to turn
>
> <L101>:
>  .builtin_stack_restore (saved_stack.116_22);
>  resx 1
>
> into
>
> <L101>:
>  GIMPLE_NOP
>  resx 1
>
> This is valid when the block has no outgoing edge.  Then ehcleanup can in turn
> delete the cleanup as empty.  The problem is that pass_fold_builtins runs very
> late in the game, so most of the optimizations, e.g. vectorization, are
> constrained by the EH structure, all the more so if -fnon-call-exceptions is
> enabled like in Ada.  This happens as soon as you do dynamic stack allocation,
> because then you have a call to __builtin_stack_restore in the FINALLY part of
> a TRY-FINALLY structure, hence the cleanup.
>
> The first change enhances ehcleanup so as to remove this kind of cleanups on
> its own, without the need to wait for pass_fold_builtins.
>
>
>  2. The introduction of MEM_REF has disabled vectorization for parameters
> passed by reference in Ada.  This used to work because dr_analyze_innermost
> was always building a pointer via build_fold_addr_expr; now, if the base is a
> MEM_REF, it can just take the first operand, which is a reference and not a
> pointer for a parameter passed by reference in Ada.  And simple_iv, unlike
> other functions in tree-scalar-evolution.c, accepts only pointer types:
>
>  type = TREE_TYPE (op);
>  if (TREE_CODE (type) != INTEGER_TYPE
>      && TREE_CODE (type) != POINTER_TYPE)
>    return false;
>
> The second change makes simple_iv use the same test as the other functions in
> tree-scalar-evolution.c.
>
>
> Bootstrapped/regtested on x86_64-suse-linux, OK for mainline?

Use gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE) instead
of re-inventing it with is_gimple_stack_restore.

Otherwise ok.

Thanks,
Richard.

>
>
> 2011-09-24  Eric Botcazou  <ebotcazou@adacore.com>
>
>        * tree-eh.c (is_gimple_stack_restore): New predicate.
>        (cleanup_empty_eh): Allow a call to __builtin_stack_restore if there
>        is no outgoing edge.
>
>        * tree-scalar-evolution.c (simple_iv): Accept all pointer and integral
>        types.
>
>
> --
> Eric Botcazou
>

Patch

Index: tree-eh.c
===================================================================
--- tree-eh.c	(revision 179038)
+++ tree-eh.c	(working copy)
@@ -3818,6 +3818,26 @@  infinite_empty_loop_p (edge e_first)
   return inf_loop;
 }
 
+/* Return true if STMT is a call to __builtin_stack_restore.  */
+
+static bool
+is_gimple_stack_restore (gimple stmt)
+{
+  tree callee;
+
+  if (gimple_code (stmt) != GIMPLE_CALL)
+    return false;
+
+  callee = gimple_call_fndecl (stmt);
+
+  if (callee
+      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
+      && DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE)
+    return true;
+
+  return false;
+}
+
 /* Examine the block associated with LP to determine if it's an empty
    handler for its EH region.  If so, attempt to redirect EH edges to
    an outer region.  Return true the CFG was updated in any way.  This
@@ -3863,8 +3883,15 @@  cleanup_empty_eh (eh_landing_pad lp)
       return cleanup_empty_eh_unsplit (bb, e_out, lp);
     }
 
-  /* The block should consist only of a single RESX statement.  */
+  /* The block should consist only of a single RESX statement, modulo a
+     preceding call to __builtin_stack_restore if there is no outgoing
+     edge, since the call can be eliminated in this case.  */
   resx = gsi_stmt (gsi);
+  if (!e_out && is_gimple_stack_restore (resx))
+    {
+      gsi_next (&gsi);
+      resx = gsi_stmt (gsi);
+    }
   if (!is_gimple_resx (resx))
     return false;
   gcc_assert (gsi_one_before_end_p (gsi));
Index: tree-scalar-evolution.c
===================================================================
--- tree-scalar-evolution.c	(revision 179038)
+++ tree-scalar-evolution.c	(working copy)
@@ -3172,8 +3172,8 @@  simple_iv (struct loop *wrto_loop, struc
   iv->no_overflow = false;
 
   type = TREE_TYPE (op);
-  if (TREE_CODE (type) != INTEGER_TYPE
-      && TREE_CODE (type) != POINTER_TYPE)
+  if (!POINTER_TYPE_P (type)
+      && !INTEGRAL_TYPE_P (type))
     return false;
 
   ev = analyze_scalar_evolution_in_loop (wrto_loop, use_loop, op,