]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-inline.h (struct copy_body_data): Add transform_parameter.
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 17 Sep 2013 11:05:31 +0000 (11:05 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 17 Sep 2013 11:05:31 +0000 (11:05 +0000)
* tree-inline.h (struct copy_body_data): Add transform_parameter.
* tree-inline.c (is_parameter_of): New predicate.
(remap_gimple_op_r): Do not propagate TREE_THIS_NOTRAP on MEM_REF if
a parameter has been remapped.
(copy_tree_body_r): Likewise on INDIRECT_REF and MEM_REF.
(optimize_inline_calls): Initialize transform_parameter.
(copy_gimple_seq_and_replace_locals): Likewise.
(tree_function_versioning): Likewise.
(maybe_inline_call_in_expr): Likewise.

From-SVN: r202647

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt27.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt27_pkg.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt27_pkg.ads [new file with mode: 0644]
gcc/tree-inline.c
gcc/tree-inline.h

index e63347b2497792b0e9670f3fcb21f9135dae1a09..44c7d66134a5275b8e59c4193d48744389393276 100644 (file)
@@ -1,3 +1,15 @@
+2013-09-17  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * tree-inline.h (struct copy_body_data): Add transform_parameter.
+       * tree-inline.c (is_parameter_of): New predicate.
+       (remap_gimple_op_r): Do not propagate TREE_THIS_NOTRAP on MEM_REF if
+       a parameter has been remapped.
+       (copy_tree_body_r): Likewise on INDIRECT_REF and MEM_REF.
+       (optimize_inline_calls): Initialize transform_parameter.
+       (copy_gimple_seq_and_replace_locals): Likewise.
+       (tree_function_versioning): Likewise.
+       (maybe_inline_call_in_expr): Likewise.
+
 2013-09-17  Nick Clifton  <nickc@redhat.com>
 
        * config/msp430/msp430-protos.h: Add prototypes for new functions.
index 7b3c608c26501e1275b8167e36afa11fea6c6d7f..7ae7ea1eddb430ae6b3f7ab21ab223deb1d701e1 100644 (file)
@@ -1,3 +1,8 @@
+2013-09-17  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt27.adb: New test.
+       * gnat.dg/opt27_pkg.ad[sb]: New helper.
+
 2013-09-17  Andreas Schwab  <schwab@suse.de>
 
        * gcc.dg/tree-ssa/ldist-22.c (main): Return zero.
diff --git a/gcc/testsuite/gnat.dg/opt27.adb b/gcc/testsuite/gnat.dg/opt27.adb
new file mode 100644 (file)
index 0000000..be19800
--- /dev/null
@@ -0,0 +1,29 @@
+-- { dg-do run }\r
+-- { dg-options "-O" }\r
+\r
+with Opt27_Pkg;\r
+\r
+procedure Opt27 is\r
+\r
+    type Rec_T is record\r
+        A, B, C, D, E : Integer;\r
+    end record;\r
+\r
+    package List is new Opt27_Pkg (Rec_T);\r
+\r
+    My_List : List.List_T;\r
+\r
+    function Is_Match (Element : Rec_T; Template : Integer) return Boolean is\r
+    begin\r
+        return (Element.C = Template);\r
+    end;\r
+\r
+    function Find_Int is new List.Find_Elem (Integer, Is_Match);\r
+\r
+    Node : List.Node_T := Find_Int (10, My_List);\r
+\r
+begin\r
+    if not List.Is_Null (Node) then\r
+        raise Program_Error;\r
+    end if;\r
+end;\r
diff --git a/gcc/testsuite/gnat.dg/opt27_pkg.adb b/gcc/testsuite/gnat.dg/opt27_pkg.adb
new file mode 100644 (file)
index 0000000..17ffb73
--- /dev/null
@@ -0,0 +1,32 @@
+package body Opt27_Pkg is
+
+    type Node_Rec_T is record
+         Element : Element_T;
+         Left : Node_T;
+         Right : Node_T;
+    end record;
+
+    function Is_Null (Node : in Node_T) return Boolean is
+    begin
+        return (Node = null);
+    end Is_Null;
+
+    function Find_Elem (Template : Template_T; List : List_T) return Node_T is
+        Element_Found : Boolean := False;
+        Node_Walker : Node_T := null;
+    begin
+        Node_Walker := List.First_Node;
+
+        while not Element_Found and (Node_Walker /= null) loop
+
+            if Is_Match (Node_Walker.Element, Template) then
+                Element_Found := True;
+            else
+                Node_Walker := Node_Walker.Right;
+            end if;
+        end loop;
+
+        return Node_Walker;
+    end;
+
+end Opt27_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt27_pkg.ads b/gcc/testsuite/gnat.dg/opt27_pkg.ads
new file mode 100644 (file)
index 0000000..01b3a90
--- /dev/null
@@ -0,0 +1,33 @@
+generic
+
+    type Element_T is private;
+
+package Opt27_Pkg is
+
+    type Node_T is private;
+
+    type List_T is private;
+
+    function Is_Null (Node : in Node_T) return Boolean;
+
+    generic
+
+        type Template_T is private;
+
+        with function Is_Match
+                         (Element : in Element_T;
+                          Template : in Template_T) return Boolean is <>;
+
+    function Find_Elem (Template : Template_T; List : List_T) return Node_T;
+
+private
+
+    type Node_Rec_T;
+    type Node_T is access Node_Rec_T;
+
+    type List_T is record
+        First_Node : Node_T := null;
+        Last_Node : Node_T := null;
+    end record;
+
+end Opt27_Pkg;
index ebfd34c6dcd5aa6a47834a3c748556f31b8720ad..ebb4b9188133c73a46ceb5bd8eb33f24da50eb98 100644 (file)
@@ -751,6 +751,20 @@ copy_gimple_bind (gimple stmt, copy_body_data *id)
   return new_bind;
 }
 
