1 /* Tree-based target query functions relating to optabs
2    Copyright (C) 1987-2019 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 under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 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 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "target.h"
25 #include "insn-codes.h"
26 #include "tree.h"
27 #include "optabs-tree.h"
28 #include "stor-layout.h"
29 
30 /* Return the optab used for computing the operation given by the tree code,
31    CODE and the tree EXP.  This function is not always usable (for example, it
32    cannot give complete results for multiplication or division) but probably
33    ought to be relied on more widely throughout the expander.  */
34 optab
optab_for_tree_code(enum tree_code code,const_tree type,enum optab_subtype subtype)35 optab_for_tree_code (enum tree_code code, const_tree type,
36 		     enum optab_subtype subtype)
37 {
38   bool trapv;
39   switch (code)
40     {
41     case BIT_AND_EXPR:
42       return and_optab;
43 
44     case BIT_IOR_EXPR:
45       return ior_optab;
46 
47     case BIT_NOT_EXPR:
48       return one_cmpl_optab;
49 
50     case BIT_XOR_EXPR:
51       return xor_optab;
52 
53     case MULT_HIGHPART_EXPR:
54       return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab;
55 
56     case TRUNC_MOD_EXPR:
57     case CEIL_MOD_EXPR:
58     case FLOOR_MOD_EXPR:
59     case ROUND_MOD_EXPR:
60       return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
61 
62     case RDIV_EXPR:
63     case TRUNC_DIV_EXPR:
64     case CEIL_DIV_EXPR:
65     case FLOOR_DIV_EXPR:
66     case ROUND_DIV_EXPR:
67     case EXACT_DIV_EXPR:
68       if (TYPE_SATURATING (type))
69 	return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
70       return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
71 
72     case LSHIFT_EXPR:
73       if (TREE_CODE (type) == VECTOR_TYPE)
74 	{
75 	  if (subtype == optab_vector)
76 	    return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
77 
78 	  gcc_assert (subtype == optab_scalar);
79 	}
80       if (TYPE_SATURATING (type))
81 	return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
82       return ashl_optab;
83 
84     case RSHIFT_EXPR:
85       if (TREE_CODE (type) == VECTOR_TYPE)
86 	{
87 	  if (subtype == optab_vector)
88 	    return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
89 
90 	  gcc_assert (subtype == optab_scalar);
91 	}
92       return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
93 
94     case LROTATE_EXPR:
95       if (TREE_CODE (type) == VECTOR_TYPE)
96 	{
97 	  if (subtype == optab_vector)
98 	    return vrotl_optab;
99 
100 	  gcc_assert (subtype == optab_scalar);
101 	}
102       return rotl_optab;
103 
104     case RROTATE_EXPR:
105       if (TREE_CODE (type) == VECTOR_TYPE)
106 	{
107 	  if (subtype == optab_vector)
108 	    return vrotr_optab;
109 
110 	  gcc_assert (subtype == optab_scalar);
111 	}
112       return rotr_optab;
113 
114     case MAX_EXPR:
115       return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
116 
117     case MIN_EXPR:
118       return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
119 
120     case REALIGN_LOAD_EXPR:
121       return vec_realign_load_optab;
122 
123     case WIDEN_SUM_EXPR:
124       return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
125 
126     case DOT_PROD_EXPR:
127       return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
128 
129     case SAD_EXPR:
130       return TYPE_UNSIGNED (type) ? usad_optab : ssad_optab;
131 
132     case WIDEN_MULT_PLUS_EXPR:
133       return (TYPE_UNSIGNED (type)
134 	      ? (TYPE_SATURATING (type)
135 		 ? usmadd_widen_optab : umadd_widen_optab)
136 	      : (TYPE_SATURATING (type)
137 		 ? ssmadd_widen_optab : smadd_widen_optab));
138 
139     case WIDEN_MULT_MINUS_EXPR:
140       return (TYPE_UNSIGNED (type)
141 	      ? (TYPE_SATURATING (type)
142 		 ? usmsub_widen_optab : umsub_widen_optab)
143 	      : (TYPE_SATURATING (type)
144 		 ? ssmsub_widen_optab : smsub_widen_optab));
145 
146     case VEC_WIDEN_MULT_HI_EXPR:
147       return (TYPE_UNSIGNED (type)
148 	      ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab);
149 
150     case VEC_WIDEN_MULT_LO_EXPR:
151       return (TYPE_UNSIGNED (type)
152 	      ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab);
153 
154     case VEC_WIDEN_MULT_EVEN_EXPR:
155       return (TYPE_UNSIGNED (type)
156 	      ? vec_widen_umult_even_optab : vec_widen_smult_even_optab);
157 
158     case VEC_WIDEN_MULT_ODD_EXPR:
159       return (TYPE_UNSIGNED (type)
160 	      ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab);
161 
162     case VEC_WIDEN_LSHIFT_HI_EXPR:
163       return (TYPE_UNSIGNED (type)
164 	      ? vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab);
165 
166     case VEC_WIDEN_LSHIFT_LO_EXPR:
167       return (TYPE_UNSIGNED (type)
168 	      ? vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab);
169 
170     case VEC_UNPACK_HI_EXPR:
171       return (TYPE_UNSIGNED (type)
172 	      ? vec_unpacku_hi_optab : vec_unpacks_hi_optab);
173 
174     case VEC_UNPACK_LO_EXPR:
175       return (TYPE_UNSIGNED (type)
176 	      ? vec_unpacku_lo_optab : vec_unpacks_lo_optab);
177 
178     case VEC_UNPACK_FLOAT_HI_EXPR:
179       /* The signedness is determined from input operand.  */
180       return (TYPE_UNSIGNED (type)
181 	      ? vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab);
182 
183     case VEC_UNPACK_FLOAT_LO_EXPR:
184       /* The signedness is determined from input operand.  */
185       return (TYPE_UNSIGNED (type)
186 	      ? vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab);
187 
188     case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
189       /* The signedness is determined from output operand.  */
190       return (TYPE_UNSIGNED (type)
191 	      ? vec_unpack_ufix_trunc_hi_optab
192 	      : vec_unpack_sfix_trunc_hi_optab);
193 
194     case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
195       /* The signedness is determined from output operand.  */
196       return (TYPE_UNSIGNED (type)
197 	      ? vec_unpack_ufix_trunc_lo_optab
198 	      : vec_unpack_sfix_trunc_lo_optab);
199 
200     case VEC_PACK_TRUNC_EXPR:
201       return vec_pack_trunc_optab;
202 
203     case VEC_PACK_SAT_EXPR:
204       return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
205 
206     case VEC_PACK_FIX_TRUNC_EXPR:
207       /* The signedness is determined from output operand.  */
208       return (TYPE_UNSIGNED (type)
209 	      ? vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab);
210 
211     case VEC_PACK_FLOAT_EXPR:
212       /* The signedness is determined from input operand.  */
213       return (TYPE_UNSIGNED (type)
214 	      ? vec_packu_float_optab : vec_packs_float_optab);
215 
216     case VEC_DUPLICATE_EXPR:
217       return vec_duplicate_optab;
218 
219     case VEC_SERIES_EXPR:
220       return vec_series_optab;
221 
222     default:
223       break;
224     }
225 
226   trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
227   switch (code)
228     {
229     case POINTER_PLUS_EXPR:
230     case PLUS_EXPR:
231       if (TYPE_SATURATING (type))
232 	return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
233       return trapv ? addv_optab : add_optab;
234 
235     case POINTER_DIFF_EXPR:
236     case MINUS_EXPR:
237       if (TYPE_SATURATING (type))
238 	return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
239       return trapv ? subv_optab : sub_optab;
240 
241     case MULT_EXPR:
242       if (TYPE_SATURATING (type))
243 	return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
244       return trapv ? smulv_optab : smul_optab;
245 
246     case NEGATE_EXPR:
247       if (TYPE_SATURATING (type))
248 	return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
249       return trapv ? negv_optab : neg_optab;
250 
251     case ABS_EXPR:
252       return trapv ? absv_optab : abs_optab;
253 
254     case ABSU_EXPR:
255       return abs_optab;
256     default:
257       return unknown_optab;
258     }
259 }
260 
261 /* Function supportable_convert_operation
262 
263    Check whether an operation represented by the code CODE is a
264    convert operation that is supported by the target platform in
265    vector form (i.e., when operating on arguments of type VECTYPE_IN
266    producing a result of type VECTYPE_OUT).
267 
268    Convert operations we currently support directly are FIX_TRUNC and FLOAT.
269    This function checks if these operations are supported
270    by the target platform either directly (via vector tree-codes), or via
271    target builtins.
272 
273    Output:
274    - CODE1 is code of vector operation to be used when
275    vectorizing the operation, if available.
276    - DECL is decl of target builtin functions to be used
277    when vectorizing the operation, if available.  In this case,
278    CODE1 is CALL_EXPR.  */
279 
280 bool
supportable_convert_operation(enum tree_code code,tree vectype_out,tree vectype_in,tree * decl,enum tree_code * code1)281 supportable_convert_operation (enum tree_code code,
282 			       tree vectype_out, tree vectype_in,
283 			       tree *decl, enum tree_code *code1)
284 {
285   machine_mode m1,m2;
286   bool truncp;
287 
288   m1 = TYPE_MODE (vectype_out);
289   m2 = TYPE_MODE (vectype_in);
290 
291   /* First check if we can done conversion directly.  */
292   if ((code == FIX_TRUNC_EXPR
293        && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp)
294 	  != CODE_FOR_nothing)
295       || (code == FLOAT_EXPR
296 	  && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
297 	     != CODE_FOR_nothing))
298     {
299       *code1 = code;
300       return true;
301     }
302 
303   /* Now check for builtin.  */
304   if (targetm.vectorize.builtin_conversion
305       && targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
306     {
307       *code1 = CALL_EXPR;
308       *decl = targetm.vectorize.builtin_conversion (code, vectype_out,
309 						    vectype_in);
310       return true;
311     }
312   return false;
313 }
314 
315 /* Return TRUE if appropriate vector insn is available
316    for vector comparison expr with vector type VALUE_TYPE
317    and resulting mask with MASK_TYPE.  */
318 
319 bool
expand_vec_cmp_expr_p(tree value_type,tree mask_type,enum tree_code code)320 expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
321 {
322   if (get_vec_cmp_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type),
323 			 TYPE_UNSIGNED (value_type)) != CODE_FOR_nothing)
324     return true;
325   if ((code == EQ_EXPR || code == NE_EXPR)
326       && (get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
327 	  != CODE_FOR_nothing))
328     return true;
329   return false;
330 }
331 
332 /* Return TRUE iff, appropriate vector insns are available
333    for vector cond expr with vector type VALUE_TYPE and a comparison
334    with operand vector types in CMP_OP_TYPE.  */
335 
336 bool
expand_vec_cond_expr_p(tree value_type,tree cmp_op_type,enum tree_code code)337 expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
338 {
339   machine_mode value_mode = TYPE_MODE (value_type);
340   machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
341   if (VECTOR_BOOLEAN_TYPE_P (cmp_op_type)
342       && get_vcond_mask_icode (TYPE_MODE (value_type),
343 			       TYPE_MODE (cmp_op_type)) != CODE_FOR_nothing)
344     return true;
345 
346   if (maybe_ne (GET_MODE_SIZE (value_mode), GET_MODE_SIZE (cmp_op_mode))
347       || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
348     return false;
349 
350   if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
351 		       TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
352       && ((code != EQ_EXPR && code != NE_EXPR)
353 	  || get_vcond_eq_icode (TYPE_MODE (value_type),
354 				 TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
355     return false;
356 
357   return true;
358 }
359 
360 /* Use the current target and options to initialize
361    TREE_OPTIMIZATION_OPTABS (OPTNODE).  */
362 
363 void
init_tree_optimization_optabs(tree optnode)364 init_tree_optimization_optabs (tree optnode)
365 {
366   /* Quick exit if we have already computed optabs for this target.  */
367   if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs)
368     return;
369 
370   /* Forget any previous information and set up for the current target.  */
371   TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs;
372   struct target_optabs *tmp_optabs = (struct target_optabs *)
373     TREE_OPTIMIZATION_OPTABS (optnode);
374   if (tmp_optabs)
375     memset (tmp_optabs, 0, sizeof (struct target_optabs));
376   else
377     tmp_optabs = ggc_cleared_alloc<target_optabs> ();
378 
379   /* Generate a new set of optabs into tmp_optabs.  */
380   init_all_optabs (tmp_optabs);
381 
382   /* If the optabs changed, record it.  */
383   if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
384     TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
385   else
386     {
387       TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
388       ggc_free (tmp_optabs);
389     }
390 }
391 
392 /* Return TRUE if the target has support for vector right shift of an
393    operand of type TYPE.  If OT_TYPE is OPTAB_DEFAULT, check for existence
394    of a shift by either a scalar or a vector.  Otherwise, check only
395    for a shift that matches OT_TYPE.  */
396 
397 bool
target_supports_op_p(tree type,enum tree_code code,enum optab_subtype ot_subtype)398 target_supports_op_p (tree type, enum tree_code code,
399 		      enum optab_subtype ot_subtype)
400 {
401   optab ot = optab_for_tree_code (code, type, ot_subtype);
402   return (ot != unknown_optab
403 	  && optab_handler (ot, TYPE_MODE (type)) != CODE_FOR_nothing);
404 }
405 
406