openmp: Implement OpenMP 5.0 base-pointer attachement and clause ordering
[gcc.git] / gcc / gimple-isel.cc
1 /* Schedule GIMPLE vector statements.
2 Copyright (C) 2020 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "backend.h"
24 #include "rtl.h"
25 #include "tree.h"
26 #include "gimple.h"
27 #include "tree-pass.h"
28 #include "ssa.h"
29 #include "expmed.h"
30 #include "optabs-tree.h"
31 #include "tree-eh.h"
32 #include "gimple-iterator.h"
33 #include "gimplify-me.h"
34 #include "gimplify.h"
35 #include "tree-cfg.h"
36 #include "bitmap.h"
37 #include "tree-ssa-dce.h"
38 #include "memmodel.h"
39 #include "optabs.h"
40
41 /* Expand all ARRAY_REF(VIEW_CONVERT_EXPR) gimple assignments into calls to
42 internal function based on vector type of selected expansion.
43 i.e.:
44 VIEW_CONVERT_EXPR<int[4]>(u)[_1] = = i_4(D);
45 =>
46 _7 = u;
47 _8 = .VEC_SET (_7, i_4(D), _1);
48 u = _8; */
49
50 static gimple *
51 gimple_expand_vec_set_expr (gimple_stmt_iterator *gsi)
52 {
53 enum tree_code code;
54 gcall *new_stmt = NULL;
55 gassign *ass_stmt = NULL;
56
57 /* Only consider code == GIMPLE_ASSIGN. */
58 gassign *stmt = dyn_cast<gassign *> (gsi_stmt (*gsi));
59 if (!stmt)
60 return NULL;
61
62 tree lhs = gimple_assign_lhs (stmt);
63 code = TREE_CODE (lhs);
64 if (code != ARRAY_REF)
65 return NULL;
66
67 tree val = gimple_assign_rhs1 (stmt);
68 tree op0 = TREE_OPERAND (lhs, 0);
69 if (TREE_CODE (op0) == VIEW_CONVERT_EXPR && DECL_P (TREE_OPERAND (op0, 0))
70 && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
71 && TYPE_MODE (TREE_TYPE (lhs))
72 == TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0)))))
73 {
74 tree pos = TREE_OPERAND (lhs, 1);
75 tree view_op0 = TREE_OPERAND (op0, 0);
76 machine_mode outermode = TYPE_MODE (TREE_TYPE (view_op0));
77 if (auto_var_in_fn_p (view_op0, cfun->decl)
78 && !TREE_ADDRESSABLE (view_op0) && can_vec_set_var_idx_p (outermode))
79 {
80 location_t loc = gimple_location (stmt);
81 tree var_src = make_ssa_name (TREE_TYPE (view_op0));
82 tree var_dst = make_ssa_name (TREE_TYPE (view_op0));
83
84 ass_stmt = gimple_build_assign (var_src, view_op0);
85 gimple_set_vuse (ass_stmt, gimple_vuse (stmt));
86 gimple_set_location (ass_stmt, loc);
87 gsi_insert_before (gsi, ass_stmt, GSI_SAME_STMT);
88
89 new_stmt
90 = gimple_build_call_internal (IFN_VEC_SET, 3, var_src, val, pos);
91 gimple_call_set_lhs (new_stmt, var_dst);
92 gimple_set_location (new_stmt, loc);
93 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
94
95 ass_stmt = gimple_build_assign (view_op0, var_dst);
96 gimple_set_location (ass_stmt, loc);
97 gsi_insert_before (gsi, ass_stmt, GSI_SAME_STMT);
98
99 gimple_move_vops (ass_stmt, stmt);
100 gsi_remove (gsi, true);
101 }
102 }
103
104 return ass_stmt;
105 }
106
107 /* Expand all VEC_COND_EXPR gimple assignments into calls to internal
108 function based on type of selected expansion. */
109
110 static gimple *
111 gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
112 hash_map<tree, unsigned int> *vec_cond_ssa_name_uses)
113 {
114 tree lhs, op0a = NULL_TREE, op0b = NULL_TREE;
115 enum tree_code code;
116 enum tree_code tcode;
117 machine_mode cmp_op_mode;
118 bool unsignedp;
119 enum insn_code icode;
120 imm_use_iterator imm_iter;
121
122 /* Only consider code == GIMPLE_ASSIGN. */
123 gassign *stmt = dyn_cast<gassign *> (gsi_stmt (*gsi));
124 if (!stmt)
125 return NULL;
126
127 code = gimple_assign_rhs_code (stmt);
128 if (code != VEC_COND_EXPR)
129 return NULL;
130
131 tree op0 = gimple_assign_rhs1 (stmt);
132 tree op1 = gimple_assign_rhs2 (stmt);
133 tree op2 = gimple_assign_rhs3 (stmt);
134 lhs = gimple_assign_lhs (stmt);
135 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
136
137 gcc_assert (!COMPARISON_CLASS_P (op0));
138 if (TREE_CODE (op0) == SSA_NAME)
139 {
140 unsigned int used_vec_cond_exprs = 0;
141 unsigned int *slot = vec_cond_ssa_name_uses->get (op0);
142 if (slot)
143 used_vec_cond_exprs = *slot;
144 else
145 {
146 gimple *use_stmt;
147 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, op0)
148 {
149 gassign *assign = dyn_cast<gassign *> (use_stmt);
150 if (assign != NULL
151 && gimple_assign_rhs_code (assign) == VEC_COND_EXPR
152 && gimple_assign_rhs1 (assign) == op0)
153 used_vec_cond_exprs++;
154 }
155 vec_cond_ssa_name_uses->put (op0, used_vec_cond_exprs);
156 }
157
158 gassign *def_stmt = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (op0));
159 if (def_stmt)
160 {
161 tcode = gimple_assign_rhs_code (def_stmt);
162 op0a = gimple_assign_rhs1 (def_stmt);
163 op0b = gimple_assign_rhs2 (def_stmt);
164
165 tree op0_type = TREE_TYPE (op0);
166 tree op0a_type = TREE_TYPE (op0a);
167 if (used_vec_cond_exprs >= 2
168 && (get_vcond_mask_icode (mode, TYPE_MODE (op0_type))
169 != CODE_FOR_nothing)
170 && expand_vec_cmp_expr_p (op0a_type, op0_type, tcode))
171 {
172 /* Keep the SSA name and use vcond_mask. */
173 tcode = TREE_CODE (op0);
174 }
175 }
176 else
177 tcode = TREE_CODE (op0);
178 }
179 else
180 tcode = TREE_CODE (op0);
181
182 if (TREE_CODE_CLASS (tcode) != tcc_comparison)
183 {
184 gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
185 if (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
186 != CODE_FOR_nothing)
187 return gimple_build_call_internal (IFN_VCOND_MASK, 3, op0, op1, op2);
188 /* Fake op0 < 0. */
189 else
190 {
191 gcc_assert (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (op0)))
192 == MODE_VECTOR_INT);
193 op0a = op0;
194 op0b = build_zero_cst (TREE_TYPE (op0));
195 tcode = LT_EXPR;
196 }
197 }
198 cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
199 unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
200
201
202 gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode))
203 && known_eq (GET_MODE_NUNITS (mode),
204 GET_MODE_NUNITS (cmp_op_mode)));
205
206 icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
207 if (icode == CODE_FOR_nothing)
208 {
209 if (tcode == LT_EXPR
210 && op0a == op0)
211 {
212 /* A VEC_COND_EXPR condition could be folded from EQ_EXPR/NE_EXPR
213 into a constant when only get_vcond_eq_icode is supported.
214 Try changing it to NE_EXPR. */
215 tcode = NE_EXPR;
216 }
217 if (tcode == EQ_EXPR || tcode == NE_EXPR)
218 {
219 tree tcode_tree = build_int_cst (integer_type_node, tcode);
220 return gimple_build_call_internal (IFN_VCONDEQ, 5, op0a, op0b, op1,
221 op2, tcode_tree);
222 }
223 }
224
225 gcc_assert (icode != CODE_FOR_nothing);
226 tree tcode_tree = build_int_cst (integer_type_node, tcode);
227 return gimple_build_call_internal (unsignedp ? IFN_VCONDU : IFN_VCOND,
228 5, op0a, op0b, op1, op2, tcode_tree);
229 }
230
231
232
233 /* Iterate all gimple statements and try to expand
234 VEC_COND_EXPR assignments. */
235
236 static unsigned int
237 gimple_expand_vec_exprs (void)
238 {
239 gimple_stmt_iterator gsi;
240 basic_block bb;
241 hash_map<tree, unsigned int> vec_cond_ssa_name_uses;
242 auto_bitmap dce_ssa_names;
243
244 FOR_EACH_BB_FN (bb, cfun)
245 {
246 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
247 {
248 gimple *g = gimple_expand_vec_cond_expr (&gsi,
249 &vec_cond_ssa_name_uses);
250
251 if (g != NULL)
252 {
253 tree lhs = gimple_assign_lhs (gsi_stmt (gsi));
254 gimple_set_lhs (g, lhs);
255 gsi_replace (&gsi, g, false);
256 }
257
258 gimple_expand_vec_set_expr (&gsi);
259 }
260 }
261
262 for (hash_map<tree, unsigned int>::iterator it = vec_cond_ssa_name_uses.begin ();
263 it != vec_cond_ssa_name_uses.end (); ++it)
264 bitmap_set_bit (dce_ssa_names, SSA_NAME_VERSION ((*it).first));
265
266 simple_dce_from_worklist (dce_ssa_names);
267
268 return 0;
269 }
270
271 namespace {
272
273 const pass_data pass_data_gimple_isel =
274 {
275 GIMPLE_PASS, /* type */
276 "isel", /* name */
277 OPTGROUP_VEC, /* optinfo_flags */
278 TV_NONE, /* tv_id */
279 PROP_cfg, /* properties_required */
280 0, /* properties_provided */
281 0, /* properties_destroyed */
282 0, /* todo_flags_start */
283 TODO_update_ssa, /* todo_flags_finish */
284 };
285
286 class pass_gimple_isel : public gimple_opt_pass
287 {
288 public:
289 pass_gimple_isel (gcc::context *ctxt)
290 : gimple_opt_pass (pass_data_gimple_isel, ctxt)
291 {}
292
293 /* opt_pass methods: */
294 virtual bool gate (function *)
295 {
296 return true;
297 }
298
299 virtual unsigned int execute (function *)
300 {
301 return gimple_expand_vec_exprs ();
302 }
303
304 }; // class pass_gimple_isel
305
306 } // anon namespace
307
308 gimple_opt_pass *
309 make_pass_gimple_isel (gcc::context *ctxt)
310 {
311 return new pass_gimple_isel (ctxt);
312 }
313