+/* Return true if DECL is a parameter or a SSA_NAME for a parameter.  */
+
+static bool
+is_parm (tree decl)
+{
+  if (TREE_CODE (decl) == SSA_NAME)
+    {
+      decl = SSA_NAME_VAR (decl);
+      if (!decl)
+       return false;
+    }
+
+  return (TREE_CODE (decl) == PARM_DECL);
+}
 
 /* Remap the GIMPLE operand pointed to by *TP.  DATA is really a
    'struct walk_stmt_info *'.  DATA->INFO is a 'copy_body_data *'.
@@ -840,20 +854,24 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
 
       if (TREE_CODE (*tp) == MEM_REF)
        {
-         tree ptr = TREE_OPERAND (*tp, 0);
-         tree type = remap_type (TREE_TYPE (*tp), id);
-         tree old = *tp;
-
          /* We need to re-canonicalize MEM_REFs from inline substitutions
             that can happen when a pointer argument is an ADDR_EXPR.
             Recurse here manually to allow that.  */
+         tree ptr = TREE_OPERAND (*tp, 0);
+         tree type = remap_type (TREE_TYPE (*tp), id);
+         tree old = *tp;
          walk_tree (&ptr, remap_gimple_op_r, data, NULL);
-         *tp = fold_build2 (MEM_REF, type,
-                            ptr, TREE_OPERAND (*tp, 1));
-         TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old);
+         *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1));
          TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
          TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
          TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+         /* We cannot propagate the TREE_THIS_NOTRAP flag if we have
+            remapped a parameter as the property might be valid only
+            for the parameter itself.  */
+         if (TREE_THIS_NOTRAP (old)
+             && (!is_parm (TREE_OPERAND (old, 0))
+                 || (!id->transform_parameter && is_parm (ptr))))
+           TREE_THIS_NOTRAP (*tp) = 1;
          *walk_subtrees = 0;
          return NULL;
        }
@@ -1043,45 +1061,44 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
          /* Get rid of *& from inline substitutions that can happen when a
             pointer argument is an ADDR_EXPR.  */
          tree decl = TREE_OPERAND (*tp, 0);
