]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gimple-isel.cc
gcov: rename 2 options.
[thirdparty/gcc.git] / gcc / gimple-isel.cc
CommitLineData
502d63b6
ML
1/* Schedule GIMPLE vector statements.
2 Copyright (C) 2020 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 3, or (at your option) any
9later version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT
12ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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"
a8d8caca
ML
36#include "bitmap.h"
37#include "tree-ssa-dce.h"
502d63b6
ML
38
39/* Expand all VEC_COND_EXPR gimple assignments into calls to internal
40 function based on type of selected expansion. */
41
42static gimple *
43gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
44 hash_map<tree, unsigned int> *vec_cond_ssa_name_uses)
45{
46 tree lhs, op0a = NULL_TREE, op0b = NULL_TREE;
47 enum tree_code code;
48 enum tree_code tcode;
49 machine_mode cmp_op_mode;
50 bool unsignedp;
51 enum insn_code icode;
52 imm_use_iterator imm_iter;
53
54 /* Only consider code == GIMPLE_ASSIGN. */
55 gassign *stmt = dyn_cast<gassign *> (gsi_stmt (*gsi));
56 if (!stmt)
57 return NULL;
58
59 code = gimple_assign_rhs_code (stmt);
60 if (code != VEC_COND_EXPR)
61 return NULL;
62
63 tree op0 = gimple_assign_rhs1 (stmt);
64 tree op1 = gimple_assign_rhs2 (stmt);
65 tree op2 = gimple_assign_rhs3 (stmt);
66 lhs = gimple_assign_lhs (stmt);
67 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
68
69 gcc_assert (!COMPARISON_CLASS_P (op0));
70 if (TREE_CODE (op0) == SSA_NAME)
71 {
72 unsigned int used_vec_cond_exprs = 0;
73 unsigned int *slot = vec_cond_ssa_name_uses->get (op0);
74 if (slot)
75 used_vec_cond_exprs = *slot;
76 else
77 {
78 gimple *use_stmt;
79 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, op0)
80 {
81 gassign *assign = dyn_cast<gassign *> (use_stmt);
82 if (assign != NULL
83 && gimple_assign_rhs_code (assign) == VEC_COND_EXPR
84 && gimple_assign_rhs1 (assign) == op0)
85 used_vec_cond_exprs++;
86 }
87 vec_cond_ssa_name_uses->put (op0, used_vec_cond_exprs);
88 }
89
90 gassign *def_stmt = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (op0));
91 if (def_stmt)
92 {
93 tcode = gimple_assign_rhs_code (def_stmt);
94 op0a = gimple_assign_rhs1 (def_stmt);
95 op0b = gimple_assign_rhs2 (def_stmt);
96
97 tree op0a_type = TREE_TYPE (op0a);
98 if (used_vec_cond_exprs >= 2
99 && (get_vcond_mask_icode (mode, TYPE_MODE (op0a_type))
100 != CODE_FOR_nothing)
101 && expand_vec_cmp_expr_p (op0a_type, TREE_TYPE (lhs), tcode))
102 {
103 /* Keep the SSA name and use vcond_mask. */
104 tcode = TREE_CODE (op0);
105 }
106 }
107 else
108 tcode = TREE_CODE (op0);
109 }
110 else
111 tcode = TREE_CODE (op0);
112
113 if (TREE_CODE_CLASS (tcode) != tcc_comparison)
114 {
115 gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
116 if (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
117 != CODE_FOR_nothing)
118 return gimple_build_call_internal (IFN_VCOND_MASK, 3, op0, op1, op2);
119 /* Fake op0 < 0. */
120 else
121 {
122 gcc_assert (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (op0)))
123 == MODE_VECTOR_INT);
124 op0a = op0;
125 op0b = build_zero_cst (TREE_TYPE (op0));
126 tcode = LT_EXPR;
127 }
128 }
129 cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
130 unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
131
132
133 gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode))
134 && known_eq (GET_MODE_NUNITS (mode),
135 GET_MODE_NUNITS (cmp_op_mode)));
136
137 icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
138 if (icode == CODE_FOR_nothing)
139 {
140 if (tcode == LT_EXPR
141 && op0a == op0
142 && TREE_CODE (op0) == VECTOR_CST)
143 {
144 /* A VEC_COND_EXPR condition could be folded from EQ_EXPR/NE_EXPR
145 into a constant when only get_vcond_eq_icode is supported.
146 Verify < 0 and != 0 behave the same and change it to NE_EXPR. */
147 unsigned HOST_WIDE_INT nelts;
148 if (!VECTOR_CST_NELTS (op0).is_constant (&nelts))
149 {
150 if (VECTOR_CST_STEPPED_P (op0))
151 gcc_unreachable ();
152 nelts = vector_cst_encoded_nelts (op0);
153 }
154 for (unsigned int i = 0; i < nelts; ++i)
155 if (tree_int_cst_sgn (vector_cst_elt (op0, i)) == 1)
156 gcc_unreachable ();
157 tcode = NE_EXPR;
158 }
159 if (tcode == EQ_EXPR || tcode == NE_EXPR)
160 {
161 tree tcode_tree = build_int_cst (integer_type_node, tcode);
162 return gimple_build_call_internal (IFN_VCONDEQ, 5, op0a, op0b, op1,
163 op2, tcode_tree);
164 }
165 }
166
167 gcc_assert (icode != CODE_FOR_nothing);
168 tree tcode_tree = build_int_cst (integer_type_node, tcode);
169 return gimple_build_call_internal (unsignedp ? IFN_VCONDU : IFN_VCOND,
170 5, op0a, op0b, op1, op2, tcode_tree);
171}
172
173
174
175/* Iterate all gimple statements and try to expand
176 VEC_COND_EXPR assignments. */
177
178static unsigned int
179gimple_expand_vec_cond_exprs (void)
180{
181 gimple_stmt_iterator gsi;
182 basic_block bb;
502d63b6 183 hash_map<tree, unsigned int> vec_cond_ssa_name_uses;
a8d8caca 184 auto_bitmap dce_ssa_names;
502d63b6
ML
185
186 FOR_EACH_BB_FN (bb, cfun)
187 {
188 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
189 {
190 gimple *g = gimple_expand_vec_cond_expr (&gsi,
191 &vec_cond_ssa_name_uses);
192 if (g != NULL)
193 {
194 tree lhs = gimple_assign_lhs (gsi_stmt (gsi));
195 gimple_set_lhs (g, lhs);
196 gsi_replace (&gsi, g, false);
197 }
198 }
199 }
200
a8d8caca
ML
201 for (hash_map<tree, unsigned int>::iterator it = vec_cond_ssa_name_uses.begin ();
202 it != vec_cond_ssa_name_uses.end (); ++it)
203 bitmap_set_bit (dce_ssa_names, SSA_NAME_VERSION ((*it).first));
204
205 simple_dce_from_worklist (dce_ssa_names);
206
207 return 0;
502d63b6
ML
208}
209
210namespace {
211
212const pass_data pass_data_gimple_isel =
213{
214 GIMPLE_PASS, /* type */
215 "isel", /* name */
216 OPTGROUP_VEC, /* optinfo_flags */
217 TV_NONE, /* tv_id */
218 PROP_cfg, /* properties_required */
219 0, /* properties_provided */
220 0, /* properties_destroyed */
221 0, /* todo_flags_start */
222 TODO_update_ssa, /* todo_flags_finish */
223};
224
225class pass_gimple_isel : public gimple_opt_pass
226{
227public:
228 pass_gimple_isel (gcc::context *ctxt)
229 : gimple_opt_pass (pass_data_gimple_isel, ctxt)
230 {}
231
232 /* opt_pass methods: */
233 virtual bool gate (function *)
234 {
235 return true;
236 }
237
238 virtual unsigned int execute (function *)
239 {
240 return gimple_expand_vec_cond_exprs ();
241 }
242
243}; // class pass_gimple_isel
244
245} // anon namespace
246
247gimple_opt_pass *
248make_pass_gimple_isel (gcc::context *ctxt)
249{
250 return new pass_gimple_isel (ctxt);
251}
252