diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2013-09-17 11:05:31 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2013-09-17 11:05:31 +0000 |
commit | 78bbd7655eb53cf2d0fcdf45f250a3b40e51f35a (patch) | |
tree | 219c5c5f83f0c8d87a806be3e5dd0643b4ad1ba8 | |
parent | 00c90ae1796a2cc6d9006d246e829793bc3cba0d (diff) | |
download | gcc-78bbd7655eb53cf2d0fcdf45f250a3b40e51f35a.zip gcc-78bbd7655eb53cf2d0fcdf45f250a3b40e51f35a.tar.gz gcc-78bbd7655eb53cf2d0fcdf45f250a3b40e51f35a.tar.bz2 |
tree-inline.h (struct copy_body_data): Add transform_parameter.
* 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
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt27.adb | 29 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt27_pkg.adb | 32 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt27_pkg.ads | 33 | ||||
-rw-r--r-- | gcc/tree-inline.c | 89 | ||||
-rw-r--r-- | gcc/tree-inline.h | 4 |
7 files changed, 172 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e63347b..44c7d66 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7b3c608..7ae7ea1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..be19800 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt27.adb @@ -0,0 +1,29 @@ +-- { dg-do run }
+-- { dg-options "-O" }
+
+with Opt27_Pkg;
+
+procedure Opt27 is
+
+ type Rec_T is record
+ A, B, C, D, E : Integer;
+ end record;
+
+ package List is new Opt27_Pkg (Rec_T);
+
+ My_List : List.List_T;
+
+ function Is_Match (Element : Rec_T; Template : Integer) return Boolean is
+ begin
+ return (Element.C = Template);
+ end;
+
+ function Find_Int is new List.Find_Elem (Integer, Is_Match);
+
+ Node : List.Node_T := Find_Int (10, My_List);
+
+begin
+ if not List.Is_Null (Node) then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt27_pkg.adb b/gcc/testsuite/gnat.dg/opt27_pkg.adb new file mode 100644 index 0000000..17ffb73 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt27_pkg.adb @@ -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 index 0000000..01b3a90 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt27_pkg.ads @@ -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; diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index ebfd34c..ebb4b91 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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 diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index 620ec97..a78e4b6 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -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; |