c++: ICE with alias in pack expansion [PR103769]
[official-gcc.git] / gcc / gimple-isel.cc
blob3635585bf454d1426b17bbb69b6188949ad60a15
1 /* Schedule GIMPLE vector statements.
2 Copyright (C) 2020-2022 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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 #include "gimple-fold.h"
41 #include "internal-fn.h"
43 /* Expand all ARRAY_REF(VIEW_CONVERT_EXPR) gimple assignments into calls to
44 internal function based on vector type of selected expansion.
45 i.e.:
46 VIEW_CONVERT_EXPR<int[4]>(u)[_1] = = i_4(D);
48 _7 = u;
49 _8 = .VEC_SET (_7, i_4(D), _1);
50 u = _8; */
52 static gimple *
53 gimple_expand_vec_set_expr (struct function *fun, gimple_stmt_iterator *gsi)
55 enum tree_code code;
56 gcall *new_stmt = NULL;
57 gassign *ass_stmt = NULL;
59 /* Only consider code == GIMPLE_ASSIGN. */
60 gassign *stmt = dyn_cast<gassign *> (gsi_stmt (*gsi));
61 if (!stmt)
62 return NULL;
64 tree lhs = gimple_assign_lhs (stmt);
65 code = TREE_CODE (lhs);
66 if (code != ARRAY_REF)
67 return NULL;
69 tree val = gimple_assign_rhs1 (stmt);
70 tree op0 = TREE_OPERAND (lhs, 0);
71 if (TREE_CODE (op0) == VIEW_CONVERT_EXPR && DECL_P (TREE_OPERAND (op0, 0))
72 && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
73 && TYPE_MODE (TREE_TYPE (lhs))
74 == TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0)))))
76 tree pos = TREE_OPERAND (lhs, 1);
77 tree view_op0 = TREE_OPERAND (op0, 0);
78 machine_mode outermode = TYPE_MODE (TREE_TYPE (view_op0));
79 if (auto_var_in_fn_p (view_op0, fun->decl)
80 && !TREE_ADDRESSABLE (view_op0) && can_vec_set_var_idx_p (outermode))
82 location_t loc = gimple_location (stmt);
83 tree var_src = make_ssa_name (TREE_TYPE (view_op0));
84 tree var_dst = make_ssa_name (TREE_TYPE (view_op0));
86 ass_stmt = gimple_build_assign (var_src, view_op0);
87 gimple_set_vuse (ass_stmt, gimple_vuse (stmt));
88 gimple_set_location (ass_stmt, loc);
89 gsi_insert_before (gsi, ass_stmt, GSI_SAME_STMT);
91 new_stmt
92 = gimple_build_call_internal (IFN_VEC_SET, 3, var_src, val, pos);
93 gimple_call_set_lhs (new_stmt, var_dst);
94 gimple_set_location (new_stmt, loc);
95 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
97 ass_stmt = gimple_build_assign (view_op0, var_dst);
98 gimple_set_location (ass_stmt, loc);
99 gsi_insert_before (gsi, ass_stmt, GSI_SAME_STMT);
101 gimple_move_vops (ass_stmt, stmt);
102 gsi_remove (gsi, true);
106 return ass_stmt;
109 /* Expand all VEC_COND_EXPR gimple assignments into calls to internal
110 function based on type of selected expansion. */
112 static gimple *
113 gimple_expand_vec_cond_expr (struct function *fun, gimple_stmt_iterator *gsi,
114 hash_map<tree, unsigned int> *vec_cond_ssa_name_uses)
116 tree lhs, op0a = NULL_TREE, op0b = NULL_TREE;
117 enum tree_code code;
118 enum tree_code tcode;
119 machine_mode cmp_op_mode;
120 bool unsignedp;
121 enum insn_code icode;
122 imm_use_iterator imm_iter;
124 /* Only consider code == GIMPLE_ASSIGN. */
125 gassign *stmt = dyn_cast<gassign *> (gsi_stmt (*gsi));
126 if (!stmt)
127 return NULL;
129 code = gimple_assign_rhs_code (stmt);
130 if (code != VEC_COND_EXPR)
131 return NULL;
133 tree op0 = gimple_assign_rhs1 (stmt);
134 tree op1 = gimple_assign_rhs2 (stmt);
135 tree op2 = gimple_assign_rhs3 (stmt);
136 lhs = gimple_assign_lhs (stmt);
137 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
139 /* Lower mask typed, non-vector mode VEC_COND_EXPRs to bitwise operations.
140 Those can end up generated by folding and at least for integer mode masks
141 we cannot expect vcond expanders to exist. We lower a ? b : c
142 to (b & a) | (c & ~a). */
143 if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (lhs))
144 && !VECTOR_MODE_P (mode))
146 gcc_assert (types_compatible_p (TREE_TYPE (op0), TREE_TYPE (op1)));
147 gimple_seq stmts = NULL;
148 tree type = TREE_TYPE (lhs);
149 location_t loc = gimple_location (stmt);
150 tree tem0 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op1, op0);
151 tree tem1 = gimple_build (&stmts, loc, BIT_NOT_EXPR, type, op0);
152 tree tem2 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op2, tem1);
153 tree tem3 = gimple_build (&stmts, loc, BIT_IOR_EXPR, type, tem0, tem2);
154 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
155 return gimple_build_assign (lhs, tem3);
158 bool can_compute_op0 = true;
159 gcc_assert (!COMPARISON_CLASS_P (op0));
160 if (TREE_CODE (op0) == SSA_NAME)
162 unsigned int used_vec_cond_exprs = 0;
163 unsigned int *slot = vec_cond_ssa_name_uses->get (op0);
164 if (slot)
165 used_vec_cond_exprs = *slot;
166 else
168 gimple *use_stmt;
169 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, op0)
171 gassign *assign = dyn_cast<gassign *> (use_stmt);
172 if (assign != NULL
173 && gimple_assign_rhs_code (assign) == VEC_COND_EXPR
174 && gimple_assign_rhs1 (assign) == op0)
175 used_vec_cond_exprs++;
177 vec_cond_ssa_name_uses->put (op0, used_vec_cond_exprs);
180 gassign *def_stmt = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (op0));
181 if (def_stmt)
183 tcode = gimple_assign_rhs_code (def_stmt);
184 op0a = gimple_assign_rhs1 (def_stmt);
185 op0b = gimple_assign_rhs2 (def_stmt);
187 tree op0_type = TREE_TYPE (op0);
188 tree op0a_type = TREE_TYPE (op0a);
189 if (TREE_CODE_CLASS (tcode) == tcc_comparison)
190 can_compute_op0 = expand_vec_cmp_expr_p (op0a_type, op0_type,
191 tcode);
193 /* Try to fold x CMP y ? -1 : 0 to x CMP y. */
194 if (can_compute_op0
195 && integer_minus_onep (op1)
196 && integer_zerop (op2)
197 && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (TREE_TYPE (op0)))
199 tree conv_op = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), op0);
200 gassign *new_stmt = gimple_build_assign (lhs, conv_op);
201 gsi_replace (gsi, new_stmt, true);
202 return new_stmt;
205 /* When the compare has EH we do not want to forward it when
206 it has multiple uses and in general because of the complication
207 with EH redirection. */
208 if (stmt_can_throw_internal (fun, def_stmt))
209 tcode = TREE_CODE (op0);
211 /* If we can compute op0 and have multiple uses, keep the SSA
212 name and use vcond_mask. */
213 else if (can_compute_op0
214 && used_vec_cond_exprs >= 2
215 && (get_vcond_mask_icode (mode, TYPE_MODE (op0_type))
216 != CODE_FOR_nothing))
217 tcode = TREE_CODE (op0);
219 else
220 tcode = TREE_CODE (op0);
222 else
223 tcode = TREE_CODE (op0);
225 if (TREE_CODE_CLASS (tcode) != tcc_comparison)
227 gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
228 if (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
229 != CODE_FOR_nothing)
230 return gimple_build_call_internal (IFN_VCOND_MASK, 3, op0, op1, op2);
231 /* Fake op0 < 0. */
232 else
234 gcc_assert (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (op0)))
235 == MODE_VECTOR_INT);
236 op0a = op0;
237 op0b = build_zero_cst (TREE_TYPE (op0));
238 tcode = LT_EXPR;
241 cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
242 unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
244 gcc_assert (known_eq (GET_MODE_NUNITS (mode),
245 GET_MODE_NUNITS (cmp_op_mode)));
247 icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
248 if (icode == CODE_FOR_nothing)
250 if (tcode == LT_EXPR
251 && op0a == op0)
253 /* A VEC_COND_EXPR condition could be folded from EQ_EXPR/NE_EXPR
254 into a constant when only get_vcond_eq_icode is supported.
255 Try changing it to NE_EXPR. */
256 tcode = NE_EXPR;
258 if ((tcode == EQ_EXPR || tcode == NE_EXPR)
259 && direct_internal_fn_supported_p (IFN_VCONDEQ, TREE_TYPE (lhs),
260 TREE_TYPE (op0a),
261 OPTIMIZE_FOR_BOTH))
263 tree tcode_tree = build_int_cst (integer_type_node, tcode);
264 return gimple_build_call_internal (IFN_VCONDEQ, 5, op0a, op0b, op1,
265 op2, tcode_tree);
268 gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0))
269 && can_compute_op0
270 && (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
271 != CODE_FOR_nothing));
272 return gimple_build_call_internal (IFN_VCOND_MASK, 3, op0, op1, op2);
275 tree tcode_tree = build_int_cst (integer_type_node, tcode);
276 return gimple_build_call_internal (unsignedp ? IFN_VCONDU : IFN_VCOND,
277 5, op0a, op0b, op1, op2, tcode_tree);
282 /* Iterate all gimple statements and try to expand
283 VEC_COND_EXPR assignments. */
285 static unsigned int
286 gimple_expand_vec_exprs (struct function *fun)
288 gimple_stmt_iterator gsi;
289 basic_block bb;
290 hash_map<tree, unsigned int> vec_cond_ssa_name_uses;
291 auto_bitmap dce_ssa_names;
293 FOR_EACH_BB_FN (bb, fun)
295 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
297 gimple *g = gimple_expand_vec_cond_expr (fun, &gsi,
298 &vec_cond_ssa_name_uses);
299 if (g != NULL)
301 tree lhs = gimple_assign_lhs (gsi_stmt (gsi));
302 gimple_set_lhs (g, lhs);
303 gsi_replace (&gsi, g, false);
306 gimple_expand_vec_set_expr (fun, &gsi);
307 if (gsi_end_p (gsi))
308 break;
312 for (hash_map<tree, unsigned int>::iterator it = vec_cond_ssa_name_uses.begin ();
313 it != vec_cond_ssa_name_uses.end (); ++it)
314 bitmap_set_bit (dce_ssa_names, SSA_NAME_VERSION ((*it).first));
316 simple_dce_from_worklist (dce_ssa_names);
318 return 0;
321 namespace {
323 const pass_data pass_data_gimple_isel =
325 GIMPLE_PASS, /* type */
326 "isel", /* name */
327 OPTGROUP_VEC, /* optinfo_flags */
328 TV_NONE, /* tv_id */
329 PROP_cfg, /* properties_required */
330 0, /* properties_provided */
331 0, /* properties_destroyed */
332 0, /* todo_flags_start */
333 TODO_update_ssa, /* todo_flags_finish */
336 class pass_gimple_isel : public gimple_opt_pass
338 public:
339 pass_gimple_isel (gcc::context *ctxt)
340 : gimple_opt_pass (pass_data_gimple_isel, ctxt)
343 /* opt_pass methods: */
344 virtual bool gate (function *)
346 return true;
349 virtual unsigned int execute (function *fun)
351 return gimple_expand_vec_exprs (fun);
354 }; // class pass_gimple_isel
356 } // anon namespace
358 gimple_opt_pass *
359 make_pass_gimple_isel (gcc::context *ctxt)
361 return new pass_gimple_isel (ctxt);