annotate gcc/coroutine-passes.cc @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1 /* coroutine expansion and optimisation passes.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 Copyright (C) 2018-2020 Free Software Foundation, Inc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 This file is part of GCC.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 GCC is free software; you can redistribute it and/or modify it under
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 the terms of the GNU General Public License as published by the Free
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11 Software Foundation; either version 3, or (at your option) any later
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 You should have received a copy of the GNU General Public License
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20 along with GCC; see the file COPYING3. If not see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 <http://www.gnu.org/licenses/>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 #include "config.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24 #include "system.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 #include "coretypes.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 #include "backend.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 #include "target.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 #include "tree.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 #include "gimple.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 #include "tree-pass.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 #include "ssa.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 #include "cgraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 #include "pretty-print.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 #include "diagnostic-core.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 #include "fold-const.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 #include "internal-fn.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 #include "langhooks.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 #include "gimplify.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 #include "gimple-iterator.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 #include "gimplify-me.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 #include "gimple-walk.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 #include "gimple-fold.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 #include "tree-cfg.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 #include "tree-into-ssa.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 #include "tree-ssa-propagate.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 #include "gimple-pretty-print.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 #include "cfghooks.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 /* Here we:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 * lower the internal function that implements an exit from scope.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 * expand the builtins that are used to implement the library
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 interfaces to the coroutine frame. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 lower_coro_builtin (gimple_stmt_iterator *gsi, bool *handled_ops_p,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 struct walk_stmt_info *wi ATTRIBUTE_UNUSED)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 gimple *stmt = gsi_stmt (*gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 *handled_ops_p = !gimple_has_substatements (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 if (gimple_code (stmt) != GIMPLE_CALL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 /* This internal function implements an exit from scope without
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 performing any cleanups; it jumps directly to the label provided. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 if (gimple_call_internal_p (stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 && gimple_call_internal_fn (stmt) == IFN_CO_SUSPN)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 tree dest = TREE_OPERAND (gimple_call_arg (stmt, 0), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 ggoto *g = gimple_build_goto (dest);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 gsi_replace (gsi, g, /* do EH */ false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 *handled_ops_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 tree decl = gimple_call_fndecl (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 if (!decl || !fndecl_built_in_p (decl, BUILT_IN_NORMAL))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 /* The remaining builtins implement the library interfaces to the coro
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 frame. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 unsigned call_idx = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 switch (DECL_FUNCTION_CODE (decl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 case BUILT_IN_CORO_PROMISE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 /* If we are discarding this, then skip it; the function has no
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 side-effects. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 tree lhs = gimple_call_lhs (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 if (!lhs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 gsi_remove (gsi, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 *handled_ops_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 /* The coro frame starts with two pointers (to the resume and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 destroy() functions). These are followed by the promise which
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 is aligned as per type [or user attribute].
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 The input pointer is the first argument.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 The promise alignment is the second and the third is a bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 that is true when we are converting from a promise ptr to a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 frame pointer, and false for the inverse. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 tree ptr = gimple_call_arg (stmt, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 tree align_t = gimple_call_arg (stmt, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 tree from = gimple_call_arg (stmt, 2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 gcc_checking_assert (TREE_CODE (align_t) == INTEGER_CST);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 gcc_checking_assert (TREE_CODE (from) == INTEGER_CST);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 bool dir = wi::to_wide (from) != 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 HOST_WIDE_INT promise_align = TREE_INT_CST_LOW (align_t);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 HOST_WIDE_INT psize =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ptr_type_node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 HOST_WIDE_INT align = TYPE_ALIGN_UNIT (ptr_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 align = MAX (align, promise_align);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 psize *= 2; /* Start with two pointers. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 psize = ROUND_UP (psize, align);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 HOST_WIDE_INT offs = dir ? -psize : psize;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 tree repl = build2 (POINTER_PLUS_EXPR, ptr_type_node, ptr,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 size_int (offs));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 gassign *grpl = gimple_build_assign (lhs, repl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 gsi_replace (gsi, grpl, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 *handled_ops_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 case BUILT_IN_CORO_DESTROY:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 call_idx = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 /* FALLTHROUGH */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 case BUILT_IN_CORO_RESUME:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 tree ptr = gimple_call_arg (stmt, 0); /* frame ptr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 HOST_WIDE_INT psize =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ptr_type_node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 HOST_WIDE_INT offset = call_idx * psize;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 tree fntype = TREE_TYPE (decl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 tree fntype_ptr = build_pointer_type (fntype);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 tree fntype_ppp = build_pointer_type (fntype_ptr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 tree indirect = fold_build2 (MEM_REF, fntype_ptr, ptr,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 build_int_cst (fntype_ppp, offset));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 tree f_ptr_tmp = make_ssa_name (TYPE_MAIN_VARIANT (fntype_ptr));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 gassign *get_fptr = gimple_build_assign (f_ptr_tmp, indirect);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 gsi_insert_before (gsi, get_fptr, GSI_SAME_STMT);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 gimple_call_set_fn (static_cast<gcall *> (stmt), f_ptr_tmp);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 *handled_ops_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 case BUILT_IN_CORO_DONE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 /* If we are discarding this, then skip it; the function has no
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 side-effects. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 tree lhs = gimple_call_lhs (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 if (!lhs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 gsi_remove (gsi, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 *handled_ops_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 /* When we're done, the resume fn is set to NULL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 tree ptr = gimple_call_arg (stmt, 0); /* frame ptr. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 tree vpp = build_pointer_type (ptr_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 tree indirect
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 = fold_build2 (MEM_REF, vpp, ptr, build_int_cst (vpp, 0));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 tree d_ptr_tmp = make_ssa_name (ptr_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 gassign *get_dptr = gimple_build_assign (d_ptr_tmp, indirect);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 gsi_insert_before (gsi, get_dptr, GSI_SAME_STMT);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 tree done = fold_build2 (EQ_EXPR, boolean_type_node, d_ptr_tmp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 null_pointer_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 gassign *get_res = gimple_build_assign (lhs, done);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 gsi_replace (gsi, get_res, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 *handled_ops_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 /* Main entry point for lowering coroutine FE builtins. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 static unsigned int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 execute_lower_coro_builtins (void)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 struct walk_stmt_info wi;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 gimple_seq body;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 body = gimple_body (current_function_decl);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 memset (&wi, 0, sizeof (wi));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 walk_gimple_seq_mod (&body, lower_coro_builtin, NULL, &wi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 gimple_set_body (current_function_decl, body);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 namespace {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 const pass_data pass_data_coroutine_lower_builtins = {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 GIMPLE_PASS, /* type */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 "coro-lower-builtins", /* name */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 OPTGROUP_NONE, /* optinfo_flags */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 TV_NONE, /* tv_id */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 0, /* properties_required */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 0, /* properties_provided */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 0, /* properties_destroyed */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 0, /* todo_flags_start */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 0 /* todo_flags_finish */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 class pass_coroutine_lower_builtins : public gimple_opt_pass
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 pass_coroutine_lower_builtins (gcc::context *ctxt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 : gimple_opt_pass (pass_data_coroutine_lower_builtins, ctxt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 /* opt_pass methods: */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 virtual bool gate (function *) { return flag_coroutines; };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 virtual unsigned int execute (function *f ATTRIBUTE_UNUSED)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 return execute_lower_coro_builtins ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223 }; // class pass_coroutine_lower_builtins
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225 } // namespace
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 gimple_opt_pass *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 make_pass_coroutine_lower_builtins (gcc::context *ctxt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 return new pass_coroutine_lower_builtins (ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 /* Expand the remaining coroutine IFNs.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235 In the front end we construct a single actor function that contains
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 the coroutine state machine.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 The actor function has three entry conditions:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239 1. from the ramp, resume point 0 - to initial-suspend.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 2. when resume () is executed (resume point N).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241 3. from the destroy () shim when that is executed.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243 The actor function begins with two dispatchers; one for resume and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 one for destroy (where the initial entry from the ramp is a special-
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 case of resume point 0).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 Each suspend point and each dispatch entry is marked with an IFN such
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 that we can connect the relevant dispatchers to their target labels.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 So, if we have:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 CO_YIELD (NUM, FINAL, RES_LAB, DEST_LAB, FRAME_PTR)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254 This is await point NUM, and is the final await if FINAL is non-zero.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 The resume point is RES_LAB, and the destroy point is DEST_LAB.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 We expect to find a CO_ACTOR (NUM) in the resume dispatcher and a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 CO_ACTOR (NUM+1) in the destroy dispatcher.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 Initially, the intent of keeping the resume and destroy paths together
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 is that the conditionals controlling them are identical, and thus there
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 would be duplication of any optimisation of those paths if the split
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 were earlier.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 Subsequent inlining of the actor (and DCE) is then able to extract the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 resume and destroy paths as separate functions if that is found
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 profitable by the optimisers.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269 Once we have remade the connections to their correct postions, we elide
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 the labels that the front end inserted. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 static void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 move_edge_and_update (edge e, basic_block old_bb, basic_block new_bb)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275 if (dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 fprintf (dump_file, "redirecting edge from bb %u to bb %u\n", old_bb->index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 new_bb->index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 e = redirect_edge_and_branch (e, new_bb);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 if (!e && dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 fprintf (dump_file, "failed to redirect edge .. \n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 /* Die if we failed. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 gcc_checking_assert (e);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 static unsigned int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 execute_early_expand_coro_ifns (void)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 /* Don't rebuild stuff unless we have to. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 unsigned int todoflags = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 bool changed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 /* Some of the possible YIELD points will hopefully have been removed by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 earlier optimisations; record the ones that are still present. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 hash_map<int_hash<HOST_WIDE_INT, -1, -2>, tree> destinations;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 /* Labels we added to carry the CFG changes, we need to remove these to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 avoid confusing EH. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 hash_set<tree> to_remove;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 /* List of dispatch points to update. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 auto_vec<gimple_stmt_iterator, 16> actor_worklist;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 basic_block bb;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 gimple_stmt_iterator gsi;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 FOR_EACH_BB_FN (bb, cfun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 gimple *stmt = gsi_stmt (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 if (!is_gimple_call (stmt) || !gimple_call_internal_p (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 gsi_next (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 switch (gimple_call_internal_fn (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316 case IFN_CO_FRAME:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 /* This internal function is a placeholder for the frame
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319 size. In principle, we might lower it later (after some
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 optimisation had reduced the frame size). At present,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 without any such optimisation, we just set it here. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 tree lhs = gimple_call_lhs (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 tree size = gimple_call_arg (stmt, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 /* Right now, this is a trivial operation - copy through
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 the size computed during initial layout. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 gassign *grpl = gimple_build_assign (lhs, size);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 gsi_replace (&gsi, grpl, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 gsi_next (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 case IFN_CO_ACTOR:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 changed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 actor_worklist.safe_push (gsi); /* Save for later. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 gsi_next (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336 case IFN_CO_YIELD:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 changed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 /* .CO_YIELD (NUM, FINAL, RES_LAB, DEST_LAB, FRAME_PTR);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 NUM = await number.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 FINAL = 1 if this is the final_suspend() await.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 RES_LAB = resume point label.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 DEST_LAB = destroy point label.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 FRAME_PTR = is a null pointer with the type of the coro
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 frame, so that we can resize, if needed. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 if (dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347 fprintf (dump_file, "saw CO_YIELD in BB %u\n", bb->index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 tree num = gimple_call_arg (stmt, 0); /* yield point. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 HOST_WIDE_INT idx = TREE_INT_CST_LOW (num);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 bool existed;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 tree res_tgt = TREE_OPERAND (gimple_call_arg (stmt, 2), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 tree &res_dest = destinations.get_or_insert (idx, &existed);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 if (existed && dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355 fprintf (
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 dump_file,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 "duplicate YIELD RESUME point (" HOST_WIDE_INT_PRINT_DEC
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 ") ?\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 res_dest = res_tgt;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 tree dst_tgt = TREE_OPERAND (gimple_call_arg (stmt, 3), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365 tree &dst_dest = destinations.get_or_insert (idx + 1, &existed);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366 if (existed && dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 fprintf (
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369 dump_file,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 "duplicate YIELD DESTROY point (" HOST_WIDE_INT_PRINT_DEC
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371 ") ?\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372 idx + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376 dst_dest = dst_tgt;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377 to_remove.add (res_tgt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 to_remove.add (dst_tgt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379 /* lose the co_yield. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380 gsi_remove (&gsi, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381 stmt = gsi_stmt (gsi); /* next. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382 /* lose the copy present at O0. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383 if (is_gimple_assign (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 gsi_remove (&gsi, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 stmt = gsi_stmt (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388 /* Simplify the switch or if following. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389 if (gswitch *gsw = dyn_cast<gswitch *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 gimple_switch_set_index (gsw, integer_zero_node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392 fold_stmt (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 else if (gcond *gif = dyn_cast<gcond *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 if (gimple_cond_code (gif) == EQ_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397 gimple_cond_make_true (gif);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 gimple_cond_make_false (gif);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400 fold_stmt (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 else if (dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404 if (gsi_end_p (gsi))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409 gsi_next (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 if (!changed)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 if (dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417 fprintf (dump_file, "coro: nothing to do\n");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418 return todoflags;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 while (!actor_worklist.is_empty ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 gsi = actor_worklist.pop ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424 gimple *stmt = gsi_stmt (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425 gcc_checking_assert (is_gimple_call (stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426 && gimple_call_internal_p (stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427 && gimple_call_internal_fn (stmt) == IFN_CO_ACTOR);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428 bb = gsi_bb (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429 HOST_WIDE_INT idx = TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430 tree *seen = destinations.get (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 changed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433 if (dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434 fprintf (dump_file, "saw CO_ACTOR in BB %u\n", bb->index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436 if (!seen)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438 /* If we never saw this index, it means that the CO_YIELD
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439 associated was elided during earlier optimisations, so we
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440 don't need to fix up the switch targets. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 if (dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 fprintf (dump_file, "yield point " HOST_WIDE_INT_PRINT_DEC
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443 " not used, removing it .. \n", idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444 gsi_remove (&gsi, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445 release_defs (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 /* So we need to switch the target of this switch case to the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450 relevant BB. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451 basic_block new_bb = label_to_block (cfun, *seen);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452 /* We expect the block we're modifying to contain a single
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453 CO_ACTOR() followed by a goto <switch default bb>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 gcc_checking_assert (EDGE_COUNT (bb->succs) == 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
455 edge e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
456 edge_iterator ei;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
457 FOR_EACH_EDGE (e, ei, bb->succs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459 basic_block old_bb = e->dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 move_edge_and_update (e, old_bb, new_bb);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 gsi_remove (&gsi, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 /* Remove the labels we inserted to map our hidden CFG, this
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467 avoids confusing block merges when there are also EH labels. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468 FOR_EACH_BB_FN (bb, cfun)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471 gimple *stmt = gsi_stmt (gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472 if (glabel *glab = dyn_cast<glabel *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474 tree rem = gimple_label_label (glab);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475 if (to_remove.contains (rem))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477 gsi_remove (&gsi, true);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478 to_remove.remove (rem);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 continue; /* We already moved to the next insn. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 gsi_next (&gsi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487 /* Changed the CFG. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488 todoflags |= TODO_cleanup_cfg;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489 return todoflags;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492 namespace {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494 const pass_data pass_data_coroutine_early_expand_ifns = {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495 GIMPLE_PASS, /* type */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496 "coro-early-expand-ifns", /* name */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 OPTGROUP_NONE, /* optinfo_flags */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498 TV_NONE, /* tv_id */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499 (PROP_cfg), /* properties_required */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500 0, /* properties_provided */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 0, /* properties_destroyed */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 0, /* todo_flags_start */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 0 /* todo_flags_finish, set this in the fn. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506 class pass_coroutine_early_expand_ifns : public gimple_opt_pass
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509 pass_coroutine_early_expand_ifns (gcc::context *ctxt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510 : gimple_opt_pass (pass_data_coroutine_early_expand_ifns, ctxt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513 /* opt_pass methods: */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514 virtual bool gate (function *f)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 return flag_coroutines && f->coroutine_component;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519 virtual unsigned int execute (function *f ATTRIBUTE_UNUSED)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521 return execute_early_expand_coro_ifns ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524 }; // class pass_coroutine_expand_ifns
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526 } // namespace
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 gimple_opt_pass *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529 make_pass_coroutine_early_expand_ifns (gcc::context *ctxt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531 return new pass_coroutine_early_expand_ifns (ctxt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 }