GCC Middle and Back End API Reference
optabs.h
Go to the documentation of this file.
1 /* Definitions for code generation pass of GNU compiler.
2  Copyright (C) 2001-2013 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-codes.h"
24 #include "insn-opinit.h"
25 
26 typedef enum optab_tag optab;
27 typedef enum optab_tag convert_optab;
28 typedef enum optab_tag direct_optab;
29 
30 struct optab_libcall_d
31 {
32  char libcall_suffix;
33  const char *libcall_basename;
34  void (*libcall_gen) (optab, const char *name,
35  char suffix, enum machine_mode);
36 };
37 
39 {
40  const char *libcall_basename;
41  void (*libcall_gen) (convert_optab, const char *name,
42  enum machine_mode, enum machine_mode);
43 };
44 
45 /* Given an enum insn_code, access the function to construct
46  the body of that kind of insn. */
47 #define GEN_FCN(CODE) (insn_data[CODE].genfun)
48 
49 /* Contains the optab used for each rtx code, and vice-versa. */
50 extern const optab code_to_optab_[NUM_RTX_CODE];
51 extern const enum rtx_code optab_to_code_[NUM_OPTABS];
52 
53 static inline optab
54 code_to_optab (enum rtx_code code)
55 {
56  return code_to_optab_[code];
57 }
58 
59 static inline enum rtx_code
61 {
62  return optab_to_code_[op];
63 }
64 
65 extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];
66 extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];
67 
68 /* Returns the active icode for the given (encoded) optab. */
69 extern enum insn_code raw_optab_handler (unsigned);
70 extern bool swap_optab_enable (optab, enum machine_mode, bool);
71 
72 /* Target-dependent globals. */
73 struct target_optabs {
74  /* Patterns that are used by optabs that are enabled for this target. */
75  bool pat_enable[NUM_OPTAB_PATTERNS];
76 };
77 
79 extern struct target_optabs *this_fn_optabs;
80 #if SWITCHABLE_TARGET
82 #else
83 #define this_target_optabs (&default_target_optabs)
84 #endif
85 
86 /* Define functions given in optabs.c. */
87 
88 extern rtx expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
89  rtx target, int unsignedp);
90 
91 extern rtx expand_ternary_op (enum machine_mode mode, optab ternary_optab,
92  rtx op0, rtx op1, rtx op2, rtx target,
93  int unsignedp);
94 
95 /* Expand a binary operation given optab and rtx operands. */
96 extern rtx expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
97  enum optab_methods);
98 
99 extern rtx simplify_expand_binop (enum machine_mode mode, optab binoptab,
100  rtx op0, rtx op1, rtx target, int unsignedp,
101  enum optab_methods methods);
102 
103 extern bool force_expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
104  enum optab_methods);
105 
106 /* Expand a binary operation with both signed and unsigned forms. */
107 extern rtx sign_expand_binop (enum machine_mode, optab, optab, rtx, rtx,
108  rtx, int, enum optab_methods);
109 
110 /* Generate code to perform an operation on one operand with two results. */
111 extern int expand_twoval_unop (optab, rtx, rtx, rtx, int);
112 
113 /* Generate code to perform an operation on two operands with two results. */
114 extern int expand_twoval_binop (optab, rtx, rtx, rtx, rtx, int);
115 
116 /* Generate code to perform an operation on two operands with two
117  results, using a library function. */
119  enum rtx_code);
120 
121 /* Expand a unary arithmetic operation given optab rtx operand. */
122 extern rtx expand_unop (enum machine_mode, optab, rtx, rtx, int);
123 
124 /* Expand the absolute value operation. */
125 extern rtx expand_abs_nojump (enum machine_mode, rtx, rtx, int);
126 extern rtx expand_abs (enum machine_mode, rtx, rtx, int, int);
127 
128 /* Expand the one's complement absolute value operation. */
129 extern rtx expand_one_cmpl_abs_nojump (enum machine_mode, rtx, rtx);
130 
131 /* Expand the copysign operation. */
132 extern rtx expand_copysign (rtx, rtx, rtx);
133 
134 /* Generate an instruction with a given INSN_CODE with an output and
135  an input. */
136 extern void emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
137 extern bool maybe_emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
138 
139 /* Find a widening optab even if it doesn't widen as much as we want. */
140 #define find_widening_optab_handler(A,B,C,D) \
141  find_widening_optab_handler_and_mode (A, B, C, D, NULL)
142 extern enum insn_code find_widening_optab_handler_and_mode (optab,
143  enum machine_mode,
144  enum machine_mode,
145  int,
146  enum machine_mode *);
147 
148 /* An extra flag to control optab_for_tree_code's behavior. This is needed to
149  distinguish between machines with a vector shift that takes a scalar for the
150  shift amount vs. machines that take a vector for the shift amount. */
151 enum optab_subtype
152 {
154  optab_scalar,
156 };
157 
158 /* Return the optab used for computing the given operation on the type given by
159  the second argument. The third argument distinguishes between the types of
160  vector shifts and rotates */
162 
163 /* The various uses that a comparison can have; used by can_compare_p:
164  jumps, conditional moves, store flag operations. */
166 {
167  ccp_jump,
168  ccp_cmov,
170 };
171 
172 /* Nonzero if a compare of mode MODE can be done straightforwardly
173  (without splitting it into pieces). */
174 extern int can_compare_p (enum rtx_code, enum machine_mode,
175  enum can_compare_purpose);
176 
177 /* Return the INSN_CODE to use for an extend operation. */
178 extern enum insn_code can_extend_p (enum machine_mode, enum machine_mode, int);
179 
180 /* Generate the body of an insn to extend Y (with mode MFROM)
181  into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
182 extern rtx gen_extend_insn (rtx, rtx, enum machine_mode,
183  enum machine_mode, int);
184 
185 /* Call this to reset the function entry for one optab. */
186 extern void set_optab_libfunc (optab, enum machine_mode, const char *);
187 extern void set_conv_libfunc (convert_optab, enum machine_mode,
188  enum machine_mode, const char *);
190 /* Call this to install all of the __sync libcalls up to size MAX. */
191 extern void init_sync_libfuncs (int max);
192 
193 /* Generate code for a FIXED_CONVERT_EXPR. */
194 extern void expand_fixed_convert (rtx, rtx, int, int);
195 
196 /* Generate code for a FLOAT_EXPR. */
197 extern void expand_float (rtx, rtx, int);
198 
199 /* Return the insn_code for a FLOAT_EXPR. */
200 enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
201 
202 /* Return true if there is an inline compare and swap pattern. */
203 extern bool can_compare_and_swap_p (enum machine_mode, bool);
204 
205 /* Return true if there is an inline atomic exchange pattern. */
206 extern bool can_atomic_exchange_p (enum machine_mode, bool);
207 
208 /* Generate code for a compare and swap. */
209 extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
210  enum memmodel, enum memmodel);
211 
212 /* Generate memory barriers. */
213 extern void expand_mem_thread_fence (enum memmodel);
214 extern void expand_mem_signal_fence (enum memmodel);
215 
216 /* Check whether an operation represented by the code CODE is a
217  convert operation that is supported by the target platform in
218  vector form */
220  enum tree_code *);
221 
222 /* Generate code for a FIX_EXPR. */
223 extern void expand_fix (rtx, rtx, int);
224 
225 /* Generate code for float to integral conversion. */
226 extern bool expand_sfix_optab (rtx, rtx, convert_optab);
227 
228 /* Generate code for a widening multiply. */
229 extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
230 
231 /* Return tree if target supports vector operations for COND_EXPR. */
233 
234 /* Generate code for VEC_COND_EXPR. */
236 /* Generate code for VEC_LSHIFT_EXPR and VEC_RSHIFT_EXPR. */
238 
239 /* Return tree if target supports vector operations for VEC_PERM_EXPR. */
240 extern bool can_vec_perm_p (enum machine_mode, bool, const unsigned char *);
241 
242 /* Generate code for VEC_PERM_EXPR. */
243 extern rtx expand_vec_perm (enum machine_mode, rtx, rtx, rtx, rtx);
244 
245 /* Return non-zero if target supports a given highpart multiplication. */
246 extern int can_mult_highpart_p (enum machine_mode, bool);
247 
248 /* Generate code for MULT_HIGHPART_EXPR. */
249 extern rtx expand_mult_highpart (enum machine_mode, rtx, rtx, rtx, bool);
250 
251 /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
252  if the target does not have such an insn. */
253 
254 static inline enum insn_code
255 optab_handler (optab op, enum machine_mode mode)
256 {
257  unsigned scode = (op << 16) | mode;
258  gcc_assert (op > LAST_CONV_OPTAB);
259  return raw_optab_handler (scode);
260 }
261 
262 /* Return the insn used to perform conversion OP from mode FROM_MODE
263  to mode TO_MODE; return CODE_FOR_nothing if the target does not have
264  such an insn. */
265 
266 static inline enum insn_code
267 convert_optab_handler (convert_optab op, enum machine_mode to_mode,
268  enum machine_mode from_mode)
269 {
270  unsigned scode = (op << 16) | (from_mode << 8) | to_mode;
271  gcc_assert (op > unknown_optab && op <= LAST_CONV_OPTAB);
272  return raw_optab_handler (scode);
273 }
274 
275 /* Like optab_handler, but for widening_operations that have a
276  TO_MODE and a FROM_MODE. */
277 
278 static inline enum insn_code
279 widening_optab_handler (optab op, enum machine_mode to_mode,
280  enum machine_mode from_mode)
281 {
282  unsigned scode = (op << 16) | to_mode;
283  if (to_mode != from_mode && from_mode != VOIDmode)
284  {
285  /* ??? Why does find_widening_optab_handler_and_mode attempt to
286  widen things that can't be widened? E.g. add_optab... */
287  if (op > LAST_CONV_OPTAB)
288  return CODE_FOR_nothing;
289  scode |= from_mode << 8;
290  }
291  return raw_optab_handler (scode);
292 }
293 
294 /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
295  if the target does not have such an insn. */
296 
297 static inline enum insn_code
298 direct_optab_handler (direct_optab op, enum machine_mode mode)
299 {
300  return optab_handler (op, mode);
301 }
302 
303 /* Return true if UNOPTAB is for a trapping-on-overflow operation. */
304 
305 static inline bool
306 trapv_unoptab_p (optab unoptab)
307 {
308  return (unoptab == negv_optab
309  || unoptab == absv_optab);
310 }
311 
312 /* Return true if BINOPTAB is for a trapping-on-overflow operation. */
314 static inline bool
315 trapv_binoptab_p (optab binoptab)
316 {
317  return (binoptab == addv_optab
318  || binoptab == subv_optab
319  || binoptab == smulv_optab);
320 }
321 
322 extern rtx optab_libfunc (optab optab, enum machine_mode mode);
323 extern rtx convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
324  enum machine_mode mode2);
325 
326 /* Describes an instruction that inserts or extracts a bitfield. */
327 struct extraction_insn
328 {
329  /* The code of the instruction. */
330  enum insn_code icode;
331 
332  /* The mode that the structure operand should have. This is byte_mode
333  when using the legacy insv, extv and extzv patterns to access memory. */
334  enum machine_mode struct_mode;
335 
336  /* The mode of the field to be inserted or extracted, and by extension
337  the mode of the insertion or extraction itself. */
338  enum machine_mode field_mode;
339 
340  /* The mode of the field's bit position. This is only important
341  when the position is variable rather than constant. */
342  enum machine_mode pos_mode;
343 };
344 
345 /* Enumerates the possible extraction_insn operations. */
349  enum extraction_pattern,
350  unsigned HOST_WIDE_INT,
351  enum machine_mode);
352 
354  enum extraction_pattern,
356  enum machine_mode);
357 
358 extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
359  rtx operand);
360 
361 /* Describes the type of an expand_operand. Each value is associated
362  with a create_*_operand function; see the comments above those
363  functions for details. */
364 enum expand_operand_type {
365  EXPAND_FIXED,
367  EXPAND_INPUT,
372 };
373 
374 /* Information about an operand for instruction expansion. */
375 struct expand_operand {
376  /* The type of operand. */
377  ENUM_BITFIELD (expand_operand_type) type : 8;
378 
379  /* True if any conversion should treat VALUE as being unsigned
380  rather than signed. Only meaningful for certain types. */
381  unsigned int unsigned_p : 1;
382 
383  /* Unused; available for future use. */
384  unsigned int unused : 7;
385 
386  /* The mode passed to the convert_*_operand function. It has a
387  type-dependent meaning. */
388  ENUM_BITFIELD (machine_mode) mode : 16;
389 
390  /* The value of the operand. */
391  rtx value;
392 };
394 /* Initialize OP with the given fields. Initialise the other fields
395  to their default values. */
396 
397 static inline void
400  rtx value, enum machine_mode mode,
401  bool unsigned_p)
402 {
403  op->type = type;
404  op->unsigned_p = unsigned_p;
405  op->unused = 0;
406  op->mode = mode;
407  op->value = value;
408 }
409 
410 /* Make OP describe an operand that must use rtx X, even if X is volatile. */
411 
412 static inline void
414 {
415  create_expand_operand (op, EXPAND_FIXED, x, VOIDmode, false);
416 }
417 
418 /* Make OP describe an output operand that must have mode MODE.
419  X, if nonnull, is a suggestion for where the output should be stored.
420  It is OK for VALUE to be inconsistent with MODE, although it will just
421  be ignored in that case. */
423 static inline void
425  enum machine_mode mode)
426 {
427  create_expand_operand (op, EXPAND_OUTPUT, x, mode, false);
428 }
430 /* Make OP describe an input operand that must have mode MODE and
431  value VALUE; MODE cannot be VOIDmode. The backend may request that
432  VALUE be copied into a different kind of rtx before being passed
433  as an operand. */
435 static inline void
437  enum machine_mode mode)
438 {
439  create_expand_operand (op, EXPAND_INPUT, value, mode, false);
440 }
441 
442 /* Like create_input_operand, except that VALUE must first be converted
443  to mode MODE. UNSIGNED_P says whether VALUE is unsigned. */
444 
445 static inline void
447  enum machine_mode mode, bool unsigned_p)
448 {
449  create_expand_operand (op, EXPAND_CONVERT_TO, value, mode, unsigned_p);
450 }
452 /* Make OP describe an input operand that should have the same value
453  as VALUE, after any mode conversion that the backend might request.
454  If VALUE is a CONST_INT, it should be treated as having mode MODE.
455  UNSIGNED_P says whether VALUE is unsigned. */
456 
457 static inline void
459  enum machine_mode mode, bool unsigned_p)
460 {
461  create_expand_operand (op, EXPAND_CONVERT_FROM, value, mode, unsigned_p);
462 }
464 extern void create_convert_operand_from_type (struct expand_operand *op,
465  rtx value, tree type);
466 
467 /* Make OP describe an input Pmode address operand. VALUE is the value
468  of the address, but it may need to be converted to Pmode first. */
469 
470 static inline void
472 {
473  create_expand_operand (op, EXPAND_ADDRESS, value, Pmode, false);
474 }
475 
476 /* Make OP describe an input operand that has value INTVAL and that has
477  no inherent mode. This function should only be used for operands that
478  are always expand-time constants. The backend may request that INTVAL
479  be copied into a different kind of rtx, but it must specify the mode
480  of that rtx if so. */
481 
482 static inline void
484 {
485  create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
486 }
487 
488 extern bool valid_multiword_target_p (rtx);
489 
490 extern bool maybe_legitimize_operands (enum insn_code icode,
491  unsigned int opno, unsigned int nops,
492  struct expand_operand *ops);
493 extern rtx maybe_gen_insn (enum insn_code icode, unsigned int nops,
494  struct expand_operand *ops);
495 extern bool maybe_expand_insn (enum insn_code icode, unsigned int nops,
496  struct expand_operand *ops);
497 extern bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
498  struct expand_operand *ops);
499 extern void expand_insn (enum insn_code icode, unsigned int nops,
500  struct expand_operand *ops);
501 extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
502  struct expand_operand *ops);
503 
504 extern rtx prepare_operand (enum insn_code, rtx, int, enum machine_mode,
505  enum machine_mode, int);
506 
507 extern void gen_int_libfunc (optab, const char *, char, enum machine_mode);
508 extern void gen_fp_libfunc (optab, const char *, char, enum machine_mode);
509 extern void gen_fixed_libfunc (optab, const char *, char, enum machine_mode);
510 extern void gen_signed_fixed_libfunc (optab, const char *, char,
511  enum machine_mode);
512 extern void gen_unsigned_fixed_libfunc (optab, const char *, char,
513  enum machine_mode);
514 extern void gen_int_fp_libfunc (optab, const char *, char, enum machine_mode);
515 extern void gen_intv_fp_libfunc (optab, const char *, char, enum machine_mode);
516 extern void gen_int_fp_fixed_libfunc (optab, const char *, char,
517  enum machine_mode);
518 extern void gen_int_fp_signed_fixed_libfunc (optab, const char *, char,
519  enum machine_mode);
520 extern void gen_int_fixed_libfunc (optab, const char *, char,
521  enum machine_mode);
522 extern void gen_int_signed_fixed_libfunc (optab, const char *, char,
523  enum machine_mode);
524 extern void gen_int_unsigned_fixed_libfunc (optab, const char *, char,
525  enum machine_mode);
526 
527 extern void gen_interclass_conv_libfunc (convert_optab, const char *,
528  enum machine_mode, enum machine_mode);
529 extern void gen_int_to_fp_conv_libfunc (convert_optab, const char *,
530  enum machine_mode, enum machine_mode);
531 extern void gen_ufloat_conv_libfunc (convert_optab, const char *,
532  enum machine_mode, enum machine_mode);
534  const char *,
535  enum machine_mode,
536  enum machine_mode);
537 extern void gen_fp_to_int_conv_libfunc (convert_optab, const char *,
538  enum machine_mode, enum machine_mode);
539 extern void gen_intraclass_conv_libfunc (convert_optab, const char *,
540  enum machine_mode, enum machine_mode);
541 extern void gen_trunc_conv_libfunc (convert_optab, const char *,
542  enum machine_mode, enum machine_mode);
543 extern void gen_extend_conv_libfunc (convert_optab, const char *,
544  enum machine_mode, enum machine_mode);
545 extern void gen_fract_conv_libfunc (convert_optab, const char *,
546  enum machine_mode, enum machine_mode);
547 extern void gen_fractuns_conv_libfunc (convert_optab, const char *,
548  enum machine_mode, enum machine_mode);
549 extern void gen_satfract_conv_libfunc (convert_optab, const char *,
550  enum machine_mode, enum machine_mode);
551 extern void gen_satfractuns_conv_libfunc (convert_optab, const char *,
552  enum machine_mode,
553  enum machine_mode);
554 
555 #endif /* GCC_OPTABS_H */