-         tree *n;
-
-         n = (tree *) pointer_map_contains (id->decl_map, decl);
+         tree *n = (tree *) pointer_map_contains (id->decl_map, decl);
          if (n)
            {
-             tree new_tree;
-             tree old;
              /* If we happen to get an ADDR_EXPR in n->value, strip
                 it manually here as we'll eventually get ADDR_EXPRs
                 which lie about their types pointed to.  In this case
                 build_fold_indirect_ref wouldn't strip the INDIRECT_REF,
                 but we absolutely rely on that.  As fold_indirect_ref
                 does other useful transformations, try that first, though.  */
-             tree type = TREE_TYPE (TREE_TYPE (*n));
-             if (id->do_not_unshare)
-               new_tree = *n;
-             else
-               new_tree = unshare_expr (*n);
-             old = *tp;
-             *tp = gimple_fold_indirect_ref (new_tree);
+             tree type = TREE_TYPE (*tp);
+             tree ptr = id->do_not_unshare ? *n : unshare_expr (*n);
+             tree old = *tp;
+             *tp = gimple_fold_indirect_ref (ptr);
              if (! *tp)
                {
-                 if (TREE_CODE (new_tree) == ADDR_EXPR)
+                 if (TREE_CODE (ptr) == ADDR_EXPR)
                    {
-                     *tp = fold_indirect_ref_1 (EXPR_LOCATION (new_tree),
-                                                type, new_tree);
+                     *tp
+                       = fold_indirect_ref_1 (EXPR_LOCATION (ptr), type, ptr);
                      /* ???  We should either assert here or build
                         a VIEW_CONVERT_EXPR instead of blindly leaking
                         incompatible types to our IL.  */
                      if (! *tp)
-                       *tp = TREE_OPERAND (new_tree, 0);
+                       *tp = TREE_OPERAND (ptr, 0);
                    }
                  else
                    {
-                     *tp = build1 (INDIRECT_REF, type, new_tree);
+                     *tp = build1 (INDIRECT_REF, type, ptr);
                      TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
                      TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
                      TREE_READONLY (*tp) = TREE_READONLY (old);
-                     TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old);
+                     /* We cannot propagate the TREE_THIS_NOTRAP flag if we
+                        have remapped a parameter as the property might be
+                        valid only for the parameter itself.  */
+                     if (TREE_THIS_NOTRAP (old)
+                         && (!is_parm (TREE_OPERAND (old, 0))
+                             || (!id->transform_parameter && is_parm (ptr))))
+                       TREE_THIS_NOTRAP (*tp) = 1;
                    }
                }
              *walk_subtrees = 0;
@@ -1090,20 +1107,24 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
        }
       else if (TREE_CODE (*tp) == MEM_REF)
        {
-         tree ptr = TREE_OPERAND (*tp, 0);
-         tree type = remap_type (TREE_TYPE (*tp), id);
-         tree old = *tp;
-
          /* We need to re-canonicalize MEM_REFs from inline substitutions
             that can happen when a pointer argument is an ADDR_EXPR.
             Recurse here manually to allow that.  */
+         tree ptr = TREE_OPERAND (*tp, 0);
+         tree type = remap_type (TREE_TYPE (*tp), id);
+         tree old = *tp;
          walk_tree (&ptr, copy_tree_body_r, data, NULL);
-         *tp = fold_build2 (MEM_REF, type,
-                            ptr, TREE_OPERAND (*tp, 1));
-         TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old);
+         *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1));
          TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
          TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
          TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+         /* We cannot propagate the TREE_THIS_NOTRAP flag if we have
+            remapped a parameter as the property might be valid only
+            for the parameter itself.  */
+         if (TREE_THIS_NOTRAP (old)
+             && (!is_parm (TREE_OPERAND (old, 0))
+                 || (!id->transform_parameter && is_parm (ptr))))
+           TREE_THIS_NOTRAP (*tp) = 1;
          *walk_subtrees = 0;
          return NULL;
        }
@@ -4452,6 +4473,7 @@ optimize_inline_calls (tree fn)
   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
   id.transform_new_cfg = false;
   id.transform_return_to_modify = true;
+  id.transform_parameter = true;
   id.transform_lang_insert_block = NULL;
   id.statements_to_fold = pointer_set_create ();
 
@@ -4757,6 +4779,7 @@ copy_gimple_seq_and_replace_locals (gimple_seq seq)
   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
   id.transform_new_cfg = false;
   id.transform_return_to_modify = false;
+  id.transform_parameter = false;
   id.transform_lang_insert_block = NULL;
 
   /* Walk the tree once to find local labels.  */
@@ -5216,6 +5239,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
     = update_clones ? CB_CGE_MOVE_CLONES : CB_CGE_MOVE;
   id.transform_new_cfg = true;
   id.transform_return_to_modify = false;
+  id.transform_parameter = false;
   id.transform_lang_insert_block = NULL;
 
   old_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION
@@ -5440,6 +5464,7 @@ maybe_inline_call_in_expr (tree exp)
       id.transform_call_graph_edges = CB_CGE_DUPLICATE;
       id.transform_new_cfg = false;
       id.transform_return_to_modify = true;
+      id.transform_parameter = true;
       id.transform_lang_insert_block = NULL;
 
       /* Make sure not to unshare trees behind the front-end's back
index 620ec9777685474a88433325aed61f93add8ae6c..a78e4b69f0efdf4d1f50838f42162fd3e7630a32 100644 (file)
@@ -97,6 +97,10 @@ typedef struct copy_body_data
      by manipulating the CFG rather than a statement.  */
   bool transform_return_to_modify;
 
+  /* True if the parameters of the source function are transformed.
+     Only true for inlining.  */
+  bool transform_parameter;
+
   /* True if this statement will need to be regimplified.  */
   bool regimplify;