[ARM] Fix CLZ_DEFINED_VALUE_AT_ZERO for vector modes
[official-gcc.git] / gcc / optabs.h
blob91e36d61b3bc10ed8a5ba4cf5b368e7e341a3d49
1 /* Definitions for code generation pass of GNU compiler.
2 Copyright (C) 2001-2014 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License 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 #ifndef GCC_OPTABS_H
21 #define GCC_OPTABS_H
23 #include "insn-opinit.h"
25 /* Generate code for a widening multiply. */
26 extern rtx expand_widening_mult (machine_mode, rtx, rtx, rtx, int, optab);
28 /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
29 if the target does not have such an insn. */
31 static inline enum insn_code
32 optab_handler (optab op, machine_mode mode)
34 unsigned scode = (op << 16) | mode;
35 gcc_assert (op > LAST_CONV_OPTAB);
36 return raw_optab_handler (scode);
39 /* Return the insn used to perform conversion OP from mode FROM_MODE
40 to mode TO_MODE; return CODE_FOR_nothing if the target does not have
41 such an insn. */
43 static inline enum insn_code
44 convert_optab_handler (convert_optab op, machine_mode to_mode,
45 machine_mode from_mode)
47 unsigned scode = (op << 16) | (from_mode << 8) | to_mode;
48 gcc_assert (op > unknown_optab && op <= LAST_CONV_OPTAB);
49 return raw_optab_handler (scode);
52 /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
53 if the target does not have such an insn. */
55 static inline enum insn_code
56 direct_optab_handler (direct_optab op, machine_mode mode)
58 return optab_handler (op, mode);
61 /* Return true if UNOPTAB is for a trapping-on-overflow operation. */
63 static inline bool
64 trapv_unoptab_p (optab unoptab)
66 return (unoptab == negv_optab
67 || unoptab == absv_optab);
70 /* Return true if BINOPTAB is for a trapping-on-overflow operation. */
72 static inline bool
73 trapv_binoptab_p (optab binoptab)
75 return (binoptab == addv_optab
76 || binoptab == subv_optab
77 || binoptab == smulv_optab);
82 /* Describes an instruction that inserts or extracts a bitfield. */
83 struct extraction_insn
85 /* The code of the instruction. */
86 enum insn_code icode;
88 /* The mode that the structure operand should have. This is byte_mode
89 when using the legacy insv, extv and extzv patterns to access memory. */
90 machine_mode struct_mode;
92 /* The mode of the field to be inserted or extracted, and by extension
93 the mode of the insertion or extraction itself. */
94 machine_mode field_mode;
96 /* The mode of the field's bit position. This is only important
97 when the position is variable rather than constant. */
98 machine_mode pos_mode;
104 /* Describes the type of an expand_operand. Each value is associated
105 with a create_*_operand function; see the comments above those
106 functions for details. */
107 enum expand_operand_type {
108 EXPAND_FIXED,
109 EXPAND_OUTPUT,
110 EXPAND_INPUT,
111 EXPAND_CONVERT_TO,
112 EXPAND_CONVERT_FROM,
113 EXPAND_ADDRESS,
114 EXPAND_INTEGER
117 /* Information about an operand for instruction expansion. */
118 struct expand_operand {
119 /* The type of operand. */
120 ENUM_BITFIELD (expand_operand_type) type : 8;
122 /* True if any conversion should treat VALUE as being unsigned
123 rather than signed. Only meaningful for certain types. */
124 unsigned int unsigned_p : 1;
126 /* Unused; available for future use. */
127 unsigned int unused : 7;
129 /* The mode passed to the convert_*_operand function. It has a
130 type-dependent meaning. */
131 ENUM_BITFIELD (machine_mode) mode : 16;
133 /* The value of the operand. */
134 rtx value;
137 /* Initialize OP with the given fields. Initialise the other fields
138 to their default values. */
140 static inline void
141 create_expand_operand (struct expand_operand *op,
142 enum expand_operand_type type,
143 rtx value, machine_mode mode,
144 bool unsigned_p)
146 op->type = type;
147 op->unsigned_p = unsigned_p;
148 op->unused = 0;
149 op->mode = mode;
150 op->value = value;
153 /* Make OP describe an operand that must use rtx X, even if X is volatile. */
155 static inline void
156 create_fixed_operand (struct expand_operand *op, rtx x)
158 create_expand_operand (op, EXPAND_FIXED, x, VOIDmode, false);
161 /* Make OP describe an output operand that must have mode MODE.
162 X, if nonnull, is a suggestion for where the output should be stored.
163 It is OK for VALUE to be inconsistent with MODE, although it will just
164 be ignored in that case. */
166 static inline void
167 create_output_operand (struct expand_operand *op, rtx x,
168 machine_mode mode)
170 create_expand_operand (op, EXPAND_OUTPUT, x, mode, false);
173 /* Make OP describe an input operand that must have mode MODE and
174 value VALUE; MODE cannot be VOIDmode. The backend may request that
175 VALUE be copied into a different kind of rtx before being passed
176 as an operand. */
178 static inline void
179 create_input_operand (struct expand_operand *op, rtx value,
180 machine_mode mode)
182 create_expand_operand (op, EXPAND_INPUT, value, mode, false);
185 /* Like create_input_operand, except that VALUE must first be converted
186 to mode MODE. UNSIGNED_P says whether VALUE is unsigned. */
188 static inline void
189 create_convert_operand_to (struct expand_operand *op, rtx value,
190 machine_mode mode, bool unsigned_p)
192 create_expand_operand (op, EXPAND_CONVERT_TO, value, mode, unsigned_p);
195 /* Make OP describe an input operand that should have the same value
196 as VALUE, after any mode conversion that the backend might request.
197 If VALUE is a CONST_INT, it should be treated as having mode MODE.
198 UNSIGNED_P says whether VALUE is unsigned. */
200 static inline void
201 create_convert_operand_from (struct expand_operand *op, rtx value,
202 machine_mode mode, bool unsigned_p)
204 create_expand_operand (op, EXPAND_CONVERT_FROM, value, mode, unsigned_p);
208 /* Make OP describe an input Pmode address operand. VALUE is the value
209 of the address, but it may need to be converted to Pmode first. */
211 static inline void
212 create_address_operand (struct expand_operand *op, rtx value)
214 create_expand_operand (op, EXPAND_ADDRESS, value, Pmode, false);
217 /* Make OP describe an input operand that has value INTVAL and that has
218 no inherent mode. This function should only be used for operands that
219 are always expand-time constants. The backend may request that INTVAL
220 be copied into a different kind of rtx, but it must specify the mode
221 of that rtx if so. */
223 static inline void
224 create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval)
226 create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
230 extern rtx convert_optab_libfunc (convert_optab optab, machine_mode mode1,
231 machine_mode mode2);
232 extern rtx optab_libfunc (optab optab, machine_mode mode);
233 extern enum insn_code widening_optab_handler (optab, machine_mode,
234 machine_mode);
235 /* Find a widening optab even if it doesn't widen as much as we want. */
236 #define find_widening_optab_handler(A,B,C,D) \
237 find_widening_optab_handler_and_mode (A, B, C, D, NULL)
238 extern enum insn_code find_widening_optab_handler_and_mode (optab,
239 machine_mode,
240 machine_mode,
241 int,
242 machine_mode *);
244 /* An extra flag to control optab_for_tree_code's behavior. This is needed to
245 distinguish between machines with a vector shift that takes a scalar for the
246 shift amount vs. machines that take a vector for the shift amount. */
247 enum optab_subtype
249 optab_default,
250 optab_scalar,
251 optab_vector
254 /* Passed to expand_simple_binop and expand_binop to say which options
255 to try to use if the requested operation can't be open-coded on the
256 requisite mode. Either OPTAB_LIB or OPTAB_LIB_WIDEN says try using
257 a library call. Either OPTAB_WIDEN or OPTAB_LIB_WIDEN says try
258 using a wider mode. OPTAB_MUST_WIDEN says try widening and don't
259 try anything else. */
261 enum optab_methods
263 OPTAB_DIRECT,
264 OPTAB_LIB,
265 OPTAB_WIDEN,
266 OPTAB_LIB_WIDEN,
267 OPTAB_MUST_WIDEN
270 /* Return the optab used for computing the given operation on the type given by
271 the second argument. The third argument distinguishes between the types of
272 vector shifts and rotates */
273 extern optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
275 /* Given an optab that reduces a vector to a scalar, find instead the old
276 optab that produces a vector with the reduction result in one element,
277 for a tree with the specified type. */
278 extern optab scalar_reduc_to_vector (optab, const_tree type);
280 extern rtx expand_widen_pattern_expr (struct separate_ops *, rtx , rtx , rtx,
281 rtx, int);
282 extern rtx expand_ternary_op (machine_mode mode, optab ternary_optab,
283 rtx op0, rtx op1, rtx op2, rtx target,
284 int unsignedp);
285 extern rtx simplify_expand_binop (machine_mode mode, optab binoptab,
286 rtx op0, rtx op1, rtx target, int unsignedp,
287 enum optab_methods methods);
288 extern bool force_expand_binop (machine_mode, optab, rtx, rtx, rtx, int,
289 enum optab_methods);
290 /* Generate code for VEC_RSHIFT_EXPR. */
291 extern rtx expand_vec_shift_expr (struct separate_ops *, rtx);
293 /* Generate code for a simple binary or unary operation. "Simple" in
294 this case means "can be unambiguously described by a (mode, code)
295 pair and mapped to a single optab." */
296 extern rtx expand_simple_binop (machine_mode, enum rtx_code, rtx,
297 rtx, rtx, int, enum optab_methods);
299 /* Expand a binary operation given optab and rtx operands. */
300 extern rtx expand_binop (machine_mode, optab, rtx, rtx, rtx, int,
301 enum optab_methods);
303 /* Expand a binary operation with both signed and unsigned forms. */
304 extern rtx sign_expand_binop (machine_mode, optab, optab, rtx, rtx,
305 rtx, int, enum optab_methods);
307 /* Generate code to perform an operation on one operand with two results. */
308 extern int expand_twoval_unop (optab, rtx, rtx, rtx, int);
310 /* Generate code to perform an operation on two operands with two results. */
311 extern int expand_twoval_binop (optab, rtx, rtx, rtx, rtx, int);
313 /* Generate code to perform an operation on two operands with two
314 results, using a library function. */
315 extern bool expand_twoval_binop_libfunc (optab, rtx, rtx, rtx, rtx,
316 enum rtx_code);
317 extern rtx expand_simple_unop (machine_mode, enum rtx_code, rtx, rtx,
318 int);
320 /* Expand a unary arithmetic operation given optab rtx operand. */
321 extern rtx expand_unop (machine_mode, optab, rtx, rtx, int);
323 /* Expand the absolute value operation. */
324 extern rtx expand_abs_nojump (machine_mode, rtx, rtx, int);
325 extern rtx expand_abs (machine_mode, rtx, rtx, int, int);
327 /* Expand the one's complement absolute value operation. */
328 extern rtx expand_one_cmpl_abs_nojump (machine_mode, rtx, rtx);
330 /* Expand the copysign operation. */
331 extern rtx expand_copysign (rtx, rtx, rtx);
332 /* Generate an instruction with a given INSN_CODE with an output and
333 an input. */
334 extern bool maybe_emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
335 extern void emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
337 /* Emit code to make a call to a constant function or a library call. */
338 extern void emit_libcall_block (rtx, rtx, rtx, rtx);
340 /* The various uses that a comparison can have; used by can_compare_p:
341 jumps, conditional moves, store flag operations. */
342 enum can_compare_purpose
344 ccp_jump,
345 ccp_cmov,
346 ccp_store_flag
349 /* Nonzero if a compare of mode MODE can be done straightforwardly
350 (without splitting it into pieces). */
351 extern int can_compare_p (enum rtx_code, machine_mode,
352 enum can_compare_purpose);
353 extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
354 machine_mode, int);
355 /* Emit a pair of rtl insns to compare two rtx's and to jump
356 to a label if the comparison is true. */
357 extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
358 machine_mode, int, rtx, int prob=-1);
360 /* Generate code to indirectly jump to a location given in the rtx LOC. */
361 extern void emit_indirect_jump (rtx);
363 #include "insn-config.h"
365 #ifndef GCC_INSN_CONFIG_H
366 #error "insn-config.h must be included before optabs.h"
367 #endif
369 #ifdef HAVE_conditional_move
370 /* Emit a conditional move operation. */
371 rtx emit_conditional_move (rtx, enum rtx_code, rtx, rtx, machine_mode,
372 rtx, rtx, machine_mode, int);
374 /* Return nonzero if the conditional move is supported. */
375 int can_conditionally_move_p (machine_mode mode);
377 #endif
378 rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx, machine_mode,
379 rtx, rtx, machine_mode, int);
381 /* Create but don't emit one rtl instruction to perform certain operations.
382 Modes must match; operands must meet the operation's predicates.
383 Likewise for subtraction and for just copying. */
384 extern rtx gen_add2_insn (rtx, rtx);
385 extern rtx gen_add3_insn (rtx, rtx, rtx);
386 extern int have_add2_insn (rtx, rtx);
387 extern rtx gen_addptr3_insn (rtx, rtx, rtx);
388 extern int have_addptr3_insn (rtx, rtx, rtx);
389 extern rtx gen_sub2_insn (rtx, rtx);
390 extern rtx gen_sub3_insn (rtx, rtx, rtx);
391 extern int have_sub2_insn (rtx, rtx);
393 /* Return the INSN_CODE to use for an extend operation. */
394 extern enum insn_code can_extend_p (machine_mode, machine_mode, int);
396 /* Generate the body of an insn to extend Y (with mode MFROM)
397 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
398 extern rtx gen_extend_insn (rtx, rtx, machine_mode,
399 machine_mode, int);
401 /* Return the insn_code for a FLOAT_EXPR. */
402 enum insn_code can_float_p (machine_mode, machine_mode, int);
404 /* Check whether an operation represented by the code CODE is a
405 convert operation that is supported by the target platform in
406 vector form */
407 bool supportable_convert_operation (enum tree_code, tree, tree, tree *,
408 enum tree_code *);
410 /* Generate code for a FLOAT_EXPR. */
411 extern void expand_float (rtx, rtx, int);
413 /* Generate code for a FIX_EXPR. */
414 extern void expand_fix (rtx, rtx, int);
416 /* Generate code for a FIXED_CONVERT_EXPR. */
417 extern void expand_fixed_convert (rtx, rtx, int, int);
419 /* Generate code for float to integral conversion. */
420 extern bool expand_sfix_optab (rtx, rtx, convert_optab);
422 /* Report whether the machine description contains an insn which can
423 perform the operation described by CODE and MODE. */
424 extern int have_insn_for (enum rtx_code, machine_mode);
426 extern void gen_int_libfunc (optab, const char *, char, machine_mode);
427 extern void gen_fp_libfunc (optab, const char *, char, machine_mode);
428 extern void gen_fixed_libfunc (optab, const char *, char, machine_mode);
429 extern void gen_signed_fixed_libfunc (optab, const char *, char,
430 machine_mode);
431 extern void gen_unsigned_fixed_libfunc (optab, const char *, char,
432 machine_mode);
433 extern void gen_int_fp_libfunc (optab, const char *, char, machine_mode);
434 extern void gen_intv_fp_libfunc (optab, const char *, char, machine_mode);
435 extern void gen_int_fp_fixed_libfunc (optab, const char *, char,
436 machine_mode);
437 extern void gen_int_fp_signed_fixed_libfunc (optab, const char *, char,
438 machine_mode);
439 extern void gen_int_fixed_libfunc (optab, const char *, char,
440 machine_mode);
441 extern void gen_int_signed_fixed_libfunc (optab, const char *, char,
442 machine_mode);
443 extern void gen_int_unsigned_fixed_libfunc (optab, const char *, char,
444 machine_mode);
446 extern void gen_interclass_conv_libfunc (convert_optab, const char *,
447 machine_mode, machine_mode);
448 extern void gen_int_to_fp_conv_libfunc (convert_optab, const char *,
449 machine_mode, machine_mode);
450 extern void gen_ufloat_conv_libfunc (convert_optab, const char *,
451 machine_mode, machine_mode);
452 extern void gen_int_to_fp_nondecimal_conv_libfunc (convert_optab,
453 const char *,
454 machine_mode,
455 machine_mode);
456 extern void gen_fp_to_int_conv_libfunc (convert_optab, const char *,
457 machine_mode, machine_mode);
458 extern void gen_intraclass_conv_libfunc (convert_optab, const char *,
459 machine_mode, machine_mode);
460 extern void gen_trunc_conv_libfunc (convert_optab, const char *,
461 machine_mode, machine_mode);
462 extern void gen_extend_conv_libfunc (convert_optab, const char *,
463 machine_mode, machine_mode);
464 extern void gen_fract_conv_libfunc (convert_optab, const char *,
465 machine_mode, machine_mode);
466 extern void gen_fractuns_conv_libfunc (convert_optab, const char *,
467 machine_mode, machine_mode);
468 extern void gen_satfract_conv_libfunc (convert_optab, const char *,
469 machine_mode, machine_mode);
470 extern void gen_satfractuns_conv_libfunc (convert_optab, const char *,
471 machine_mode,
472 machine_mode);
474 /* Build a decl for a libfunc named NAME. */
475 extern tree build_libfunc_function (const char *);
477 /* Call this to initialize an optab function entry. */
478 extern rtx init_one_libfunc (const char *);
479 extern rtx set_user_assembler_libfunc (const char *, const char *);
481 /* Call this to reset the function entry for one optab. */
482 extern void set_optab_libfunc (optab, machine_mode, const char *);
483 extern void set_conv_libfunc (convert_optab, machine_mode,
484 machine_mode, const char *);
486 /* Call this once to initialize the contents of the optabs
487 appropriately for the current target machine. */
488 extern void init_optabs (void);
489 extern void init_tree_optimization_optabs (tree);
491 /* Call this to install all of the __sync libcalls up to size MAX. */
492 extern void init_sync_libfuncs (int max);
494 /* Generate a conditional trap instruction. */
495 extern rtx gen_cond_trap (enum rtx_code, rtx, rtx, rtx);
497 /* Return true if target supports vector operations for VEC_PERM_EXPR. */
498 extern bool can_vec_perm_p (machine_mode, bool, const unsigned char *);
500 /* Generate code for VEC_PERM_EXPR. */
501 extern rtx expand_vec_perm (machine_mode, rtx, rtx, rtx, rtx);
503 /* Return tree if target supports vector operations for COND_EXPR. */
504 bool expand_vec_cond_expr_p (tree, tree);
506 /* Generate code for VEC_COND_EXPR. */
507 extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
509 /* Return non-zero if target supports a given highpart multiplication. */
510 extern int can_mult_highpart_p (machine_mode, bool);
512 /* Generate code for MULT_HIGHPART_EXPR. */
513 extern rtx expand_mult_highpart (machine_mode, rtx, rtx, rtx, bool);
515 /* Return true if target supports vector masked load/store for mode. */
516 extern bool can_vec_mask_load_store_p (machine_mode, bool);
518 /* Return true if there is an inline compare and swap pattern. */
519 extern bool can_compare_and_swap_p (machine_mode, bool);
521 /* Return true if there is an inline atomic exchange pattern. */
522 extern bool can_atomic_exchange_p (machine_mode, bool);
524 extern rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
525 extern rtx expand_atomic_test_and_set (rtx, rtx, enum memmodel);
526 extern rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
527 extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
528 enum memmodel, enum memmodel);
529 /* Generate memory barriers. */
530 extern void expand_mem_thread_fence (enum memmodel);
531 extern void expand_mem_signal_fence (enum memmodel);
533 rtx expand_atomic_load (rtx, rtx, enum memmodel);
534 rtx expand_atomic_store (rtx, rtx, enum memmodel, bool);
535 rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel,
536 bool);
538 extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
539 rtx operand);
540 extern bool valid_multiword_target_p (rtx);
541 extern void create_convert_operand_from_type (struct expand_operand *op,
542 rtx value, tree type);
543 extern bool maybe_legitimize_operands (enum insn_code icode,
544 unsigned int opno, unsigned int nops,
545 struct expand_operand *ops);
546 extern rtx maybe_gen_insn (enum insn_code icode, unsigned int nops,
547 struct expand_operand *ops);
548 extern bool maybe_expand_insn (enum insn_code icode, unsigned int nops,
549 struct expand_operand *ops);
550 extern bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
551 struct expand_operand *ops);
552 extern void expand_insn (enum insn_code icode, unsigned int nops,
553 struct expand_operand *ops);
554 extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
555 struct expand_operand *ops);
557 /* Enumerates the possible extraction_insn operations. */
558 enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
560 extern bool get_best_reg_extraction_insn (extraction_insn *,
561 enum extraction_pattern,
562 unsigned HOST_WIDE_INT,
563 machine_mode);
564 extern bool get_best_mem_extraction_insn (extraction_insn *,
565 enum extraction_pattern,
566 HOST_WIDE_INT, HOST_WIDE_INT,
567 machine_mode);
569 extern bool lshift_cheap_p (bool);
571 #endif /* GCC_OPTABS_H */