68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1 /* Function splitting pass
|
111
|
2 Copyright (C) 2010-2017 Free Software Foundation, Inc.
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
3 Contributed by Jan Hubicka <jh@suse.cz>
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
4
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
5 This file is part of GCC.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 GCC is free software; you can redistribute it and/or modify it under
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8 the terms of the GNU General Public License as published by the Free
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9 Software Foundation; either version 3, or (at your option) any later
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
10 version.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15 for more details.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
16
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
17 You should have received a copy of the GNU General Public License
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 along with GCC; see the file COPYING3. If not see
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
19 <http://www.gnu.org/licenses/>. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
20
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
21 /* The purpose of this pass is to split function bodies to improve
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
22 inlining. I.e. for function of the form:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
23
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
24 func (...)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
25 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
26 if (cheap_test)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
27 something_small
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
28 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
29 something_big
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
30 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
31
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
32 Produce:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
33
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
34 func.part (...)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
35 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
36 something_big
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
37 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
38
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
39 func (...)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
40 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
41 if (cheap_test)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
42 something_small
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
43 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
44 func.part (...);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
45 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
46
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
47 When func becomes inlinable and when cheap_test is often true, inlining func,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
48 but not fund.part leads to performance improvement similar as inlining
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
49 original func while the code size growth is smaller.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
50
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
51 The pass is organized in three stages:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
52 1) Collect local info about basic block into BB_INFO structure and
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
53 compute function body estimated size and time.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
54 2) Via DFS walk find all possible basic blocks where we can split
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
55 and chose best one.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
56 3) If split point is found, split at the specified BB by creating a clone
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
57 and updating function to call it.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
58
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
59 The decisions what functions to split are in execute_split_functions
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
60 and consider_split.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
61
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
62 There are several possible future improvements for this pass including:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
63
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
64 1) Splitting to break up large functions
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
65 2) Splitting to reduce stack frame usage
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
66 3) Allow split part of function to use values computed in the header part.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
67 The values needs to be passed to split function, perhaps via same
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
68 interface as for nested functions or as argument.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
69 4) Support for simple rematerialization. I.e. when split part use
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
70 value computed in header from function parameter in very cheap way, we
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
71 can just recompute it.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
72 5) Support splitting of nested functions.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
73 6) Support non-SSA arguments.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
74 7) There is nothing preventing us from producing multiple parts of single function
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
75 when needed or splitting also the parts. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
76
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
77 #include "config.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
78 #include "system.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
79 #include "coretypes.h"
|
111
|
80 #include "backend.h"
|
|
81 #include "rtl.h"
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
82 #include "tree.h"
|
111
|
83 #include "gimple.h"
|
|
84 #include "cfghooks.h"
|
|
85 #include "alloc-pool.h"
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
86 #include "tree-pass.h"
|
111
|
87 #include "ssa.h"
|
|
88 #include "cgraph.h"
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
89 #include "diagnostic.h"
|
111
|
90 #include "fold-const.h"
|
|
91 #include "cfganal.h"
|
|
92 #include "calls.h"
|
|
93 #include "gimplify.h"
|
|
94 #include "gimple-iterator.h"
|
|
95 #include "gimplify-me.h"
|
|
96 #include "gimple-walk.h"
|
|
97 #include "symbol-summary.h"
|
|
98 #include "ipa-prop.h"
|
|
99 #include "tree-cfg.h"
|
|
100 #include "tree-into-ssa.h"
|
|
101 #include "tree-dfa.h"
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
102 #include "tree-inline.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
103 #include "params.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
104 #include "gimple-pretty-print.h"
|
111
|
105 #include "ipa-fnsummary.h"
|
|
106 #include "cfgloop.h"
|
|
107 #include "tree-chkp.h"
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
108
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
109 /* Per basic block info. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
110
|
111
|
111 struct split_bb_info
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
112 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
113 unsigned int size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
114 unsigned int time;
|
111
|
115 };
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
116
|
111
|
117 static vec<split_bb_info> bb_info_vec;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
118
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
119 /* Description of split point. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
120
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
121 struct split_point
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
122 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
123 /* Size of the partitions. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
124 unsigned int header_time, header_size, split_time, split_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
125
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
126 /* SSA names that need to be passed into spit function. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
127 bitmap ssa_names_to_pass;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
128
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
129 /* Basic block where we split (that will become entry point of new function. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
130 basic_block entry_bb;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
131
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
132 /* Basic blocks we are splitting away. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
133 bitmap split_bbs;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
134
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
135 /* True when return value is computed on split part and thus it needs
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
136 to be returned. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
137 bool split_part_set_retval;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
138 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
139
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
140 /* Best split point found. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
141
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
142 struct split_point best_split_point;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
143
|
111
|
144 /* Set of basic blocks that are not allowed to dominate a split point. */
|
|
145
|
|
146 static bitmap forbidden_dominators;
|
|
147
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
148 static tree find_retval (basic_block return_bb);
|
111
|
149 static tree find_retbnd (basic_block return_bb);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
150
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
151 /* Callback for walk_stmt_load_store_addr_ops. If T is non-SSA automatic
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
152 variable, check it if it is present in bitmap passed via DATA. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
153
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
154 static bool
|
111
|
155 test_nonssa_use (gimple *, tree t, tree, void *data)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
156 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
157 t = get_base_address (t);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
158
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
159 if (!t || is_gimple_reg (t))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
160 return false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
161
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
162 if (TREE_CODE (t) == PARM_DECL
|
111
|
163 || (VAR_P (t)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
164 && auto_var_in_fn_p (t, current_function_decl))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
165 || TREE_CODE (t) == RESULT_DECL
|
111
|
166 /* Normal labels are part of CFG and will be handled gratefuly.
|
|
167 Forced labels however can be used directly by statements and
|
|
168 need to stay in one partition along with their uses. */
|
|
169 || (TREE_CODE (t) == LABEL_DECL
|
|
170 && FORCED_LABEL (t)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
171 return bitmap_bit_p ((bitmap)data, DECL_UID (t));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
172
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
173 /* For DECL_BY_REFERENCE, the return value is actually a pointer. We want
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
174 to pretend that the value pointed to is actual result decl. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
175 if ((TREE_CODE (t) == MEM_REF || INDIRECT_REF_P (t))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
176 && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
|
111
|
177 && SSA_NAME_VAR (TREE_OPERAND (t, 0))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
178 && TREE_CODE (SSA_NAME_VAR (TREE_OPERAND (t, 0))) == RESULT_DECL
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
179 && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
180 return
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
181 bitmap_bit_p ((bitmap)data,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
182 DECL_UID (DECL_RESULT (current_function_decl)));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
183
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
184 return false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
185 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
186
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
187 /* Dump split point CURRENT. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
188
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
189 static void
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
190 dump_split_point (FILE * file, struct split_point *current)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
191 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
192 fprintf (file,
|
111
|
193 "Split point at BB %i\n"
|
|
194 " header time: %i header size: %i\n"
|
|
195 " split time: %i split size: %i\n bbs: ",
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
196 current->entry_bb->index, current->header_time,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
197 current->header_size, current->split_time, current->split_size);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
198 dump_bitmap (file, current->split_bbs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
199 fprintf (file, " SSA names to pass: ");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
200 dump_bitmap (file, current->ssa_names_to_pass);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
201 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
202
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
203 /* Look for all BBs in header that might lead to the split part and verify
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
204 that they are not defining any non-SSA var used by the split part.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
205 Parameters are the same as for consider_split. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
206
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
207 static bool
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
208 verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
209 basic_block return_bb)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
210 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
211 bitmap seen = BITMAP_ALLOC (NULL);
|
111
|
212 vec<basic_block> worklist = vNULL;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
213 edge e;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
214 edge_iterator ei;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
215 bool ok = true;
|
111
|
216 basic_block bb;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
217
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
218 FOR_EACH_EDGE (e, ei, current->entry_bb->preds)
|
111
|
219 if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
220 && !bitmap_bit_p (current->split_bbs, e->src->index))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
221 {
|
111
|
222 worklist.safe_push (e->src);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
223 bitmap_set_bit (seen, e->src->index);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
224 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
225
|
111
|
226 while (!worklist.is_empty ())
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
227 {
|
111
|
228 bb = worklist.pop ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
229 FOR_EACH_EDGE (e, ei, bb->preds)
|
111
|
230 if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
231 && bitmap_set_bit (seen, e->src->index))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
232 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
233 gcc_checking_assert (!bitmap_bit_p (current->split_bbs,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
234 e->src->index));
|
111
|
235 worklist.safe_push (e->src);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
236 }
|
111
|
237 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
|
|
238 gsi_next (&bsi))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
239 {
|
111
|
240 gimple *stmt = gsi_stmt (bsi);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
241 if (is_gimple_debug (stmt))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
242 continue;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
243 if (walk_stmt_load_store_addr_ops
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
244 (stmt, non_ssa_vars, test_nonssa_use, test_nonssa_use,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
245 test_nonssa_use))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
246 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
247 ok = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
248 goto done;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
249 }
|
111
|
250 if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
|
|
251 if (test_nonssa_use (stmt, gimple_label_label (label_stmt),
|
|
252 NULL_TREE, non_ssa_vars))
|
|
253 {
|
|
254 ok = false;
|
|
255 goto done;
|
|
256 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
257 }
|
111
|
258 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
|
|
259 gsi_next (&bsi))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
260 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
261 if (walk_stmt_load_store_addr_ops
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
262 (gsi_stmt (bsi), non_ssa_vars, test_nonssa_use, test_nonssa_use,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
263 test_nonssa_use))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
264 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
265 ok = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
266 goto done;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
267 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
268 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
269 FOR_EACH_EDGE (e, ei, bb->succs)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
270 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
271 if (e->dest != return_bb)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
272 continue;
|
111
|
273 for (gphi_iterator bsi = gsi_start_phis (return_bb);
|
|
274 !gsi_end_p (bsi);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
275 gsi_next (&bsi))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
276 {
|
111
|
277 gphi *stmt = bsi.phi ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
278 tree op = gimple_phi_arg_def (stmt, e->dest_idx);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
279
|
111
|
280 if (virtual_operand_p (gimple_phi_result (stmt)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
281 continue;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
282 if (TREE_CODE (op) != SSA_NAME
|
111
|
283 && test_nonssa_use (stmt, op, op, non_ssa_vars))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
284 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
285 ok = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
286 goto done;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
287 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
288 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
289 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
290 }
|
111
|
291
|
|
292 /* Verify that the rest of function does not define any label
|
|
293 used by the split part. */
|
|
294 FOR_EACH_BB_FN (bb, cfun)
|
|
295 if (!bitmap_bit_p (current->split_bbs, bb->index)
|
|
296 && !bitmap_bit_p (seen, bb->index))
|
|
297 {
|
|
298 gimple_stmt_iterator bsi;
|
|
299 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
|
|
300 if (glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (bsi)))
|
|
301 {
|
|
302 if (test_nonssa_use (label_stmt,
|
|
303 gimple_label_label (label_stmt),
|
|
304 NULL_TREE, non_ssa_vars))
|
|
305 {
|
|
306 ok = false;
|
|
307 goto done;
|
|
308 }
|
|
309 }
|
|
310 else
|
|
311 break;
|
|
312 }
|
|
313
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
314 done:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
315 BITMAP_FREE (seen);
|
111
|
316 worklist.release ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
317 return ok;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
318 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
319
|
111
|
320 /* If STMT is a call, check the callee against a list of forbidden
|
|
321 predicate functions. If a match is found, look for uses of the
|
|
322 call result in condition statements that compare against zero.
|
|
323 For each such use, find the block targeted by the condition
|
|
324 statement for the nonzero result, and set the bit for this block
|
|
325 in the forbidden dominators bitmap. The purpose of this is to avoid
|
|
326 selecting a split point where we are likely to lose the chance
|
|
327 to optimize away an unused function call. */
|
|
328
|
|
329 static void
|
|
330 check_forbidden_calls (gimple *stmt)
|
|
331 {
|
|
332 imm_use_iterator use_iter;
|
|
333 use_operand_p use_p;
|
|
334 tree lhs;
|
|
335
|
|
336 /* At the moment, __builtin_constant_p is the only forbidden
|
|
337 predicate function call (see PR49642). */
|
|
338 if (!gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P))
|
|
339 return;
|
|
340
|
|
341 lhs = gimple_call_lhs (stmt);
|
|
342
|
|
343 if (!lhs || TREE_CODE (lhs) != SSA_NAME)
|
|
344 return;
|
|
345
|
|
346 FOR_EACH_IMM_USE_FAST (use_p, use_iter, lhs)
|
|
347 {
|
|
348 tree op1;
|
|
349 basic_block use_bb, forbidden_bb;
|
|
350 enum tree_code code;
|
|
351 edge true_edge, false_edge;
|
|
352 gcond *use_stmt;
|
|
353
|
|
354 use_stmt = dyn_cast <gcond *> (USE_STMT (use_p));
|
|
355 if (!use_stmt)
|
|
356 continue;
|
|
357
|
|
358 /* Assuming canonical form for GIMPLE_COND here, with constant
|
|
359 in second position. */
|
|
360 op1 = gimple_cond_rhs (use_stmt);
|
|
361 code = gimple_cond_code (use_stmt);
|
|
362 use_bb = gimple_bb (use_stmt);
|
|
363
|
|
364 extract_true_false_edges_from_block (use_bb, &true_edge, &false_edge);
|
|
365
|
|
366 /* We're only interested in comparisons that distinguish
|
|
367 unambiguously from zero. */
|
|
368 if (!integer_zerop (op1) || code == LE_EXPR || code == GE_EXPR)
|
|
369 continue;
|
|
370
|
|
371 if (code == EQ_EXPR)
|
|
372 forbidden_bb = false_edge->dest;
|
|
373 else
|
|
374 forbidden_bb = true_edge->dest;
|
|
375
|
|
376 bitmap_set_bit (forbidden_dominators, forbidden_bb->index);
|
|
377 }
|
|
378 }
|
|
379
|
|
380 /* If BB is dominated by any block in the forbidden dominators set,
|
|
381 return TRUE; else FALSE. */
|
|
382
|
|
383 static bool
|
|
384 dominated_by_forbidden (basic_block bb)
|
|
385 {
|
|
386 unsigned dom_bb;
|
|
387 bitmap_iterator bi;
|
|
388
|
|
389 EXECUTE_IF_SET_IN_BITMAP (forbidden_dominators, 1, dom_bb, bi)
|
|
390 {
|
|
391 if (dominated_by_p (CDI_DOMINATORS, bb,
|
|
392 BASIC_BLOCK_FOR_FN (cfun, dom_bb)))
|
|
393 return true;
|
|
394 }
|
|
395
|
|
396 return false;
|
|
397 }
|
|
398
|
|
399 /* For give split point CURRENT and return block RETURN_BB return 1
|
|
400 if ssa name VAL is set by split part and 0 otherwise. */
|
|
401 static bool
|
|
402 split_part_set_ssa_name_p (tree val, struct split_point *current,
|
|
403 basic_block return_bb)
|
|
404 {
|
|
405 if (TREE_CODE (val) != SSA_NAME)
|
|
406 return false;
|
|
407
|
|
408 return (!SSA_NAME_IS_DEFAULT_DEF (val)
|
|
409 && (bitmap_bit_p (current->split_bbs,
|
|
410 gimple_bb (SSA_NAME_DEF_STMT (val))->index)
|
|
411 || gimple_bb (SSA_NAME_DEF_STMT (val)) == return_bb));
|
|
412 }
|
|
413
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
414 /* We found an split_point CURRENT. NON_SSA_VARS is bitmap of all non ssa
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
415 variables used and RETURN_BB is return basic block.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
416 See if we can split function here. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
417
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
418 static void
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
419 consider_split (struct split_point *current, bitmap non_ssa_vars,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
420 basic_block return_bb)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
421 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
422 tree parm;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
423 unsigned int num_args = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
424 unsigned int call_overhead;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
425 edge e;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
426 edge_iterator ei;
|
111
|
427 gphi_iterator bsi;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
428 unsigned int i;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
429 int incoming_freq = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
430 tree retval;
|
111
|
431 tree retbnd;
|
|
432 bool back_edge = false;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
433
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
434 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
435 dump_split_point (dump_file, current);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
436
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
437 FOR_EACH_EDGE (e, ei, current->entry_bb->preds)
|
111
|
438 {
|
|
439 if (e->flags & EDGE_DFS_BACK)
|
|
440 back_edge = true;
|
|
441 if (!bitmap_bit_p (current->split_bbs, e->src->index))
|
|
442 incoming_freq += EDGE_FREQUENCY (e);
|
|
443 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
444
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
445 /* Do not split when we would end up calling function anyway. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
446 if (incoming_freq
|
111
|
447 >= (ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
448 * PARAM_VALUE (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY) / 100))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
449 {
|
111
|
450 /* When profile is guessed, we can not expect it to give us
|
|
451 realistic estimate on likelyness of function taking the
|
|
452 complex path. As a special case, when tail of the function is
|
|
453 a loop, enable splitting since inlining code skipping the loop
|
|
454 is likely noticeable win. */
|
|
455 if (back_edge
|
|
456 && profile_status_for_fn (cfun) != PROFILE_READ
|
|
457 && incoming_freq < ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency)
|
|
458 {
|
|
459 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
460 fprintf (dump_file,
|
|
461 " Split before loop, accepting despite low frequencies %i %i.\n",
|
|
462 incoming_freq,
|
|
463 ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency);
|
|
464 }
|
|
465 else
|
|
466 {
|
|
467 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
468 fprintf (dump_file,
|
|
469 " Refused: incoming frequency is too large.\n");
|
|
470 return;
|
|
471 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
472 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
473
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
474 if (!current->header_size)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
475 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
476 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
477 fprintf (dump_file, " Refused: header empty\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
478 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
479 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
480
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
481 /* Verify that PHI args on entry are either virtual or all their operands
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
482 incoming from header are the same. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
483 for (bsi = gsi_start_phis (current->entry_bb); !gsi_end_p (bsi); gsi_next (&bsi))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
484 {
|
111
|
485 gphi *stmt = bsi.phi ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
486 tree val = NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
487
|
111
|
488 if (virtual_operand_p (gimple_phi_result (stmt)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
489 continue;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
490 for (i = 0; i < gimple_phi_num_args (stmt); i++)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
491 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
492 edge e = gimple_phi_arg_edge (stmt, i);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
493 if (!bitmap_bit_p (current->split_bbs, e->src->index))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
494 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
495 tree edge_val = gimple_phi_arg_def (stmt, i);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
496 if (val && edge_val != val)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
497 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
498 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
499 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
500 " Refused: entry BB has PHI with multiple variants\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
501 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
502 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
503 val = edge_val;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
504 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
505 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
506 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
507
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
508
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
509 /* See what argument we will pass to the split function and compute
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
510 call overhead. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
511 call_overhead = eni_size_weights.call_cost;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
512 for (parm = DECL_ARGUMENTS (current_function_decl); parm;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
513 parm = DECL_CHAIN (parm))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
514 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
515 if (!is_gimple_reg (parm))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
516 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
517 if (bitmap_bit_p (non_ssa_vars, DECL_UID (parm)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
518 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
519 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
520 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
521 " Refused: need to pass non-ssa param values\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
522 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
523 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
524 }
|
111
|
525 else
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
526 {
|
111
|
527 tree ddef = ssa_default_def (cfun, parm);
|
|
528 if (ddef
|
|
529 && bitmap_bit_p (current->ssa_names_to_pass,
|
|
530 SSA_NAME_VERSION (ddef)))
|
|
531 {
|
|
532 if (!VOID_TYPE_P (TREE_TYPE (parm)))
|
|
533 call_overhead += estimate_move_cost (TREE_TYPE (parm), false);
|
|
534 num_args++;
|
|
535 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
536 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
537 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
538 if (!VOID_TYPE_P (TREE_TYPE (current_function_decl)))
|
111
|
539 call_overhead += estimate_move_cost (TREE_TYPE (current_function_decl),
|
|
540 false);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
541
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
542 if (current->split_size <= call_overhead)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
543 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
544 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
545 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
546 " Refused: split size is smaller than call overhead\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
547 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
548 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
549 if (current->header_size + call_overhead
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
550 >= (unsigned int)(DECL_DECLARED_INLINE_P (current_function_decl)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
551 ? MAX_INLINE_INSNS_SINGLE
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
552 : MAX_INLINE_INSNS_AUTO))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
553 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
554 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
555 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
556 " Refused: header size is too large for inline candidate\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
557 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
558 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
559
|
111
|
560 /* Splitting functions brings the target out of comdat group; this will
|
|
561 lead to code duplication if the function is reused by other unit.
|
|
562 Limit this duplication. This is consistent with limit in tree-sra.c
|
|
563 FIXME: with LTO we ought to be able to do better! */
|
|
564 if (DECL_ONE_ONLY (current_function_decl)
|
|
565 && current->split_size >= (unsigned int) MAX_INLINE_INSNS_AUTO)
|
|
566 {
|
|
567 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
568 fprintf (dump_file,
|
|
569 " Refused: function is COMDAT and tail is too large\n");
|
|
570 return;
|
|
571 }
|
|
572 /* For comdat functions also reject very small tails; those will likely get
|
|
573 inlined back and we do not want to risk the duplication overhead.
|
|
574 FIXME: with LTO we ought to be able to do better! */
|
|
575 if (DECL_ONE_ONLY (current_function_decl)
|
|
576 && current->split_size
|
|
577 <= (unsigned int) PARAM_VALUE (PARAM_EARLY_INLINING_INSNS) / 2)
|
|
578 {
|
|
579 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
580 fprintf (dump_file,
|
|
581 " Refused: function is COMDAT and tail is too small\n");
|
|
582 return;
|
|
583 }
|
|
584
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
585 /* FIXME: we currently can pass only SSA function parameters to the split
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
586 arguments. Once parm_adjustment infrastructure is supported by cloning,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
587 we can pass more than that. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
588 if (num_args != bitmap_count_bits (current->ssa_names_to_pass))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
589 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
590
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
591 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
592 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
593 " Refused: need to pass non-param values\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
594 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
595 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
596
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
597 /* When there are non-ssa vars used in the split region, see if they
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
598 are used in the header region. If so, reject the split.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
599 FIXME: we can use nested function support to access both. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
600 if (!bitmap_empty_p (non_ssa_vars)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
601 && !verify_non_ssa_vars (current, non_ssa_vars, return_bb))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
602 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
603 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
604 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
605 " Refused: split part has non-ssa uses\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
606 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
607 }
|
111
|
608
|
|
609 /* If the split point is dominated by a forbidden block, reject
|
|
610 the split. */
|
|
611 if (!bitmap_empty_p (forbidden_dominators)
|
|
612 && dominated_by_forbidden (current->entry_bb))
|
|
613 {
|
|
614 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
615 fprintf (dump_file,
|
|
616 " Refused: split point dominated by forbidden block\n");
|
|
617 return;
|
|
618 }
|
|
619
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
620 /* See if retval used by return bb is computed by header or split part.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
621 When it is computed by split part, we need to produce return statement
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
622 in the split part and add code to header to pass it around.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
623
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
624 This is bit tricky to test:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
625 1) When there is no return_bb or no return value, we always pass
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
626 value around.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
627 2) Invariants are always computed by caller.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
628 3) For SSA we need to look if defining statement is in header or split part
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
629 4) For non-SSA we need to look where the var is computed. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
630 retval = find_retval (return_bb);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
631 if (!retval)
|
111
|
632 {
|
|
633 /* If there is a return_bb with no return value in function returning
|
|
634 value by reference, also make the split part return void, otherwise
|
|
635 we expansion would try to create a non-POD temporary, which is
|
|
636 invalid. */
|
|
637 if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
|
|
638 && DECL_RESULT (current_function_decl)
|
|
639 && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
|
|
640 current->split_part_set_retval = false;
|
|
641 else
|
|
642 current->split_part_set_retval = true;
|
|
643 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
644 else if (is_gimple_min_invariant (retval))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
645 current->split_part_set_retval = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
646 /* Special case is value returned by reference we record as if it was non-ssa
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
647 set to result_decl. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
648 else if (TREE_CODE (retval) == SSA_NAME
|
111
|
649 && SSA_NAME_VAR (retval)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
650 && TREE_CODE (SSA_NAME_VAR (retval)) == RESULT_DECL
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
651 && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
652 current->split_part_set_retval
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
653 = bitmap_bit_p (non_ssa_vars, DECL_UID (SSA_NAME_VAR (retval)));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
654 else if (TREE_CODE (retval) == SSA_NAME)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
655 current->split_part_set_retval
|
111
|
656 = split_part_set_ssa_name_p (retval, current, return_bb);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
657 else if (TREE_CODE (retval) == PARM_DECL)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
658 current->split_part_set_retval = false;
|
111
|
659 else if (VAR_P (retval)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
660 || TREE_CODE (retval) == RESULT_DECL)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
661 current->split_part_set_retval
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
662 = bitmap_bit_p (non_ssa_vars, DECL_UID (retval));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
663 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
664 current->split_part_set_retval = true;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
665
|
111
|
666 /* See if retbnd used by return bb is computed by header or split part. */
|
|
667 retbnd = find_retbnd (return_bb);
|
|
668 if (retbnd)
|
|
669 {
|
|
670 bool split_part_set_retbnd
|
|
671 = split_part_set_ssa_name_p (retbnd, current, return_bb);
|
|
672
|
|
673 /* If we have both return value and bounds then keep their definitions
|
|
674 in a single function. We use SSA names to link returned bounds and
|
|
675 value and therefore do not handle cases when result is passed by
|
|
676 reference (which should not be our case anyway since bounds are
|
|
677 returned for pointers only). */
|
|
678 if ((DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))
|
|
679 && current->split_part_set_retval)
|
|
680 || split_part_set_retbnd != current->split_part_set_retval)
|
|
681 {
|
|
682 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
683 fprintf (dump_file,
|
|
684 " Refused: split point splits return value and bounds\n");
|
|
685 return;
|
|
686 }
|
|
687 }
|
|
688
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
689 /* split_function fixes up at most one PHI non-virtual PHI node in return_bb,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
690 for the return value. If there are other PHIs, give up. */
|
111
|
691 if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
692 {
|
111
|
693 gphi_iterator psi;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
694
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
695 for (psi = gsi_start_phis (return_bb); !gsi_end_p (psi); gsi_next (&psi))
|
111
|
696 if (!virtual_operand_p (gimple_phi_result (psi.phi ()))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
697 && !(retval
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
698 && current->split_part_set_retval
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
699 && TREE_CODE (retval) == SSA_NAME
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
700 && !DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))
|
111
|
701 && SSA_NAME_DEF_STMT (retval) == psi.phi ()))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
702 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
703 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
704 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
705 " Refused: return bb has extra PHIs\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
706 return;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
707 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
708 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
709
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
710 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
711 fprintf (dump_file, " Accepted!\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
712
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
713 /* At the moment chose split point with lowest frequency and that leaves
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
714 out smallest size of header.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
715 In future we might re-consider this heuristics. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
716 if (!best_split_point.split_bbs
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
717 || best_split_point.entry_bb->frequency > current->entry_bb->frequency
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
718 || (best_split_point.entry_bb->frequency == current->entry_bb->frequency
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
719 && best_split_point.split_size < current->split_size))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
720
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
721 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
722 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
723 fprintf (dump_file, " New best split point!\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
724 if (best_split_point.ssa_names_to_pass)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
725 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
726 BITMAP_FREE (best_split_point.ssa_names_to_pass);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
727 BITMAP_FREE (best_split_point.split_bbs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
728 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
729 best_split_point = *current;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
730 best_split_point.ssa_names_to_pass = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
731 bitmap_copy (best_split_point.ssa_names_to_pass,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
732 current->ssa_names_to_pass);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
733 best_split_point.split_bbs = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
734 bitmap_copy (best_split_point.split_bbs, current->split_bbs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
735 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
736 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
737
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
738 /* Return basic block containing RETURN statement. We allow basic blocks
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
739 of the form:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
740 <retval> = tmp_var;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
741 return <retval>
|
111
|
742 but return_bb can not be more complex than this (except for
|
|
743 -fsanitize=thread we allow TSAN_FUNC_EXIT () internal call in there).
|
|
744 If nothing is found, return the exit block.
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
745
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
746 When there are multiple RETURN statement, chose one with return value,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
747 since that one is more likely shared by multiple code paths.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
748
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
749 Return BB is special, because for function splitting it is the only
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
750 basic block that is duplicated in between header and split part of the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
751 function.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
752
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
753 TODO: We might support multiple return blocks. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
754
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
755 static basic_block
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
756 find_return_bb (void)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
757 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
758 edge e;
|
111
|
759 basic_block return_bb = EXIT_BLOCK_PTR_FOR_FN (cfun);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
760 gimple_stmt_iterator bsi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
761 bool found_return = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
762 tree retval = NULL_TREE;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
763
|
111
|
764 if (!single_pred_p (EXIT_BLOCK_PTR_FOR_FN (cfun)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
765 return return_bb;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
766
|
111
|
767 e = single_pred_edge (EXIT_BLOCK_PTR_FOR_FN (cfun));
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
768 for (bsi = gsi_last_bb (e->src); !gsi_end_p (bsi); gsi_prev (&bsi))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
769 {
|
111
|
770 gimple *stmt = gsi_stmt (bsi);
|
|
771 if (gimple_code (stmt) == GIMPLE_LABEL
|
|
772 || is_gimple_debug (stmt)
|
|
773 || gimple_clobber_p (stmt))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
774 ;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
775 else if (gimple_code (stmt) == GIMPLE_ASSIGN
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
776 && found_return
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
777 && gimple_assign_single_p (stmt)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
778 && (auto_var_in_fn_p (gimple_assign_rhs1 (stmt),
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
779 current_function_decl)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
780 || is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
781 && retval == gimple_assign_lhs (stmt))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
782 ;
|
111
|
783 else if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
784 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
785 found_return = true;
|
111
|
786 retval = gimple_return_retval (return_stmt);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
787 }
|
111
|
788 /* For -fsanitize=thread, allow also TSAN_FUNC_EXIT () in the return
|
|
789 bb. */
|
|
790 else if ((flag_sanitize & SANITIZE_THREAD)
|
|
791 && gimple_call_internal_p (stmt, IFN_TSAN_FUNC_EXIT))
|
|
792 ;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
793 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
794 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
795 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
796 if (gsi_end_p (bsi) && found_return)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
797 return_bb = e->src;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
798
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
799 return return_bb;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
800 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
801
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
802 /* Given return basic block RETURN_BB, see where return value is really
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
803 stored. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
804 static tree
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
805 find_retval (basic_block return_bb)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
806 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
807 gimple_stmt_iterator bsi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
808 for (bsi = gsi_start_bb (return_bb); !gsi_end_p (bsi); gsi_next (&bsi))
|
111
|
809 if (greturn *return_stmt = dyn_cast <greturn *> (gsi_stmt (bsi)))
|
|
810 return gimple_return_retval (return_stmt);
|
|
811 else if (gimple_code (gsi_stmt (bsi)) == GIMPLE_ASSIGN
|
|
812 && !gimple_clobber_p (gsi_stmt (bsi)))
|
|
813 return gimple_assign_rhs1 (gsi_stmt (bsi));
|
|
814 return NULL;
|
|
815 }
|
|
816
|
|
817 /* Given return basic block RETURN_BB, see where return bounds are really
|
|
818 stored. */
|
|
819 static tree
|
|
820 find_retbnd (basic_block return_bb)
|
|
821 {
|
|
822 gimple_stmt_iterator bsi;
|
|
823 for (bsi = gsi_last_bb (return_bb); !gsi_end_p (bsi); gsi_prev (&bsi))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
824 if (gimple_code (gsi_stmt (bsi)) == GIMPLE_RETURN)
|
111
|
825 return gimple_return_retbnd (gsi_stmt (bsi));
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
826 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
827 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
828
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
829 /* Callback for walk_stmt_load_store_addr_ops. If T is non-SSA automatic
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
830 variable, mark it as used in bitmap passed via DATA.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
831 Return true when access to T prevents splitting the function. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
832
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
833 static bool
|
111
|
834 mark_nonssa_use (gimple *, tree t, tree, void *data)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
835 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
836 t = get_base_address (t);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
837
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
838 if (!t || is_gimple_reg (t))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
839 return false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
840
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
841 /* At present we can't pass non-SSA arguments to split function.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
842 FIXME: this can be relaxed by passing references to arguments. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
843 if (TREE_CODE (t) == PARM_DECL)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
844 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
845 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
846 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
847 "Cannot split: use of non-ssa function parameter.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
848 return true;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
849 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
850
|
111
|
851 if ((VAR_P (t) && auto_var_in_fn_p (t, current_function_decl))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
852 || TREE_CODE (t) == RESULT_DECL
|
111
|
853 || (TREE_CODE (t) == LABEL_DECL && FORCED_LABEL (t)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
854 bitmap_set_bit ((bitmap)data, DECL_UID (t));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
855
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
856 /* For DECL_BY_REFERENCE, the return value is actually a pointer. We want
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
857 to pretend that the value pointed to is actual result decl. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
858 if ((TREE_CODE (t) == MEM_REF || INDIRECT_REF_P (t))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
859 && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
|
111
|
860 && SSA_NAME_VAR (TREE_OPERAND (t, 0))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
861 && TREE_CODE (SSA_NAME_VAR (TREE_OPERAND (t, 0))) == RESULT_DECL
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
862 && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
863 return
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
864 bitmap_bit_p ((bitmap)data,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
865 DECL_UID (DECL_RESULT (current_function_decl)));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
866
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
867 return false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
868 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
869
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
870 /* Compute local properties of basic block BB we collect when looking for
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
871 split points. We look for ssa defs and store them in SET_SSA_NAMES,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
872 for ssa uses and store them in USED_SSA_NAMES and for any non-SSA automatic
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
873 vars stored in NON_SSA_VARS.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
874
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
875 When BB has edge to RETURN_BB, collect uses in RETURN_BB too.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
876
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
877 Return false when BB contains something that prevents it from being put into
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
878 split function. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
879
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
880 static bool
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
881 visit_bb (basic_block bb, basic_block return_bb,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
882 bitmap set_ssa_names, bitmap used_ssa_names,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
883 bitmap non_ssa_vars)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
884 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
885 edge e;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
886 edge_iterator ei;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
887 bool can_split = true;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
888
|
111
|
889 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
|
|
890 gsi_next (&bsi))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
891 {
|
111
|
892 gimple *stmt = gsi_stmt (bsi);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
893 tree op;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
894 ssa_op_iter iter;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
895 tree decl;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
896
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
897 if (is_gimple_debug (stmt))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
898 continue;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
899
|
111
|
900 if (gimple_clobber_p (stmt))
|
|
901 continue;
|
|
902
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
903 /* FIXME: We can split regions containing EH. We can not however
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
904 split RESX, EH_DISPATCH and EH_POINTER referring to same region
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
905 into different partitions. This would require tracking of
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
906 EH regions and checking in consider_split_point if they
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
907 are not used elsewhere. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
908 if (gimple_code (stmt) == GIMPLE_RESX)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
909 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
910 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
911 fprintf (dump_file, "Cannot split: resx.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
912 can_split = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
913 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
914 if (gimple_code (stmt) == GIMPLE_EH_DISPATCH)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
915 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
916 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
917 fprintf (dump_file, "Cannot split: eh dispatch.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
918 can_split = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
919 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
920
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
921 /* Check builtins that prevent splitting. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
922 if (gimple_code (stmt) == GIMPLE_CALL
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
923 && (decl = gimple_call_fndecl (stmt)) != NULL_TREE
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
924 && DECL_BUILT_IN (decl)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
925 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
926 switch (DECL_FUNCTION_CODE (decl))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
927 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
928 /* FIXME: once we will allow passing non-parm values to split part,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
929 we need to be sure to handle correct builtin_stack_save and
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
930 builtin_stack_restore. At the moment we are safe; there is no
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
931 way to store builtin_stack_save result in non-SSA variable
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
932 since all calls to those are compiler generated. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
933 case BUILT_IN_APPLY:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
934 case BUILT_IN_APPLY_ARGS:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
935 case BUILT_IN_VA_START:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
936 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
937 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
938 "Cannot split: builtin_apply and va_start.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
939 can_split = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
940 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
941 case BUILT_IN_EH_POINTER:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
942 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
943 fprintf (dump_file, "Cannot split: builtin_eh_pointer.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
944 can_split = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
945 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
946 default:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
947 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
948 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
949
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
950 FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
951 bitmap_set_bit (set_ssa_names, SSA_NAME_VERSION (op));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
952 FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
953 bitmap_set_bit (used_ssa_names, SSA_NAME_VERSION (op));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
954 can_split &= !walk_stmt_load_store_addr_ops (stmt, non_ssa_vars,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
955 mark_nonssa_use,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
956 mark_nonssa_use,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
957 mark_nonssa_use);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
958 }
|
111
|
959 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
|
|
960 gsi_next (&bsi))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
961 {
|
111
|
962 gphi *stmt = bsi.phi ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
963 unsigned int i;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
964
|
111
|
965 if (virtual_operand_p (gimple_phi_result (stmt)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
966 continue;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
967 bitmap_set_bit (set_ssa_names,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
968 SSA_NAME_VERSION (gimple_phi_result (stmt)));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
969 for (i = 0; i < gimple_phi_num_args (stmt); i++)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
970 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
971 tree op = gimple_phi_arg_def (stmt, i);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
972 if (TREE_CODE (op) == SSA_NAME)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
973 bitmap_set_bit (used_ssa_names, SSA_NAME_VERSION (op));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
974 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
975 can_split &= !walk_stmt_load_store_addr_ops (stmt, non_ssa_vars,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
976 mark_nonssa_use,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
977 mark_nonssa_use,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
978 mark_nonssa_use);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
979 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
980 /* Record also uses coming from PHI operand in return BB. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
981 FOR_EACH_EDGE (e, ei, bb->succs)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
982 if (e->dest == return_bb)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
983 {
|
111
|
984 for (gphi_iterator bsi = gsi_start_phis (return_bb);
|
|
985 !gsi_end_p (bsi);
|
|
986 gsi_next (&bsi))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
987 {
|
111
|
988 gphi *stmt = bsi.phi ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
989 tree op = gimple_phi_arg_def (stmt, e->dest_idx);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
990
|
111
|
991 if (virtual_operand_p (gimple_phi_result (stmt)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
992 continue;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
993 if (TREE_CODE (op) == SSA_NAME)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
994 bitmap_set_bit (used_ssa_names, SSA_NAME_VERSION (op));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
995 else
|
111
|
996 can_split &= !mark_nonssa_use (stmt, op, op, non_ssa_vars);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
997 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
998 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
999 return can_split;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1000 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1001
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1002 /* Stack entry for recursive DFS walk in find_split_point. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1003
|
111
|
1004 struct stack_entry
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1005 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1006 /* Basic block we are examining. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1007 basic_block bb;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1008
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1009 /* SSA names set and used by the BB and all BBs reachable
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1010 from it via DFS walk. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1011 bitmap set_ssa_names, used_ssa_names;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1012 bitmap non_ssa_vars;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1013
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1014 /* All BBS visited from this BB via DFS walk. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1015 bitmap bbs_visited;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1016
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1017 /* Last examined edge in DFS walk. Since we walk unoriented graph,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1018 the value is up to sum of incoming and outgoing edges of BB. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1019 unsigned int edge_num;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1020
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1021 /* Stack entry index of earliest BB reachable from current BB
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1022 or any BB visited later in DFS walk. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1023 int earliest;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1024
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1025 /* Overall time and size of all BBs reached from this BB in DFS walk. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1026 int overall_time, overall_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1027
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1028 /* When false we can not split on this BB. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1029 bool can_split;
|
111
|
1030 };
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1031
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1032
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1033 /* Find all articulations and call consider_split on them.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1034 OVERALL_TIME and OVERALL_SIZE is time and size of the function.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1035
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1036 We perform basic algorithm for finding an articulation in a graph
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1037 created from CFG by considering it to be an unoriented graph.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1038
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1039 The articulation is discovered via DFS walk. We collect earliest
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1040 basic block on stack that is reachable via backward edge. Articulation
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1041 is any basic block such that there is no backward edge bypassing it.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1042 To reduce stack usage we maintain heap allocated stack in STACK vector.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1043 AUX pointer of BB is set to index it appears in the stack or -1 once
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1044 it is visited and popped off the stack.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1045
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1046 The algorithm finds articulation after visiting the whole component
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1047 reachable by it. This makes it convenient to collect information about
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1048 the component used by consider_split. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1049
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1050 static void
|
111
|
1051 find_split_points (basic_block return_bb, int overall_time, int overall_size)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1052 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1053 stack_entry first;
|
111
|
1054 vec<stack_entry> stack = vNULL;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1055 basic_block bb;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1056 struct split_point current;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1057
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1058 current.header_time = overall_time;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1059 current.header_size = overall_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1060 current.split_time = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1061 current.split_size = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1062 current.ssa_names_to_pass = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1063
|
111
|
1064 first.bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1065 first.edge_num = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1066 first.overall_time = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1067 first.overall_size = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1068 first.earliest = INT_MAX;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1069 first.set_ssa_names = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1070 first.used_ssa_names = 0;
|
111
|
1071 first.non_ssa_vars = 0;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1072 first.bbs_visited = 0;
|
111
|
1073 first.can_split = false;
|
|
1074 stack.safe_push (first);
|
|
1075 ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux = (void *)(intptr_t)-1;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1076
|
111
|
1077 while (!stack.is_empty ())
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1078 {
|
111
|
1079 stack_entry *entry = &stack.last ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1080
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1081 /* We are walking an acyclic graph, so edge_num counts
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1082 succ and pred edges together. However when considering
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1083 articulation, we want to have processed everything reachable
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1084 from articulation but nothing that reaches into it. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1085 if (entry->edge_num == EDGE_COUNT (entry->bb->succs)
|
111
|
1086 && entry->bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1087 {
|
111
|
1088 int pos = stack.length ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1089 entry->can_split &= visit_bb (entry->bb, return_bb,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1090 entry->set_ssa_names,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1091 entry->used_ssa_names,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1092 entry->non_ssa_vars);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1093 if (pos <= entry->earliest && !entry->can_split
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1094 && dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1095 fprintf (dump_file,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1096 "found articulation at bb %i but can not split\n",
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1097 entry->bb->index);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1098 if (pos <= entry->earliest && entry->can_split)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1099 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1100 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1101 fprintf (dump_file, "found articulation at bb %i\n",
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1102 entry->bb->index);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1103 current.entry_bb = entry->bb;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1104 current.ssa_names_to_pass = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1105 bitmap_and_compl (current.ssa_names_to_pass,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1106 entry->used_ssa_names, entry->set_ssa_names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1107 current.header_time = overall_time - entry->overall_time;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1108 current.header_size = overall_size - entry->overall_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1109 current.split_time = entry->overall_time;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1110 current.split_size = entry->overall_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1111 current.split_bbs = entry->bbs_visited;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1112 consider_split (¤t, entry->non_ssa_vars, return_bb);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1113 BITMAP_FREE (current.ssa_names_to_pass);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1114 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1115 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1116 /* Do actual DFS walk. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1117 if (entry->edge_num
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1118 < (EDGE_COUNT (entry->bb->succs)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1119 + EDGE_COUNT (entry->bb->preds)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1120 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1121 edge e;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1122 basic_block dest;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1123 if (entry->edge_num < EDGE_COUNT (entry->bb->succs))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1124 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1125 e = EDGE_SUCC (entry->bb, entry->edge_num);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1126 dest = e->dest;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1127 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1128 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1129 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1130 e = EDGE_PRED (entry->bb, entry->edge_num
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1131 - EDGE_COUNT (entry->bb->succs));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1132 dest = e->src;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1133 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1134
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1135 entry->edge_num++;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1136
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1137 /* New BB to visit, push it to the stack. */
|
111
|
1138 if (dest != return_bb && dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1139 && !dest->aux)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1140 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1141 stack_entry new_entry;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1142
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1143 new_entry.bb = dest;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1144 new_entry.edge_num = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1145 new_entry.overall_time
|
111
|
1146 = bb_info_vec[dest->index].time;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1147 new_entry.overall_size
|
111
|
1148 = bb_info_vec[dest->index].size;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1149 new_entry.earliest = INT_MAX;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1150 new_entry.set_ssa_names = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1151 new_entry.used_ssa_names = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1152 new_entry.bbs_visited = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1153 new_entry.non_ssa_vars = BITMAP_ALLOC (NULL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1154 new_entry.can_split = true;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1155 bitmap_set_bit (new_entry.bbs_visited, dest->index);
|
111
|
1156 stack.safe_push (new_entry);
|
|
1157 dest->aux = (void *)(intptr_t)stack.length ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1158 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1159 /* Back edge found, record the earliest point. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1160 else if ((intptr_t)dest->aux > 0
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1161 && (intptr_t)dest->aux < entry->earliest)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1162 entry->earliest = (intptr_t)dest->aux;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1163 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1164 /* We are done with examining the edges. Pop off the value from stack
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1165 and merge stuff we accumulate during the walk. */
|
111
|
1166 else if (entry->bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1167 {
|
111
|
1168 stack_entry *prev = &stack[stack.length () - 2];
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1169
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1170 entry->bb->aux = (void *)(intptr_t)-1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1171 prev->can_split &= entry->can_split;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1172 if (prev->set_ssa_names)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1173 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1174 bitmap_ior_into (prev->set_ssa_names, entry->set_ssa_names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1175 bitmap_ior_into (prev->used_ssa_names, entry->used_ssa_names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1176 bitmap_ior_into (prev->bbs_visited, entry->bbs_visited);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1177 bitmap_ior_into (prev->non_ssa_vars, entry->non_ssa_vars);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1178 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1179 if (prev->earliest > entry->earliest)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1180 prev->earliest = entry->earliest;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1181 prev->overall_time += entry->overall_time;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1182 prev->overall_size += entry->overall_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1183 BITMAP_FREE (entry->set_ssa_names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1184 BITMAP_FREE (entry->used_ssa_names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1185 BITMAP_FREE (entry->bbs_visited);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1186 BITMAP_FREE (entry->non_ssa_vars);
|
111
|
1187 stack.pop ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1188 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1189 else
|
111
|
1190 stack.pop ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1191 }
|
111
|
1192 ENTRY_BLOCK_PTR_FOR_FN (cfun)->aux = NULL;
|
|
1193 FOR_EACH_BB_FN (bb, cfun)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1194 bb->aux = NULL;
|
111
|
1195 stack.release ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1196 BITMAP_FREE (current.ssa_names_to_pass);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1197 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1198
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1199 /* Split function at SPLIT_POINT. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1200
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1201 static void
|
111
|
1202 split_function (basic_block return_bb, struct split_point *split_point,
|
|
1203 bool add_tsan_func_exit)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1204 {
|
111
|
1205 vec<tree> args_to_pass = vNULL;
|
|
1206 bitmap args_to_skip;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1207 tree parm;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1208 int num = 0;
|
111
|
1209 cgraph_node *node, *cur_node = cgraph_node::get (current_function_decl);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1210 basic_block call_bb;
|
111
|
1211 gcall *call, *tsan_func_exit_call = NULL;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1212 edge e;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1213 edge_iterator ei;
|
111
|
1214 tree retval = NULL, real_retval = NULL, retbnd = NULL;
|
|
1215 bool with_bounds = chkp_function_instrumented_p (current_function_decl);
|
|
1216 gimple *last_stmt = NULL;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1217 unsigned int i;
|
111
|
1218 tree arg, ddef;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1219
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1220 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1221 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1222 fprintf (dump_file, "\n\nSplitting function at:\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1223 dump_split_point (dump_file, split_point);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1224 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1225
|
111
|
1226 if (cur_node->local.can_change_signature)
|
|
1227 args_to_skip = BITMAP_ALLOC (NULL);
|
|
1228 else
|
|
1229 args_to_skip = NULL;
|
|
1230
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1231 /* Collect the parameters of new function and args_to_skip bitmap. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1232 for (parm = DECL_ARGUMENTS (current_function_decl);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1233 parm; parm = DECL_CHAIN (parm), num++)
|
111
|
1234 if (args_to_skip
|
|
1235 && (!is_gimple_reg (parm)
|
|
1236 || (ddef = ssa_default_def (cfun, parm)) == NULL_TREE
|
|
1237 || !bitmap_bit_p (split_point->ssa_names_to_pass,
|
|
1238 SSA_NAME_VERSION (ddef))))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1239 bitmap_set_bit (args_to_skip, num);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1240 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1241 {
|
111
|
1242 /* This parm might not have been used up to now, but is going to be
|
|
1243 used, hence register it. */
|
|
1244 if (is_gimple_reg (parm))
|
|
1245 arg = get_or_create_ssa_default_def (cfun, parm);
|
|
1246 else
|
|
1247 arg = parm;
|
|
1248
|
|
1249 if (!useless_type_conversion_p (DECL_ARG_TYPE (parm), TREE_TYPE (arg)))
|
|
1250 arg = fold_convert (DECL_ARG_TYPE (parm), arg);
|
|
1251 args_to_pass.safe_push (arg);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1252 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1253
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1254 /* See if the split function will return. */
|
111
|
1255 bool split_part_return_p = false;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1256 FOR_EACH_EDGE (e, ei, return_bb->preds)
|
111
|
1257 {
|
|
1258 if (bitmap_bit_p (split_point->split_bbs, e->src->index))
|
|
1259 split_part_return_p = true;
|
|
1260 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1261
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1262 /* Add return block to what will become the split function.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1263 We do not return; no return block is needed. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1264 if (!split_part_return_p)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1265 ;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1266 /* We have no return block, so nothing is needed. */
|
111
|
1267 else if (return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1268 ;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1269 /* When we do not want to return value, we need to construct
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1270 new return block with empty return statement.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1271 FIXME: Once we are able to change return type, we should change function
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1272 to return void instead of just outputting function with undefined return
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1273 value. For structures this affects quality of codegen. */
|
111
|
1274 else if ((retval = find_retval (return_bb))
|
|
1275 && !split_point->split_part_set_retval)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1276 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1277 bool redirected = true;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1278 basic_block new_return_bb = create_basic_block (NULL, 0, return_bb);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1279 gimple_stmt_iterator gsi = gsi_start_bb (new_return_bb);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1280 gsi_insert_after (&gsi, gimple_build_return (NULL), GSI_NEW_STMT);
|
111
|
1281 new_return_bb->count = profile_count::zero ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1282 while (redirected)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1283 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1284 redirected = false;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1285 FOR_EACH_EDGE (e, ei, return_bb->preds)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1286 if (bitmap_bit_p (split_point->split_bbs, e->src->index))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1287 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1288 new_return_bb->frequency += EDGE_FREQUENCY (e);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1289 redirect_edge_and_branch (e, new_return_bb);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1290 redirected = true;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1291 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1292 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1293 }
|
111
|
1294 e = make_single_succ_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
|
|
1295 add_bb_to_loop (new_return_bb, current_loops->tree_root);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1296 bitmap_set_bit (split_point->split_bbs, new_return_bb->index);
|
111
|
1297 retbnd = find_retbnd (return_bb);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1298 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1299 /* When we pass around the value, use existing return block. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1300 else
|
111
|
1301 {
|
|
1302 bitmap_set_bit (split_point->split_bbs, return_bb->index);
|
|
1303 retbnd = find_retbnd (return_bb);
|
|
1304 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1305
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1306 /* If RETURN_BB has virtual operand PHIs, they must be removed and the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1307 virtual operand marked for renaming as we change the CFG in a way that
|
111
|
1308 tree-inline is not able to compensate for.
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1309
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1310 Note this can happen whether or not we have a return value. If we have
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1311 a return value, then RETURN_BB may have PHIs for real operands too. */
|
111
|
1312 if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1313 {
|
111
|
1314 bool phi_p = false;
|
|
1315 for (gphi_iterator gsi = gsi_start_phis (return_bb);
|
|
1316 !gsi_end_p (gsi);)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1317 {
|
111
|
1318 gphi *stmt = gsi.phi ();
|
|
1319 if (!virtual_operand_p (gimple_phi_result (stmt)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1320 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1321 gsi_next (&gsi);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1322 continue;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1323 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1324 mark_virtual_phi_result_for_renaming (stmt);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1325 remove_phi_node (&gsi, true);
|
111
|
1326 phi_p = true;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1327 }
|
111
|
1328 /* In reality we have to rename the reaching definition of the
|
|
1329 virtual operand at return_bb as we will eventually release it
|
|
1330 when we remove the code region we outlined.
|
|
1331 So we have to rename all immediate virtual uses of that region
|
|
1332 if we didn't see a PHI definition yet. */
|
|
1333 /* ??? In real reality we want to set the reaching vdef of the
|
|
1334 entry of the SESE region as the vuse of the call and the reaching
|
|
1335 vdef of the exit of the SESE region as the vdef of the call. */
|
|
1336 if (!phi_p)
|
|
1337 for (gimple_stmt_iterator gsi = gsi_start_bb (return_bb);
|
|
1338 !gsi_end_p (gsi);
|
|
1339 gsi_next (&gsi))
|
|
1340 {
|
|
1341 gimple *stmt = gsi_stmt (gsi);
|
|
1342 if (gimple_vuse (stmt))
|
|
1343 {
|
|
1344 gimple_set_vuse (stmt, NULL_TREE);
|
|
1345 update_stmt (stmt);
|
|
1346 }
|
|
1347 if (gimple_vdef (stmt))
|
|
1348 break;
|
|
1349 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1350 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1351
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1352 /* Now create the actual clone. */
|
111
|
1353 cgraph_edge::rebuild_edges ();
|
|
1354 node = cur_node->create_version_clone_with_body
|
|
1355 (vNULL, NULL, args_to_skip,
|
|
1356 !split_part_return_p || !split_point->split_part_set_retval,
|
|
1357 split_point->split_bbs, split_point->entry_bb, "part");
|
|
1358
|
|
1359 node->split_part = true;
|
|
1360
|
|
1361 if (cur_node->same_comdat_group)
|
|
1362 {
|
|
1363 /* TODO: call is versionable if we make sure that all
|
|
1364 callers are inside of a comdat group. */
|
|
1365 cur_node->calls_comdat_local = 1;
|
|
1366 node->add_to_same_comdat_group (cur_node);
|
|
1367 }
|
|
1368
|
|
1369
|
|
1370 /* Let's take a time profile for splitted function. */
|
|
1371 node->tp_first_run = cur_node->tp_first_run + 1;
|
|
1372
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1373 /* For usual cloning it is enough to clear builtin only when signature
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1374 changes. For partial inlining we however can not expect the part
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1375 of builtin implementation to have same semantic as the whole. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1376 if (DECL_BUILT_IN (node->decl))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1377 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1378 DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1379 DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1380 }
|
111
|
1381
|
|
1382 /* If return_bb contains any clobbers that refer to SSA_NAMEs
|
|
1383 set in the split part, remove them. Also reset debug stmts that
|
|
1384 refer to SSA_NAMEs set in the split part. */
|
|
1385 if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
|
|
1386 {
|
|
1387 gimple_stmt_iterator gsi = gsi_start_bb (return_bb);
|
|
1388 while (!gsi_end_p (gsi))
|
|
1389 {
|
|
1390 tree op;
|
|
1391 ssa_op_iter iter;
|
|
1392 gimple *stmt = gsi_stmt (gsi);
|
|
1393 bool remove = false;
|
|
1394 if (gimple_clobber_p (stmt) || is_gimple_debug (stmt))
|
|
1395 FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
|
|
1396 {
|
|
1397 basic_block bb = gimple_bb (SSA_NAME_DEF_STMT (op));
|
|
1398 if (op != retval
|
|
1399 && bb
|
|
1400 && bb != return_bb
|
|
1401 && bitmap_bit_p (split_point->split_bbs, bb->index))
|
|
1402 {
|
|
1403 if (is_gimple_debug (stmt))
|
|
1404 {
|
|
1405 gimple_debug_bind_reset_value (stmt);
|
|
1406 update_stmt (stmt);
|
|
1407 }
|
|
1408 else
|
|
1409 remove = true;
|
|
1410 break;
|
|
1411 }
|
|
1412 }
|
|
1413 if (remove)
|
|
1414 gsi_remove (&gsi, true);
|
|
1415 else
|
|
1416 gsi_next (&gsi);
|
|
1417 }
|
|
1418 }
|
|
1419
|
|
1420 /* If the original function is instrumented then it's
|
|
1421 part is also instrumented. */
|
|
1422 if (with_bounds)
|
|
1423 chkp_function_mark_instrumented (node->decl);
|
|
1424
|
|
1425 /* If the original function is declared inline, there is no point in issuing
|
|
1426 a warning for the non-inlinable part. */
|
|
1427 DECL_NO_INLINE_WARNING_P (node->decl) = 1;
|
|
1428 cur_node->remove_callees ();
|
|
1429 cur_node->remove_all_references ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1430 if (!split_part_return_p)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1431 TREE_THIS_VOLATILE (node->decl) = 1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1432 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1433 dump_function_to_file (node->decl, dump_file, dump_flags);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1434
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1435 /* Create the basic block we place call into. It is the entry basic block
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1436 split after last label. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1437 call_bb = split_point->entry_bb;
|
111
|
1438 for (gimple_stmt_iterator gsi = gsi_start_bb (call_bb); !gsi_end_p (gsi);)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1439 if (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1440 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1441 last_stmt = gsi_stmt (gsi);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1442 gsi_next (&gsi);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1443 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1444 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1445 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1446 e = split_block (split_point->entry_bb, last_stmt);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1447 remove_edge (e);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1448
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1449 /* Produce the call statement. */
|
111
|
1450 gimple_stmt_iterator gsi = gsi_last_bb (call_bb);
|
|
1451 FOR_EACH_VEC_ELT (args_to_pass, i, arg)
|
|
1452 if (!is_gimple_val (arg))
|
|
1453 {
|
|
1454 arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
|
|
1455 false, GSI_CONTINUE_LINKING);
|
|
1456 args_to_pass[i] = arg;
|
|
1457 }
|
|
1458 call = gimple_build_call_vec (node->decl, args_to_pass);
|
|
1459 gimple_call_set_with_bounds (call, with_bounds);
|
|
1460 gimple_set_block (call, DECL_INITIAL (current_function_decl));
|
|
1461 args_to_pass.release ();
|
|
1462
|
|
1463 /* For optimized away parameters, add on the caller side
|
|
1464 before the call
|
|
1465 DEBUG D#X => parm_Y(D)
|
|
1466 stmts and associate D#X with parm in decl_debug_args_lookup
|
|
1467 vector to say for debug info that if parameter parm had been passed,
|
|
1468 it would have value parm_Y(D). */
|
|
1469 if (args_to_skip)
|
|
1470 {
|
|
1471 vec<tree, va_gc> **debug_args = NULL;
|
|
1472 unsigned i = 0, len = 0;
|
|
1473 if (MAY_HAVE_DEBUG_STMTS)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1474 {
|
111
|
1475 debug_args = decl_debug_args_lookup (node->decl);
|
|
1476 if (debug_args)
|
|
1477 len = vec_safe_length (*debug_args);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1478 }
|
111
|
1479 for (parm = DECL_ARGUMENTS (current_function_decl), num = 0;
|
|
1480 parm; parm = DECL_CHAIN (parm), num++)
|
|
1481 if (bitmap_bit_p (args_to_skip, num) && is_gimple_reg (parm))
|
|
1482 {
|
|
1483 tree ddecl;
|
|
1484 gimple *def_temp;
|
|
1485
|
|
1486 /* This needs to be done even without MAY_HAVE_DEBUG_STMTS,
|
|
1487 otherwise if it didn't exist before, we'd end up with
|
|
1488 different SSA_NAME_VERSIONs between -g and -g0. */
|
|
1489 arg = get_or_create_ssa_default_def (cfun, parm);
|
|
1490 if (!MAY_HAVE_DEBUG_STMTS || debug_args == NULL)
|
|
1491 continue;
|
|
1492
|
|
1493 while (i < len && (**debug_args)[i] != DECL_ORIGIN (parm))
|
|
1494 i += 2;
|
|
1495 if (i >= len)
|
|
1496 continue;
|
|
1497 ddecl = (**debug_args)[i + 1];
|
|
1498 def_temp
|
|
1499 = gimple_build_debug_bind (ddecl, unshare_expr (arg), call);
|
|
1500 gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
|
|
1501 }
|
|
1502 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1503
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1504 /* We avoid address being taken on any variable used by split part,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1505 so return slot optimization is always possible. Moreover this is
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1506 required to make DECL_BY_REFERENCE work. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1507 if (aggregate_value_p (DECL_RESULT (current_function_decl),
|
111
|
1508 TREE_TYPE (current_function_decl))
|
|
1509 && (!is_gimple_reg_type (TREE_TYPE (DECL_RESULT (current_function_decl)))
|
|
1510 || DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1511 gimple_call_set_return_slot_opt (call, true);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1512
|
111
|
1513 if (add_tsan_func_exit)
|
|
1514 tsan_func_exit_call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
|
|
1515
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1516 /* Update return value. This is bit tricky. When we do not return,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1517 do nothing. When we return we might need to update return_bb
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1518 or produce a new return statement. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1519 if (!split_part_return_p)
|
111
|
1520 {
|
|
1521 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
|
|
1522 if (tsan_func_exit_call)
|
|
1523 gsi_insert_after (&gsi, tsan_func_exit_call, GSI_NEW_STMT);
|
|
1524 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1525 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1526 {
|
111
|
1527 e = make_single_succ_edge (call_bb, return_bb,
|
|
1528 return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
|
|
1529 ? 0 : EDGE_FALLTHRU);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1530
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1531 /* If there is return basic block, see what value we need to store
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1532 return value into and put call just before it. */
|
111
|
1533 if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1534 {
|
111
|
1535 real_retval = retval;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1536 if (real_retval && split_point->split_part_set_retval)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1537 {
|
111
|
1538 gphi_iterator psi;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1539
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1540 /* See if we need new SSA_NAME for the result.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1541 When DECL_BY_REFERENCE is true, retval is actually pointer to
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1542 return value and it is constant in whole function. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1543 if (TREE_CODE (retval) == SSA_NAME
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1544 && !DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1545 {
|
111
|
1546 retval = copy_ssa_name (retval, call);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1547
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1548 /* See if there is PHI defining return value. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1549 for (psi = gsi_start_phis (return_bb);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1550 !gsi_end_p (psi); gsi_next (&psi))
|
111
|
1551 if (!virtual_operand_p (gimple_phi_result (psi.phi ())))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1552 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1553
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1554 /* When there is PHI, just update its value. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1555 if (TREE_CODE (retval) == SSA_NAME
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1556 && !gsi_end_p (psi))
|
111
|
1557 add_phi_arg (psi.phi (), retval, e, UNKNOWN_LOCATION);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1558 /* Otherwise update the return BB itself.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1559 find_return_bb allows at most one assignment to return value,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1560 so update first statement. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1561 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1562 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1563 gimple_stmt_iterator bsi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1564 for (bsi = gsi_start_bb (return_bb); !gsi_end_p (bsi);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1565 gsi_next (&bsi))
|
111
|
1566 if (greturn *return_stmt
|
|
1567 = dyn_cast <greturn *> (gsi_stmt (bsi)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1568 {
|
111
|
1569 gimple_return_set_retval (return_stmt, retval);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1570 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1571 }
|
111
|
1572 else if (gimple_code (gsi_stmt (bsi)) == GIMPLE_ASSIGN
|
|
1573 && !gimple_clobber_p (gsi_stmt (bsi)))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1574 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1575 gimple_assign_set_rhs1 (gsi_stmt (bsi), retval);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1576 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1577 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1578 update_stmt (gsi_stmt (bsi));
|
111
|
1579 /* Also adjust clobbers and debug stmts in return_bb. */
|
|
1580 for (bsi = gsi_start_bb (return_bb); !gsi_end_p (bsi);
|
|
1581 gsi_next (&bsi))
|
|
1582 {
|
|
1583 gimple *stmt = gsi_stmt (bsi);
|
|
1584 if (gimple_clobber_p (stmt)
|
|
1585 || is_gimple_debug (stmt))
|
|
1586 {
|
|
1587 ssa_op_iter iter;
|
|
1588 use_operand_p use_p;
|
|
1589 bool update = false;
|
|
1590 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
|
|
1591 SSA_OP_USE)
|
|
1592 if (USE_FROM_PTR (use_p) == real_retval)
|
|
1593 {
|
|
1594 SET_USE (use_p, retval);
|
|
1595 update = true;
|
|
1596 }
|
|
1597 if (update)
|
|
1598 update_stmt (stmt);
|
|
1599 }
|
|
1600 }
|
|
1601 }
|
|
1602
|
|
1603 /* Replace retbnd with new one. */
|
|
1604 if (retbnd)
|
|
1605 {
|
|
1606 gimple_stmt_iterator bsi;
|
|
1607 for (bsi = gsi_last_bb (return_bb); !gsi_end_p (bsi);
|
|
1608 gsi_prev (&bsi))
|
|
1609 if (gimple_code (gsi_stmt (bsi)) == GIMPLE_RETURN)
|
|
1610 {
|
|
1611 retbnd = copy_ssa_name (retbnd, call);
|
|
1612 gimple_return_set_retbnd (gsi_stmt (bsi), retbnd);
|
|
1613 update_stmt (gsi_stmt (bsi));
|
|
1614 break;
|
|
1615 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1616 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1617 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1618 if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
|
111
|
1619 {
|
|
1620 gimple_call_set_lhs (call, build_simple_mem_ref (retval));
|
|
1621 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
|
|
1622 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1623 else
|
111
|
1624 {
|
|
1625 tree restype;
|
|
1626 restype = TREE_TYPE (DECL_RESULT (current_function_decl));
|
|
1627 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
|
|
1628 if (!useless_type_conversion_p (TREE_TYPE (retval), restype))
|
|
1629 {
|
|
1630 gimple *cpy;
|
|
1631 tree tem = create_tmp_reg (restype);
|
|
1632 tem = make_ssa_name (tem, call);
|
|
1633 cpy = gimple_build_assign (retval, NOP_EXPR, tem);
|
|
1634 gsi_insert_after (&gsi, cpy, GSI_NEW_STMT);
|
|
1635 retval = tem;
|
|
1636 }
|
|
1637 /* Build bndret call to obtain returned bounds. */
|
|
1638 if (retbnd)
|
|
1639 chkp_insert_retbnd_call (retbnd, retval, &gsi);
|
|
1640 gimple_call_set_lhs (call, retval);
|
|
1641 update_stmt (call);
|
|
1642 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1643 }
|
111
|
1644 else
|
|
1645 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
|
|
1646 if (tsan_func_exit_call)
|
|
1647 gsi_insert_after (&gsi, tsan_func_exit_call, GSI_NEW_STMT);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1648 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1649 /* We don't use return block (there is either no return in function or
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1650 multiple of them). So create new basic block with return statement.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1651 */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1652 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1653 {
|
111
|
1654 greturn *ret;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1655 if (split_point->split_part_set_retval
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1656 && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1657 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1658 retval = DECL_RESULT (current_function_decl);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1659
|
111
|
1660 if (chkp_function_instrumented_p (current_function_decl)
|
|
1661 && BOUNDED_P (retval))
|
|
1662 retbnd = create_tmp_reg (pointer_bounds_type_node);
|
|
1663
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1664 /* We use temporary register to hold value when aggregate_value_p
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1665 is false. Similarly for DECL_BY_REFERENCE we must avoid extra
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1666 copy. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1667 if (!aggregate_value_p (retval, TREE_TYPE (current_function_decl))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1668 && !DECL_BY_REFERENCE (retval))
|
111
|
1669 retval = create_tmp_reg (TREE_TYPE (retval));
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1670 if (is_gimple_reg (retval))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1671 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1672 /* When returning by reference, there is only one SSA name
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1673 assigned to RESULT_DECL (that is pointer to return value).
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1674 Look it up or create new one if it is missing. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1675 if (DECL_BY_REFERENCE (retval))
|
111
|
1676 retval = get_or_create_ssa_default_def (cfun, retval);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1677 /* Otherwise produce new SSA name for return value. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1678 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1679 retval = make_ssa_name (retval, call);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1680 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1681 if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1682 gimple_call_set_lhs (call, build_simple_mem_ref (retval));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1683 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1684 gimple_call_set_lhs (call, retval);
|
111
|
1685 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1686 }
|
111
|
1687 else
|
|
1688 {
|
|
1689 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
|
|
1690 if (retval
|
|
1691 && is_gimple_reg_type (TREE_TYPE (retval))
|
|
1692 && !is_gimple_val (retval))
|
|
1693 {
|
|
1694 gassign *g
|
|
1695 = gimple_build_assign (make_ssa_name (TREE_TYPE (retval)),
|
|
1696 retval);
|
|
1697 retval = gimple_assign_lhs (g);
|
|
1698 gsi_insert_after (&gsi, g, GSI_NEW_STMT);
|
|
1699 }
|
|
1700 }
|
|
1701 /* Build bndret call to obtain returned bounds. */
|
|
1702 if (retbnd)
|
|
1703 chkp_insert_retbnd_call (retbnd, retval, &gsi);
|
|
1704 if (tsan_func_exit_call)
|
|
1705 gsi_insert_after (&gsi, tsan_func_exit_call, GSI_NEW_STMT);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1706 ret = gimple_build_return (retval);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1707 gsi_insert_after (&gsi, ret, GSI_NEW_STMT);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1708 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1709 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1710 free_dominance_info (CDI_DOMINATORS);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1711 free_dominance_info (CDI_POST_DOMINATORS);
|
111
|
1712 compute_fn_summary (node, true);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1713 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1714
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1715 /* Execute function splitting pass. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1716
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1717 static unsigned int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1718 execute_split_functions (void)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1719 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1720 gimple_stmt_iterator bsi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1721 basic_block bb;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1722 int overall_time = 0, overall_size = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1723 int todo = 0;
|
111
|
1724 struct cgraph_node *node = cgraph_node::get (current_function_decl);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1725
|
111
|
1726 if (flags_from_decl_or_type (current_function_decl)
|
|
1727 & (ECF_NORETURN|ECF_MALLOC))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1728 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1729 if (dump_file)
|
111
|
1730 fprintf (dump_file, "Not splitting: noreturn/malloc function.\n");
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1731 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1732 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1733 if (MAIN_NAME_P (DECL_NAME (current_function_decl)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1734 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1735 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1736 fprintf (dump_file, "Not splitting: main function.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1737 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1738 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1739 /* This can be relaxed; function might become inlinable after splitting
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1740 away the uninlinable part. */
|
111
|
1741 if (ipa_fn_summaries
|
|
1742 && !ipa_fn_summaries->get (node)->inlinable)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1743 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1744 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1745 fprintf (dump_file, "Not splitting: not inlinable.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1746 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1747 }
|
111
|
1748 if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1749 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1750 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1751 fprintf (dump_file, "Not splitting: disregarding inline limits.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1752 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1753 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1754 /* This can be relaxed; most of versioning tests actually prevents
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1755 a duplication. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1756 if (!tree_versionable_function_p (current_function_decl))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1757 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1758 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1759 fprintf (dump_file, "Not splitting: not versionable.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1760 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1761 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1762 /* FIXME: we could support this. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1763 if (DECL_STRUCT_FUNCTION (current_function_decl)->static_chain_decl)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1764 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1765 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1766 fprintf (dump_file, "Not splitting: nested function.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1767 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1768 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1769
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1770 /* See if it makes sense to try to split.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1771 It makes sense to split if we inline, that is if we have direct calls to
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1772 handle or direct calls are possibly going to appear as result of indirect
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1773 inlining or LTO. Also handle -fprofile-generate as LTO to allow non-LTO
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1774 training for LTO -fprofile-use build.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1775
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1776 Note that we are not completely conservative about disqualifying functions
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1777 called once. It is possible that the caller is called more then once and
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1778 then inlining would still benefit. */
|
111
|
1779 if ((!node->callers
|
|
1780 /* Local functions called once will be completely inlined most of time. */
|
|
1781 || (!node->callers->next_caller && node->local.local))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1782 && !node->address_taken
|
111
|
1783 && !node->has_aliases_p ()
|
|
1784 && (!flag_lto || !node->externally_visible))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1785 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1786 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1787 fprintf (dump_file, "Not splitting: not called directly "
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1788 "or called once.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1789 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1790 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1791
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1792 /* FIXME: We can actually split if splitting reduces call overhead. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1793 if (!flag_inline_small_functions
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1794 && !DECL_DECLARED_INLINE_P (current_function_decl))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1795 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1796 if (dump_file)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1797 fprintf (dump_file, "Not splitting: not autoinlining and function"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1798 " is not inline.\n");
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1799 return 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1800 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1801
|
111
|
1802 /* We enforce splitting after loop headers when profile info is not
|
|
1803 available. */
|
|
1804 if (profile_status_for_fn (cfun) != PROFILE_READ)
|
|
1805 mark_dfs_back_edges ();
|
|
1806
|
|
1807 /* Initialize bitmap to track forbidden calls. */
|
|
1808 forbidden_dominators = BITMAP_ALLOC (NULL);
|
|
1809 calculate_dominance_info (CDI_DOMINATORS);
|
|
1810
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1811 /* Compute local info about basic blocks and determine function size/time. */
|
111
|
1812 bb_info_vec.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1813 memset (&best_split_point, 0, sizeof (best_split_point));
|
111
|
1814 basic_block return_bb = find_return_bb ();
|
|
1815 int tsan_exit_found = -1;
|
|
1816 FOR_EACH_BB_FN (bb, cfun)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1817 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1818 int time = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1819 int size = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1820 int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1821
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1822 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1823 fprintf (dump_file, "Basic block %i\n", bb->index);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1824
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1825 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1826 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1827 int this_time, this_size;
|
111
|
1828 gimple *stmt = gsi_stmt (bsi);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1829
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1830 this_size = estimate_num_insns (stmt, &eni_size_weights);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1831 this_time = estimate_num_insns (stmt, &eni_time_weights) * freq;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1832 size += this_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1833 time += this_time;
|
111
|
1834 check_forbidden_calls (stmt);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1835
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1836 if (dump_file && (dump_flags & TDF_DETAILS))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1837 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1838 fprintf (dump_file, " freq:%6i size:%3i time:%3i ",
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1839 freq, this_size, this_time);
|
111
|
1840 print_gimple_stmt (dump_file, stmt, 0);
|
|
1841 }
|
|
1842
|
|
1843 if ((flag_sanitize & SANITIZE_THREAD)
|
|
1844 && gimple_call_internal_p (stmt, IFN_TSAN_FUNC_EXIT))
|
|
1845 {
|
|
1846 /* We handle TSAN_FUNC_EXIT for splitting either in the
|
|
1847 return_bb, or in its immediate predecessors. */
|
|
1848 if ((bb != return_bb && !find_edge (bb, return_bb))
|
|
1849 || (tsan_exit_found != -1
|
|
1850 && tsan_exit_found != (bb != return_bb)))
|
|
1851 {
|
|
1852 if (dump_file)
|
|
1853 fprintf (dump_file, "Not splitting: TSAN_FUNC_EXIT"
|
|
1854 " in unexpected basic block.\n");
|
|
1855 BITMAP_FREE (forbidden_dominators);
|
|
1856 bb_info_vec.release ();
|
|
1857 return 0;
|
|
1858 }
|
|
1859 tsan_exit_found = bb != return_bb;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1860 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1861 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1862 overall_time += time;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1863 overall_size += size;
|
111
|
1864 bb_info_vec[bb->index].time = time;
|
|
1865 bb_info_vec[bb->index].size = size;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1866 }
|
111
|
1867 find_split_points (return_bb, overall_time, overall_size);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1868 if (best_split_point.split_bbs)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1869 {
|
111
|
1870 split_function (return_bb, &best_split_point, tsan_exit_found == 1);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1871 BITMAP_FREE (best_split_point.ssa_names_to_pass);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1872 BITMAP_FREE (best_split_point.split_bbs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1873 todo = TODO_update_ssa | TODO_cleanup_cfg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1874 }
|
111
|
1875 BITMAP_FREE (forbidden_dominators);
|
|
1876 bb_info_vec.release ();
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1877 return todo;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1878 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1879
|
111
|
1880 namespace {
|
|
1881
|
|
1882 const pass_data pass_data_split_functions =
|
|
1883 {
|
|
1884 GIMPLE_PASS, /* type */
|
|
1885 "fnsplit", /* name */
|
|
1886 OPTGROUP_NONE, /* optinfo_flags */
|
|
1887 TV_IPA_FNSPLIT, /* tv_id */
|
|
1888 PROP_cfg, /* properties_required */
|
|
1889 0, /* properties_provided */
|
|
1890 0, /* properties_destroyed */
|
|
1891 0, /* todo_flags_start */
|
|
1892 0, /* todo_flags_finish */
|
|
1893 };
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1894
|
111
|
1895 class pass_split_functions : public gimple_opt_pass
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1896 {
|
111
|
1897 public:
|
|
1898 pass_split_functions (gcc::context *ctxt)
|
|
1899 : gimple_opt_pass (pass_data_split_functions, ctxt)
|
|
1900 {}
|
|
1901
|
|
1902 /* opt_pass methods: */
|
|
1903 virtual bool gate (function *);
|
|
1904 virtual unsigned int execute (function *)
|
|
1905 {
|
|
1906 return execute_split_functions ();
|
|
1907 }
|
|
1908
|
|
1909 }; // class pass_split_functions
|
|
1910
|
|
1911 bool
|
|
1912 pass_split_functions::gate (function *)
|
|
1913 {
|
|
1914 /* When doing profile feedback, we want to execute the pass after profiling
|
|
1915 is read. So disable one in early optimization. */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1916 return (flag_partial_inlining
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1917 && !profile_arc_flag && !flag_branch_probabilities);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1918 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1919
|
111
|
1920 } // anon namespace
|
|
1921
|
|
1922 gimple_opt_pass *
|
|
1923 make_pass_split_functions (gcc::context *ctxt)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1924 {
|
111
|
1925 return new pass_split_functions (ctxt);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1926 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1927
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1928 /* Execute function splitting pass. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1929
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1930 static unsigned int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1931 execute_feedback_split_functions (void)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1932 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1933 unsigned int retval = execute_split_functions ();
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1934 if (retval)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1935 retval |= TODO_rebuild_cgraph_edges;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1936 return retval;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1937 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1938
|
111
|
1939 namespace {
|
|
1940
|
|
1941 const pass_data pass_data_feedback_split_functions =
|
|
1942 {
|
|
1943 GIMPLE_PASS, /* type */
|
|
1944 "feedback_fnsplit", /* name */
|
|
1945 OPTGROUP_NONE, /* optinfo_flags */
|
|
1946 TV_IPA_FNSPLIT, /* tv_id */
|
|
1947 PROP_cfg, /* properties_required */
|
|
1948 0, /* properties_provided */
|
|
1949 0, /* properties_destroyed */
|
|
1950 0, /* todo_flags_start */
|
|
1951 0, /* todo_flags_finish */
|
|
1952 };
|
|
1953
|
|
1954 class pass_feedback_split_functions : public gimple_opt_pass
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1955 {
|
111
|
1956 public:
|
|
1957 pass_feedback_split_functions (gcc::context *ctxt)
|
|
1958 : gimple_opt_pass (pass_data_feedback_split_functions, ctxt)
|
|
1959 {}
|
|
1960
|
|
1961 /* opt_pass methods: */
|
|
1962 virtual bool gate (function *);
|
|
1963 virtual unsigned int execute (function *)
|
|
1964 {
|
|
1965 return execute_feedback_split_functions ();
|
|
1966 }
|
|
1967
|
|
1968 }; // class pass_feedback_split_functions
|
|
1969
|
|
1970 bool
|
|
1971 pass_feedback_split_functions::gate (function *)
|
|
1972 {
|
|
1973 /* We don't need to split when profiling at all, we are producing
|
|
1974 lousy code anyway. */
|
|
1975 return (flag_partial_inlining
|
|
1976 && flag_branch_probabilities);
|
|
1977 }
|
|
1978
|
|
1979 } // anon namespace
|
|
1980
|
|
1981 gimple_opt_pass *
|
|
1982 make_pass_feedback_split_functions (gcc::context *ctxt)
|
|
1983 {
|
|
1984 return new pass_feedback_split_functions (ctxt);
|
|
1985 }
|