xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/optabs.h (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* Definitions for code generation pass of GNU compiler.
2    Copyright (C) 2001-2015 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
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.
10 
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.
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 #ifndef GCC_OPTABS_H
21 #define GCC_OPTABS_H
22 
23 #include "insn-opinit.h"
24 
25 /* Generate code for a widening multiply.  */
26 extern rtx expand_widening_mult (machine_mode, rtx, rtx, rtx, int, optab);
27 
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.  */
30 
31 static inline enum insn_code
32 optab_handler (optab op, machine_mode mode)
33 {
34   unsigned scode = (op << 16) | mode;
35   gcc_assert (op > LAST_CONV_OPTAB);
36   return raw_optab_handler (scode);
37 }
38 
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.  */
42 
43 static inline enum insn_code
44 convert_optab_handler (convert_optab op, machine_mode to_mode,
45 		       machine_mode from_mode)
46 {
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);
50 }
51 
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.  */
54 
55 static inline enum insn_code
56 direct_optab_handler (direct_optab op, machine_mode mode)
57 {
58   return optab_handler (op, mode);
59 }
60 
61 /* Return true if UNOPTAB is for a trapping-on-overflow operation.  */
62 
63 static inline bool
64 trapv_unoptab_p (optab unoptab)
65 {
66   return (unoptab == negv_optab
67 	  || unoptab == absv_optab);
68 }
69 
70 /* Return true if BINOPTAB is for a trapping-on-overflow operation.  */
71 
72 static inline bool
73 trapv_binoptab_p (optab binoptab)
74 {
75   return (binoptab == addv_optab
76 	  || binoptab == subv_optab
77 	  || binoptab == smulv_optab);
78 }
79 
80 
81 
82 /* Describes an instruction that inserts or extracts a bitfield.  */
83 struct extraction_insn
84 {
85   /* The code of the instruction.  */
86   enum insn_code icode;
87 
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;
91 
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;
95 
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;
99 };
100 
101 
102 
103 
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
115 };
116 
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;
121 
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;
125 
126   /* Unused; available for future use.  */
127   unsigned int unused : 7;
128 
129   /* The mode passed to the convert_*_operand function.  It has a
130      type-dependent meaning.  */
131   ENUM_BITFIELD (machine_mode) mode : 16;
132 
133   /* The value of the operand.  */
134   rtx value;
135 };
136 
137 /* Initialize OP with the given fields.  Initialise the other fields
138    to their default values.  */
139 
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)
145 {
146   op->type = type;
147   op->unsigned_p = unsigned_p;
148   op->unused = 0;
149   op->mode = mode;
150   op->value = value;
151 }
152 
153 /* Make OP describe an operand that must use rtx X, even if X is volatile.  */
154 
155 static inline void
156 create_fixed_operand (struct expand_operand *op, rtx x)
157 {
158   create_expand_operand (op, EXPAND_FIXED, x, VOIDmode, false);
159 }
160 
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.  */
165 
166 static inline void
167 create_output_operand (struct expand_operand *op, rtx x,
168 		       machine_mode mode)
169 {
170   create_expand_operand (op, EXPAND_OUTPUT, x, mode, false);
171 }
172 
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.  */
177 
178 static inline void
179 create_input_operand (struct expand_operand *op, rtx value,
180 		      machine_mode mode)
181 {
182   create_expand_operand (op, EXPAND_INPUT, value, mode, false);
183 }
184 
185 /* Like create_input_operand, except that VALUE must first be converted
186    to mode MODE.  UNSIGNED_P says whether VALUE is unsigned.  */
187 
188 static inline void
189 create_convert_operand_to (struct expand_operand *op, rtx value,
190 			   machine_mode mode, bool unsigned_p)
191 {
192   create_expand_operand (op, EXPAND_CONVERT_TO, value, mode, unsigned_p);
193 }
194 
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.  */
199 
200 static inline void
201 create_convert_operand_from (struct expand_operand *op, rtx value,
202 			     machine_mode mode, bool unsigned_p)
203 {
204   create_expand_operand (op, EXPAND_CONVERT_FROM, value, mode, unsigned_p);
205 }
206 
207 
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.  */
210 
211 static inline void
212 create_address_operand (struct expand_operand *op, rtx value)
213 {
214   create_expand_operand (op, EXPAND_ADDRESS, value, Pmode, false);
215 }
216 
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.  */
222 
223 static inline void
224 create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval)
225 {
226   create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
227 }
228 
229 
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 *);
243 
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
248 {
249   optab_default,
250   optab_scalar,
251   optab_vector
252 };
253 
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.  */
260 
261 enum optab_methods
262 {
263   OPTAB_DIRECT,
264   OPTAB_LIB,
265   OPTAB_WIDEN,
266   OPTAB_LIB_WIDEN,
267   OPTAB_MUST_WIDEN
268 };
269 
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);
274 
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);
279 
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 
291 /* Generate code for a simple binary or unary operation.  "Simple" in
292    this case means "can be unambiguously described by a (mode, code)
293    pair and mapped to a single optab."  */
294 extern rtx expand_simple_binop (machine_mode, enum rtx_code, rtx,
295 				rtx, rtx, int, enum optab_methods);
296 
297 /* Expand a binary operation given optab and rtx operands.  */
298 extern rtx expand_binop (machine_mode, optab, rtx, rtx, rtx, int,
299 			 enum optab_methods);
300 
301 /* Expand a binary operation with both signed and unsigned forms.  */
302 extern rtx sign_expand_binop (machine_mode, optab, optab, rtx, rtx,
303 			      rtx, int, enum optab_methods);
304 
305 /* Generate code to perform an operation on one operand with two results.  */
306 extern int expand_twoval_unop (optab, rtx, rtx, rtx, int);
307 
308 /* Generate code to perform an operation on two operands with two results.  */
309 extern int expand_twoval_binop (optab, rtx, rtx, rtx, rtx, int);
310 
311 /* Generate code to perform an operation on two operands with two
312    results, using a library function.  */
313 extern bool expand_twoval_binop_libfunc (optab, rtx, rtx, rtx, rtx,
314 					 enum rtx_code);
315 extern rtx expand_simple_unop (machine_mode, enum rtx_code, rtx, rtx,
316 			       int);
317 
318 /* Expand a unary arithmetic operation given optab rtx operand.  */
319 extern rtx expand_unop (machine_mode, optab, rtx, rtx, int);
320 
321 /* Expand the absolute value operation.  */
322 extern rtx expand_abs_nojump (machine_mode, rtx, rtx, int);
323 extern rtx expand_abs (machine_mode, rtx, rtx, int, int);
324 
325 /* Expand the one's complement absolute value operation.  */
326 extern rtx expand_one_cmpl_abs_nojump (machine_mode, rtx, rtx);
327 
328 /* Expand the copysign operation.  */
329 extern rtx expand_copysign (rtx, rtx, rtx);
330 /* Generate an instruction with a given INSN_CODE with an output and
331    an input.  */
332 extern bool maybe_emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
333 extern void emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
334 
335 /* Emit code to make a call to a constant function or a library call.  */
336 extern void emit_libcall_block (rtx, rtx, rtx, rtx);
337 
338 /* The various uses that a comparison can have; used by can_compare_p:
339    jumps, conditional moves, store flag operations.  */
340 enum can_compare_purpose
341 {
342   ccp_jump,
343   ccp_cmov,
344   ccp_store_flag
345 };
346 
347 /* Nonzero if a compare of mode MODE can be done straightforwardly
348    (without splitting it into pieces).  */
349 extern int can_compare_p (enum rtx_code, machine_mode,
350 			  enum can_compare_purpose);
351 extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
352 			    machine_mode, int);
353 /* Emit a pair of rtl insns to compare two rtx's and to jump
354    to a label if the comparison is true.  */
355 extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
356 				     machine_mode, int, rtx, int prob=-1);
357 
358 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
359 extern void emit_indirect_jump (rtx);
360 
361 #include "insn-config.h"
362 
363 #ifndef GCC_INSN_CONFIG_H
364 #error "insn-config.h must be included before optabs.h"
365 #endif
366 
367 #ifdef HAVE_conditional_move
368 /* Emit a conditional move operation.  */
369 rtx emit_conditional_move (rtx, enum rtx_code, rtx, rtx, machine_mode,
370 			   rtx, rtx, machine_mode, int);
371 
372 /* Return nonzero if the conditional move is supported.  */
373 int can_conditionally_move_p (machine_mode mode);
374 
375 #endif
376 rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx, machine_mode,
377 			  rtx, rtx, machine_mode, int);
378 
379 /* Create but don't emit one rtl instruction to perform certain operations.
380    Modes must match; operands must meet the operation's predicates.
381    Likewise for subtraction and for just copying.  */
382 extern rtx gen_add2_insn (rtx, rtx);
383 extern rtx gen_add3_insn (rtx, rtx, rtx);
384 extern int have_add2_insn (rtx, rtx);
385 extern rtx gen_addptr3_insn (rtx, rtx, rtx);
386 extern int have_addptr3_insn (rtx, rtx, rtx);
387 extern rtx gen_sub2_insn (rtx, rtx);
388 extern rtx gen_sub3_insn (rtx, rtx, rtx);
389 extern int have_sub2_insn (rtx, rtx);
390 
391 /* Return the INSN_CODE to use for an extend operation.  */
392 extern enum insn_code can_extend_p (machine_mode, machine_mode, int);
393 
394 /* Generate the body of an insn to extend Y (with mode MFROM)
395    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
396 extern rtx gen_extend_insn (rtx, rtx, machine_mode,
397 			    machine_mode, int);
398 
399 /* Return the insn_code for a FLOAT_EXPR.  */
400 enum insn_code can_float_p (machine_mode, machine_mode, int);
401 
402 /* Check whether an operation represented by the code CODE is a
403    convert operation that is supported by the target platform in
404    vector form */
405 bool supportable_convert_operation (enum tree_code, tree, tree, tree *,
406                                     enum tree_code *);
407 
408 /* Generate code for a FLOAT_EXPR.  */
409 extern void expand_float (rtx, rtx, int);
410 
411 /* Generate code for a FIX_EXPR.  */
412 extern void expand_fix (rtx, rtx, int);
413 
414 /* Generate code for a FIXED_CONVERT_EXPR.  */
415 extern void expand_fixed_convert (rtx, rtx, int, int);
416 
417 /* Generate code for float to integral conversion.  */
418 extern bool expand_sfix_optab (rtx, rtx, convert_optab);
419 
420 /* Report whether the machine description contains an insn which can
421    perform the operation described by CODE and MODE.  */
422 extern int have_insn_for (enum rtx_code, machine_mode);
423 
424 extern void gen_int_libfunc (optab, const char *, char, machine_mode);
425 extern void gen_fp_libfunc (optab, const char *, char, machine_mode);
426 extern void gen_fixed_libfunc (optab, const char *, char, machine_mode);
427 extern void gen_signed_fixed_libfunc (optab, const char *, char,
428 				      machine_mode);
429 extern void gen_unsigned_fixed_libfunc (optab, const char *, char,
430 					machine_mode);
431 extern void gen_int_fp_libfunc (optab, const char *, char, machine_mode);
432 extern void gen_intv_fp_libfunc (optab, const char *, char, machine_mode);
433 extern void gen_int_fp_fixed_libfunc (optab, const char *, char,
434 				      machine_mode);
435 extern void gen_int_fp_signed_fixed_libfunc (optab, const char *, char,
436 					     machine_mode);
437 extern void gen_int_fixed_libfunc (optab, const char *, char,
438 				   machine_mode);
439 extern void gen_int_signed_fixed_libfunc (optab, const char *, char,
440 					  machine_mode);
441 extern void gen_int_unsigned_fixed_libfunc (optab, const char *, char,
442 					    machine_mode);
443 
444 extern void gen_interclass_conv_libfunc (convert_optab, const char *,
445 					 machine_mode, machine_mode);
446 extern void gen_int_to_fp_conv_libfunc (convert_optab, const char *,
447 					machine_mode, machine_mode);
448 extern void gen_ufloat_conv_libfunc (convert_optab, const char *,
449 				     machine_mode, machine_mode);
450 extern void gen_int_to_fp_nondecimal_conv_libfunc  (convert_optab,
451 						    const char *,
452 						    machine_mode,
453 						    machine_mode);
454 extern void gen_fp_to_int_conv_libfunc (convert_optab, const char *,
455 					machine_mode, machine_mode);
456 extern void gen_intraclass_conv_libfunc (convert_optab, const char *,
457 					 machine_mode, machine_mode);
458 extern void gen_trunc_conv_libfunc (convert_optab, const char *,
459 				    machine_mode, machine_mode);
460 extern void gen_extend_conv_libfunc (convert_optab, const char *,
461 				     machine_mode, machine_mode);
462 extern void gen_fract_conv_libfunc (convert_optab, const char *,
463 				    machine_mode, machine_mode);
464 extern void gen_fractuns_conv_libfunc (convert_optab, const char *,
465 				       machine_mode, machine_mode);
466 extern void gen_satfract_conv_libfunc (convert_optab, const char *,
467 				       machine_mode, machine_mode);
468 extern void gen_satfractuns_conv_libfunc (convert_optab, const char *,
469 					  machine_mode,
470 					  machine_mode);
471 
472 /* Build a decl for a libfunc named NAME. */
473 extern tree build_libfunc_function (const char *);
474 
475 /* Call this to initialize an optab function entry.  */
476 extern rtx init_one_libfunc (const char *);
477 extern rtx set_user_assembler_libfunc (const char *, const char *);
478 
479 /* Call this to reset the function entry for one optab.  */
480 extern void set_optab_libfunc (optab, machine_mode, const char *);
481 extern void set_conv_libfunc (convert_optab, machine_mode,
482 			      machine_mode, const char *);
483 
484 /* Call this once to initialize the contents of the optabs
485    appropriately for the current target machine.  */
486 extern void init_optabs (void);
487 extern void init_tree_optimization_optabs (tree);
488 
489 /* Call this to install all of the __sync libcalls up to size MAX.  */
490 extern void init_sync_libfuncs (int max);
491 
492 /* Generate a conditional trap instruction.  */
493 extern rtx gen_cond_trap (enum rtx_code, rtx, rtx, rtx);
494 
495 /* Return true if target supports vector operations for VEC_PERM_EXPR.  */
496 extern bool can_vec_perm_p (machine_mode, bool, const unsigned char *);
497 
498 /* Generate code for VEC_PERM_EXPR.  */
499 extern rtx expand_vec_perm (machine_mode, rtx, rtx, rtx, rtx);
500 
501 /* Return tree if target supports vector operations for COND_EXPR.  */
502 bool expand_vec_cond_expr_p (tree, tree);
503 
504 /* Generate code for VEC_COND_EXPR.  */
505 extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
506 
507 /* Return non-zero if target supports a given highpart multiplication.  */
508 extern int can_mult_highpart_p (machine_mode, bool);
509 
510 /* Generate code for MULT_HIGHPART_EXPR.  */
511 extern rtx expand_mult_highpart (machine_mode, rtx, rtx, rtx, bool);
512 
513 /* Return true if target supports vector masked load/store for mode.  */
514 extern bool can_vec_mask_load_store_p (machine_mode, bool);
515 
516 /* Return true if there is an inline compare and swap pattern.  */
517 extern bool can_compare_and_swap_p (machine_mode, bool);
518 
519 /* Return true if there is an inline atomic exchange pattern.  */
520 extern bool can_atomic_exchange_p (machine_mode, bool);
521 
522 extern rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
523 extern rtx expand_atomic_test_and_set (rtx, rtx, enum memmodel);
524 extern rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
525 extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
526 					    enum memmodel, enum memmodel);
527 /* Generate memory barriers.  */
528 extern void expand_mem_thread_fence (enum memmodel);
529 extern void expand_mem_signal_fence (enum memmodel);
530 
531 rtx expand_atomic_load (rtx, rtx, enum memmodel);
532 rtx expand_atomic_store (rtx, rtx, enum memmodel, bool);
533 rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel,
534 			      bool);
535 
536 extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
537 				  rtx operand);
538 extern bool valid_multiword_target_p (rtx);
539 extern void create_convert_operand_from_type (struct expand_operand *op,
540 					      rtx value, tree type);
541 extern bool maybe_legitimize_operands (enum insn_code icode,
542 				       unsigned int opno, unsigned int nops,
543 				       struct expand_operand *ops);
544 extern rtx maybe_gen_insn (enum insn_code icode, unsigned int nops,
545 			   struct expand_operand *ops);
546 extern bool maybe_expand_insn (enum insn_code icode, unsigned int nops,
547 			       struct expand_operand *ops);
548 extern bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
549 				    struct expand_operand *ops);
550 extern void expand_insn (enum insn_code icode, unsigned int nops,
551 			 struct expand_operand *ops);
552 extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
553 			      struct expand_operand *ops);
554 
555 /* Enumerates the possible extraction_insn operations.  */
556 enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
557 
558 extern bool get_best_reg_extraction_insn (extraction_insn *,
559 					  enum extraction_pattern,
560 					  unsigned HOST_WIDE_INT,
561 					  machine_mode);
562 extern bool get_best_mem_extraction_insn (extraction_insn *,
563 					  enum extraction_pattern,
564 					  HOST_WIDE_INT, HOST_WIDE_INT,
565 					  machine_mode);
566 
567 extern bool lshift_cheap_p (bool);
568 
569 extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
570 
571 #endif /* GCC_OPTABS_H */
572