Remove outermost loop parameter.
[official-gcc/graphite-test-results.git] / gcc / optabs.c
blobe022114a0e3b152acf3a163e059899ac11d4bb23
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "toplev.h"
29 /* Include insn-config.h before expr.h so that HAVE_conditional_move
30 is properly defined. */
31 #include "insn-config.h"
32 #include "rtl.h"
33 #include "tree.h"
34 #include "tm_p.h"
35 #include "flags.h"
36 #include "function.h"
37 #include "except.h"
38 #include "expr.h"
39 #include "optabs.h"
40 #include "libfuncs.h"
41 #include "recog.h"
42 #include "reload.h"
43 #include "ggc.h"
44 #include "basic-block.h"
45 #include "target.h"
47 /* Each optab contains info on how this target machine
48 can perform a particular operation
49 for all sizes and kinds of operands.
51 The operation to be performed is often specified
52 by passing one of these optabs as an argument.
54 See expr.h for documentation of these optabs. */
56 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
57 __extension__ struct optab_d optab_table[OTI_MAX]
58 = { [0 ... OTI_MAX - 1].handlers[0 ... NUM_MACHINE_MODES - 1].insn_code
59 = CODE_FOR_nothing };
60 #else
61 /* init_insn_codes will do runtime initialization otherwise. */
62 struct optab_d optab_table[OTI_MAX];
63 #endif
65 rtx libfunc_table[LTI_MAX];
67 /* Tables of patterns for converting one mode to another. */
68 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
69 __extension__ struct convert_optab_d convert_optab_table[COI_MAX]
70 = { [0 ... COI_MAX - 1].handlers[0 ... NUM_MACHINE_MODES - 1]
71 [0 ... NUM_MACHINE_MODES - 1].insn_code
72 = CODE_FOR_nothing };
73 #else
74 /* init_convert_optab will do runtime initialization otherwise. */
75 struct convert_optab_d convert_optab_table[COI_MAX];
76 #endif
78 /* Contains the optab used for each rtx code. */
79 optab code_to_optab[NUM_RTX_CODE + 1];
81 #ifdef HAVE_conditional_move
82 /* Indexed by the machine mode, gives the insn code to make a conditional
83 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
84 setcc_gen_code to cut down on the number of named patterns. Consider a day
85 when a lot more rtx codes are conditional (eg: for the ARM). */
87 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
88 #endif
90 /* Indexed by the machine mode, gives the insn code for vector conditional
91 operation. */
93 enum insn_code vcond_gen_code[NUM_MACHINE_MODES];
94 enum insn_code vcondu_gen_code[NUM_MACHINE_MODES];
96 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
97 enum machine_mode *);
98 static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
100 /* Debug facility for use in GDB. */
101 void debug_optab_libfuncs (void);
103 /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
104 #if ENABLE_DECIMAL_BID_FORMAT
105 #define DECIMAL_PREFIX "bid_"
106 #else
107 #define DECIMAL_PREFIX "dpd_"
108 #endif
111 /* Info about libfunc. We use same hashtable for normal optabs and conversion
112 optab. In the first case mode2 is unused. */
113 struct GTY(()) libfunc_entry {
114 size_t optab;
115 enum machine_mode mode1, mode2;
116 rtx libfunc;
119 /* Hash table used to convert declarations into nodes. */
120 static GTY((param_is (struct libfunc_entry))) htab_t libfunc_hash;
122 /* Used for attribute_hash. */
124 static hashval_t
125 hash_libfunc (const void *p)
127 const struct libfunc_entry *const e = (const struct libfunc_entry *) p;
129 return (((int) e->mode1 + (int) e->mode2 * NUM_MACHINE_MODES)
130 ^ e->optab);
133 /* Used for optab_hash. */
135 static int
136 eq_libfunc (const void *p, const void *q)
138 const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p;
139 const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q;
141 return (e1->optab == e2->optab
142 && e1->mode1 == e2->mode1
143 && e1->mode2 == e2->mode2);
146 /* Return libfunc corresponding operation defined by OPTAB converting
147 from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL
148 if no libfunc is available. */
150 convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
151 enum machine_mode mode2)
153 struct libfunc_entry e;
154 struct libfunc_entry **slot;
156 e.optab = (size_t) (optab - &convert_optab_table[0]);
157 e.mode1 = mode1;
158 e.mode2 = mode2;
159 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
160 if (!slot)
162 if (optab->libcall_gen)
164 optab->libcall_gen (optab, optab->libcall_basename, mode1, mode2);
165 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
166 if (slot)
167 return (*slot)->libfunc;
168 else
169 return NULL;
171 return NULL;
173 return (*slot)->libfunc;
176 /* Return libfunc corresponding operation defined by OPTAB in MODE.
177 Trigger lazy initialization if needed, return NULL if no libfunc is
178 available. */
180 optab_libfunc (optab optab, enum machine_mode mode)
182 struct libfunc_entry e;
183 struct libfunc_entry **slot;
185 e.optab = (size_t) (optab - &optab_table[0]);
186 e.mode1 = mode;
187 e.mode2 = VOIDmode;
188 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
189 if (!slot)
191 if (optab->libcall_gen)
193 optab->libcall_gen (optab, optab->libcall_basename,
194 optab->libcall_suffix, mode);
195 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash,
196 &e, NO_INSERT);
197 if (slot)
198 return (*slot)->libfunc;
199 else
200 return NULL;
202 return NULL;
204 return (*slot)->libfunc;
208 /* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
209 the result of operation CODE applied to OP0 (and OP1 if it is a binary
210 operation).
212 If the last insn does not set TARGET, don't do anything, but return 1.
214 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
215 don't add the REG_EQUAL note but return 0. Our caller can then try
216 again, ensuring that TARGET is not one of the operands. */
218 static int
219 add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
221 rtx last_insn, insn, set;
222 rtx note;
224 gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
226 if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
227 && GET_RTX_CLASS (code) != RTX_BIN_ARITH
228 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
229 && GET_RTX_CLASS (code) != RTX_COMPARE
230 && GET_RTX_CLASS (code) != RTX_UNARY)
231 return 1;
233 if (GET_CODE (target) == ZERO_EXTRACT)
234 return 1;
236 for (last_insn = insns;
237 NEXT_INSN (last_insn) != NULL_RTX;
238 last_insn = NEXT_INSN (last_insn))
241 set = single_set (last_insn);
242 if (set == NULL_RTX)
243 return 1;
245 if (! rtx_equal_p (SET_DEST (set), target)
246 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it. */
247 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
248 || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
249 return 1;
251 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
252 besides the last insn. */
253 if (reg_overlap_mentioned_p (target, op0)
254 || (op1 && reg_overlap_mentioned_p (target, op1)))
256 insn = PREV_INSN (last_insn);
257 while (insn != NULL_RTX)
259 if (reg_set_p (target, insn))
260 return 0;
262 insn = PREV_INSN (insn);
266 if (GET_RTX_CLASS (code) == RTX_UNARY)
267 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
268 else
269 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
271 set_unique_reg_note (last_insn, REG_EQUAL, note);
273 return 1;
276 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
277 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
278 not actually do a sign-extend or zero-extend, but can leave the
279 higher-order bits of the result rtx undefined, for example, in the case
280 of logical operations, but not right shifts. */
282 static rtx
283 widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
284 int unsignedp, int no_extend)
286 rtx result;
288 /* If we don't have to extend and this is a constant, return it. */
289 if (no_extend && GET_MODE (op) == VOIDmode)
290 return op;
292 /* If we must extend do so. If OP is a SUBREG for a promoted object, also
293 extend since it will be more efficient to do so unless the signedness of
294 a promoted object differs from our extension. */
295 if (! no_extend
296 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
297 && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
298 return convert_modes (mode, oldmode, op, unsignedp);
300 /* If MODE is no wider than a single word, we return a paradoxical
301 SUBREG. */
302 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
303 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
305 /* Otherwise, get an object of MODE, clobber it, and set the low-order
306 part to OP. */
308 result = gen_reg_rtx (mode);
309 emit_clobber (result);
310 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
311 return result;
314 /* Return the optab used for computing the operation given by the tree code,
315 CODE and the tree EXP. This function is not always usable (for example, it
316 cannot give complete results for multiplication or division) but probably
317 ought to be relied on more widely throughout the expander. */
318 optab
319 optab_for_tree_code (enum tree_code code, const_tree type,
320 enum optab_subtype subtype)
322 bool trapv;
323 switch (code)
325 case BIT_AND_EXPR:
326 return and_optab;
328 case BIT_IOR_EXPR:
329 return ior_optab;
331 case BIT_NOT_EXPR:
332 return one_cmpl_optab;
334 case BIT_XOR_EXPR:
335 return xor_optab;
337 case TRUNC_MOD_EXPR:
338 case CEIL_MOD_EXPR:
339 case FLOOR_MOD_EXPR:
340 case ROUND_MOD_EXPR:
341 return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
343 case RDIV_EXPR:
344 case TRUNC_DIV_EXPR:
345 case CEIL_DIV_EXPR:
346 case FLOOR_DIV_EXPR:
347 case ROUND_DIV_EXPR:
348 case EXACT_DIV_EXPR:
349 if (TYPE_SATURATING(type))
350 return TYPE_UNSIGNED(type) ? usdiv_optab : ssdiv_optab;
351 return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
353 case LSHIFT_EXPR:
354 if (VECTOR_MODE_P (TYPE_MODE (type)))
356 if (subtype == optab_vector)
357 return TYPE_SATURATING (type) ? NULL : vashl_optab;
359 gcc_assert (subtype == optab_scalar);
361 if (TYPE_SATURATING(type))
362 return TYPE_UNSIGNED(type) ? usashl_optab : ssashl_optab;
363 return ashl_optab;
365 case RSHIFT_EXPR:
366 if (VECTOR_MODE_P (TYPE_MODE (type)))
368 if (subtype == optab_vector)
369 return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
371 gcc_assert (subtype == optab_scalar);
373 return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
375 case LROTATE_EXPR:
376 if (VECTOR_MODE_P (TYPE_MODE (type)))
378 if (subtype == optab_vector)
379 return vrotl_optab;
381 gcc_assert (subtype == optab_scalar);
383 return rotl_optab;
385 case RROTATE_EXPR:
386 if (VECTOR_MODE_P (TYPE_MODE (type)))
388 if (subtype == optab_vector)
389 return vrotr_optab;
391 gcc_assert (subtype == optab_scalar);
393 return rotr_optab;
395 case MAX_EXPR:
396 return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
398 case MIN_EXPR:
399 return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
401 case REALIGN_LOAD_EXPR:
402 return vec_realign_load_optab;
404 case WIDEN_SUM_EXPR:
405 return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
407 case DOT_PROD_EXPR:
408 return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
410 case REDUC_MAX_EXPR:
411 return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab;
413 case REDUC_MIN_EXPR:
414 return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab;
416 case REDUC_PLUS_EXPR:
417 return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
419 case VEC_LSHIFT_EXPR:
420 return vec_shl_optab;
422 case VEC_RSHIFT_EXPR:
423 return vec_shr_optab;
425 case VEC_WIDEN_MULT_HI_EXPR:
426 return TYPE_UNSIGNED (type) ?
427 vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
429 case VEC_WIDEN_MULT_LO_EXPR:
430 return TYPE_UNSIGNED (type) ?
431 vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
433 case VEC_UNPACK_HI_EXPR:
434 return TYPE_UNSIGNED (type) ?
435 vec_unpacku_hi_optab : vec_unpacks_hi_optab;
437 case VEC_UNPACK_LO_EXPR:
438 return TYPE_UNSIGNED (type) ?
439 vec_unpacku_lo_optab : vec_unpacks_lo_optab;
441 case VEC_UNPACK_FLOAT_HI_EXPR:
442 /* The signedness is determined from input operand. */
443 return TYPE_UNSIGNED (type) ?
444 vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
446 case VEC_UNPACK_FLOAT_LO_EXPR:
447 /* The signedness is determined from input operand. */
448 return TYPE_UNSIGNED (type) ?
449 vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
451 case VEC_PACK_TRUNC_EXPR:
452 return vec_pack_trunc_optab;
454 case VEC_PACK_SAT_EXPR:
455 return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
457 case VEC_PACK_FIX_TRUNC_EXPR:
458 /* The signedness is determined from output operand. */
459 return TYPE_UNSIGNED (type) ?
460 vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
462 default:
463 break;
466 trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
467 switch (code)
469 case POINTER_PLUS_EXPR:
470 case PLUS_EXPR:
471 if (TYPE_SATURATING(type))
472 return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
473 return trapv ? addv_optab : add_optab;
475 case MINUS_EXPR:
476 if (TYPE_SATURATING(type))
477 return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
478 return trapv ? subv_optab : sub_optab;
480 case MULT_EXPR:
481 if (TYPE_SATURATING(type))
482 return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
483 return trapv ? smulv_optab : smul_optab;
485 case NEGATE_EXPR:
486 if (TYPE_SATURATING(type))
487 return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
488 return trapv ? negv_optab : neg_optab;
490 case ABS_EXPR:
491 return trapv ? absv_optab : abs_optab;
493 case VEC_EXTRACT_EVEN_EXPR:
494 return vec_extract_even_optab;
496 case VEC_EXTRACT_ODD_EXPR:
497 return vec_extract_odd_optab;
499 case VEC_INTERLEAVE_HIGH_EXPR:
500 return vec_interleave_high_optab;
502 case VEC_INTERLEAVE_LOW_EXPR:
503 return vec_interleave_low_optab;
505 default:
506 return NULL;
511 /* Expand vector widening operations.
513 There are two different classes of operations handled here:
514 1) Operations whose result is wider than all the arguments to the operation.
515 Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR
516 In this case OP0 and optionally OP1 would be initialized,
517 but WIDE_OP wouldn't (not relevant for this case).
518 2) Operations whose result is of the same size as the last argument to the
519 operation, but wider than all the other arguments to the operation.
520 Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR.
521 In the case WIDE_OP, OP0 and optionally OP1 would be initialized.
523 E.g, when called to expand the following operations, this is how
524 the arguments will be initialized:
525 nops OP0 OP1 WIDE_OP
526 widening-sum 2 oprnd0 - oprnd1
527 widening-dot-product 3 oprnd0 oprnd1 oprnd2
528 widening-mult 2 oprnd0 oprnd1 -
529 type-promotion (vec-unpack) 1 oprnd0 - - */
532 expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
533 rtx target, int unsignedp)
535 tree oprnd0, oprnd1, oprnd2;
536 enum machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
537 optab widen_pattern_optab;
538 int icode;
539 enum machine_mode xmode0, xmode1 = VOIDmode, wxmode = VOIDmode;
540 rtx temp;
541 rtx pat;
542 rtx xop0, xop1, wxop;
543 int nops = TREE_CODE_LENGTH (ops->code);
545 oprnd0 = ops->op0;
546 tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
547 widen_pattern_optab =
548 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
549 icode = (int) optab_handler (widen_pattern_optab, tmode0)->insn_code;
550 gcc_assert (icode != CODE_FOR_nothing);
551 xmode0 = insn_data[icode].operand[1].mode;
553 if (nops >= 2)
555 oprnd1 = ops->op1;
556 tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
557 xmode1 = insn_data[icode].operand[2].mode;
560 /* The last operand is of a wider mode than the rest of the operands. */
561 if (nops == 2)
563 wmode = tmode1;
564 wxmode = xmode1;
566 else if (nops == 3)
568 gcc_assert (tmode1 == tmode0);
569 gcc_assert (op1);
570 oprnd2 = ops->op2;
571 wmode = TYPE_MODE (TREE_TYPE (oprnd2));
572 wxmode = insn_data[icode].operand[3].mode;
575 if (!wide_op)
576 wmode = wxmode = insn_data[icode].operand[0].mode;
578 if (!target
579 || ! (*insn_data[icode].operand[0].predicate) (target, wmode))
580 temp = gen_reg_rtx (wmode);
581 else
582 temp = target;
584 xop0 = op0;
585 xop1 = op1;
586 wxop = wide_op;
588 /* In case the insn wants input operands in modes different from
589 those of the actual operands, convert the operands. It would
590 seem that we don't need to convert CONST_INTs, but we do, so
591 that they're properly zero-extended, sign-extended or truncated
592 for their mode. */
594 if (GET_MODE (op0) != xmode0 && xmode0 != VOIDmode)
595 xop0 = convert_modes (xmode0,
596 GET_MODE (op0) != VOIDmode
597 ? GET_MODE (op0)
598 : tmode0,
599 xop0, unsignedp);
601 if (op1)
602 if (GET_MODE (op1) != xmode1 && xmode1 != VOIDmode)
603 xop1 = convert_modes (xmode1,
604 GET_MODE (op1) != VOIDmode
605 ? GET_MODE (op1)
606 : tmode1,
607 xop1, unsignedp);
609 if (wide_op)
610 if (GET_MODE (wide_op) != wxmode && wxmode != VOIDmode)
611 wxop = convert_modes (wxmode,
612 GET_MODE (wide_op) != VOIDmode
613 ? GET_MODE (wide_op)
614 : wmode,
615 wxop, unsignedp);
617 /* Now, if insn's predicates don't allow our operands, put them into
618 pseudo regs. */
620 if (! (*insn_data[icode].operand[1].predicate) (xop0, xmode0)
621 && xmode0 != VOIDmode)
622 xop0 = copy_to_mode_reg (xmode0, xop0);
624 if (op1)
626 if (! (*insn_data[icode].operand[2].predicate) (xop1, xmode1)
627 && xmode1 != VOIDmode)
628 xop1 = copy_to_mode_reg (xmode1, xop1);
630 if (wide_op)
632 if (! (*insn_data[icode].operand[3].predicate) (wxop, wxmode)
633 && wxmode != VOIDmode)
634 wxop = copy_to_mode_reg (wxmode, wxop);
636 pat = GEN_FCN (icode) (temp, xop0, xop1, wxop);
638 else
639 pat = GEN_FCN (icode) (temp, xop0, xop1);
641 else
643 if (wide_op)
645 if (! (*insn_data[icode].operand[2].predicate) (wxop, wxmode)
646 && wxmode != VOIDmode)
647 wxop = copy_to_mode_reg (wxmode, wxop);
649 pat = GEN_FCN (icode) (temp, xop0, wxop);
651 else
652 pat = GEN_FCN (icode) (temp, xop0);
655 emit_insn (pat);
656 return temp;
659 /* Generate code to perform an operation specified by TERNARY_OPTAB
660 on operands OP0, OP1 and OP2, with result having machine-mode MODE.
662 UNSIGNEDP is for the case where we have to widen the operands
663 to perform the operation. It says to use zero-extension.
665 If TARGET is nonzero, the value
666 is generated there, if it is convenient to do so.
667 In all cases an rtx is returned for the locus of the value;
668 this may or may not be TARGET. */
671 expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
672 rtx op1, rtx op2, rtx target, int unsignedp)
674 int icode = (int) optab_handler (ternary_optab, mode)->insn_code;
675 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
676 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
677 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
678 rtx temp;
679 rtx pat;
680 rtx xop0 = op0, xop1 = op1, xop2 = op2;
682 gcc_assert (optab_handler (ternary_optab, mode)->insn_code
683 != CODE_FOR_nothing);
685 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
686 temp = gen_reg_rtx (mode);
687 else
688 temp = target;
690 /* In case the insn wants input operands in modes different from
691 those of the actual operands, convert the operands. It would
692 seem that we don't need to convert CONST_INTs, but we do, so
693 that they're properly zero-extended, sign-extended or truncated
694 for their mode. */
696 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
697 xop0 = convert_modes (mode0,
698 GET_MODE (op0) != VOIDmode
699 ? GET_MODE (op0)
700 : mode,
701 xop0, unsignedp);
703 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
704 xop1 = convert_modes (mode1,
705 GET_MODE (op1) != VOIDmode
706 ? GET_MODE (op1)
707 : mode,
708 xop1, unsignedp);
710 if (GET_MODE (op2) != mode2 && mode2 != VOIDmode)
711 xop2 = convert_modes (mode2,
712 GET_MODE (op2) != VOIDmode
713 ? GET_MODE (op2)
714 : mode,
715 xop2, unsignedp);
717 /* Now, if insn's predicates don't allow our operands, put them into
718 pseudo regs. */
720 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
721 && mode0 != VOIDmode)
722 xop0 = copy_to_mode_reg (mode0, xop0);
724 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
725 && mode1 != VOIDmode)
726 xop1 = copy_to_mode_reg (mode1, xop1);
728 if (!insn_data[icode].operand[3].predicate (xop2, mode2)
729 && mode2 != VOIDmode)
730 xop2 = copy_to_mode_reg (mode2, xop2);
732 pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
734 emit_insn (pat);
735 return temp;
739 /* Like expand_binop, but return a constant rtx if the result can be
740 calculated at compile time. The arguments and return value are
741 otherwise the same as for expand_binop. */
743 static rtx
744 simplify_expand_binop (enum machine_mode mode, optab binoptab,
745 rtx op0, rtx op1, rtx target, int unsignedp,
746 enum optab_methods methods)
748 if (CONSTANT_P (op0) && CONSTANT_P (op1))
750 rtx x = simplify_binary_operation (binoptab->code, mode, op0, op1);
752 if (x)
753 return x;
756 return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
759 /* Like simplify_expand_binop, but always put the result in TARGET.
760 Return true if the expansion succeeded. */
762 bool
763 force_expand_binop (enum machine_mode mode, optab binoptab,
764 rtx op0, rtx op1, rtx target, int unsignedp,
765 enum optab_methods methods)
767 rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
768 target, unsignedp, methods);
769 if (x == 0)
770 return false;
771 if (x != target)
772 emit_move_insn (target, x);
773 return true;
776 /* Generate insns for VEC_LSHIFT_EXPR, VEC_RSHIFT_EXPR. */
779 expand_vec_shift_expr (sepops ops, rtx target)
781 enum insn_code icode;
782 rtx rtx_op1, rtx_op2;
783 enum machine_mode mode1;
784 enum machine_mode mode2;
785 enum machine_mode mode = TYPE_MODE (ops->type);
786 tree vec_oprnd = ops->op0;
787 tree shift_oprnd = ops->op1;
788 optab shift_optab;
789 rtx pat;
791 switch (ops->code)
793 case VEC_RSHIFT_EXPR:
794 shift_optab = vec_shr_optab;
795 break;
796 case VEC_LSHIFT_EXPR:
797 shift_optab = vec_shl_optab;
798 break;
799 default:
800 gcc_unreachable ();
803 icode = optab_handler (shift_optab, mode)->insn_code;
804 gcc_assert (icode != CODE_FOR_nothing);
806 mode1 = insn_data[icode].operand[1].mode;
807 mode2 = insn_data[icode].operand[2].mode;
809 rtx_op1 = expand_normal (vec_oprnd);
810 if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode1)
811 && mode1 != VOIDmode)
812 rtx_op1 = force_reg (mode1, rtx_op1);
814 rtx_op2 = expand_normal (shift_oprnd);
815 if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode2)
816 && mode2 != VOIDmode)
817 rtx_op2 = force_reg (mode2, rtx_op2);
819 if (!target
820 || ! (*insn_data[icode].operand[0].predicate) (target, mode))
821 target = gen_reg_rtx (mode);
823 /* Emit instruction */
824 pat = GEN_FCN (icode) (target, rtx_op1, rtx_op2);
825 gcc_assert (pat);
826 emit_insn (pat);
828 return target;
831 /* This subroutine of expand_doubleword_shift handles the cases in which
832 the effective shift value is >= BITS_PER_WORD. The arguments and return
833 value are the same as for the parent routine, except that SUPERWORD_OP1
834 is the shift count to use when shifting OUTOF_INPUT into INTO_TARGET.
835 INTO_TARGET may be null if the caller has decided to calculate it. */
837 static bool
838 expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
839 rtx outof_target, rtx into_target,
840 int unsignedp, enum optab_methods methods)
842 if (into_target != 0)
843 if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
844 into_target, unsignedp, methods))
845 return false;
847 if (outof_target != 0)
849 /* For a signed right shift, we must fill OUTOF_TARGET with copies
850 of the sign bit, otherwise we must fill it with zeros. */
851 if (binoptab != ashr_optab)
852 emit_move_insn (outof_target, CONST0_RTX (word_mode));
853 else
854 if (!force_expand_binop (word_mode, binoptab,
855 outof_input, GEN_INT (BITS_PER_WORD - 1),
856 outof_target, unsignedp, methods))
857 return false;
859 return true;
862 /* This subroutine of expand_doubleword_shift handles the cases in which
863 the effective shift value is < BITS_PER_WORD. The arguments and return
864 value are the same as for the parent routine. */
866 static bool
867 expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
868 rtx outof_input, rtx into_input, rtx op1,
869 rtx outof_target, rtx into_target,
870 int unsignedp, enum optab_methods methods,
871 unsigned HOST_WIDE_INT shift_mask)
873 optab reverse_unsigned_shift, unsigned_shift;
874 rtx tmp, carries;
876 reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
877 unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
879 /* The low OP1 bits of INTO_TARGET come from the high bits of OUTOF_INPUT.
880 We therefore need to shift OUTOF_INPUT by (BITS_PER_WORD - OP1) bits in
881 the opposite direction to BINOPTAB. */
882 if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
884 carries = outof_input;
885 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
886 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
887 0, true, methods);
889 else
891 /* We must avoid shifting by BITS_PER_WORD bits since that is either
892 the same as a zero shift (if shift_mask == BITS_PER_WORD - 1) or
893 has unknown behavior. Do a single shift first, then shift by the
894 remainder. It's OK to use ~OP1 as the remainder if shift counts
895 are truncated to the mode size. */
896 carries = expand_binop (word_mode, reverse_unsigned_shift,
897 outof_input, const1_rtx, 0, unsignedp, methods);
898 if (shift_mask == BITS_PER_WORD - 1)
900 tmp = immed_double_const (-1, -1, op1_mode);
901 tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
902 0, true, methods);
904 else
906 tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode);
907 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
908 0, true, methods);
911 if (tmp == 0 || carries == 0)
912 return false;
913 carries = expand_binop (word_mode, reverse_unsigned_shift,
914 carries, tmp, 0, unsignedp, methods);
915 if (carries == 0)
916 return false;
918 /* Shift INTO_INPUT logically by OP1. This is the last use of INTO_INPUT
919 so the result can go directly into INTO_TARGET if convenient. */
920 tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
921 into_target, unsignedp, methods);
922 if (tmp == 0)
923 return false;
925 /* Now OR in the bits carried over from OUTOF_INPUT. */
926 if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
927 into_target, unsignedp, methods))
928 return false;
930 /* Use a standard word_mode shift for the out-of half. */
931 if (outof_target != 0)
932 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
933 outof_target, unsignedp, methods))
934 return false;
936 return true;
940 #ifdef HAVE_conditional_move
941 /* Try implementing expand_doubleword_shift using conditional moves.
942 The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
943 otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1
944 are the shift counts to use in the former and latter case. All other
945 arguments are the same as the parent routine. */
947 static bool
948 expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
949 enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
950 rtx outof_input, rtx into_input,
951 rtx subword_op1, rtx superword_op1,
952 rtx outof_target, rtx into_target,
953 int unsignedp, enum optab_methods methods,
954 unsigned HOST_WIDE_INT shift_mask)
956 rtx outof_superword, into_superword;
958 /* Put the superword version of the output into OUTOF_SUPERWORD and
959 INTO_SUPERWORD. */
960 outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
961 if (outof_target != 0 && subword_op1 == superword_op1)
963 /* The value INTO_TARGET >> SUBWORD_OP1, which we later store in
964 OUTOF_TARGET, is the same as the value of INTO_SUPERWORD. */
965 into_superword = outof_target;
966 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
967 outof_superword, 0, unsignedp, methods))
968 return false;
970 else
972 into_superword = gen_reg_rtx (word_mode);
973 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
974 outof_superword, into_superword,
975 unsignedp, methods))
976 return false;
979 /* Put the subword version directly in OUTOF_TARGET and INTO_TARGET. */
980 if (!expand_subword_shift (op1_mode, binoptab,
981 outof_input, into_input, subword_op1,
982 outof_target, into_target,
983 unsignedp, methods, shift_mask))
984 return false;
986 /* Select between them. Do the INTO half first because INTO_SUPERWORD
987 might be the current value of OUTOF_TARGET. */
988 if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
989 into_target, into_superword, word_mode, false))
990 return false;
992 if (outof_target != 0)
993 if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
994 outof_target, outof_superword,
995 word_mode, false))
996 return false;
998 return true;
1000 #endif
1002 /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
1003 OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
1004 input operand; the shift moves bits in the direction OUTOF_INPUT->
1005 INTO_TARGET. OUTOF_TARGET and INTO_TARGET are the equivalent words
1006 of the target. OP1 is the shift count and OP1_MODE is its mode.
1007 If OP1 is constant, it will have been truncated as appropriate
1008 and is known to be nonzero.
1010 If SHIFT_MASK is zero, the result of word shifts is undefined when the
1011 shift count is outside the range [0, BITS_PER_WORD). This routine must
1012 avoid generating such shifts for OP1s in the range [0, BITS_PER_WORD * 2).
1014 If SHIFT_MASK is nonzero, all word-mode shift counts are effectively
1015 masked by it and shifts in the range [BITS_PER_WORD, SHIFT_MASK) will
1016 fill with zeros or sign bits as appropriate.
1018 If SHIFT_MASK is BITS_PER_WORD - 1, this routine will synthesize
1019 a doubleword shift whose equivalent mask is BITS_PER_WORD * 2 - 1.
1020 Doing this preserves semantics required by SHIFT_COUNT_TRUNCATED.
1021 In all other cases, shifts by values outside [0, BITS_PER_UNIT * 2)
1022 are undefined.
1024 BINOPTAB, UNSIGNEDP and METHODS are as for expand_binop. This function
1025 may not use INTO_INPUT after modifying INTO_TARGET, and similarly for
1026 OUTOF_INPUT and OUTOF_TARGET. OUTOF_TARGET can be null if the parent
1027 function wants to calculate it itself.
1029 Return true if the shift could be successfully synthesized. */
1031 static bool
1032 expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
1033 rtx outof_input, rtx into_input, rtx op1,
1034 rtx outof_target, rtx into_target,
1035 int unsignedp, enum optab_methods methods,
1036 unsigned HOST_WIDE_INT shift_mask)
1038 rtx superword_op1, tmp, cmp1, cmp2;
1039 rtx subword_label, done_label;
1040 enum rtx_code cmp_code;
1042 /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
1043 fill the result with sign or zero bits as appropriate. If so, the value
1044 of OUTOF_TARGET will always be (SHIFT OUTOF_INPUT OP1). Recursively call
1045 this routine to calculate INTO_TARGET (which depends on both OUTOF_INPUT
1046 and INTO_INPUT), then emit code to set up OUTOF_TARGET.
1048 This isn't worthwhile for constant shifts since the optimizers will
1049 cope better with in-range shift counts. */
1050 if (shift_mask >= BITS_PER_WORD
1051 && outof_target != 0
1052 && !CONSTANT_P (op1))
1054 if (!expand_doubleword_shift (op1_mode, binoptab,
1055 outof_input, into_input, op1,
1056 0, into_target,
1057 unsignedp, methods, shift_mask))
1058 return false;
1059 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
1060 outof_target, unsignedp, methods))
1061 return false;
1062 return true;
1065 /* Set CMP_CODE, CMP1 and CMP2 so that the rtx (CMP_CODE CMP1 CMP2)
1066 is true when the effective shift value is less than BITS_PER_WORD.
1067 Set SUPERWORD_OP1 to the shift count that should be used to shift
1068 OUTOF_INPUT into INTO_TARGET when the condition is false. */
1069 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
1070 if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
1072 /* Set CMP1 to OP1 & BITS_PER_WORD. The result is zero iff OP1
1073 is a subword shift count. */
1074 cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
1075 0, true, methods);
1076 cmp2 = CONST0_RTX (op1_mode);
1077 cmp_code = EQ;
1078 superword_op1 = op1;
1080 else
1082 /* Set CMP1 to OP1 - BITS_PER_WORD. */
1083 cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
1084 0, true, methods);
1085 cmp2 = CONST0_RTX (op1_mode);
1086 cmp_code = LT;
1087 superword_op1 = cmp1;
1089 if (cmp1 == 0)
1090 return false;
1092 /* If we can compute the condition at compile time, pick the
1093 appropriate subroutine. */
1094 tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
1095 if (tmp != 0 && CONST_INT_P (tmp))
1097 if (tmp == const0_rtx)
1098 return expand_superword_shift (binoptab, outof_input, superword_op1,
1099 outof_target, into_target,
1100 unsignedp, methods);
1101 else
1102 return expand_subword_shift (op1_mode, binoptab,
1103 outof_input, into_input, op1,
1104 outof_target, into_target,
1105 unsignedp, methods, shift_mask);
1108 #ifdef HAVE_conditional_move
1109 /* Try using conditional moves to generate straight-line code. */
1111 rtx start = get_last_insn ();
1112 if (expand_doubleword_shift_condmove (op1_mode, binoptab,
1113 cmp_code, cmp1, cmp2,
1114 outof_input, into_input,
1115 op1, superword_op1,
1116 outof_target, into_target,
1117 unsignedp, methods, shift_mask))
1118 return true;
1119 delete_insns_since (start);
1121 #endif
1123 /* As a last resort, use branches to select the correct alternative. */
1124 subword_label = gen_label_rtx ();
1125 done_label = gen_label_rtx ();
1127 NO_DEFER_POP;
1128 do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
1129 0, 0, subword_label, -1);
1130 OK_DEFER_POP;
1132 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
1133 outof_target, into_target,
1134 unsignedp, methods))
1135 return false;
1137 emit_jump_insn (gen_jump (done_label));
1138 emit_barrier ();
1139 emit_label (subword_label);
1141 if (!expand_subword_shift (op1_mode, binoptab,
1142 outof_input, into_input, op1,
1143 outof_target, into_target,
1144 unsignedp, methods, shift_mask))
1145 return false;
1147 emit_label (done_label);
1148 return true;
1151 /* Subroutine of expand_binop. Perform a double word multiplication of
1152 operands OP0 and OP1 both of mode MODE, which is exactly twice as wide
1153 as the target's word_mode. This function return NULL_RTX if anything
1154 goes wrong, in which case it may have already emitted instructions
1155 which need to be deleted.
1157 If we want to multiply two two-word values and have normal and widening
1158 multiplies of single-word values, we can do this with three smaller
1159 multiplications.
1161 The multiplication proceeds as follows:
1162 _______________________
1163 [__op0_high_|__op0_low__]
1164 _______________________
1165 * [__op1_high_|__op1_low__]
1166 _______________________________________________
1167 _______________________
1168 (1) [__op0_low__*__op1_low__]
1169 _______________________
1170 (2a) [__op0_low__*__op1_high_]
1171 _______________________
1172 (2b) [__op0_high_*__op1_low__]
1173 _______________________
1174 (3) [__op0_high_*__op1_high_]
1177 This gives a 4-word result. Since we are only interested in the
1178 lower 2 words, partial result (3) and the upper words of (2a) and
1179 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1180 calculated using non-widening multiplication.
1182 (1), however, needs to be calculated with an unsigned widening
1183 multiplication. If this operation is not directly supported we
1184 try using a signed widening multiplication and adjust the result.
1185 This adjustment works as follows:
1187 If both operands are positive then no adjustment is needed.
1189 If the operands have different signs, for example op0_low < 0 and
1190 op1_low >= 0, the instruction treats the most significant bit of
1191 op0_low as a sign bit instead of a bit with significance
1192 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1193 with 2**BITS_PER_WORD - op0_low, and two's complements the
1194 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1195 the result.
1197 Similarly, if both operands are negative, we need to add
1198 (op0_low + op1_low) * 2**BITS_PER_WORD.
1200 We use a trick to adjust quickly. We logically shift op0_low right
1201 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1202 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1203 logical shift exists, we do an arithmetic right shift and subtract
1204 the 0 or -1. */
1206 static rtx
1207 expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
1208 bool umulp, enum optab_methods methods)
1210 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1211 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1212 rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
1213 rtx product, adjust, product_high, temp;
1215 rtx op0_high = operand_subword_force (op0, high, mode);
1216 rtx op0_low = operand_subword_force (op0, low, mode);
1217 rtx op1_high = operand_subword_force (op1, high, mode);
1218 rtx op1_low = operand_subword_force (op1, low, mode);
1220 /* If we're using an unsigned multiply to directly compute the product
1221 of the low-order words of the operands and perform any required
1222 adjustments of the operands, we begin by trying two more multiplications
1223 and then computing the appropriate sum.
1225 We have checked above that the required addition is provided.
1226 Full-word addition will normally always succeed, especially if
1227 it is provided at all, so we don't worry about its failure. The
1228 multiplication may well fail, however, so we do handle that. */
1230 if (!umulp)
1232 /* ??? This could be done with emit_store_flag where available. */
1233 temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1234 NULL_RTX, 1, methods);
1235 if (temp)
1236 op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
1237 NULL_RTX, 0, OPTAB_DIRECT);
1238 else
1240 temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1241 NULL_RTX, 0, methods);
1242 if (!temp)
1243 return NULL_RTX;
1244 op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
1245 NULL_RTX, 0, OPTAB_DIRECT);
1248 if (!op0_high)
1249 return NULL_RTX;
1252 adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
1253 NULL_RTX, 0, OPTAB_DIRECT);
1254 if (!adjust)
1255 return NULL_RTX;
1257 /* OP0_HIGH should now be dead. */
1259 if (!umulp)
1261 /* ??? This could be done with emit_store_flag where available. */
1262 temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1263 NULL_RTX, 1, methods);
1264 if (temp)
1265 op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
1266 NULL_RTX, 0, OPTAB_DIRECT);
1267 else
1269 temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1270 NULL_RTX, 0, methods);
1271 if (!temp)
1272 return NULL_RTX;
1273 op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
1274 NULL_RTX, 0, OPTAB_DIRECT);
1277 if (!op1_high)
1278 return NULL_RTX;
1281 temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
1282 NULL_RTX, 0, OPTAB_DIRECT);
1283 if (!temp)
1284 return NULL_RTX;
1286 /* OP1_HIGH should now be dead. */
1288 adjust = expand_binop (word_mode, add_optab, adjust, temp,
1289 adjust, 0, OPTAB_DIRECT);
1291 if (target && !REG_P (target))
1292 target = NULL_RTX;
1294 if (umulp)
1295 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1296 target, 1, OPTAB_DIRECT);
1297 else
1298 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1299 target, 1, OPTAB_DIRECT);
1301 if (!product)
1302 return NULL_RTX;
1304 product_high = operand_subword (product, high, 1, mode);
1305 adjust = expand_binop (word_mode, add_optab, product_high, adjust,
1306 REG_P (product_high) ? product_high : adjust,
1307 0, OPTAB_DIRECT);
1308 emit_move_insn (product_high, adjust);
1309 return product;
1312 /* Wrapper around expand_binop which takes an rtx code to specify
1313 the operation to perform, not an optab pointer. All other
1314 arguments are the same. */
1316 expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
1317 rtx op1, rtx target, int unsignedp,
1318 enum optab_methods methods)
1320 optab binop = code_to_optab[(int) code];
1321 gcc_assert (binop);
1323 return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
1326 /* Return whether OP0 and OP1 should be swapped when expanding a commutative
1327 binop. Order them according to commutative_operand_precedence and, if
1328 possible, try to put TARGET or a pseudo first. */
1329 static bool
1330 swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
1332 int op0_prec = commutative_operand_precedence (op0);
1333 int op1_prec = commutative_operand_precedence (op1);
1335 if (op0_prec < op1_prec)
1336 return true;
1338 if (op0_prec > op1_prec)
1339 return false;
1341 /* With equal precedence, both orders are ok, but it is better if the
1342 first operand is TARGET, or if both TARGET and OP0 are pseudos. */
1343 if (target == 0 || REG_P (target))
1344 return (REG_P (op1) && !REG_P (op0)) || target == op1;
1345 else
1346 return rtx_equal_p (op1, target);
1349 /* Return true if BINOPTAB implements a shift operation. */
1351 static bool
1352 shift_optab_p (optab binoptab)
1354 switch (binoptab->code)
1356 case ASHIFT:
1357 case SS_ASHIFT:
1358 case US_ASHIFT:
1359 case ASHIFTRT:
1360 case LSHIFTRT:
1361 case ROTATE:
1362 case ROTATERT:
1363 return true;
1365 default:
1366 return false;
1370 /* Return true if BINOPTAB implements a commutative binary operation. */
1372 static bool
1373 commutative_optab_p (optab binoptab)
1375 return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
1376 || binoptab == smul_widen_optab
1377 || binoptab == umul_widen_optab
1378 || binoptab == smul_highpart_optab
1379 || binoptab == umul_highpart_optab);
1382 /* X is to be used in mode MODE as an operand to BINOPTAB. If we're
1383 optimizing, and if the operand is a constant that costs more than
1384 1 instruction, force the constant into a register and return that
1385 register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */
1387 static rtx
1388 avoid_expensive_constant (enum machine_mode mode, optab binoptab,
1389 rtx x, bool unsignedp)
1391 bool speed = optimize_insn_for_speed_p ();
1393 if (mode != VOIDmode
1394 && optimize
1395 && CONSTANT_P (x)
1396 && rtx_cost (x, binoptab->code, speed) > rtx_cost (x, SET, speed))
1398 if (CONST_INT_P (x))
1400 HOST_WIDE_INT intval = trunc_int_for_mode (INTVAL (x), mode);
1401 if (intval != INTVAL (x))
1402 x = GEN_INT (intval);
1404 else
1405 x = convert_modes (mode, VOIDmode, x, unsignedp);
1406 x = force_reg (mode, x);
1408 return x;
1411 /* Helper function for expand_binop: handle the case where there
1412 is an insn that directly implements the indicated operation.
1413 Returns null if this is not possible. */
1414 static rtx
1415 expand_binop_directly (enum machine_mode mode, optab binoptab,
1416 rtx op0, rtx op1,
1417 rtx target, int unsignedp, enum optab_methods methods,
1418 rtx last)
1420 int icode = (int) optab_handler (binoptab, mode)->insn_code;
1421 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
1422 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
1423 enum machine_mode tmp_mode;
1424 bool commutative_p;
1425 rtx pat;
1426 rtx xop0 = op0, xop1 = op1;
1427 rtx temp;
1428 rtx swap;
1430 if (target)
1431 temp = target;
1432 else
1433 temp = gen_reg_rtx (mode);
1435 /* If it is a commutative operator and the modes would match
1436 if we would swap the operands, we can save the conversions. */
1437 commutative_p = commutative_optab_p (binoptab);
1438 if (commutative_p
1439 && GET_MODE (xop0) != mode0 && GET_MODE (xop1) != mode1
1440 && GET_MODE (xop0) == mode1 && GET_MODE (xop1) == mode1)
1442 swap = xop0;
1443 xop0 = xop1;
1444 xop1 = swap;
1447 /* If we are optimizing, force expensive constants into a register. */
1448 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
1449 if (!shift_optab_p (binoptab))
1450 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
1452 /* In case the insn wants input operands in modes different from
1453 those of the actual operands, convert the operands. It would
1454 seem that we don't need to convert CONST_INTs, but we do, so
1455 that they're properly zero-extended, sign-extended or truncated
1456 for their mode. */
1458 if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode)
1459 xop0 = convert_modes (mode0,
1460 GET_MODE (xop0) != VOIDmode
1461 ? GET_MODE (xop0)
1462 : mode,
1463 xop0, unsignedp);
1465 if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode)
1466 xop1 = convert_modes (mode1,
1467 GET_MODE (xop1) != VOIDmode
1468 ? GET_MODE (xop1)
1469 : mode,
1470 xop1, unsignedp);
1472 /* If operation is commutative,
1473 try to make the first operand a register.
1474 Even better, try to make it the same as the target.
1475 Also try to make the last operand a constant. */
1476 if (commutative_p
1477 && swap_commutative_operands_with_target (target, xop0, xop1))
1479 swap = xop1;
1480 xop1 = xop0;
1481 xop0 = swap;
1484 /* Now, if insn's predicates don't allow our operands, put them into
1485 pseudo regs. */
1487 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
1488 && mode0 != VOIDmode)
1489 xop0 = copy_to_mode_reg (mode0, xop0);
1491 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
1492 && mode1 != VOIDmode)
1493 xop1 = copy_to_mode_reg (mode1, xop1);
1495 if (binoptab == vec_pack_trunc_optab
1496 || binoptab == vec_pack_usat_optab
1497 || binoptab == vec_pack_ssat_optab
1498 || binoptab == vec_pack_ufix_trunc_optab
1499 || binoptab == vec_pack_sfix_trunc_optab)
1501 /* The mode of the result is different then the mode of the
1502 arguments. */
1503 tmp_mode = insn_data[icode].operand[0].mode;
1504 if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
1505 return 0;
1507 else
1508 tmp_mode = mode;
1510 if (!insn_data[icode].operand[0].predicate (temp, tmp_mode))
1511 temp = gen_reg_rtx (tmp_mode);
1513 pat = GEN_FCN (icode) (temp, xop0, xop1);
1514 if (pat)
1516 /* If PAT is composed of more than one insn, try to add an appropriate
1517 REG_EQUAL note to it. If we can't because TEMP conflicts with an
1518 operand, call expand_binop again, this time without a target. */
1519 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
1520 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
1522 delete_insns_since (last);
1523 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
1524 unsignedp, methods);
1527 emit_insn (pat);
1528 return temp;
1531 delete_insns_since (last);
1532 return NULL_RTX;
1535 /* Generate code to perform an operation specified by BINOPTAB
1536 on operands OP0 and OP1, with result having machine-mode MODE.
1538 UNSIGNEDP is for the case where we have to widen the operands
1539 to perform the operation. It says to use zero-extension.
1541 If TARGET is nonzero, the value
1542 is generated there, if it is convenient to do so.
1543 In all cases an rtx is returned for the locus of the value;
1544 this may or may not be TARGET. */
1547 expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
1548 rtx target, int unsignedp, enum optab_methods methods)
1550 enum optab_methods next_methods
1551 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
1552 ? OPTAB_WIDEN : methods);
1553 enum mode_class mclass;
1554 enum machine_mode wider_mode;
1555 rtx libfunc;
1556 rtx temp;
1557 rtx entry_last = get_last_insn ();
1558 rtx last;
1560 mclass = GET_MODE_CLASS (mode);
1562 /* If subtracting an integer constant, convert this into an addition of
1563 the negated constant. */
1565 if (binoptab == sub_optab && CONST_INT_P (op1))
1567 op1 = negate_rtx (mode, op1);
1568 binoptab = add_optab;
1571 /* Record where to delete back to if we backtrack. */
1572 last = get_last_insn ();
1574 /* If we can do it with a three-operand insn, do so. */
1576 if (methods != OPTAB_MUST_WIDEN
1577 && optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing)
1579 temp = expand_binop_directly (mode, binoptab, op0, op1, target,
1580 unsignedp, methods, last);
1581 if (temp)
1582 return temp;
1585 /* If we were trying to rotate, and that didn't work, try rotating
1586 the other direction before falling back to shifts and bitwise-or. */
1587 if (((binoptab == rotl_optab
1588 && optab_handler (rotr_optab, mode)->insn_code != CODE_FOR_nothing)
1589 || (binoptab == rotr_optab
1590 && optab_handler (rotl_optab, mode)->insn_code != CODE_FOR_nothing))
1591 && mclass == MODE_INT)
1593 optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
1594 rtx newop1;
1595 unsigned int bits = GET_MODE_BITSIZE (mode);
1597 if (CONST_INT_P (op1))
1598 newop1 = GEN_INT (bits - INTVAL (op1));
1599 else if (targetm.shift_truncation_mask (mode) == bits - 1)
1600 newop1 = negate_rtx (GET_MODE (op1), op1);
1601 else
1602 newop1 = expand_binop (GET_MODE (op1), sub_optab,
1603 GEN_INT (bits), op1,
1604 NULL_RTX, unsignedp, OPTAB_DIRECT);
1606 temp = expand_binop_directly (mode, otheroptab, op0, newop1,
1607 target, unsignedp, methods, last);
1608 if (temp)
1609 return temp;
1612 /* If this is a multiply, see if we can do a widening operation that
1613 takes operands of this mode and makes a wider mode. */
1615 if (binoptab == smul_optab
1616 && GET_MODE_WIDER_MODE (mode) != VOIDmode
1617 && ((optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab),
1618 GET_MODE_WIDER_MODE (mode))->insn_code)
1619 != CODE_FOR_nothing))
1621 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
1622 unsignedp ? umul_widen_optab : smul_widen_optab,
1623 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
1625 if (temp != 0)
1627 if (GET_MODE_CLASS (mode) == MODE_INT
1628 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1629 GET_MODE_BITSIZE (GET_MODE (temp))))
1630 return gen_lowpart (mode, temp);
1631 else
1632 return convert_to_mode (mode, temp, unsignedp);
1636 /* Look for a wider mode of the same class for which we think we
1637 can open-code the operation. Check for a widening multiply at the
1638 wider mode as well. */
1640 if (CLASS_HAS_WIDER_MODES_P (mclass)
1641 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
1642 for (wider_mode = GET_MODE_WIDER_MODE (mode);
1643 wider_mode != VOIDmode;
1644 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1646 if (optab_handler (binoptab, wider_mode)->insn_code != CODE_FOR_nothing
1647 || (binoptab == smul_optab
1648 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
1649 && ((optab_handler ((unsignedp ? umul_widen_optab
1650 : smul_widen_optab),
1651 GET_MODE_WIDER_MODE (wider_mode))->insn_code)
1652 != CODE_FOR_nothing)))
1654 rtx xop0 = op0, xop1 = op1;
1655 int no_extend = 0;
1657 /* For certain integer operations, we need not actually extend
1658 the narrow operands, as long as we will truncate
1659 the results to the same narrowness. */
1661 if ((binoptab == ior_optab || binoptab == and_optab
1662 || binoptab == xor_optab
1663 || binoptab == add_optab || binoptab == sub_optab
1664 || binoptab == smul_optab || binoptab == ashl_optab)
1665 && mclass == MODE_INT)
1667 no_extend = 1;
1668 xop0 = avoid_expensive_constant (mode, binoptab,
1669 xop0, unsignedp);
1670 if (binoptab != ashl_optab)
1671 xop1 = avoid_expensive_constant (mode, binoptab,
1672 xop1, unsignedp);
1675 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
1677 /* The second operand of a shift must always be extended. */
1678 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1679 no_extend && binoptab != ashl_optab);
1681 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1682 unsignedp, OPTAB_DIRECT);
1683 if (temp)
1685 if (mclass != MODE_INT
1686 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1687 GET_MODE_BITSIZE (wider_mode)))
1689 if (target == 0)
1690 target = gen_reg_rtx (mode);
1691 convert_move (target, temp, 0);
1692 return target;
1694 else
1695 return gen_lowpart (mode, temp);
1697 else
1698 delete_insns_since (last);
1702 /* If operation is commutative,
1703 try to make the first operand a register.
1704 Even better, try to make it the same as the target.
1705 Also try to make the last operand a constant. */
1706 if (commutative_optab_p (binoptab)
1707 && swap_commutative_operands_with_target (target, op0, op1))
1709 temp = op1;
1710 op1 = op0;
1711 op0 = temp;
1714 /* These can be done a word at a time. */
1715 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
1716 && mclass == MODE_INT
1717 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1718 && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
1720 int i;
1721 rtx insns;
1723 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1724 won't be accurate, so use a new target. */
1725 if (target == 0 || target == op0 || target == op1)
1726 target = gen_reg_rtx (mode);
1728 start_sequence ();
1730 /* Do the actual arithmetic. */
1731 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1733 rtx target_piece = operand_subword (target, i, 1, mode);
1734 rtx x = expand_binop (word_mode, binoptab,
1735 operand_subword_force (op0, i, mode),
1736 operand_subword_force (op1, i, mode),
1737 target_piece, unsignedp, next_methods);
1739 if (x == 0)
1740 break;
1742 if (target_piece != x)
1743 emit_move_insn (target_piece, x);
1746 insns = get_insns ();
1747 end_sequence ();
1749 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1751 emit_insn (insns);
1752 return target;
1756 /* Synthesize double word shifts from single word shifts. */
1757 if ((binoptab == lshr_optab || binoptab == ashl_optab
1758 || binoptab == ashr_optab)
1759 && mclass == MODE_INT
1760 && (CONST_INT_P (op1) || optimize_insn_for_speed_p ())
1761 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1762 && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing
1763 && optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
1764 && optab_handler (lshr_optab, word_mode)->insn_code != CODE_FOR_nothing)
1766 unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
1767 enum machine_mode op1_mode;
1769 double_shift_mask = targetm.shift_truncation_mask (mode);
1770 shift_mask = targetm.shift_truncation_mask (word_mode);
1771 op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
1773 /* Apply the truncation to constant shifts. */
1774 if (double_shift_mask > 0 && CONST_INT_P (op1))
1775 op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
1777 if (op1 == CONST0_RTX (op1_mode))
1778 return op0;
1780 /* Make sure that this is a combination that expand_doubleword_shift
1781 can handle. See the comments there for details. */
1782 if (double_shift_mask == 0
1783 || (shift_mask == BITS_PER_WORD - 1
1784 && double_shift_mask == BITS_PER_WORD * 2 - 1))
1786 rtx insns;
1787 rtx into_target, outof_target;
1788 rtx into_input, outof_input;
1789 int left_shift, outof_word;
1791 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1792 won't be accurate, so use a new target. */
1793 if (target == 0 || target == op0 || target == op1)
1794 target = gen_reg_rtx (mode);
1796 start_sequence ();
1798 /* OUTOF_* is the word we are shifting bits away from, and
1799 INTO_* is the word that we are shifting bits towards, thus
1800 they differ depending on the direction of the shift and
1801 WORDS_BIG_ENDIAN. */
1803 left_shift = binoptab == ashl_optab;
1804 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1806 outof_target = operand_subword (target, outof_word, 1, mode);
1807 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1809 outof_input = operand_subword_force (op0, outof_word, mode);
1810 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1812 if (expand_doubleword_shift (op1_mode, binoptab,
1813 outof_input, into_input, op1,
1814 outof_target, into_target,
1815 unsignedp, next_methods, shift_mask))
1817 insns = get_insns ();
1818 end_sequence ();
1820 emit_insn (insns);
1821 return target;
1823 end_sequence ();
1827 /* Synthesize double word rotates from single word shifts. */
1828 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1829 && mclass == MODE_INT
1830 && CONST_INT_P (op1)
1831 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1832 && optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
1833 && optab_handler (lshr_optab, word_mode)->insn_code != CODE_FOR_nothing)
1835 rtx insns;
1836 rtx into_target, outof_target;
1837 rtx into_input, outof_input;
1838 rtx inter;
1839 int shift_count, left_shift, outof_word;
1841 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1842 won't be accurate, so use a new target. Do this also if target is not
1843 a REG, first because having a register instead may open optimization
1844 opportunities, and second because if target and op0 happen to be MEMs
1845 designating the same location, we would risk clobbering it too early
1846 in the code sequence we generate below. */
1847 if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
1848 target = gen_reg_rtx (mode);
1850 start_sequence ();
1852 shift_count = INTVAL (op1);
1854 /* OUTOF_* is the word we are shifting bits away from, and
1855 INTO_* is the word that we are shifting bits towards, thus
1856 they differ depending on the direction of the shift and
1857 WORDS_BIG_ENDIAN. */
1859 left_shift = (binoptab == rotl_optab);
1860 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1862 outof_target = operand_subword (target, outof_word, 1, mode);
1863 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1865 outof_input = operand_subword_force (op0, outof_word, mode);
1866 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1868 if (shift_count == BITS_PER_WORD)
1870 /* This is just a word swap. */
1871 emit_move_insn (outof_target, into_input);
1872 emit_move_insn (into_target, outof_input);
1873 inter = const0_rtx;
1875 else
1877 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1878 rtx first_shift_count, second_shift_count;
1879 optab reverse_unsigned_shift, unsigned_shift;
1881 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1882 ? lshr_optab : ashl_optab);
1884 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1885 ? ashl_optab : lshr_optab);
1887 if (shift_count > BITS_PER_WORD)
1889 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1890 second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
1892 else
1894 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1895 second_shift_count = GEN_INT (shift_count);
1898 into_temp1 = expand_binop (word_mode, unsigned_shift,
1899 outof_input, first_shift_count,
1900 NULL_RTX, unsignedp, next_methods);
1901 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1902 into_input, second_shift_count,
1903 NULL_RTX, unsignedp, next_methods);
1905 if (into_temp1 != 0 && into_temp2 != 0)
1906 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1907 into_target, unsignedp, next_methods);
1908 else
1909 inter = 0;
1911 if (inter != 0 && inter != into_target)
1912 emit_move_insn (into_target, inter);
1914 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1915 into_input, first_shift_count,
1916 NULL_RTX, unsignedp, next_methods);
1917 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1918 outof_input, second_shift_count,
1919 NULL_RTX, unsignedp, next_methods);
1921 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1922 inter = expand_binop (word_mode, ior_optab,
1923 outof_temp1, outof_temp2,
1924 outof_target, unsignedp, next_methods);
1926 if (inter != 0 && inter != outof_target)
1927 emit_move_insn (outof_target, inter);
1930 insns = get_insns ();
1931 end_sequence ();
1933 if (inter != 0)
1935 emit_insn (insns);
1936 return target;
1940 /* These can be done a word at a time by propagating carries. */
1941 if ((binoptab == add_optab || binoptab == sub_optab)
1942 && mclass == MODE_INT
1943 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1944 && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
1946 unsigned int i;
1947 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1948 const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1949 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1950 rtx xop0, xop1, xtarget;
1952 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1953 value is one of those, use it. Otherwise, use 1 since it is the
1954 one easiest to get. */
1955 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1956 int normalizep = STORE_FLAG_VALUE;
1957 #else
1958 int normalizep = 1;
1959 #endif
1961 /* Prepare the operands. */
1962 xop0 = force_reg (mode, op0);
1963 xop1 = force_reg (mode, op1);
1965 xtarget = gen_reg_rtx (mode);
1967 if (target == 0 || !REG_P (target))
1968 target = xtarget;
1970 /* Indicate for flow that the entire target reg is being set. */
1971 if (REG_P (target))
1972 emit_clobber (xtarget);
1974 /* Do the actual arithmetic. */
1975 for (i = 0; i < nwords; i++)
1977 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1978 rtx target_piece = operand_subword (xtarget, index, 1, mode);
1979 rtx op0_piece = operand_subword_force (xop0, index, mode);
1980 rtx op1_piece = operand_subword_force (xop1, index, mode);
1981 rtx x;
1983 /* Main add/subtract of the input operands. */
1984 x = expand_binop (word_mode, binoptab,
1985 op0_piece, op1_piece,
1986 target_piece, unsignedp, next_methods);
1987 if (x == 0)
1988 break;
1990 if (i + 1 < nwords)
1992 /* Store carry from main add/subtract. */
1993 carry_out = gen_reg_rtx (word_mode);
1994 carry_out = emit_store_flag_force (carry_out,
1995 (binoptab == add_optab
1996 ? LT : GT),
1997 x, op0_piece,
1998 word_mode, 1, normalizep);
2001 if (i > 0)
2003 rtx newx;
2005 /* Add/subtract previous carry to main result. */
2006 newx = expand_binop (word_mode,
2007 normalizep == 1 ? binoptab : otheroptab,
2008 x, carry_in,
2009 NULL_RTX, 1, next_methods);
2011 if (i + 1 < nwords)
2013 /* Get out carry from adding/subtracting carry in. */
2014 rtx carry_tmp = gen_reg_rtx (word_mode);
2015 carry_tmp = emit_store_flag_force (carry_tmp,
2016 (binoptab == add_optab
2017 ? LT : GT),
2018 newx, x,
2019 word_mode, 1, normalizep);
2021 /* Logical-ior the two poss. carry together. */
2022 carry_out = expand_binop (word_mode, ior_optab,
2023 carry_out, carry_tmp,
2024 carry_out, 0, next_methods);
2025 if (carry_out == 0)
2026 break;
2028 emit_move_insn (target_piece, newx);
2030 else
2032 if (x != target_piece)
2033 emit_move_insn (target_piece, x);
2036 carry_in = carry_out;
2039 if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
2041 if (optab_handler (mov_optab, mode)->insn_code != CODE_FOR_nothing
2042 || ! rtx_equal_p (target, xtarget))
2044 rtx temp = emit_move_insn (target, xtarget);
2046 set_unique_reg_note (temp,
2047 REG_EQUAL,
2048 gen_rtx_fmt_ee (binoptab->code, mode,
2049 copy_rtx (xop0),
2050 copy_rtx (xop1)));
2052 else
2053 target = xtarget;
2055 return target;
2058 else
2059 delete_insns_since (last);
2062 /* Attempt to synthesize double word multiplies using a sequence of word
2063 mode multiplications. We first attempt to generate a sequence using a
2064 more efficient unsigned widening multiply, and if that fails we then
2065 try using a signed widening multiply. */
2067 if (binoptab == smul_optab
2068 && mclass == MODE_INT
2069 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
2070 && optab_handler (smul_optab, word_mode)->insn_code != CODE_FOR_nothing
2071 && optab_handler (add_optab, word_mode)->insn_code != CODE_FOR_nothing)
2073 rtx product = NULL_RTX;
2075 if (optab_handler (umul_widen_optab, mode)->insn_code
2076 != CODE_FOR_nothing)
2078 product = expand_doubleword_mult (mode, op0, op1, target,
2079 true, methods);
2080 if (!product)
2081 delete_insns_since (last);
2084 if (product == NULL_RTX
2085 && optab_handler (smul_widen_optab, mode)->insn_code
2086 != CODE_FOR_nothing)
2088 product = expand_doubleword_mult (mode, op0, op1, target,
2089 false, methods);
2090 if (!product)
2091 delete_insns_since (last);
2094 if (product != NULL_RTX)
2096 if (optab_handler (mov_optab, mode)->insn_code != CODE_FOR_nothing)
2098 temp = emit_move_insn (target ? target : product, product);
2099 set_unique_reg_note (temp,
2100 REG_EQUAL,
2101 gen_rtx_fmt_ee (MULT, mode,
2102 copy_rtx (op0),
2103 copy_rtx (op1)));
2105 return product;
2109 /* It can't be open-coded in this mode.
2110 Use a library call if one is available and caller says that's ok. */
2112 libfunc = optab_libfunc (binoptab, mode);
2113 if (libfunc
2114 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
2116 rtx insns;
2117 rtx op1x = op1;
2118 enum machine_mode op1_mode = mode;
2119 rtx value;
2121 start_sequence ();
2123 if (shift_optab_p (binoptab))
2125 op1_mode = targetm.libgcc_shift_count_mode ();
2126 /* Specify unsigned here,
2127 since negative shift counts are meaningless. */
2128 op1x = convert_to_mode (op1_mode, op1, 1);
2131 if (GET_MODE (op0) != VOIDmode
2132 && GET_MODE (op0) != mode)
2133 op0 = convert_to_mode (mode, op0, unsignedp);
2135 /* Pass 1 for NO_QUEUE so we don't lose any increments
2136 if the libcall is cse'd or moved. */
2137 value = emit_library_call_value (libfunc,
2138 NULL_RTX, LCT_CONST, mode, 2,
2139 op0, mode, op1x, op1_mode);
2141 insns = get_insns ();
2142 end_sequence ();
2144 target = gen_reg_rtx (mode);
2145 emit_libcall_block (insns, target, value,
2146 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
2148 return target;
2151 delete_insns_since (last);
2153 /* It can't be done in this mode. Can we do it in a wider mode? */
2155 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
2156 || methods == OPTAB_MUST_WIDEN))
2158 /* Caller says, don't even try. */
2159 delete_insns_since (entry_last);
2160 return 0;
2163 /* Compute the value of METHODS to pass to recursive calls.
2164 Don't allow widening to be tried recursively. */
2166 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
2168 /* Look for a wider mode of the same class for which it appears we can do
2169 the operation. */
2171 if (CLASS_HAS_WIDER_MODES_P (mclass))
2173 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2174 wider_mode != VOIDmode;
2175 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2177 if ((optab_handler (binoptab, wider_mode)->insn_code
2178 != CODE_FOR_nothing)
2179 || (methods == OPTAB_LIB
2180 && optab_libfunc (binoptab, wider_mode)))
2182 rtx xop0 = op0, xop1 = op1;
2183 int no_extend = 0;
2185 /* For certain integer operations, we need not actually extend
2186 the narrow operands, as long as we will truncate
2187 the results to the same narrowness. */
2189 if ((binoptab == ior_optab || binoptab == and_optab
2190 || binoptab == xor_optab
2191 || binoptab == add_optab || binoptab == sub_optab
2192 || binoptab == smul_optab || binoptab == ashl_optab)
2193 && mclass == MODE_INT)
2194 no_extend = 1;
2196 xop0 = widen_operand (xop0, wider_mode, mode,
2197 unsignedp, no_extend);
2199 /* The second operand of a shift must always be extended. */
2200 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
2201 no_extend && binoptab != ashl_optab);
2203 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
2204 unsignedp, methods);
2205 if (temp)
2207 if (mclass != MODE_INT
2208 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
2209 GET_MODE_BITSIZE (wider_mode)))
2211 if (target == 0)
2212 target = gen_reg_rtx (mode);
2213 convert_move (target, temp, 0);
2214 return target;
2216 else
2217 return gen_lowpart (mode, temp);
2219 else
2220 delete_insns_since (last);
2225 delete_insns_since (entry_last);
2226 return 0;
2229 /* Expand a binary operator which has both signed and unsigned forms.
2230 UOPTAB is the optab for unsigned operations, and SOPTAB is for
2231 signed operations.
2233 If we widen unsigned operands, we may use a signed wider operation instead
2234 of an unsigned wider operation, since the result would be the same. */
2237 sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
2238 rtx op0, rtx op1, rtx target, int unsignedp,
2239 enum optab_methods methods)
2241 rtx temp;
2242 optab direct_optab = unsignedp ? uoptab : soptab;
2243 struct optab_d wide_soptab;
2245 /* Do it without widening, if possible. */
2246 temp = expand_binop (mode, direct_optab, op0, op1, target,
2247 unsignedp, OPTAB_DIRECT);
2248 if (temp || methods == OPTAB_DIRECT)
2249 return temp;
2251 /* Try widening to a signed int. Make a fake signed optab that
2252 hides any signed insn for direct use. */
2253 wide_soptab = *soptab;
2254 optab_handler (&wide_soptab, mode)->insn_code = CODE_FOR_nothing;
2255 /* We don't want to generate new hash table entries from this fake
2256 optab. */
2257 wide_soptab.libcall_gen = NULL;
2259 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2260 unsignedp, OPTAB_WIDEN);
2262 /* For unsigned operands, try widening to an unsigned int. */
2263 if (temp == 0 && unsignedp)
2264 temp = expand_binop (mode, uoptab, op0, op1, target,
2265 unsignedp, OPTAB_WIDEN);
2266 if (temp || methods == OPTAB_WIDEN)
2267 return temp;
2269 /* Use the right width libcall if that exists. */
2270 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
2271 if (temp || methods == OPTAB_LIB)
2272 return temp;
2274 /* Must widen and use a libcall, use either signed or unsigned. */
2275 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2276 unsignedp, methods);
2277 if (temp != 0)
2278 return temp;
2279 if (unsignedp)
2280 return expand_binop (mode, uoptab, op0, op1, target,
2281 unsignedp, methods);
2282 return 0;
2285 /* Generate code to perform an operation specified by UNOPPTAB
2286 on operand OP0, with two results to TARG0 and TARG1.
2287 We assume that the order of the operands for the instruction
2288 is TARG0, TARG1, OP0.
2290 Either TARG0 or TARG1 may be zero, but what that means is that
2291 the result is not actually wanted. We will generate it into
2292 a dummy pseudo-reg and discard it. They may not both be zero.
2294 Returns 1 if this operation can be performed; 0 if not. */
2297 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
2298 int unsignedp)
2300 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2301 enum mode_class mclass;
2302 enum machine_mode wider_mode;
2303 rtx entry_last = get_last_insn ();
2304 rtx last;
2306 mclass = GET_MODE_CLASS (mode);
2308 if (!targ0)
2309 targ0 = gen_reg_rtx (mode);
2310 if (!targ1)
2311 targ1 = gen_reg_rtx (mode);
2313 /* Record where to go back to if we fail. */
2314 last = get_last_insn ();
2316 if (optab_handler (unoptab, mode)->insn_code != CODE_FOR_nothing)
2318 int icode = (int) optab_handler (unoptab, mode)->insn_code;
2319 enum machine_mode mode0 = insn_data[icode].operand[2].mode;
2320 rtx pat;
2321 rtx xop0 = op0;
2323 if (GET_MODE (xop0) != VOIDmode
2324 && GET_MODE (xop0) != mode0)
2325 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2327 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2328 if (!insn_data[icode].operand[2].predicate (xop0, mode0))
2329 xop0 = copy_to_mode_reg (mode0, xop0);
2331 /* We could handle this, but we should always be called with a pseudo
2332 for our targets and all insns should take them as outputs. */
2333 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2334 gcc_assert (insn_data[icode].operand[1].predicate (targ1, mode));
2336 pat = GEN_FCN (icode) (targ0, targ1, xop0);
2337 if (pat)
2339 emit_insn (pat);
2340 return 1;
2342 else
2343 delete_insns_since (last);
2346 /* It can't be done in this mode. Can we do it in a wider mode? */
2348 if (CLASS_HAS_WIDER_MODES_P (mclass))
2350 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2351 wider_mode != VOIDmode;
2352 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2354 if (optab_handler (unoptab, wider_mode)->insn_code
2355 != CODE_FOR_nothing)
2357 rtx t0 = gen_reg_rtx (wider_mode);
2358 rtx t1 = gen_reg_rtx (wider_mode);
2359 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2361 if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
2363 convert_move (targ0, t0, unsignedp);
2364 convert_move (targ1, t1, unsignedp);
2365 return 1;
2367 else
2368 delete_insns_since (last);
2373 delete_insns_since (entry_last);
2374 return 0;
2377 /* Generate code to perform an operation specified by BINOPTAB
2378 on operands OP0 and OP1, with two results to TARG1 and TARG2.
2379 We assume that the order of the operands for the instruction
2380 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2381 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2383 Either TARG0 or TARG1 may be zero, but what that means is that
2384 the result is not actually wanted. We will generate it into
2385 a dummy pseudo-reg and discard it. They may not both be zero.
2387 Returns 1 if this operation can be performed; 0 if not. */
2390 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
2391 int unsignedp)
2393 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2394 enum mode_class mclass;
2395 enum machine_mode wider_mode;
2396 rtx entry_last = get_last_insn ();
2397 rtx last;
2399 mclass = GET_MODE_CLASS (mode);
2401 if (!targ0)
2402 targ0 = gen_reg_rtx (mode);
2403 if (!targ1)
2404 targ1 = gen_reg_rtx (mode);
2406 /* Record where to go back to if we fail. */
2407 last = get_last_insn ();
2409 if (optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing)
2411 int icode = (int) optab_handler (binoptab, mode)->insn_code;
2412 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2413 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
2414 rtx pat;
2415 rtx xop0 = op0, xop1 = op1;
2417 /* If we are optimizing, force expensive constants into a register. */
2418 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
2419 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
2421 /* In case the insn wants input operands in modes different from
2422 those of the actual operands, convert the operands. It would
2423 seem that we don't need to convert CONST_INTs, but we do, so
2424 that they're properly zero-extended, sign-extended or truncated
2425 for their mode. */
2427 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
2428 xop0 = convert_modes (mode0,
2429 GET_MODE (op0) != VOIDmode
2430 ? GET_MODE (op0)
2431 : mode,
2432 xop0, unsignedp);
2434 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
2435 xop1 = convert_modes (mode1,
2436 GET_MODE (op1) != VOIDmode
2437 ? GET_MODE (op1)
2438 : mode,
2439 xop1, unsignedp);
2441 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2442 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
2443 xop0 = copy_to_mode_reg (mode0, xop0);
2445 if (!insn_data[icode].operand[2].predicate (xop1, mode1))
2446 xop1 = copy_to_mode_reg (mode1, xop1);
2448 /* We could handle this, but we should always be called with a pseudo
2449 for our targets and all insns should take them as outputs. */
2450 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2451 gcc_assert (insn_data[icode].operand[3].predicate (targ1, mode));
2453 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
2454 if (pat)
2456 emit_insn (pat);
2457 return 1;
2459 else
2460 delete_insns_since (last);
2463 /* It can't be done in this mode. Can we do it in a wider mode? */
2465 if (CLASS_HAS_WIDER_MODES_P (mclass))
2467 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2468 wider_mode != VOIDmode;
2469 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2471 if (optab_handler (binoptab, wider_mode)->insn_code
2472 != CODE_FOR_nothing)
2474 rtx t0 = gen_reg_rtx (wider_mode);
2475 rtx t1 = gen_reg_rtx (wider_mode);
2476 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2477 rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
2479 if (expand_twoval_binop (binoptab, cop0, cop1,
2480 t0, t1, unsignedp))
2482 convert_move (targ0, t0, unsignedp);
2483 convert_move (targ1, t1, unsignedp);
2484 return 1;
2486 else
2487 delete_insns_since (last);
2492 delete_insns_since (entry_last);
2493 return 0;
2496 /* Expand the two-valued library call indicated by BINOPTAB, but
2497 preserve only one of the values. If TARG0 is non-NULL, the first
2498 value is placed into TARG0; otherwise the second value is placed
2499 into TARG1. Exactly one of TARG0 and TARG1 must be non-NULL. The
2500 value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
2501 This routine assumes that the value returned by the library call is
2502 as if the return value was of an integral mode twice as wide as the
2503 mode of OP0. Returns 1 if the call was successful. */
2505 bool
2506 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
2507 rtx targ0, rtx targ1, enum rtx_code code)
2509 enum machine_mode mode;
2510 enum machine_mode libval_mode;
2511 rtx libval;
2512 rtx insns;
2513 rtx libfunc;
2515 /* Exactly one of TARG0 or TARG1 should be non-NULL. */
2516 gcc_assert (!targ0 != !targ1);
2518 mode = GET_MODE (op0);
2519 libfunc = optab_libfunc (binoptab, mode);
2520 if (!libfunc)
2521 return false;
2523 /* The value returned by the library function will have twice as
2524 many bits as the nominal MODE. */
2525 libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
2526 MODE_INT);
2527 start_sequence ();
2528 libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
2529 libval_mode, 2,
2530 op0, mode,
2531 op1, mode);
2532 /* Get the part of VAL containing the value that we want. */
2533 libval = simplify_gen_subreg (mode, libval, libval_mode,
2534 targ0 ? 0 : GET_MODE_SIZE (mode));
2535 insns = get_insns ();
2536 end_sequence ();
2537 /* Move the into the desired location. */
2538 emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
2539 gen_rtx_fmt_ee (code, mode, op0, op1));
2541 return true;
2545 /* Wrapper around expand_unop which takes an rtx code to specify
2546 the operation to perform, not an optab pointer. All other
2547 arguments are the same. */
2549 expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
2550 rtx target, int unsignedp)
2552 optab unop = code_to_optab[(int) code];
2553 gcc_assert (unop);
2555 return expand_unop (mode, unop, op0, target, unsignedp);
2558 /* Try calculating
2559 (clz:narrow x)
2561 (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)). */
2562 static rtx
2563 widen_clz (enum machine_mode mode, rtx op0, rtx target)
2565 enum mode_class mclass = GET_MODE_CLASS (mode);
2566 if (CLASS_HAS_WIDER_MODES_P (mclass))
2568 enum machine_mode wider_mode;
2569 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2570 wider_mode != VOIDmode;
2571 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2573 if (optab_handler (clz_optab, wider_mode)->insn_code
2574 != CODE_FOR_nothing)
2576 rtx xop0, temp, last;
2578 last = get_last_insn ();
2580 if (target == 0)
2581 target = gen_reg_rtx (mode);
2582 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2583 temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
2584 if (temp != 0)
2585 temp = expand_binop (wider_mode, sub_optab, temp,
2586 GEN_INT (GET_MODE_BITSIZE (wider_mode)
2587 - GET_MODE_BITSIZE (mode)),
2588 target, true, OPTAB_DIRECT);
2589 if (temp == 0)
2590 delete_insns_since (last);
2592 return temp;
2596 return 0;
2599 /* Try calculating clz of a double-word quantity as two clz's of word-sized
2600 quantities, choosing which based on whether the high word is nonzero. */
2601 static rtx
2602 expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target)
2604 rtx xop0 = force_reg (mode, op0);
2605 rtx subhi = gen_highpart (word_mode, xop0);
2606 rtx sublo = gen_lowpart (word_mode, xop0);
2607 rtx hi0_label = gen_label_rtx ();
2608 rtx after_label = gen_label_rtx ();
2609 rtx seq, temp, result;
2611 /* If we were not given a target, use a word_mode register, not a
2612 'mode' register. The result will fit, and nobody is expecting
2613 anything bigger (the return type of __builtin_clz* is int). */
2614 if (!target)
2615 target = gen_reg_rtx (word_mode);
2617 /* In any case, write to a word_mode scratch in both branches of the
2618 conditional, so we can ensure there is a single move insn setting
2619 'target' to tag a REG_EQUAL note on. */
2620 result = gen_reg_rtx (word_mode);
2622 start_sequence ();
2624 /* If the high word is not equal to zero,
2625 then clz of the full value is clz of the high word. */
2626 emit_cmp_and_jump_insns (subhi, CONST0_RTX (word_mode), EQ, 0,
2627 word_mode, true, hi0_label);
2629 temp = expand_unop_direct (word_mode, clz_optab, subhi, result, true);
2630 if (!temp)
2631 goto fail;
2633 if (temp != result)
2634 convert_move (result, temp, true);
2636 emit_jump_insn (gen_jump (after_label));
2637 emit_barrier ();
2639 /* Else clz of the full value is clz of the low word plus the number
2640 of bits in the high word. */
2641 emit_label (hi0_label);
2643 temp = expand_unop_direct (word_mode, clz_optab, sublo, 0, true);
2644 if (!temp)
2645 goto fail;
2646 temp = expand_binop (word_mode, add_optab, temp,
2647 GEN_INT (GET_MODE_BITSIZE (word_mode)),
2648 result, true, OPTAB_DIRECT);
2649 if (!temp)
2650 goto fail;
2651 if (temp != result)
2652 convert_move (result, temp, true);
2654 emit_label (after_label);
2655 convert_move (target, result, true);
2657 seq = get_insns ();
2658 end_sequence ();
2660 add_equal_note (seq, target, CLZ, xop0, 0);
2661 emit_insn (seq);
2662 return target;
2664 fail:
2665 end_sequence ();
2666 return 0;
2669 /* Try calculating
2670 (bswap:narrow x)
2672 (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */
2673 static rtx
2674 widen_bswap (enum machine_mode mode, rtx op0, rtx target)
2676 enum mode_class mclass = GET_MODE_CLASS (mode);
2677 enum machine_mode wider_mode;
2678 rtx x, last;
2680 if (!CLASS_HAS_WIDER_MODES_P (mclass))
2681 return NULL_RTX;
2683 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2684 wider_mode != VOIDmode;
2685 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2686 if (optab_handler (bswap_optab, wider_mode)->insn_code != CODE_FOR_nothing)
2687 goto found;
2688 return NULL_RTX;
2690 found:
2691 last = get_last_insn ();
2693 x = widen_operand (op0, wider_mode, mode, true, true);
2694 x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
2696 if (x != 0)
2697 x = expand_shift (RSHIFT_EXPR, wider_mode, x,
2698 size_int (GET_MODE_BITSIZE (wider_mode)
2699 - GET_MODE_BITSIZE (mode)),
2700 NULL_RTX, true);
2702 if (x != 0)
2704 if (target == 0)
2705 target = gen_reg_rtx (mode);
2706 emit_move_insn (target, gen_lowpart (mode, x));
2708 else
2709 delete_insns_since (last);
2711 return target;
2714 /* Try calculating bswap as two bswaps of two word-sized operands. */
2716 static rtx
2717 expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
2719 rtx t0, t1;
2721 t1 = expand_unop (word_mode, bswap_optab,
2722 operand_subword_force (op, 0, mode), NULL_RTX, true);
2723 t0 = expand_unop (word_mode, bswap_optab,
2724 operand_subword_force (op, 1, mode), NULL_RTX, true);
2726 if (target == 0)
2727 target = gen_reg_rtx (mode);
2728 if (REG_P (target))
2729 emit_clobber (target);
2730 emit_move_insn (operand_subword (target, 0, 1, mode), t0);
2731 emit_move_insn (operand_subword (target, 1, 1, mode), t1);
2733 return target;
2736 /* Try calculating (parity x) as (and (popcount x) 1), where
2737 popcount can also be done in a wider mode. */
2738 static rtx
2739 expand_parity (enum machine_mode mode, rtx op0, rtx target)
2741 enum mode_class mclass = GET_MODE_CLASS (mode);
2742 if (CLASS_HAS_WIDER_MODES_P (mclass))
2744 enum machine_mode wider_mode;
2745 for (wider_mode = mode; wider_mode != VOIDmode;
2746 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2748 if (optab_handler (popcount_optab, wider_mode)->insn_code
2749 != CODE_FOR_nothing)
2751 rtx xop0, temp, last;
2753 last = get_last_insn ();
2755 if (target == 0)
2756 target = gen_reg_rtx (mode);
2757 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2758 temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
2759 true);
2760 if (temp != 0)
2761 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
2762 target, true, OPTAB_DIRECT);
2763 if (temp == 0)
2764 delete_insns_since (last);
2766 return temp;
2770 return 0;
2773 /* Try calculating ctz(x) as K - clz(x & -x) ,
2774 where K is GET_MODE_BITSIZE(mode) - 1.
2776 Both __builtin_ctz and __builtin_clz are undefined at zero, so we
2777 don't have to worry about what the hardware does in that case. (If
2778 the clz instruction produces the usual value at 0, which is K, the
2779 result of this code sequence will be -1; expand_ffs, below, relies
2780 on this. It might be nice to have it be K instead, for consistency
2781 with the (very few) processors that provide a ctz with a defined
2782 value, but that would take one more instruction, and it would be
2783 less convenient for expand_ffs anyway. */
2785 static rtx
2786 expand_ctz (enum machine_mode mode, rtx op0, rtx target)
2788 rtx seq, temp;
2790 if (optab_handler (clz_optab, mode)->insn_code == CODE_FOR_nothing)
2791 return 0;
2793 start_sequence ();
2795 temp = expand_unop_direct (mode, neg_optab, op0, NULL_RTX, true);
2796 if (temp)
2797 temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
2798 true, OPTAB_DIRECT);
2799 if (temp)
2800 temp = expand_unop_direct (mode, clz_optab, temp, NULL_RTX, true);
2801 if (temp)
2802 temp = expand_binop (mode, sub_optab, GEN_INT (GET_MODE_BITSIZE (mode) - 1),
2803 temp, target,
2804 true, OPTAB_DIRECT);
2805 if (temp == 0)
2807 end_sequence ();
2808 return 0;
2811 seq = get_insns ();
2812 end_sequence ();
2814 add_equal_note (seq, temp, CTZ, op0, 0);
2815 emit_insn (seq);
2816 return temp;
2820 /* Try calculating ffs(x) using ctz(x) if we have that instruction, or
2821 else with the sequence used by expand_clz.
2823 The ffs builtin promises to return zero for a zero value and ctz/clz
2824 may have an undefined value in that case. If they do not give us a
2825 convenient value, we have to generate a test and branch. */
2826 static rtx
2827 expand_ffs (enum machine_mode mode, rtx op0, rtx target)
2829 HOST_WIDE_INT val = 0;
2830 bool defined_at_zero = false;
2831 rtx temp, seq;
2833 if (optab_handler (ctz_optab, mode)->insn_code != CODE_FOR_nothing)
2835 start_sequence ();
2837 temp = expand_unop_direct (mode, ctz_optab, op0, 0, true);
2838 if (!temp)
2839 goto fail;
2841 defined_at_zero = (CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2);
2843 else if (optab_handler (clz_optab, mode)->insn_code != CODE_FOR_nothing)
2845 start_sequence ();
2846 temp = expand_ctz (mode, op0, 0);
2847 if (!temp)
2848 goto fail;
2850 if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
2852 defined_at_zero = true;
2853 val = (GET_MODE_BITSIZE (mode) - 1) - val;
2856 else
2857 return 0;
2859 if (defined_at_zero && val == -1)
2860 /* No correction needed at zero. */;
2861 else
2863 /* We don't try to do anything clever with the situation found
2864 on some processors (eg Alpha) where ctz(0:mode) ==
2865 bitsize(mode). If someone can think of a way to send N to -1
2866 and leave alone all values in the range 0..N-1 (where N is a
2867 power of two), cheaper than this test-and-branch, please add it.
2869 The test-and-branch is done after the operation itself, in case
2870 the operation sets condition codes that can be recycled for this.
2871 (This is true on i386, for instance.) */
2873 rtx nonzero_label = gen_label_rtx ();
2874 emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
2875 mode, true, nonzero_label);
2877 convert_move (temp, GEN_INT (-1), false);
2878 emit_label (nonzero_label);
2881 /* temp now has a value in the range -1..bitsize-1. ffs is supposed
2882 to produce a value in the range 0..bitsize. */
2883 temp = expand_binop (mode, add_optab, temp, GEN_INT (1),
2884 target, false, OPTAB_DIRECT);
2885 if (!temp)
2886 goto fail;
2888 seq = get_insns ();
2889 end_sequence ();
2891 add_equal_note (seq, temp, FFS, op0, 0);
2892 emit_insn (seq);
2893 return temp;
2895 fail:
2896 end_sequence ();
2897 return 0;
2900 /* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
2901 conditions, VAL may already be a SUBREG against which we cannot generate
2902 a further SUBREG. In this case, we expect forcing the value into a
2903 register will work around the situation. */
2905 static rtx
2906 lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
2907 enum machine_mode imode)
2909 rtx ret;
2910 ret = lowpart_subreg (omode, val, imode);
2911 if (ret == NULL)
2913 val = force_reg (imode, val);
2914 ret = lowpart_subreg (omode, val, imode);
2915 gcc_assert (ret != NULL);
2917 return ret;
2920 /* Expand a floating point absolute value or negation operation via a
2921 logical operation on the sign bit. */
2923 static rtx
2924 expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
2925 rtx op0, rtx target)
2927 const struct real_format *fmt;
2928 int bitpos, word, nwords, i;
2929 enum machine_mode imode;
2930 double_int mask;
2931 rtx temp, insns;
2933 /* The format has to have a simple sign bit. */
2934 fmt = REAL_MODE_FORMAT (mode);
2935 if (fmt == NULL)
2936 return NULL_RTX;
2938 bitpos = fmt->signbit_rw;
2939 if (bitpos < 0)
2940 return NULL_RTX;
2942 /* Don't create negative zeros if the format doesn't support them. */
2943 if (code == NEG && !fmt->has_signed_zero)
2944 return NULL_RTX;
2946 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
2948 imode = int_mode_for_mode (mode);
2949 if (imode == BLKmode)
2950 return NULL_RTX;
2951 word = 0;
2952 nwords = 1;
2954 else
2956 imode = word_mode;
2958 if (FLOAT_WORDS_BIG_ENDIAN)
2959 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
2960 else
2961 word = bitpos / BITS_PER_WORD;
2962 bitpos = bitpos % BITS_PER_WORD;
2963 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
2966 mask = double_int_setbit (double_int_zero, bitpos);
2967 if (code == ABS)
2968 mask = double_int_not (mask);
2970 if (target == 0 || target == op0)
2971 target = gen_reg_rtx (mode);
2973 if (nwords > 1)
2975 start_sequence ();
2977 for (i = 0; i < nwords; ++i)
2979 rtx targ_piece = operand_subword (target, i, 1, mode);
2980 rtx op0_piece = operand_subword_force (op0, i, mode);
2982 if (i == word)
2984 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2985 op0_piece,
2986 immed_double_int_const (mask, imode),
2987 targ_piece, 1, OPTAB_LIB_WIDEN);
2988 if (temp != targ_piece)
2989 emit_move_insn (targ_piece, temp);
2991 else
2992 emit_move_insn (targ_piece, op0_piece);
2995 insns = get_insns ();
2996 end_sequence ();
2998 emit_insn (insns);
3000 else
3002 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
3003 gen_lowpart (imode, op0),
3004 immed_double_int_const (mask, imode),
3005 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3006 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3008 set_unique_reg_note (get_last_insn (), REG_EQUAL,
3009 gen_rtx_fmt_e (code, mode, copy_rtx (op0)));
3012 return target;
3015 /* As expand_unop, but will fail rather than attempt the operation in a
3016 different mode or with a libcall. */
3017 static rtx
3018 expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3019 int unsignedp)
3021 if (optab_handler (unoptab, mode)->insn_code != CODE_FOR_nothing)
3023 int icode = (int) optab_handler (unoptab, mode)->insn_code;
3024 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3025 rtx xop0 = op0;
3026 rtx last = get_last_insn ();
3027 rtx pat, temp;
3029 if (target)
3030 temp = target;
3031 else
3032 temp = gen_reg_rtx (mode);
3034 if (GET_MODE (xop0) != VOIDmode
3035 && GET_MODE (xop0) != mode0)
3036 xop0 = convert_to_mode (mode0, xop0, unsignedp);
3038 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
3040 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
3041 xop0 = copy_to_mode_reg (mode0, xop0);
3043 if (!insn_data[icode].operand[0].predicate (temp, mode))
3044 temp = gen_reg_rtx (mode);
3046 pat = GEN_FCN (icode) (temp, xop0);
3047 if (pat)
3049 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
3050 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
3052 delete_insns_since (last);
3053 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
3056 emit_insn (pat);
3058 return temp;
3060 else
3061 delete_insns_since (last);
3063 return 0;
3066 /* Generate code to perform an operation specified by UNOPTAB
3067 on operand OP0, with result having machine-mode MODE.
3069 UNSIGNEDP is for the case where we have to widen the operands
3070 to perform the operation. It says to use zero-extension.
3072 If TARGET is nonzero, the value
3073 is generated there, if it is convenient to do so.
3074 In all cases an rtx is returned for the locus of the value;
3075 this may or may not be TARGET. */
3078 expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3079 int unsignedp)
3081 enum mode_class mclass = GET_MODE_CLASS (mode);
3082 enum machine_mode wider_mode;
3083 rtx temp;
3084 rtx libfunc;
3086 temp = expand_unop_direct (mode, unoptab, op0, target, unsignedp);
3087 if (temp)
3088 return temp;
3090 /* It can't be done in this mode. Can we open-code it in a wider mode? */
3092 /* Widening (or narrowing) clz needs special treatment. */
3093 if (unoptab == clz_optab)
3095 temp = widen_clz (mode, op0, target);
3096 if (temp)
3097 return temp;
3099 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3100 && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3102 temp = expand_doubleword_clz (mode, op0, target);
3103 if (temp)
3104 return temp;
3107 goto try_libcall;
3110 /* Widening (or narrowing) bswap needs special treatment. */
3111 if (unoptab == bswap_optab)
3113 temp = widen_bswap (mode, op0, target);
3114 if (temp)
3115 return temp;
3117 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3118 && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3120 temp = expand_doubleword_bswap (mode, op0, target);
3121 if (temp)
3122 return temp;
3125 goto try_libcall;
3128 if (CLASS_HAS_WIDER_MODES_P (mclass))
3129 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3130 wider_mode != VOIDmode;
3131 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3133 if (optab_handler (unoptab, wider_mode)->insn_code != CODE_FOR_nothing)
3135 rtx xop0 = op0;
3136 rtx last = get_last_insn ();
3138 /* For certain operations, we need not actually extend
3139 the narrow operand, as long as we will truncate the
3140 results to the same narrowness. */
3142 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3143 (unoptab == neg_optab
3144 || unoptab == one_cmpl_optab)
3145 && mclass == MODE_INT);
3147 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3148 unsignedp);
3150 if (temp)
3152 if (mclass != MODE_INT
3153 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
3154 GET_MODE_BITSIZE (wider_mode)))
3156 if (target == 0)
3157 target = gen_reg_rtx (mode);
3158 convert_move (target, temp, 0);
3159 return target;
3161 else
3162 return gen_lowpart (mode, temp);
3164 else
3165 delete_insns_since (last);
3169 /* These can be done a word at a time. */
3170 if (unoptab == one_cmpl_optab
3171 && mclass == MODE_INT
3172 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
3173 && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3175 int i;
3176 rtx insns;
3178 if (target == 0 || target == op0)
3179 target = gen_reg_rtx (mode);
3181 start_sequence ();
3183 /* Do the actual arithmetic. */
3184 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
3186 rtx target_piece = operand_subword (target, i, 1, mode);
3187 rtx x = expand_unop (word_mode, unoptab,
3188 operand_subword_force (op0, i, mode),
3189 target_piece, unsignedp);
3191 if (target_piece != x)
3192 emit_move_insn (target_piece, x);
3195 insns = get_insns ();
3196 end_sequence ();
3198 emit_insn (insns);
3199 return target;
3202 if (unoptab->code == NEG)
3204 /* Try negating floating point values by flipping the sign bit. */
3205 if (SCALAR_FLOAT_MODE_P (mode))
3207 temp = expand_absneg_bit (NEG, mode, op0, target);
3208 if (temp)
3209 return temp;
3212 /* If there is no negation pattern, and we have no negative zero,
3213 try subtracting from zero. */
3214 if (!HONOR_SIGNED_ZEROS (mode))
3216 temp = expand_binop (mode, (unoptab == negv_optab
3217 ? subv_optab : sub_optab),
3218 CONST0_RTX (mode), op0, target,
3219 unsignedp, OPTAB_DIRECT);
3220 if (temp)
3221 return temp;
3225 /* Try calculating parity (x) as popcount (x) % 2. */
3226 if (unoptab == parity_optab)
3228 temp = expand_parity (mode, op0, target);
3229 if (temp)
3230 return temp;
3233 /* Try implementing ffs (x) in terms of clz (x). */
3234 if (unoptab == ffs_optab)
3236 temp = expand_ffs (mode, op0, target);
3237 if (temp)
3238 return temp;
3241 /* Try implementing ctz (x) in terms of clz (x). */
3242 if (unoptab == ctz_optab)
3244 temp = expand_ctz (mode, op0, target);
3245 if (temp)
3246 return temp;
3249 try_libcall:
3250 /* Now try a library call in this mode. */
3251 libfunc = optab_libfunc (unoptab, mode);
3252 if (libfunc)
3254 rtx insns;
3255 rtx value;
3256 rtx eq_value;
3257 enum machine_mode outmode = mode;
3259 /* All of these functions return small values. Thus we choose to
3260 have them return something that isn't a double-word. */
3261 if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
3262 || unoptab == popcount_optab || unoptab == parity_optab)
3263 outmode
3264 = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
3265 optab_libfunc (unoptab, mode)));
3267 start_sequence ();
3269 /* Pass 1 for NO_QUEUE so we don't lose any increments
3270 if the libcall is cse'd or moved. */
3271 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, outmode,
3272 1, op0, mode);
3273 insns = get_insns ();
3274 end_sequence ();
3276 target = gen_reg_rtx (outmode);
3277 eq_value = gen_rtx_fmt_e (unoptab->code, mode, op0);
3278 if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
3279 eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
3280 else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
3281 eq_value = simplify_gen_unary (ZERO_EXTEND, outmode, eq_value, mode);
3282 emit_libcall_block (insns, target, value, eq_value);
3284 return target;
3287 /* It can't be done in this mode. Can we do it in a wider mode? */
3289 if (CLASS_HAS_WIDER_MODES_P (mclass))
3291 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3292 wider_mode != VOIDmode;
3293 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3295 if ((optab_handler (unoptab, wider_mode)->insn_code
3296 != CODE_FOR_nothing)
3297 || optab_libfunc (unoptab, wider_mode))
3299 rtx xop0 = op0;
3300 rtx last = get_last_insn ();
3302 /* For certain operations, we need not actually extend
3303 the narrow operand, as long as we will truncate the
3304 results to the same narrowness. */
3306 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3307 (unoptab == neg_optab
3308 || unoptab == one_cmpl_optab)
3309 && mclass == MODE_INT);
3311 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3312 unsignedp);
3314 /* If we are generating clz using wider mode, adjust the
3315 result. */
3316 if (unoptab == clz_optab && temp != 0)
3317 temp = expand_binop (wider_mode, sub_optab, temp,
3318 GEN_INT (GET_MODE_BITSIZE (wider_mode)
3319 - GET_MODE_BITSIZE (mode)),
3320 target, true, OPTAB_DIRECT);
3322 if (temp)
3324 if (mclass != MODE_INT)
3326 if (target == 0)
3327 target = gen_reg_rtx (mode);
3328 convert_move (target, temp, 0);
3329 return target;
3331 else
3332 return gen_lowpart (mode, temp);
3334 else
3335 delete_insns_since (last);
3340 /* One final attempt at implementing negation via subtraction,
3341 this time allowing widening of the operand. */
3342 if (unoptab->code == NEG && !HONOR_SIGNED_ZEROS (mode))
3344 rtx temp;
3345 temp = expand_binop (mode,
3346 unoptab == negv_optab ? subv_optab : sub_optab,
3347 CONST0_RTX (mode), op0,
3348 target, unsignedp, OPTAB_LIB_WIDEN);
3349 if (temp)
3350 return temp;
3353 return 0;
3356 /* Emit code to compute the absolute value of OP0, with result to
3357 TARGET if convenient. (TARGET may be 0.) The return value says
3358 where the result actually is to be found.
3360 MODE is the mode of the operand; the mode of the result is
3361 different but can be deduced from MODE.
3366 expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
3367 int result_unsignedp)
3369 rtx temp;
3371 if (! flag_trapv)
3372 result_unsignedp = 1;
3374 /* First try to do it with a special abs instruction. */
3375 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
3376 op0, target, 0);
3377 if (temp != 0)
3378 return temp;
3380 /* For floating point modes, try clearing the sign bit. */
3381 if (SCALAR_FLOAT_MODE_P (mode))
3383 temp = expand_absneg_bit (ABS, mode, op0, target);
3384 if (temp)
3385 return temp;
3388 /* If we have a MAX insn, we can do this as MAX (x, -x). */
3389 if (optab_handler (smax_optab, mode)->insn_code != CODE_FOR_nothing
3390 && !HONOR_SIGNED_ZEROS (mode))
3392 rtx last = get_last_insn ();
3394 temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
3395 if (temp != 0)
3396 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3397 OPTAB_WIDEN);
3399 if (temp != 0)
3400 return temp;
3402 delete_insns_since (last);
3405 /* If this machine has expensive jumps, we can do integer absolute
3406 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
3407 where W is the width of MODE. */
3409 if (GET_MODE_CLASS (mode) == MODE_INT
3410 && BRANCH_COST (optimize_insn_for_speed_p (),
3411 false) >= 2)
3413 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3414 size_int (GET_MODE_BITSIZE (mode) - 1),
3415 NULL_RTX, 0);
3417 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3418 OPTAB_LIB_WIDEN);
3419 if (temp != 0)
3420 temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
3421 temp, extended, target, 0, OPTAB_LIB_WIDEN);
3423 if (temp != 0)
3424 return temp;
3427 return NULL_RTX;
3431 expand_abs (enum machine_mode mode, rtx op0, rtx target,
3432 int result_unsignedp, int safe)
3434 rtx temp, op1;
3436 if (! flag_trapv)
3437 result_unsignedp = 1;
3439 temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
3440 if (temp != 0)
3441 return temp;
3443 /* If that does not win, use conditional jump and negate. */
3445 /* It is safe to use the target if it is the same
3446 as the source if this is also a pseudo register */
3447 if (op0 == target && REG_P (op0)
3448 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
3449 safe = 1;
3451 op1 = gen_label_rtx ();
3452 if (target == 0 || ! safe
3453 || GET_MODE (target) != mode
3454 || (MEM_P (target) && MEM_VOLATILE_P (target))
3455 || (REG_P (target)
3456 && REGNO (target) < FIRST_PSEUDO_REGISTER))
3457 target = gen_reg_rtx (mode);
3459 emit_move_insn (target, op0);
3460 NO_DEFER_POP;
3462 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
3463 NULL_RTX, NULL_RTX, op1, -1);
3465 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3466 target, target, 0);
3467 if (op0 != target)
3468 emit_move_insn (target, op0);
3469 emit_label (op1);
3470 OK_DEFER_POP;
3471 return target;
3474 /* Emit code to compute the one's complement absolute value of OP0
3475 (if (OP0 < 0) OP0 = ~OP0), with result to TARGET if convenient.
3476 (TARGET may be NULL_RTX.) The return value says where the result
3477 actually is to be found.
3479 MODE is the mode of the operand; the mode of the result is
3480 different but can be deduced from MODE. */
3483 expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
3485 rtx temp;
3487 /* Not applicable for floating point modes. */
3488 if (FLOAT_MODE_P (mode))
3489 return NULL_RTX;
3491 /* If we have a MAX insn, we can do this as MAX (x, ~x). */
3492 if (optab_handler (smax_optab, mode)->insn_code != CODE_FOR_nothing)
3494 rtx last = get_last_insn ();
3496 temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
3497 if (temp != 0)
3498 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3499 OPTAB_WIDEN);
3501 if (temp != 0)
3502 return temp;
3504 delete_insns_since (last);
3507 /* If this machine has expensive jumps, we can do one's complement
3508 absolute value of X as (((signed) x >> (W-1)) ^ x). */
3510 if (GET_MODE_CLASS (mode) == MODE_INT
3511 && BRANCH_COST (optimize_insn_for_speed_p (),
3512 false) >= 2)
3514 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3515 size_int (GET_MODE_BITSIZE (mode) - 1),
3516 NULL_RTX, 0);
3518 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3519 OPTAB_LIB_WIDEN);
3521 if (temp != 0)
3522 return temp;
3525 return NULL_RTX;
3528 /* A subroutine of expand_copysign, perform the copysign operation using the
3529 abs and neg primitives advertised to exist on the target. The assumption
3530 is that we have a split register file, and leaving op0 in fp registers,
3531 and not playing with subregs so much, will help the register allocator. */
3533 static rtx
3534 expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3535 int bitpos, bool op0_is_abs)
3537 enum machine_mode imode;
3538 int icode;
3539 rtx sign, label;
3541 if (target == op1)
3542 target = NULL_RTX;
3544 /* Check if the back end provides an insn that handles signbit for the
3545 argument's mode. */
3546 icode = (int) signbit_optab->handlers [(int) mode].insn_code;
3547 if (icode != CODE_FOR_nothing)
3549 imode = insn_data[icode].operand[0].mode;
3550 sign = gen_reg_rtx (imode);
3551 emit_unop_insn (icode, sign, op1, UNKNOWN);
3553 else
3555 double_int mask;
3557 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3559 imode = int_mode_for_mode (mode);
3560 if (imode == BLKmode)
3561 return NULL_RTX;
3562 op1 = gen_lowpart (imode, op1);
3564 else
3566 int word;
3568 imode = word_mode;
3569 if (FLOAT_WORDS_BIG_ENDIAN)
3570 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3571 else
3572 word = bitpos / BITS_PER_WORD;
3573 bitpos = bitpos % BITS_PER_WORD;
3574 op1 = operand_subword_force (op1, word, mode);
3577 mask = double_int_setbit (double_int_zero, bitpos);
3579 sign = expand_binop (imode, and_optab, op1,
3580 immed_double_int_const (mask, imode),
3581 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3584 if (!op0_is_abs)
3586 op0 = expand_unop (mode, abs_optab, op0, target, 0);
3587 if (op0 == NULL)
3588 return NULL_RTX;
3589 target = op0;
3591 else
3593 if (target == NULL_RTX)
3594 target = copy_to_reg (op0);
3595 else
3596 emit_move_insn (target, op0);
3599 label = gen_label_rtx ();
3600 emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
3602 if (GET_CODE (op0) == CONST_DOUBLE)
3603 op0 = simplify_unary_operation (NEG, mode, op0, mode);
3604 else
3605 op0 = expand_unop (mode, neg_optab, op0, target, 0);
3606 if (op0 != target)
3607 emit_move_insn (target, op0);
3609 emit_label (label);
3611 return target;
3615 /* A subroutine of expand_copysign, perform the entire copysign operation
3616 with integer bitmasks. BITPOS is the position of the sign bit; OP0_IS_ABS
3617 is true if op0 is known to have its sign bit clear. */
3619 static rtx
3620 expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3621 int bitpos, bool op0_is_abs)
3623 enum machine_mode imode;
3624 double_int mask;
3625 int word, nwords, i;
3626 rtx temp, insns;
3628 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3630 imode = int_mode_for_mode (mode);
3631 if (imode == BLKmode)
3632 return NULL_RTX;
3633 word = 0;
3634 nwords = 1;
3636 else
3638 imode = word_mode;
3640 if (FLOAT_WORDS_BIG_ENDIAN)
3641 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3642 else
3643 word = bitpos / BITS_PER_WORD;
3644 bitpos = bitpos % BITS_PER_WORD;
3645 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
3648 mask = double_int_setbit (double_int_zero, bitpos);
3650 if (target == 0 || target == op0 || target == op1)
3651 target = gen_reg_rtx (mode);
3653 if (nwords > 1)
3655 start_sequence ();
3657 for (i = 0; i < nwords; ++i)
3659 rtx targ_piece = operand_subword (target, i, 1, mode);
3660 rtx op0_piece = operand_subword_force (op0, i, mode);
3662 if (i == word)
3664 if (!op0_is_abs)
3665 op0_piece
3666 = expand_binop (imode, and_optab, op0_piece,
3667 immed_double_int_const (double_int_not (mask),
3668 imode),
3669 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3671 op1 = expand_binop (imode, and_optab,
3672 operand_subword_force (op1, i, mode),
3673 immed_double_int_const (mask, imode),
3674 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3676 temp = expand_binop (imode, ior_optab, op0_piece, op1,
3677 targ_piece, 1, OPTAB_LIB_WIDEN);
3678 if (temp != targ_piece)
3679 emit_move_insn (targ_piece, temp);
3681 else
3682 emit_move_insn (targ_piece, op0_piece);
3685 insns = get_insns ();
3686 end_sequence ();
3688 emit_insn (insns);
3690 else
3692 op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
3693 immed_double_int_const (mask, imode),
3694 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3696 op0 = gen_lowpart (imode, op0);
3697 if (!op0_is_abs)
3698 op0 = expand_binop (imode, and_optab, op0,
3699 immed_double_int_const (double_int_not (mask),
3700 imode),
3701 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3703 temp = expand_binop (imode, ior_optab, op0, op1,
3704 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3705 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3708 return target;
3711 /* Expand the C99 copysign operation. OP0 and OP1 must be the same
3712 scalar floating point mode. Return NULL if we do not know how to
3713 expand the operation inline. */
3716 expand_copysign (rtx op0, rtx op1, rtx target)
3718 enum machine_mode mode = GET_MODE (op0);
3719 const struct real_format *fmt;
3720 bool op0_is_abs;
3721 rtx temp;
3723 gcc_assert (SCALAR_FLOAT_MODE_P (mode));
3724 gcc_assert (GET_MODE (op1) == mode);
3726 /* First try to do it with a special instruction. */
3727 temp = expand_binop (mode, copysign_optab, op0, op1,
3728 target, 0, OPTAB_DIRECT);
3729 if (temp)
3730 return temp;
3732 fmt = REAL_MODE_FORMAT (mode);
3733 if (fmt == NULL || !fmt->has_signed_zero)
3734 return NULL_RTX;
3736 op0_is_abs = false;
3737 if (GET_CODE (op0) == CONST_DOUBLE)
3739 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
3740 op0 = simplify_unary_operation (ABS, mode, op0, mode);
3741 op0_is_abs = true;
3744 if (fmt->signbit_ro >= 0
3745 && (GET_CODE (op0) == CONST_DOUBLE
3746 || (optab_handler (neg_optab, mode)->insn_code != CODE_FOR_nothing
3747 && optab_handler (abs_optab, mode)->insn_code != CODE_FOR_nothing)))
3749 temp = expand_copysign_absneg (mode, op0, op1, target,
3750 fmt->signbit_ro, op0_is_abs);
3751 if (temp)
3752 return temp;
3755 if (fmt->signbit_rw < 0)
3756 return NULL_RTX;
3757 return expand_copysign_bit (mode, op0, op1, target,
3758 fmt->signbit_rw, op0_is_abs);
3761 /* Generate an instruction whose insn-code is INSN_CODE,
3762 with two operands: an output TARGET and an input OP0.
3763 TARGET *must* be nonzero, and the output is always stored there.
3764 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3765 the value that is stored into TARGET.
3767 Return false if expansion failed. */
3769 bool
3770 maybe_emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3772 rtx temp;
3773 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3774 rtx pat;
3775 rtx last = get_last_insn ();
3777 temp = target;
3779 /* Now, if insn does not accept our operands, put them into pseudos. */
3781 if (!insn_data[icode].operand[1].predicate (op0, mode0))
3782 op0 = copy_to_mode_reg (mode0, op0);
3784 if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
3785 temp = gen_reg_rtx (GET_MODE (temp));
3787 pat = GEN_FCN (icode) (temp, op0);
3788 if (!pat)
3790 delete_insns_since (last);
3791 return false;
3794 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
3795 add_equal_note (pat, temp, code, op0, NULL_RTX);
3797 emit_insn (pat);
3799 if (temp != target)
3800 emit_move_insn (target, temp);
3801 return true;
3803 /* Generate an instruction whose insn-code is INSN_CODE,
3804 with two operands: an output TARGET and an input OP0.
3805 TARGET *must* be nonzero, and the output is always stored there.
3806 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3807 the value that is stored into TARGET. */
3809 void
3810 emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3812 bool ok = maybe_emit_unop_insn (icode, target, op0, code);
3813 gcc_assert (ok);
3816 struct no_conflict_data
3818 rtx target, first, insn;
3819 bool must_stay;
3822 /* Called via note_stores by emit_libcall_block. Set P->must_stay if
3823 the currently examined clobber / store has to stay in the list of
3824 insns that constitute the actual libcall block. */
3825 static void
3826 no_conflict_move_test (rtx dest, const_rtx set, void *p0)
3828 struct no_conflict_data *p= (struct no_conflict_data *) p0;
3830 /* If this inns directly contributes to setting the target, it must stay. */
3831 if (reg_overlap_mentioned_p (p->target, dest))
3832 p->must_stay = true;
3833 /* If we haven't committed to keeping any other insns in the list yet,
3834 there is nothing more to check. */
3835 else if (p->insn == p->first)
3836 return;
3837 /* If this insn sets / clobbers a register that feeds one of the insns
3838 already in the list, this insn has to stay too. */
3839 else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
3840 || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
3841 || reg_used_between_p (dest, p->first, p->insn)
3842 /* Likewise if this insn depends on a register set by a previous
3843 insn in the list, or if it sets a result (presumably a hard
3844 register) that is set or clobbered by a previous insn.
3845 N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
3846 SET_DEST perform the former check on the address, and the latter
3847 check on the MEM. */
3848 || (GET_CODE (set) == SET
3849 && (modified_in_p (SET_SRC (set), p->first)
3850 || modified_in_p (SET_DEST (set), p->first)
3851 || modified_between_p (SET_SRC (set), p->first, p->insn)
3852 || modified_between_p (SET_DEST (set), p->first, p->insn))))
3853 p->must_stay = true;
3857 /* Emit code to make a call to a constant function or a library call.
3859 INSNS is a list containing all insns emitted in the call.
3860 These insns leave the result in RESULT. Our block is to copy RESULT
3861 to TARGET, which is logically equivalent to EQUIV.
3863 We first emit any insns that set a pseudo on the assumption that these are
3864 loading constants into registers; doing so allows them to be safely cse'ed
3865 between blocks. Then we emit all the other insns in the block, followed by
3866 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
3867 note with an operand of EQUIV. */
3869 void
3870 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
3872 rtx final_dest = target;
3873 rtx next, last, insn;
3875 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
3876 into a MEM later. Protect the libcall block from this change. */
3877 if (! REG_P (target) || REG_USERVAR_P (target))
3878 target = gen_reg_rtx (GET_MODE (target));
3880 /* If we're using non-call exceptions, a libcall corresponding to an
3881 operation that may trap may also trap. */
3882 /* ??? See the comment in front of make_reg_eh_region_note. */
3883 if (cfun->can_throw_non_call_exceptions && may_trap_p (equiv))
3885 for (insn = insns; insn; insn = NEXT_INSN (insn))
3886 if (CALL_P (insn))
3888 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3889 if (note)
3891 int lp_nr = INTVAL (XEXP (note, 0));
3892 if (lp_nr == 0 || lp_nr == INT_MIN)
3893 remove_note (insn, note);
3897 else
3899 /* Look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
3900 reg note to indicate that this call cannot throw or execute a nonlocal
3901 goto (unless there is already a REG_EH_REGION note, in which case
3902 we update it). */
3903 for (insn = insns; insn; insn = NEXT_INSN (insn))
3904 if (CALL_P (insn))
3905 make_reg_eh_region_note_nothrow_nononlocal (insn);
3908 /* First emit all insns that set pseudos. Remove them from the list as
3909 we go. Avoid insns that set pseudos which were referenced in previous
3910 insns. These can be generated by move_by_pieces, for example,
3911 to update an address. Similarly, avoid insns that reference things
3912 set in previous insns. */
3914 for (insn = insns; insn; insn = next)
3916 rtx set = single_set (insn);
3918 next = NEXT_INSN (insn);
3920 if (set != 0 && REG_P (SET_DEST (set))
3921 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
3923 struct no_conflict_data data;
3925 data.target = const0_rtx;
3926 data.first = insns;
3927 data.insn = insn;
3928 data.must_stay = 0;
3929 note_stores (PATTERN (insn), no_conflict_move_test, &data);
3930 if (! data.must_stay)
3932 if (PREV_INSN (insn))
3933 NEXT_INSN (PREV_INSN (insn)) = next;
3934 else
3935 insns = next;
3937 if (next)
3938 PREV_INSN (next) = PREV_INSN (insn);
3940 add_insn (insn);
3944 /* Some ports use a loop to copy large arguments onto the stack.
3945 Don't move anything outside such a loop. */
3946 if (LABEL_P (insn))
3947 break;
3950 /* Write the remaining insns followed by the final copy. */
3951 for (insn = insns; insn; insn = next)
3953 next = NEXT_INSN (insn);
3955 add_insn (insn);
3958 last = emit_move_insn (target, result);
3959 if (optab_handler (mov_optab, GET_MODE (target))->insn_code
3960 != CODE_FOR_nothing)
3961 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
3963 if (final_dest != target)
3964 emit_move_insn (final_dest, target);
3967 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
3968 PURPOSE describes how this comparison will be used. CODE is the rtx
3969 comparison code we will be using.
3971 ??? Actually, CODE is slightly weaker than that. A target is still
3972 required to implement all of the normal bcc operations, but not
3973 required to implement all (or any) of the unordered bcc operations. */
3976 can_compare_p (enum rtx_code code, enum machine_mode mode,
3977 enum can_compare_purpose purpose)
3979 rtx test;
3980 test = gen_rtx_fmt_ee (code, mode, const0_rtx, const0_rtx);
3983 int icode;
3985 if (purpose == ccp_jump
3986 && (icode = optab_handler (cbranch_optab, mode)->insn_code) != CODE_FOR_nothing
3987 && insn_data[icode].operand[0].predicate (test, mode))
3988 return 1;
3989 if (purpose == ccp_store_flag
3990 && (icode = optab_handler (cstore_optab, mode)->insn_code) != CODE_FOR_nothing
3991 && insn_data[icode].operand[1].predicate (test, mode))
3992 return 1;
3993 if (purpose == ccp_cmov
3994 && optab_handler (cmov_optab, mode)->insn_code != CODE_FOR_nothing)
3995 return 1;
3997 mode = GET_MODE_WIDER_MODE (mode);
3998 PUT_MODE (test, mode);
4000 while (mode != VOIDmode);
4002 return 0;
4005 /* This function is called when we are going to emit a compare instruction that
4006 compares the values found in *PX and *PY, using the rtl operator COMPARISON.
4008 *PMODE is the mode of the inputs (in case they are const_int).
4009 *PUNSIGNEDP nonzero says that the operands are unsigned;
4010 this matters if they need to be widened (as given by METHODS).
4012 If they have mode BLKmode, then SIZE specifies the size of both operands.
4014 This function performs all the setup necessary so that the caller only has
4015 to emit a single comparison insn. This setup can involve doing a BLKmode
4016 comparison or emitting a library call to perform the comparison if no insn
4017 is available to handle it.
4018 The values which are passed in through pointers can be modified; the caller
4019 should perform the comparison on the modified values. Constant
4020 comparisons must have already been folded. */
4022 static void
4023 prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
4024 int unsignedp, enum optab_methods methods,
4025 rtx *ptest, enum machine_mode *pmode)
4027 enum machine_mode mode = *pmode;
4028 rtx libfunc, test;
4029 enum machine_mode cmp_mode;
4030 enum mode_class mclass;
4032 /* The other methods are not needed. */
4033 gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
4034 || methods == OPTAB_LIB_WIDEN);
4036 /* If we are optimizing, force expensive constants into a register. */
4037 if (CONSTANT_P (x) && optimize
4038 && (rtx_cost (x, COMPARE, optimize_insn_for_speed_p ())
4039 > COSTS_N_INSNS (1)))
4040 x = force_reg (mode, x);
4042 if (CONSTANT_P (y) && optimize
4043 && (rtx_cost (y, COMPARE, optimize_insn_for_speed_p ())
4044 > COSTS_N_INSNS (1)))
4045 y = force_reg (mode, y);
4047 #ifdef HAVE_cc0
4048 /* Make sure if we have a canonical comparison. The RTL
4049 documentation states that canonical comparisons are required only
4050 for targets which have cc0. */
4051 gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
4052 #endif
4054 /* Don't let both operands fail to indicate the mode. */
4055 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
4056 x = force_reg (mode, x);
4057 if (mode == VOIDmode)
4058 mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : GET_MODE (y);
4060 /* Handle all BLKmode compares. */
4062 if (mode == BLKmode)
4064 enum machine_mode result_mode;
4065 enum insn_code cmp_code;
4066 tree length_type;
4067 rtx libfunc;
4068 rtx result;
4069 rtx opalign
4070 = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
4072 gcc_assert (size);
4074 /* Try to use a memory block compare insn - either cmpstr
4075 or cmpmem will do. */
4076 for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
4077 cmp_mode != VOIDmode;
4078 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
4080 cmp_code = cmpmem_optab[cmp_mode];
4081 if (cmp_code == CODE_FOR_nothing)
4082 cmp_code = cmpstr_optab[cmp_mode];
4083 if (cmp_code == CODE_FOR_nothing)
4084 cmp_code = cmpstrn_optab[cmp_mode];
4085 if (cmp_code == CODE_FOR_nothing)
4086 continue;
4088 /* Must make sure the size fits the insn's mode. */
4089 if ((CONST_INT_P (size)
4090 && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
4091 || (GET_MODE_BITSIZE (GET_MODE (size))
4092 > GET_MODE_BITSIZE (cmp_mode)))
4093 continue;
4095 result_mode = insn_data[cmp_code].operand[0].mode;
4096 result = gen_reg_rtx (result_mode);
4097 size = convert_to_mode (cmp_mode, size, 1);
4098 emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
4100 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4101 *pmode = result_mode;
4102 return;
4105 if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
4106 goto fail;
4108 /* Otherwise call a library function, memcmp. */
4109 libfunc = memcmp_libfunc;
4110 length_type = sizetype;
4111 result_mode = TYPE_MODE (integer_type_node);
4112 cmp_mode = TYPE_MODE (length_type);
4113 size = convert_to_mode (TYPE_MODE (length_type), size,
4114 TYPE_UNSIGNED (length_type));
4116 result = emit_library_call_value (libfunc, 0, LCT_PURE,
4117 result_mode, 3,
4118 XEXP (x, 0), Pmode,
4119 XEXP (y, 0), Pmode,
4120 size, cmp_mode);
4122 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4123 *pmode = result_mode;
4124 return;
4127 /* Don't allow operands to the compare to trap, as that can put the
4128 compare and branch in different basic blocks. */
4129 if (cfun->can_throw_non_call_exceptions)
4131 if (may_trap_p (x))
4132 x = force_reg (mode, x);
4133 if (may_trap_p (y))
4134 y = force_reg (mode, y);
4137 if (GET_MODE_CLASS (mode) == MODE_CC)
4139 gcc_assert (can_compare_p (comparison, CCmode, ccp_jump));
4140 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4141 return;
4144 mclass = GET_MODE_CLASS (mode);
4145 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4146 cmp_mode = mode;
4149 enum insn_code icode;
4150 icode = optab_handler (cbranch_optab, cmp_mode)->insn_code;
4151 if (icode != CODE_FOR_nothing
4152 && insn_data[icode].operand[0].predicate (test, VOIDmode))
4154 rtx last = get_last_insn ();
4155 rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp);
4156 rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp);
4157 if (op0 && op1
4158 && insn_data[icode].operand[1].predicate
4159 (op0, insn_data[icode].operand[1].mode)
4160 && insn_data[icode].operand[2].predicate
4161 (op1, insn_data[icode].operand[2].mode))
4163 XEXP (test, 0) = op0;
4164 XEXP (test, 1) = op1;
4165 *ptest = test;
4166 *pmode = cmp_mode;
4167 return;
4169 delete_insns_since (last);
4172 if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
4173 break;
4174 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode);
4176 while (cmp_mode != VOIDmode);
4178 if (methods != OPTAB_LIB_WIDEN)
4179 goto fail;
4181 if (!SCALAR_FLOAT_MODE_P (mode))
4183 rtx result;
4185 /* Handle a libcall just for the mode we are using. */
4186 libfunc = optab_libfunc (cmp_optab, mode);
4187 gcc_assert (libfunc);
4189 /* If we want unsigned, and this mode has a distinct unsigned
4190 comparison routine, use that. */
4191 if (unsignedp)
4193 rtx ulibfunc = optab_libfunc (ucmp_optab, mode);
4194 if (ulibfunc)
4195 libfunc = ulibfunc;
4198 result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4199 targetm.libgcc_cmp_return_mode (),
4200 2, x, mode, y, mode);
4202 /* There are two kinds of comparison routines. Biased routines
4203 return 0/1/2, and unbiased routines return -1/0/1. Other parts
4204 of gcc expect that the comparison operation is equivalent
4205 to the modified comparison. For signed comparisons compare the
4206 result against 1 in the biased case, and zero in the unbiased
4207 case. For unsigned comparisons always compare against 1 after
4208 biasing the unbiased result by adding 1. This gives us a way to
4209 represent LTU. */
4210 x = result;
4211 y = const1_rtx;
4213 if (!TARGET_LIB_INT_CMP_BIASED)
4215 if (unsignedp)
4216 x = plus_constant (result, 1);
4217 else
4218 y = const0_rtx;
4221 *pmode = word_mode;
4222 prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods,
4223 ptest, pmode);
4225 else
4226 prepare_float_lib_cmp (x, y, comparison, ptest, pmode);
4228 return;
4230 fail:
4231 *ptest = NULL_RTX;
4234 /* Before emitting an insn with code ICODE, make sure that X, which is going
4235 to be used for operand OPNUM of the insn, is converted from mode MODE to
4236 WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
4237 that it is accepted by the operand predicate. Return the new value. */
4240 prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
4241 enum machine_mode wider_mode, int unsignedp)
4243 if (mode != wider_mode)
4244 x = convert_modes (wider_mode, mode, x, unsignedp);
4246 if (!insn_data[icode].operand[opnum].predicate
4247 (x, insn_data[icode].operand[opnum].mode))
4249 if (reload_completed)
4250 return NULL_RTX;
4251 x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
4254 return x;
4257 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
4258 we can do the branch. */
4260 static void
4261 emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label)
4263 enum machine_mode optab_mode;
4264 enum mode_class mclass;
4265 enum insn_code icode;
4267 mclass = GET_MODE_CLASS (mode);
4268 optab_mode = (mclass == MODE_CC) ? CCmode : mode;
4269 icode = optab_handler (cbranch_optab, optab_mode)->insn_code;
4271 gcc_assert (icode != CODE_FOR_nothing);
4272 gcc_assert (insn_data[icode].operand[0].predicate (test, VOIDmode));
4273 emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0), XEXP (test, 1), label));
4276 /* Generate code to compare X with Y so that the condition codes are
4277 set and to jump to LABEL if the condition is true. If X is a
4278 constant and Y is not a constant, then the comparison is swapped to
4279 ensure that the comparison RTL has the canonical form.
4281 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
4282 need to be widened. UNSIGNEDP is also used to select the proper
4283 branch condition code.
4285 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
4287 MODE is the mode of the inputs (in case they are const_int).
4289 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
4290 It will be potentially converted into an unsigned variant based on
4291 UNSIGNEDP to select a proper jump instruction. */
4293 void
4294 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
4295 enum machine_mode mode, int unsignedp, rtx label)
4297 rtx op0 = x, op1 = y;
4298 rtx test;
4300 /* Swap operands and condition to ensure canonical RTL. */
4301 if (swap_commutative_operands_p (x, y)
4302 && can_compare_p (swap_condition (comparison), mode, ccp_jump))
4304 op0 = y, op1 = x;
4305 comparison = swap_condition (comparison);
4308 /* If OP0 is still a constant, then both X and Y must be constants
4309 or the opposite comparison is not supported. Force X into a register
4310 to create canonical RTL. */
4311 if (CONSTANT_P (op0))
4312 op0 = force_reg (mode, op0);
4314 if (unsignedp)
4315 comparison = unsigned_condition (comparison);
4317 prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
4318 &test, &mode);
4319 emit_cmp_and_jump_insn_1 (test, mode, label);
4323 /* Emit a library call comparison between floating point X and Y.
4324 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
4326 static void
4327 prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
4328 rtx *ptest, enum machine_mode *pmode)
4330 enum rtx_code swapped = swap_condition (comparison);
4331 enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
4332 enum machine_mode orig_mode = GET_MODE (x);
4333 enum machine_mode mode, cmp_mode;
4334 rtx true_rtx, false_rtx;
4335 rtx value, target, insns, equiv;
4336 rtx libfunc = 0;
4337 bool reversed_p = false;
4338 cmp_mode = targetm.libgcc_cmp_return_mode ();
4340 for (mode = orig_mode;
4341 mode != VOIDmode;
4342 mode = GET_MODE_WIDER_MODE (mode))
4344 if (code_to_optab[comparison]
4345 && (libfunc = optab_libfunc (code_to_optab[comparison], mode)))
4346 break;
4348 if (code_to_optab[swapped]
4349 && (libfunc = optab_libfunc (code_to_optab[swapped], mode)))
4351 rtx tmp;
4352 tmp = x; x = y; y = tmp;
4353 comparison = swapped;
4354 break;
4357 if (code_to_optab[reversed]
4358 && (libfunc = optab_libfunc (code_to_optab[reversed], mode)))
4360 comparison = reversed;
4361 reversed_p = true;
4362 break;
4366 gcc_assert (mode != VOIDmode);
4368 if (mode != orig_mode)
4370 x = convert_to_mode (mode, x, 0);
4371 y = convert_to_mode (mode, y, 0);
4374 /* Attach a REG_EQUAL note describing the semantics of the libcall to
4375 the RTL. The allows the RTL optimizers to delete the libcall if the
4376 condition can be determined at compile-time. */
4377 if (comparison == UNORDERED
4378 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4380 true_rtx = const_true_rtx;
4381 false_rtx = const0_rtx;
4383 else
4385 switch (comparison)
4387 case EQ:
4388 true_rtx = const0_rtx;
4389 false_rtx = const_true_rtx;
4390 break;
4392 case NE:
4393 true_rtx = const_true_rtx;
4394 false_rtx = const0_rtx;
4395 break;
4397 case GT:
4398 true_rtx = const1_rtx;
4399 false_rtx = const0_rtx;
4400 break;
4402 case GE:
4403 true_rtx = const0_rtx;
4404 false_rtx = constm1_rtx;
4405 break;
4407 case LT:
4408 true_rtx = constm1_rtx;
4409 false_rtx = const0_rtx;
4410 break;
4412 case LE:
4413 true_rtx = const0_rtx;
4414 false_rtx = const1_rtx;
4415 break;
4417 default:
4418 gcc_unreachable ();
4422 if (comparison == UNORDERED)
4424 rtx temp = simplify_gen_relational (NE, cmp_mode, mode, x, x);
4425 equiv = simplify_gen_relational (NE, cmp_mode, mode, y, y);
4426 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4427 temp, const_true_rtx, equiv);
4429 else
4431 equiv = simplify_gen_relational (comparison, cmp_mode, mode, x, y);
4432 if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4433 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4434 equiv, true_rtx, false_rtx);
4437 start_sequence ();
4438 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4439 cmp_mode, 2, x, mode, y, mode);
4440 insns = get_insns ();
4441 end_sequence ();
4443 target = gen_reg_rtx (cmp_mode);
4444 emit_libcall_block (insns, target, value, equiv);
4446 if (comparison == UNORDERED
4447 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison)
4448 || reversed_p)
4449 *ptest = gen_rtx_fmt_ee (reversed_p ? EQ : NE, VOIDmode, target, false_rtx);
4450 else
4451 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, target, const0_rtx);
4453 *pmode = cmp_mode;
4456 /* Generate code to indirectly jump to a location given in the rtx LOC. */
4458 void
4459 emit_indirect_jump (rtx loc)
4461 if (!insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate
4462 (loc, Pmode))
4463 loc = copy_to_mode_reg (Pmode, loc);
4465 emit_jump_insn (gen_indirect_jump (loc));
4466 emit_barrier ();
4469 #ifdef HAVE_conditional_move
4471 /* Emit a conditional move instruction if the machine supports one for that
4472 condition and machine mode.
4474 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4475 the mode to use should they be constants. If it is VOIDmode, they cannot
4476 both be constants.
4478 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
4479 should be stored there. MODE is the mode to use should they be constants.
4480 If it is VOIDmode, they cannot both be constants.
4482 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4483 is not supported. */
4486 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
4487 enum machine_mode cmode, rtx op2, rtx op3,
4488 enum machine_mode mode, int unsignedp)
4490 rtx tem, subtarget, comparison, insn;
4491 enum insn_code icode;
4492 enum rtx_code reversed;
4494 /* If one operand is constant, make it the second one. Only do this
4495 if the other operand is not constant as well. */
4497 if (swap_commutative_operands_p (op0, op1))
4499 tem = op0;
4500 op0 = op1;
4501 op1 = tem;
4502 code = swap_condition (code);
4505 /* get_condition will prefer to generate LT and GT even if the old
4506 comparison was against zero, so undo that canonicalization here since
4507 comparisons against zero are cheaper. */
4508 if (code == LT && op1 == const1_rtx)
4509 code = LE, op1 = const0_rtx;
4510 else if (code == GT && op1 == constm1_rtx)
4511 code = GE, op1 = const0_rtx;
4513 if (cmode == VOIDmode)
4514 cmode = GET_MODE (op0);
4516 if (swap_commutative_operands_p (op2, op3)
4517 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4518 != UNKNOWN))
4520 tem = op2;
4521 op2 = op3;
4522 op3 = tem;
4523 code = reversed;
4526 if (mode == VOIDmode)
4527 mode = GET_MODE (op2);
4529 icode = movcc_gen_code[mode];
4531 if (icode == CODE_FOR_nothing)
4532 return 0;
4534 if (!target)
4535 target = gen_reg_rtx (mode);
4537 subtarget = target;
4539 /* If the insn doesn't accept these operands, put them in pseudos. */
4541 if (!insn_data[icode].operand[0].predicate
4542 (subtarget, insn_data[icode].operand[0].mode))
4543 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4545 if (!insn_data[icode].operand[2].predicate
4546 (op2, insn_data[icode].operand[2].mode))
4547 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4549 if (!insn_data[icode].operand[3].predicate
4550 (op3, insn_data[icode].operand[3].mode))
4551 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4553 /* Everything should now be in the suitable form. */
4555 code = unsignedp ? unsigned_condition (code) : code;
4556 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4558 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4559 return NULL and let the caller figure out how best to deal with this
4560 situation. */
4561 if (!COMPARISON_P (comparison))
4562 return NULL_RTX;
4564 do_pending_stack_adjust ();
4565 start_sequence ();
4566 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4567 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4568 &comparison, &cmode);
4569 if (!comparison)
4570 insn = NULL_RTX;
4571 else
4572 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4574 /* If that failed, then give up. */
4575 if (insn == 0)
4577 end_sequence ();
4578 return 0;
4581 emit_insn (insn);
4582 insn = get_insns ();
4583 end_sequence ();
4584 emit_insn (insn);
4585 if (subtarget != target)
4586 convert_move (target, subtarget, 0);
4588 return target;
4591 /* Return nonzero if a conditional move of mode MODE is supported.
4593 This function is for combine so it can tell whether an insn that looks
4594 like a conditional move is actually supported by the hardware. If we
4595 guess wrong we lose a bit on optimization, but that's it. */
4596 /* ??? sparc64 supports conditionally moving integers values based on fp
4597 comparisons, and vice versa. How do we handle them? */
4600 can_conditionally_move_p (enum machine_mode mode)
4602 if (movcc_gen_code[mode] != CODE_FOR_nothing)
4603 return 1;
4605 return 0;
4608 #endif /* HAVE_conditional_move */
4610 /* Emit a conditional addition instruction if the machine supports one for that
4611 condition and machine mode.
4613 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4614 the mode to use should they be constants. If it is VOIDmode, they cannot
4615 both be constants.
4617 OP2 should be stored in TARGET if the comparison is true, otherwise OP2+OP3
4618 should be stored there. MODE is the mode to use should they be constants.
4619 If it is VOIDmode, they cannot both be constants.
4621 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4622 is not supported. */
4625 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
4626 enum machine_mode cmode, rtx op2, rtx op3,
4627 enum machine_mode mode, int unsignedp)
4629 rtx tem, subtarget, comparison, insn;
4630 enum insn_code icode;
4631 enum rtx_code reversed;
4633 /* If one operand is constant, make it the second one. Only do this
4634 if the other operand is not constant as well. */
4636 if (swap_commutative_operands_p (op0, op1))
4638 tem = op0;
4639 op0 = op1;
4640 op1 = tem;
4641 code = swap_condition (code);
4644 /* get_condition will prefer to generate LT and GT even if the old
4645 comparison was against zero, so undo that canonicalization here since
4646 comparisons against zero are cheaper. */
4647 if (code == LT && op1 == const1_rtx)
4648 code = LE, op1 = const0_rtx;
4649 else if (code == GT && op1 == constm1_rtx)
4650 code = GE, op1 = const0_rtx;
4652 if (cmode == VOIDmode)
4653 cmode = GET_MODE (op0);
4655 if (swap_commutative_operands_p (op2, op3)
4656 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4657 != UNKNOWN))
4659 tem = op2;
4660 op2 = op3;
4661 op3 = tem;
4662 code = reversed;
4665 if (mode == VOIDmode)
4666 mode = GET_MODE (op2);
4668 icode = optab_handler (addcc_optab, mode)->insn_code;
4670 if (icode == CODE_FOR_nothing)
4671 return 0;
4673 if (!target)
4674 target = gen_reg_rtx (mode);
4676 /* If the insn doesn't accept these operands, put them in pseudos. */
4678 if (!insn_data[icode].operand[0].predicate
4679 (target, insn_data[icode].operand[0].mode))
4680 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4681 else
4682 subtarget = target;
4684 if (!insn_data[icode].operand[2].predicate
4685 (op2, insn_data[icode].operand[2].mode))
4686 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4688 if (!insn_data[icode].operand[3].predicate
4689 (op3, insn_data[icode].operand[3].mode))
4690 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4692 /* Everything should now be in the suitable form. */
4694 code = unsignedp ? unsigned_condition (code) : code;
4695 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4697 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4698 return NULL and let the caller figure out how best to deal with this
4699 situation. */
4700 if (!COMPARISON_P (comparison))
4701 return NULL_RTX;
4703 do_pending_stack_adjust ();
4704 start_sequence ();
4705 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4706 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4707 &comparison, &cmode);
4708 if (!comparison)
4709 insn = NULL_RTX;
4710 else
4711 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4713 /* If that failed, then give up. */
4714 if (insn == 0)
4716 end_sequence ();
4717 return 0;
4720 emit_insn (insn);
4721 insn = get_insns ();
4722 end_sequence ();
4723 emit_insn (insn);
4724 if (subtarget != target)
4725 convert_move (target, subtarget, 0);
4727 return target;
4730 /* These functions attempt to generate an insn body, rather than
4731 emitting the insn, but if the gen function already emits them, we
4732 make no attempt to turn them back into naked patterns. */
4734 /* Generate and return an insn body to add Y to X. */
4737 gen_add2_insn (rtx x, rtx y)
4739 int icode = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
4741 gcc_assert (insn_data[icode].operand[0].predicate
4742 (x, insn_data[icode].operand[0].mode));
4743 gcc_assert (insn_data[icode].operand[1].predicate
4744 (x, insn_data[icode].operand[1].mode));
4745 gcc_assert (insn_data[icode].operand[2].predicate
4746 (y, insn_data[icode].operand[2].mode));
4748 return GEN_FCN (icode) (x, x, y);
4751 /* Generate and return an insn body to add r1 and c,
4752 storing the result in r0. */
4755 gen_add3_insn (rtx r0, rtx r1, rtx c)
4757 int icode = (int) optab_handler (add_optab, GET_MODE (r0))->insn_code;
4759 if (icode == CODE_FOR_nothing
4760 || !(insn_data[icode].operand[0].predicate
4761 (r0, insn_data[icode].operand[0].mode))
4762 || !(insn_data[icode].operand[1].predicate
4763 (r1, insn_data[icode].operand[1].mode))
4764 || !(insn_data[icode].operand[2].predicate
4765 (c, insn_data[icode].operand[2].mode)))
4766 return NULL_RTX;
4768 return GEN_FCN (icode) (r0, r1, c);
4772 have_add2_insn (rtx x, rtx y)
4774 int icode;
4776 gcc_assert (GET_MODE (x) != VOIDmode);
4778 icode = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
4780 if (icode == CODE_FOR_nothing)
4781 return 0;
4783 if (!(insn_data[icode].operand[0].predicate
4784 (x, insn_data[icode].operand[0].mode))
4785 || !(insn_data[icode].operand[1].predicate
4786 (x, insn_data[icode].operand[1].mode))
4787 || !(insn_data[icode].operand[2].predicate
4788 (y, insn_data[icode].operand[2].mode)))
4789 return 0;
4791 return 1;
4794 /* Generate and return an insn body to subtract Y from X. */
4797 gen_sub2_insn (rtx x, rtx y)
4799 int icode = (int) optab_handler (sub_optab, GET_MODE (x))->insn_code;
4801 gcc_assert (insn_data[icode].operand[0].predicate
4802 (x, insn_data[icode].operand[0].mode));
4803 gcc_assert (insn_data[icode].operand[1].predicate
4804 (x, insn_data[icode].operand[1].mode));
4805 gcc_assert (insn_data[icode].operand[2].predicate
4806 (y, insn_data[icode].operand[2].mode));
4808 return GEN_FCN (icode) (x, x, y);
4811 /* Generate and return an insn body to subtract r1 and c,
4812 storing the result in r0. */
4815 gen_sub3_insn (rtx r0, rtx r1, rtx c)
4817 int icode = (int) optab_handler (sub_optab, GET_MODE (r0))->insn_code;
4819 if (icode == CODE_FOR_nothing
4820 || !(insn_data[icode].operand[0].predicate
4821 (r0, insn_data[icode].operand[0].mode))
4822 || !(insn_data[icode].operand[1].predicate
4823 (r1, insn_data[icode].operand[1].mode))
4824 || !(insn_data[icode].operand[2].predicate
4825 (c, insn_data[icode].operand[2].mode)))
4826 return NULL_RTX;
4828 return GEN_FCN (icode) (r0, r1, c);
4832 have_sub2_insn (rtx x, rtx y)
4834 int icode;
4836 gcc_assert (GET_MODE (x) != VOIDmode);
4838 icode = (int) optab_handler (sub_optab, GET_MODE (x))->insn_code;
4840 if (icode == CODE_FOR_nothing)
4841 return 0;
4843 if (!(insn_data[icode].operand[0].predicate
4844 (x, insn_data[icode].operand[0].mode))
4845 || !(insn_data[icode].operand[1].predicate
4846 (x, insn_data[icode].operand[1].mode))
4847 || !(insn_data[icode].operand[2].predicate
4848 (y, insn_data[icode].operand[2].mode)))
4849 return 0;
4851 return 1;
4854 /* Generate the body of an instruction to copy Y into X.
4855 It may be a list of insns, if one insn isn't enough. */
4858 gen_move_insn (rtx x, rtx y)
4860 rtx seq;
4862 start_sequence ();
4863 emit_move_insn_1 (x, y);
4864 seq = get_insns ();
4865 end_sequence ();
4866 return seq;
4869 /* Return the insn code used to extend FROM_MODE to TO_MODE.
4870 UNSIGNEDP specifies zero-extension instead of sign-extension. If
4871 no such operation exists, CODE_FOR_nothing will be returned. */
4873 enum insn_code
4874 can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
4875 int unsignedp)
4877 convert_optab tab;
4878 #ifdef HAVE_ptr_extend
4879 if (unsignedp < 0)
4880 return CODE_FOR_ptr_extend;
4881 #endif
4883 tab = unsignedp ? zext_optab : sext_optab;
4884 return convert_optab_handler (tab, to_mode, from_mode)->insn_code;
4887 /* Generate the body of an insn to extend Y (with mode MFROM)
4888 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
4891 gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
4892 enum machine_mode mfrom, int unsignedp)
4894 enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
4895 return GEN_FCN (icode) (x, y);
4898 /* can_fix_p and can_float_p say whether the target machine
4899 can directly convert a given fixed point type to
4900 a given floating point type, or vice versa.
4901 The returned value is the CODE_FOR_... value to use,
4902 or CODE_FOR_nothing if these modes cannot be directly converted.
4904 *TRUNCP_PTR is set to 1 if it is necessary to output
4905 an explicit FTRUNC insn before the fix insn; otherwise 0. */
4907 static enum insn_code
4908 can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
4909 int unsignedp, int *truncp_ptr)
4911 convert_optab tab;
4912 enum insn_code icode;
4914 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
4915 icode = convert_optab_handler (tab, fixmode, fltmode)->insn_code;
4916 if (icode != CODE_FOR_nothing)
4918 *truncp_ptr = 0;
4919 return icode;
4922 /* FIXME: This requires a port to define both FIX and FTRUNC pattern
4923 for this to work. We need to rework the fix* and ftrunc* patterns
4924 and documentation. */
4925 tab = unsignedp ? ufix_optab : sfix_optab;
4926 icode = convert_optab_handler (tab, fixmode, fltmode)->insn_code;
4927 if (icode != CODE_FOR_nothing
4928 && optab_handler (ftrunc_optab, fltmode)->insn_code != CODE_FOR_nothing)
4930 *truncp_ptr = 1;
4931 return icode;
4934 *truncp_ptr = 0;
4935 return CODE_FOR_nothing;
4938 static enum insn_code
4939 can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
4940 int unsignedp)
4942 convert_optab tab;
4944 tab = unsignedp ? ufloat_optab : sfloat_optab;
4945 return convert_optab_handler (tab, fltmode, fixmode)->insn_code;
4948 /* Generate code to convert FROM to floating point
4949 and store in TO. FROM must be fixed point and not VOIDmode.
4950 UNSIGNEDP nonzero means regard FROM as unsigned.
4951 Normally this is done by correcting the final value
4952 if it is negative. */
4954 void
4955 expand_float (rtx to, rtx from, int unsignedp)
4957 enum insn_code icode;
4958 rtx target = to;
4959 enum machine_mode fmode, imode;
4960 bool can_do_signed = false;
4962 /* Crash now, because we won't be able to decide which mode to use. */
4963 gcc_assert (GET_MODE (from) != VOIDmode);
4965 /* Look for an insn to do the conversion. Do it in the specified
4966 modes if possible; otherwise convert either input, output or both to
4967 wider mode. If the integer mode is wider than the mode of FROM,
4968 we can do the conversion signed even if the input is unsigned. */
4970 for (fmode = GET_MODE (to); fmode != VOIDmode;
4971 fmode = GET_MODE_WIDER_MODE (fmode))
4972 for (imode = GET_MODE (from); imode != VOIDmode;
4973 imode = GET_MODE_WIDER_MODE (imode))
4975 int doing_unsigned = unsignedp;
4977 if (fmode != GET_MODE (to)
4978 && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
4979 continue;
4981 icode = can_float_p (fmode, imode, unsignedp);
4982 if (icode == CODE_FOR_nothing && unsignedp)
4984 enum insn_code scode = can_float_p (fmode, imode, 0);
4985 if (scode != CODE_FOR_nothing)
4986 can_do_signed = true;
4987 if (imode != GET_MODE (from))
4988 icode = scode, doing_unsigned = 0;
4991 if (icode != CODE_FOR_nothing)
4993 if (imode != GET_MODE (from))
4994 from = convert_to_mode (imode, from, unsignedp);
4996 if (fmode != GET_MODE (to))
4997 target = gen_reg_rtx (fmode);
4999 emit_unop_insn (icode, target, from,
5000 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
5002 if (target != to)
5003 convert_move (to, target, 0);
5004 return;
5008 /* Unsigned integer, and no way to convert directly. Convert as signed,
5009 then unconditionally adjust the result. */
5010 if (unsignedp && can_do_signed)
5012 rtx label = gen_label_rtx ();
5013 rtx temp;
5014 REAL_VALUE_TYPE offset;
5016 /* Look for a usable floating mode FMODE wider than the source and at
5017 least as wide as the target. Using FMODE will avoid rounding woes
5018 with unsigned values greater than the signed maximum value. */
5020 for (fmode = GET_MODE (to); fmode != VOIDmode;
5021 fmode = GET_MODE_WIDER_MODE (fmode))
5022 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
5023 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
5024 break;
5026 if (fmode == VOIDmode)
5028 /* There is no such mode. Pretend the target is wide enough. */
5029 fmode = GET_MODE (to);
5031 /* Avoid double-rounding when TO is narrower than FROM. */
5032 if ((significand_size (fmode) + 1)
5033 < GET_MODE_BITSIZE (GET_MODE (from)))
5035 rtx temp1;
5036 rtx neglabel = gen_label_rtx ();
5038 /* Don't use TARGET if it isn't a register, is a hard register,
5039 or is the wrong mode. */
5040 if (!REG_P (target)
5041 || REGNO (target) < FIRST_PSEUDO_REGISTER
5042 || GET_MODE (target) != fmode)
5043 target = gen_reg_rtx (fmode);
5045 imode = GET_MODE (from);
5046 do_pending_stack_adjust ();
5048 /* Test whether the sign bit is set. */
5049 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
5050 0, neglabel);
5052 /* The sign bit is not set. Convert as signed. */
5053 expand_float (target, from, 0);
5054 emit_jump_insn (gen_jump (label));
5055 emit_barrier ();
5057 /* The sign bit is set.
5058 Convert to a usable (positive signed) value by shifting right
5059 one bit, while remembering if a nonzero bit was shifted
5060 out; i.e., compute (from & 1) | (from >> 1). */
5062 emit_label (neglabel);
5063 temp = expand_binop (imode, and_optab, from, const1_rtx,
5064 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5065 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
5066 NULL_RTX, 1);
5067 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
5068 OPTAB_LIB_WIDEN);
5069 expand_float (target, temp, 0);
5071 /* Multiply by 2 to undo the shift above. */
5072 temp = expand_binop (fmode, add_optab, target, target,
5073 target, 0, OPTAB_LIB_WIDEN);
5074 if (temp != target)
5075 emit_move_insn (target, temp);
5077 do_pending_stack_adjust ();
5078 emit_label (label);
5079 goto done;
5083 /* If we are about to do some arithmetic to correct for an
5084 unsigned operand, do it in a pseudo-register. */
5086 if (GET_MODE (to) != fmode
5087 || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
5088 target = gen_reg_rtx (fmode);
5090 /* Convert as signed integer to floating. */
5091 expand_float (target, from, 0);
5093 /* If FROM is negative (and therefore TO is negative),
5094 correct its value by 2**bitwidth. */
5096 do_pending_stack_adjust ();
5097 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
5098 0, label);
5101 real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)), fmode);
5102 temp = expand_binop (fmode, add_optab, target,
5103 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
5104 target, 0, OPTAB_LIB_WIDEN);
5105 if (temp != target)
5106 emit_move_insn (target, temp);
5108 do_pending_stack_adjust ();
5109 emit_label (label);
5110 goto done;
5113 /* No hardware instruction available; call a library routine. */
5115 rtx libfunc;
5116 rtx insns;
5117 rtx value;
5118 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
5120 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
5121 from = convert_to_mode (SImode, from, unsignedp);
5123 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5124 gcc_assert (libfunc);
5126 start_sequence ();
5128 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5129 GET_MODE (to), 1, from,
5130 GET_MODE (from));
5131 insns = get_insns ();
5132 end_sequence ();
5134 emit_libcall_block (insns, target, value,
5135 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FLOAT : FLOAT,
5136 GET_MODE (to), from));
5139 done:
5141 /* Copy result to requested destination
5142 if we have been computing in a temp location. */
5144 if (target != to)
5146 if (GET_MODE (target) == GET_MODE (to))
5147 emit_move_insn (to, target);
5148 else
5149 convert_move (to, target, 0);
5153 /* Generate code to convert FROM to fixed point and store in TO. FROM
5154 must be floating point. */
5156 void
5157 expand_fix (rtx to, rtx from, int unsignedp)
5159 enum insn_code icode;
5160 rtx target = to;
5161 enum machine_mode fmode, imode;
5162 int must_trunc = 0;
5164 /* We first try to find a pair of modes, one real and one integer, at
5165 least as wide as FROM and TO, respectively, in which we can open-code
5166 this conversion. If the integer mode is wider than the mode of TO,
5167 we can do the conversion either signed or unsigned. */
5169 for (fmode = GET_MODE (from); fmode != VOIDmode;
5170 fmode = GET_MODE_WIDER_MODE (fmode))
5171 for (imode = GET_MODE (to); imode != VOIDmode;
5172 imode = GET_MODE_WIDER_MODE (imode))
5174 int doing_unsigned = unsignedp;
5176 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
5177 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
5178 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
5180 if (icode != CODE_FOR_nothing)
5182 rtx last = get_last_insn ();
5183 if (fmode != GET_MODE (from))
5184 from = convert_to_mode (fmode, from, 0);
5186 if (must_trunc)
5188 rtx temp = gen_reg_rtx (GET_MODE (from));
5189 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
5190 temp, 0);
5193 if (imode != GET_MODE (to))
5194 target = gen_reg_rtx (imode);
5196 if (maybe_emit_unop_insn (icode, target, from,
5197 doing_unsigned ? UNSIGNED_FIX : FIX))
5199 if (target != to)
5200 convert_move (to, target, unsignedp);
5201 return;
5203 delete_insns_since (last);
5207 /* For an unsigned conversion, there is one more way to do it.
5208 If we have a signed conversion, we generate code that compares
5209 the real value to the largest representable positive number. If if
5210 is smaller, the conversion is done normally. Otherwise, subtract
5211 one plus the highest signed number, convert, and add it back.
5213 We only need to check all real modes, since we know we didn't find
5214 anything with a wider integer mode.
5216 This code used to extend FP value into mode wider than the destination.
5217 This is needed for decimal float modes which cannot accurately
5218 represent one plus the highest signed number of the same size, but
5219 not for binary modes. Consider, for instance conversion from SFmode
5220 into DImode.
5222 The hot path through the code is dealing with inputs smaller than 2^63
5223 and doing just the conversion, so there is no bits to lose.
5225 In the other path we know the value is positive in the range 2^63..2^64-1
5226 inclusive. (as for other input overflow happens and result is undefined)
5227 So we know that the most important bit set in mantissa corresponds to
5228 2^63. The subtraction of 2^63 should not generate any rounding as it
5229 simply clears out that bit. The rest is trivial. */
5231 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
5232 for (fmode = GET_MODE (from); fmode != VOIDmode;
5233 fmode = GET_MODE_WIDER_MODE (fmode))
5234 if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc)
5235 && (!DECIMAL_FLOAT_MODE_P (fmode)
5236 || GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))))
5238 int bitsize;
5239 REAL_VALUE_TYPE offset;
5240 rtx limit, lab1, lab2, insn;
5242 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
5243 real_2expN (&offset, bitsize - 1, fmode);
5244 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
5245 lab1 = gen_label_rtx ();
5246 lab2 = gen_label_rtx ();
5248 if (fmode != GET_MODE (from))
5249 from = convert_to_mode (fmode, from, 0);
5251 /* See if we need to do the subtraction. */
5252 do_pending_stack_adjust ();
5253 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
5254 0, lab1);
5256 /* If not, do the signed "fix" and branch around fixup code. */
5257 expand_fix (to, from, 0);
5258 emit_jump_insn (gen_jump (lab2));
5259 emit_barrier ();
5261 /* Otherwise, subtract 2**(N-1), convert to signed number,
5262 then add 2**(N-1). Do the addition using XOR since this
5263 will often generate better code. */
5264 emit_label (lab1);
5265 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
5266 NULL_RTX, 0, OPTAB_LIB_WIDEN);
5267 expand_fix (to, target, 0);
5268 target = expand_binop (GET_MODE (to), xor_optab, to,
5269 gen_int_mode
5270 ((HOST_WIDE_INT) 1 << (bitsize - 1),
5271 GET_MODE (to)),
5272 to, 1, OPTAB_LIB_WIDEN);
5274 if (target != to)
5275 emit_move_insn (to, target);
5277 emit_label (lab2);
5279 if (optab_handler (mov_optab, GET_MODE (to))->insn_code
5280 != CODE_FOR_nothing)
5282 /* Make a place for a REG_NOTE and add it. */
5283 insn = emit_move_insn (to, to);
5284 set_unique_reg_note (insn,
5285 REG_EQUAL,
5286 gen_rtx_fmt_e (UNSIGNED_FIX,
5287 GET_MODE (to),
5288 copy_rtx (from)));
5291 return;
5294 /* We can't do it with an insn, so use a library call. But first ensure
5295 that the mode of TO is at least as wide as SImode, since those are the
5296 only library calls we know about. */
5298 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
5300 target = gen_reg_rtx (SImode);
5302 expand_fix (target, from, unsignedp);
5304 else
5306 rtx insns;
5307 rtx value;
5308 rtx libfunc;
5310 convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
5311 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5312 gcc_assert (libfunc);
5314 start_sequence ();
5316 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5317 GET_MODE (to), 1, from,
5318 GET_MODE (from));
5319 insns = get_insns ();
5320 end_sequence ();
5322 emit_libcall_block (insns, target, value,
5323 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
5324 GET_MODE (to), from));
5327 if (target != to)
5329 if (GET_MODE (to) == GET_MODE (target))
5330 emit_move_insn (to, target);
5331 else
5332 convert_move (to, target, 0);
5336 /* Generate code to convert FROM or TO a fixed-point.
5337 If UINTP is true, either TO or FROM is an unsigned integer.
5338 If SATP is true, we need to saturate the result. */
5340 void
5341 expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
5343 enum machine_mode to_mode = GET_MODE (to);
5344 enum machine_mode from_mode = GET_MODE (from);
5345 convert_optab tab;
5346 enum rtx_code this_code;
5347 enum insn_code code;
5348 rtx insns, value;
5349 rtx libfunc;
5351 if (to_mode == from_mode)
5353 emit_move_insn (to, from);
5354 return;
5357 if (uintp)
5359 tab = satp ? satfractuns_optab : fractuns_optab;
5360 this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
5362 else
5364 tab = satp ? satfract_optab : fract_optab;
5365 this_code = satp ? SAT_FRACT : FRACT_CONVERT;
5367 code = tab->handlers[to_mode][from_mode].insn_code;
5368 if (code != CODE_FOR_nothing)
5370 emit_unop_insn (code, to, from, this_code);
5371 return;
5374 libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
5375 gcc_assert (libfunc);
5377 start_sequence ();
5378 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
5379 1, from, from_mode);
5380 insns = get_insns ();
5381 end_sequence ();
5383 emit_libcall_block (insns, to, value,
5384 gen_rtx_fmt_e (tab->code, to_mode, from));
5387 /* Generate code to convert FROM to fixed point and store in TO. FROM
5388 must be floating point, TO must be signed. Use the conversion optab
5389 TAB to do the conversion. */
5391 bool
5392 expand_sfix_optab (rtx to, rtx from, convert_optab tab)
5394 enum insn_code icode;
5395 rtx target = to;
5396 enum machine_mode fmode, imode;
5398 /* We first try to find a pair of modes, one real and one integer, at
5399 least as wide as FROM and TO, respectively, in which we can open-code
5400 this conversion. If the integer mode is wider than the mode of TO,
5401 we can do the conversion either signed or unsigned. */
5403 for (fmode = GET_MODE (from); fmode != VOIDmode;
5404 fmode = GET_MODE_WIDER_MODE (fmode))
5405 for (imode = GET_MODE (to); imode != VOIDmode;
5406 imode = GET_MODE_WIDER_MODE (imode))
5408 icode = convert_optab_handler (tab, imode, fmode)->insn_code;
5409 if (icode != CODE_FOR_nothing)
5411 rtx last = get_last_insn ();
5412 if (fmode != GET_MODE (from))
5413 from = convert_to_mode (fmode, from, 0);
5415 if (imode != GET_MODE (to))
5416 target = gen_reg_rtx (imode);
5418 if (!maybe_emit_unop_insn (icode, target, from, UNKNOWN))
5420 delete_insns_since (last);
5421 continue;
5423 if (target != to)
5424 convert_move (to, target, 0);
5425 return true;
5429 return false;
5432 /* Report whether we have an instruction to perform the operation
5433 specified by CODE on operands of mode MODE. */
5435 have_insn_for (enum rtx_code code, enum machine_mode mode)
5437 return (code_to_optab[(int) code] != 0
5438 && (optab_handler (code_to_optab[(int) code], mode)->insn_code
5439 != CODE_FOR_nothing));
5442 /* Set all insn_code fields to CODE_FOR_nothing. */
5444 static void
5445 init_insn_codes (void)
5447 unsigned int i;
5449 for (i = 0; i < (unsigned int) OTI_MAX; i++)
5451 unsigned int j;
5452 optab op;
5454 op = &optab_table[i];
5455 for (j = 0; j < NUM_MACHINE_MODES; j++)
5456 optab_handler (op, j)->insn_code = CODE_FOR_nothing;
5458 for (i = 0; i < (unsigned int) COI_MAX; i++)
5460 unsigned int j, k;
5461 convert_optab op;
5463 op = &convert_optab_table[i];
5464 for (j = 0; j < NUM_MACHINE_MODES; j++)
5465 for (k = 0; k < NUM_MACHINE_MODES; k++)
5466 convert_optab_handler (op, j, k)->insn_code = CODE_FOR_nothing;
5470 /* Initialize OP's code to CODE, and write it into the code_to_optab table. */
5471 static inline void
5472 init_optab (optab op, enum rtx_code code)
5474 op->code = code;
5475 code_to_optab[(int) code] = op;
5478 /* Same, but fill in its code as CODE, and do _not_ write it into
5479 the code_to_optab table. */
5480 static inline void
5481 init_optabv (optab op, enum rtx_code code)
5483 op->code = code;
5486 /* Conversion optabs never go in the code_to_optab table. */
5487 static void
5488 init_convert_optab (convert_optab op, enum rtx_code code)
5490 op->code = code;
5493 /* Initialize the libfunc fields of an entire group of entries in some
5494 optab. Each entry is set equal to a string consisting of a leading
5495 pair of underscores followed by a generic operation name followed by
5496 a mode name (downshifted to lowercase) followed by a single character
5497 representing the number of operands for the given operation (which is
5498 usually one of the characters '2', '3', or '4').
5500 OPTABLE is the table in which libfunc fields are to be initialized.
5501 OPNAME is the generic (string) name of the operation.
5502 SUFFIX is the character which specifies the number of operands for
5503 the given generic operation.
5504 MODE is the mode to generate for.
5507 static void
5508 gen_libfunc (optab optable, const char *opname, int suffix, enum machine_mode mode)
5510 unsigned opname_len = strlen (opname);
5511 const char *mname = GET_MODE_NAME (mode);
5512 unsigned mname_len = strlen (mname);
5513 char *libfunc_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5514 char *p;
5515 const char *q;
5517 p = libfunc_name;
5518 *p++ = '_';
5519 *p++ = '_';
5520 for (q = opname; *q; )
5521 *p++ = *q++;
5522 for (q = mname; *q; q++)
5523 *p++ = TOLOWER (*q);
5524 *p++ = suffix;
5525 *p = '\0';
5527 set_optab_libfunc (optable, mode,
5528 ggc_alloc_string (libfunc_name, p - libfunc_name));
5531 /* Like gen_libfunc, but verify that integer operation is involved. */
5533 static void
5534 gen_int_libfunc (optab optable, const char *opname, char suffix,
5535 enum machine_mode mode)
5537 int maxsize = 2 * BITS_PER_WORD;
5539 if (GET_MODE_CLASS (mode) != MODE_INT)
5540 return;
5541 if (maxsize < LONG_LONG_TYPE_SIZE)
5542 maxsize = LONG_LONG_TYPE_SIZE;
5543 if (GET_MODE_CLASS (mode) != MODE_INT
5544 || mode < word_mode || GET_MODE_BITSIZE (mode) > maxsize)
5545 return;
5546 gen_libfunc (optable, opname, suffix, mode);
5549 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed. */
5551 static void
5552 gen_fp_libfunc (optab optable, const char *opname, char suffix,
5553 enum machine_mode mode)
5555 char *dec_opname;
5557 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
5558 gen_libfunc (optable, opname, suffix, mode);
5559 if (DECIMAL_FLOAT_MODE_P (mode))
5561 dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
5562 /* For BID support, change the name to have either a bid_ or dpd_ prefix
5563 depending on the low level floating format used. */
5564 memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
5565 strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
5566 gen_libfunc (optable, dec_opname, suffix, mode);
5570 /* Like gen_libfunc, but verify that fixed-point operation is involved. */
5572 static void
5573 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
5574 enum machine_mode mode)
5576 if (!ALL_FIXED_POINT_MODE_P (mode))
5577 return;
5578 gen_libfunc (optable, opname, suffix, mode);
5581 /* Like gen_libfunc, but verify that signed fixed-point operation is
5582 involved. */
5584 static void
5585 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
5586 enum machine_mode mode)
5588 if (!SIGNED_FIXED_POINT_MODE_P (mode))
5589 return;
5590 gen_libfunc (optable, opname, suffix, mode);
5593 /* Like gen_libfunc, but verify that unsigned fixed-point operation is
5594 involved. */
5596 static void
5597 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
5598 enum machine_mode mode)
5600 if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
5601 return;
5602 gen_libfunc (optable, opname, suffix, mode);
5605 /* Like gen_libfunc, but verify that FP or INT operation is involved. */
5607 static void
5608 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
5609 enum machine_mode mode)
5611 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5612 gen_fp_libfunc (optable, name, suffix, mode);
5613 if (INTEGRAL_MODE_P (mode))
5614 gen_int_libfunc (optable, name, suffix, mode);
5617 /* Like gen_libfunc, but verify that FP or INT operation is involved
5618 and add 'v' suffix for integer operation. */
5620 static void
5621 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
5622 enum machine_mode mode)
5624 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5625 gen_fp_libfunc (optable, name, suffix, mode);
5626 if (GET_MODE_CLASS (mode) == MODE_INT)
5628 int len = strlen (name);
5629 char *v_name = XALLOCAVEC (char, len + 2);
5630 strcpy (v_name, name);
5631 v_name[len] = 'v';
5632 v_name[len + 1] = 0;
5633 gen_int_libfunc (optable, v_name, suffix, mode);
5637 /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
5638 involved. */
5640 static void
5641 gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
5642 enum machine_mode mode)
5644 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5645 gen_fp_libfunc (optable, name, suffix, mode);
5646 if (INTEGRAL_MODE_P (mode))
5647 gen_int_libfunc (optable, name, suffix, mode);
5648 if (ALL_FIXED_POINT_MODE_P (mode))
5649 gen_fixed_libfunc (optable, name, suffix, mode);
5652 /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
5653 involved. */
5655 static void
5656 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5657 enum machine_mode mode)
5659 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5660 gen_fp_libfunc (optable, name, suffix, mode);
5661 if (INTEGRAL_MODE_P (mode))
5662 gen_int_libfunc (optable, name, suffix, mode);
5663 if (SIGNED_FIXED_POINT_MODE_P (mode))
5664 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5667 /* Like gen_libfunc, but verify that INT or FIXED operation is
5668 involved. */
5670 static void
5671 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
5672 enum machine_mode mode)
5674 if (INTEGRAL_MODE_P (mode))
5675 gen_int_libfunc (optable, name, suffix, mode);
5676 if (ALL_FIXED_POINT_MODE_P (mode))
5677 gen_fixed_libfunc (optable, name, suffix, mode);
5680 /* Like gen_libfunc, but verify that INT or signed FIXED operation is
5681 involved. */
5683 static void
5684 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5685 enum machine_mode mode)
5687 if (INTEGRAL_MODE_P (mode))
5688 gen_int_libfunc (optable, name, suffix, mode);
5689 if (SIGNED_FIXED_POINT_MODE_P (mode))
5690 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5693 /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
5694 involved. */
5696 static void
5697 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
5698 enum machine_mode mode)
5700 if (INTEGRAL_MODE_P (mode))
5701 gen_int_libfunc (optable, name, suffix, mode);
5702 if (UNSIGNED_FIXED_POINT_MODE_P (mode))
5703 gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
5706 /* Initialize the libfunc fields of an entire group of entries of an
5707 inter-mode-class conversion optab. The string formation rules are
5708 similar to the ones for init_libfuncs, above, but instead of having
5709 a mode name and an operand count these functions have two mode names
5710 and no operand count. */
5712 static void
5713 gen_interclass_conv_libfunc (convert_optab tab,
5714 const char *opname,
5715 enum machine_mode tmode,
5716 enum machine_mode fmode)
5718 size_t opname_len = strlen (opname);
5719 size_t mname_len = 0;
5721 const char *fname, *tname;
5722 const char *q;
5723 char *libfunc_name, *suffix;
5724 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5725 char *p;
5727 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5728 depends on which underlying decimal floating point format is used. */
5729 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5731 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5733 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5734 nondec_name[0] = '_';
5735 nondec_name[1] = '_';
5736 memcpy (&nondec_name[2], opname, opname_len);
5737 nondec_suffix = nondec_name + opname_len + 2;
5739 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5740 dec_name[0] = '_';
5741 dec_name[1] = '_';
5742 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5743 memcpy (&dec_name[2+dec_len], opname, opname_len);
5744 dec_suffix = dec_name + dec_len + opname_len + 2;
5746 fname = GET_MODE_NAME (fmode);
5747 tname = GET_MODE_NAME (tmode);
5749 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5751 libfunc_name = dec_name;
5752 suffix = dec_suffix;
5754 else
5756 libfunc_name = nondec_name;
5757 suffix = nondec_suffix;
5760 p = suffix;
5761 for (q = fname; *q; p++, q++)
5762 *p = TOLOWER (*q);
5763 for (q = tname; *q; p++, q++)
5764 *p = TOLOWER (*q);
5766 *p = '\0';
5768 set_conv_libfunc (tab, tmode, fmode,
5769 ggc_alloc_string (libfunc_name, p - libfunc_name));
5772 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5773 int->fp conversion. */
5775 static void
5776 gen_int_to_fp_conv_libfunc (convert_optab tab,
5777 const char *opname,
5778 enum machine_mode tmode,
5779 enum machine_mode fmode)
5781 if (GET_MODE_CLASS (fmode) != MODE_INT)
5782 return;
5783 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5784 return;
5785 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5788 /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
5789 naming scheme. */
5791 static void
5792 gen_ufloat_conv_libfunc (convert_optab tab,
5793 const char *opname ATTRIBUTE_UNUSED,
5794 enum machine_mode tmode,
5795 enum machine_mode fmode)
5797 if (DECIMAL_FLOAT_MODE_P (tmode))
5798 gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
5799 else
5800 gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
5803 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5804 fp->int conversion. */
5806 static void
5807 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
5808 const char *opname,
5809 enum machine_mode tmode,
5810 enum machine_mode fmode)
5812 if (GET_MODE_CLASS (fmode) != MODE_INT)
5813 return;
5814 if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
5815 return;
5816 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5819 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5820 fp->int conversion with no decimal floating point involved. */
5822 static void
5823 gen_fp_to_int_conv_libfunc (convert_optab tab,
5824 const char *opname,
5825 enum machine_mode tmode,
5826 enum machine_mode fmode)
5828 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5829 return;
5830 if (GET_MODE_CLASS (tmode) != MODE_INT)
5831 return;
5832 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5835 /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
5836 The string formation rules are
5837 similar to the ones for init_libfunc, above. */
5839 static void
5840 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
5841 enum machine_mode tmode, enum machine_mode fmode)
5843 size_t opname_len = strlen (opname);
5844 size_t mname_len = 0;
5846 const char *fname, *tname;
5847 const char *q;
5848 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5849 char *libfunc_name, *suffix;
5850 char *p;
5852 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5853 depends on which underlying decimal floating point format is used. */
5854 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5856 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5858 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5859 nondec_name[0] = '_';
5860 nondec_name[1] = '_';
5861 memcpy (&nondec_name[2], opname, opname_len);
5862 nondec_suffix = nondec_name + opname_len + 2;
5864 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5865 dec_name[0] = '_';
5866 dec_name[1] = '_';
5867 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5868 memcpy (&dec_name[2 + dec_len], opname, opname_len);
5869 dec_suffix = dec_name + dec_len + opname_len + 2;
5871 fname = GET_MODE_NAME (fmode);
5872 tname = GET_MODE_NAME (tmode);
5874 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5876 libfunc_name = dec_name;
5877 suffix = dec_suffix;
5879 else
5881 libfunc_name = nondec_name;
5882 suffix = nondec_suffix;
5885 p = suffix;
5886 for (q = fname; *q; p++, q++)
5887 *p = TOLOWER (*q);
5888 for (q = tname; *q; p++, q++)
5889 *p = TOLOWER (*q);
5891 *p++ = '2';
5892 *p = '\0';
5894 set_conv_libfunc (tab, tmode, fmode,
5895 ggc_alloc_string (libfunc_name, p - libfunc_name));
5898 /* Pick proper libcall for trunc_optab. We need to chose if we do
5899 truncation or extension and interclass or intraclass. */
5901 static void
5902 gen_trunc_conv_libfunc (convert_optab tab,
5903 const char *opname,
5904 enum machine_mode tmode,
5905 enum machine_mode fmode)
5907 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5908 return;
5909 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5910 return;
5911 if (tmode == fmode)
5912 return;
5914 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5915 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5916 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5918 if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
5919 return;
5921 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5922 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5923 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5924 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5927 /* Pick proper libcall for extend_optab. We need to chose if we do
5928 truncation or extension and interclass or intraclass. */
5930 static void
5931 gen_extend_conv_libfunc (convert_optab tab,
5932 const char *opname ATTRIBUTE_UNUSED,
5933 enum machine_mode tmode,
5934 enum machine_mode fmode)
5936 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5937 return;
5938 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5939 return;
5940 if (tmode == fmode)
5941 return;
5943 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5944 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5945 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5947 if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
5948 return;
5950 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5951 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5952 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5953 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5956 /* Pick proper libcall for fract_optab. We need to chose if we do
5957 interclass or intraclass. */
5959 static void
5960 gen_fract_conv_libfunc (convert_optab tab,
5961 const char *opname,
5962 enum machine_mode tmode,
5963 enum machine_mode fmode)
5965 if (tmode == fmode)
5966 return;
5967 if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
5968 return;
5970 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
5971 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5972 else
5973 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5976 /* Pick proper libcall for fractuns_optab. */
5978 static void
5979 gen_fractuns_conv_libfunc (convert_optab tab,
5980 const char *opname,
5981 enum machine_mode tmode,
5982 enum machine_mode fmode)
5984 if (tmode == fmode)
5985 return;
5986 /* One mode must be a fixed-point mode, and the other must be an integer
5987 mode. */
5988 if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
5989 || (ALL_FIXED_POINT_MODE_P (fmode)
5990 && GET_MODE_CLASS (tmode) == MODE_INT)))
5991 return;
5993 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5996 /* Pick proper libcall for satfract_optab. We need to chose if we do
5997 interclass or intraclass. */
5999 static void
6000 gen_satfract_conv_libfunc (convert_optab tab,
6001 const char *opname,
6002 enum machine_mode tmode,
6003 enum machine_mode fmode)
6005 if (tmode == fmode)
6006 return;
6007 /* TMODE must be a fixed-point mode. */
6008 if (!ALL_FIXED_POINT_MODE_P (tmode))
6009 return;
6011 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
6012 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6013 else
6014 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6017 /* Pick proper libcall for satfractuns_optab. */
6019 static void
6020 gen_satfractuns_conv_libfunc (convert_optab tab,
6021 const char *opname,
6022 enum machine_mode tmode,
6023 enum machine_mode fmode)
6025 if (tmode == fmode)
6026 return;
6027 /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
6028 if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
6029 return;
6031 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6034 /* A table of previously-created libfuncs, hashed by name. */
6035 static GTY ((param_is (union tree_node))) htab_t libfunc_decls;
6037 /* Hashtable callbacks for libfunc_decls. */
6039 static hashval_t
6040 libfunc_decl_hash (const void *entry)
6042 return IDENTIFIER_HASH_VALUE (DECL_NAME ((const_tree) entry));
6045 static int
6046 libfunc_decl_eq (const void *entry1, const void *entry2)
6048 return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
6051 /* Build a decl for a libfunc named NAME. */
6053 tree
6054 build_libfunc_function (const char *name)
6056 tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
6057 get_identifier (name),
6058 build_function_type (integer_type_node, NULL_TREE));
6059 /* ??? We don't have any type information except for this is
6060 a function. Pretend this is "int foo()". */
6061 DECL_ARTIFICIAL (decl) = 1;
6062 DECL_EXTERNAL (decl) = 1;
6063 TREE_PUBLIC (decl) = 1;
6064 gcc_assert (DECL_ASSEMBLER_NAME (decl));
6066 /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
6067 are the flags assigned by targetm.encode_section_info. */
6068 SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
6070 return decl;
6074 init_one_libfunc (const char *name)
6076 tree id, decl;
6077 void **slot;
6078 hashval_t hash;
6080 if (libfunc_decls == NULL)
6081 libfunc_decls = htab_create_ggc (37, libfunc_decl_hash,
6082 libfunc_decl_eq, NULL);
6084 /* See if we have already created a libfunc decl for this function. */
6085 id = get_identifier (name);
6086 hash = IDENTIFIER_HASH_VALUE (id);
6087 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, INSERT);
6088 decl = (tree) *slot;
6089 if (decl == NULL)
6091 /* Create a new decl, so that it can be passed to
6092 targetm.encode_section_info. */
6093 decl = build_libfunc_function (name);
6094 *slot = decl;
6096 return XEXP (DECL_RTL (decl), 0);
6099 /* Adjust the assembler name of libfunc NAME to ASMSPEC. */
6102 set_user_assembler_libfunc (const char *name, const char *asmspec)
6104 tree id, decl;
6105 void **slot;
6106 hashval_t hash;
6108 id = get_identifier (name);
6109 hash = IDENTIFIER_HASH_VALUE (id);
6110 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, NO_INSERT);
6111 gcc_assert (slot);
6112 decl = (tree) *slot;
6113 set_user_assembler_name (decl, asmspec);
6114 return XEXP (DECL_RTL (decl), 0);
6117 /* Call this to reset the function entry for one optab (OPTABLE) in mode
6118 MODE to NAME, which should be either 0 or a string constant. */
6119 void
6120 set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
6122 rtx val;
6123 struct libfunc_entry e;
6124 struct libfunc_entry **slot;
6125 e.optab = (size_t) (optable - &optab_table[0]);
6126 e.mode1 = mode;
6127 e.mode2 = VOIDmode;
6129 if (name)
6130 val = init_one_libfunc (name);
6131 else
6132 val = 0;
6133 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6134 if (*slot == NULL)
6135 *slot = GGC_NEW (struct libfunc_entry);
6136 (*slot)->optab = (size_t) (optable - &optab_table[0]);
6137 (*slot)->mode1 = mode;
6138 (*slot)->mode2 = VOIDmode;
6139 (*slot)->libfunc = val;
6142 /* Call this to reset the function entry for one conversion optab
6143 (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
6144 either 0 or a string constant. */
6145 void
6146 set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
6147 enum machine_mode fmode, const char *name)
6149 rtx val;
6150 struct libfunc_entry e;
6151 struct libfunc_entry **slot;
6152 e.optab = (size_t) (optable - &convert_optab_table[0]);
6153 e.mode1 = tmode;
6154 e.mode2 = fmode;
6156 if (name)
6157 val = init_one_libfunc (name);
6158 else
6159 val = 0;
6160 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6161 if (*slot == NULL)
6162 *slot = GGC_NEW (struct libfunc_entry);
6163 (*slot)->optab = (size_t) (optable - &convert_optab_table[0]);
6164 (*slot)->mode1 = tmode;
6165 (*slot)->mode2 = fmode;
6166 (*slot)->libfunc = val;
6169 /* Call this to initialize the contents of the optabs
6170 appropriately for the current target machine. */
6172 void
6173 init_optabs (void)
6175 unsigned int i;
6176 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
6177 static bool reinit;
6178 #endif
6180 libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
6181 /* Start by initializing all tables to contain CODE_FOR_nothing. */
6183 #ifdef HAVE_conditional_move
6184 for (i = 0; i < NUM_MACHINE_MODES; i++)
6185 movcc_gen_code[i] = CODE_FOR_nothing;
6186 #endif
6188 for (i = 0; i < NUM_MACHINE_MODES; i++)
6190 vcond_gen_code[i] = CODE_FOR_nothing;
6191 vcondu_gen_code[i] = CODE_FOR_nothing;
6194 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
6195 /* We statically initialize the insn_codes with CODE_FOR_nothing. */
6196 if (reinit)
6197 init_insn_codes ();
6198 #else
6199 init_insn_codes ();
6200 #endif
6202 init_optab (add_optab, PLUS);
6203 init_optabv (addv_optab, PLUS);
6204 init_optab (sub_optab, MINUS);
6205 init_optabv (subv_optab, MINUS);
6206 init_optab (ssadd_optab, SS_PLUS);
6207 init_optab (usadd_optab, US_PLUS);
6208 init_optab (sssub_optab, SS_MINUS);
6209 init_optab (ussub_optab, US_MINUS);
6210 init_optab (smul_optab, MULT);
6211 init_optab (ssmul_optab, SS_MULT);
6212 init_optab (usmul_optab, US_MULT);
6213 init_optabv (smulv_optab, MULT);
6214 init_optab (smul_highpart_optab, UNKNOWN);
6215 init_optab (umul_highpart_optab, UNKNOWN);
6216 init_optab (smul_widen_optab, UNKNOWN);
6217 init_optab (umul_widen_optab, UNKNOWN);
6218 init_optab (usmul_widen_optab, UNKNOWN);
6219 init_optab (smadd_widen_optab, UNKNOWN);
6220 init_optab (umadd_widen_optab, UNKNOWN);
6221 init_optab (ssmadd_widen_optab, UNKNOWN);
6222 init_optab (usmadd_widen_optab, UNKNOWN);
6223 init_optab (smsub_widen_optab, UNKNOWN);
6224 init_optab (umsub_widen_optab, UNKNOWN);
6225 init_optab (ssmsub_widen_optab, UNKNOWN);
6226 init_optab (usmsub_widen_optab, UNKNOWN);
6227 init_optab (sdiv_optab, DIV);
6228 init_optab (ssdiv_optab, SS_DIV);
6229 init_optab (usdiv_optab, US_DIV);
6230 init_optabv (sdivv_optab, DIV);
6231 init_optab (sdivmod_optab, UNKNOWN);
6232 init_optab (udiv_optab, UDIV);
6233 init_optab (udivmod_optab, UNKNOWN);
6234 init_optab (smod_optab, MOD);
6235 init_optab (umod_optab, UMOD);
6236 init_optab (fmod_optab, UNKNOWN);
6237 init_optab (remainder_optab, UNKNOWN);
6238 init_optab (ftrunc_optab, UNKNOWN);
6239 init_optab (and_optab, AND);
6240 init_optab (ior_optab, IOR);
6241 init_optab (xor_optab, XOR);
6242 init_optab (ashl_optab, ASHIFT);
6243 init_optab (ssashl_optab, SS_ASHIFT);
6244 init_optab (usashl_optab, US_ASHIFT);
6245 init_optab (ashr_optab, ASHIFTRT);
6246 init_optab (lshr_optab, LSHIFTRT);
6247 init_optab (rotl_optab, ROTATE);
6248 init_optab (rotr_optab, ROTATERT);
6249 init_optab (smin_optab, SMIN);
6250 init_optab (smax_optab, SMAX);
6251 init_optab (umin_optab, UMIN);
6252 init_optab (umax_optab, UMAX);
6253 init_optab (pow_optab, UNKNOWN);
6254 init_optab (atan2_optab, UNKNOWN);
6256 /* These three have codes assigned exclusively for the sake of
6257 have_insn_for. */
6258 init_optab (mov_optab, SET);
6259 init_optab (movstrict_optab, STRICT_LOW_PART);
6260 init_optab (cbranch_optab, COMPARE);
6262 init_optab (cmov_optab, UNKNOWN);
6263 init_optab (cstore_optab, UNKNOWN);
6264 init_optab (ctrap_optab, UNKNOWN);
6266 init_optab (storent_optab, UNKNOWN);
6268 init_optab (cmp_optab, UNKNOWN);
6269 init_optab (ucmp_optab, UNKNOWN);
6271 init_optab (eq_optab, EQ);
6272 init_optab (ne_optab, NE);
6273 init_optab (gt_optab, GT);
6274 init_optab (ge_optab, GE);
6275 init_optab (lt_optab, LT);
6276 init_optab (le_optab, LE);
6277 init_optab (unord_optab, UNORDERED);
6279 init_optab (neg_optab, NEG);
6280 init_optab (ssneg_optab, SS_NEG);
6281 init_optab (usneg_optab, US_NEG);
6282 init_optabv (negv_optab, NEG);
6283 init_optab (abs_optab, ABS);
6284 init_optabv (absv_optab, ABS);
6285 init_optab (addcc_optab, UNKNOWN);
6286 init_optab (one_cmpl_optab, NOT);
6287 init_optab (bswap_optab, BSWAP);
6288 init_optab (ffs_optab, FFS);
6289 init_optab (clz_optab, CLZ);
6290 init_optab (ctz_optab, CTZ);
6291 init_optab (popcount_optab, POPCOUNT);
6292 init_optab (parity_optab, PARITY);
6293 init_optab (sqrt_optab, SQRT);
6294 init_optab (floor_optab, UNKNOWN);
6295 init_optab (ceil_optab, UNKNOWN);
6296 init_optab (round_optab, UNKNOWN);
6297 init_optab (btrunc_optab, UNKNOWN);
6298 init_optab (nearbyint_optab, UNKNOWN);
6299 init_optab (rint_optab, UNKNOWN);
6300 init_optab (sincos_optab, UNKNOWN);
6301 init_optab (sin_optab, UNKNOWN);
6302 init_optab (asin_optab, UNKNOWN);
6303 init_optab (cos_optab, UNKNOWN);
6304 init_optab (acos_optab, UNKNOWN);
6305 init_optab (exp_optab, UNKNOWN);
6306 init_optab (exp10_optab, UNKNOWN);
6307 init_optab (exp2_optab, UNKNOWN);
6308 init_optab (expm1_optab, UNKNOWN);
6309 init_optab (ldexp_optab, UNKNOWN);
6310 init_optab (scalb_optab, UNKNOWN);
6311 init_optab (significand_optab, UNKNOWN);
6312 init_optab (logb_optab, UNKNOWN);
6313 init_optab (ilogb_optab, UNKNOWN);
6314 init_optab (log_optab, UNKNOWN);
6315 init_optab (log10_optab, UNKNOWN);
6316 init_optab (log2_optab, UNKNOWN);
6317 init_optab (log1p_optab, UNKNOWN);
6318 init_optab (tan_optab, UNKNOWN);
6319 init_optab (atan_optab, UNKNOWN);
6320 init_optab (copysign_optab, UNKNOWN);
6321 init_optab (signbit_optab, UNKNOWN);
6323 init_optab (isinf_optab, UNKNOWN);
6325 init_optab (strlen_optab, UNKNOWN);
6326 init_optab (push_optab, UNKNOWN);
6328 init_optab (reduc_smax_optab, UNKNOWN);
6329 init_optab (reduc_umax_optab, UNKNOWN);
6330 init_optab (reduc_smin_optab, UNKNOWN);
6331 init_optab (reduc_umin_optab, UNKNOWN);
6332 init_optab (reduc_splus_optab, UNKNOWN);
6333 init_optab (reduc_uplus_optab, UNKNOWN);
6335 init_optab (ssum_widen_optab, UNKNOWN);
6336 init_optab (usum_widen_optab, UNKNOWN);
6337 init_optab (sdot_prod_optab, UNKNOWN);
6338 init_optab (udot_prod_optab, UNKNOWN);
6340 init_optab (vec_extract_optab, UNKNOWN);
6341 init_optab (vec_extract_even_optab, UNKNOWN);
6342 init_optab (vec_extract_odd_optab, UNKNOWN);
6343 init_optab (vec_interleave_high_optab, UNKNOWN);
6344 init_optab (vec_interleave_low_optab, UNKNOWN);
6345 init_optab (vec_set_optab, UNKNOWN);
6346 init_optab (vec_init_optab, UNKNOWN);
6347 init_optab (vec_shl_optab, UNKNOWN);
6348 init_optab (vec_shr_optab, UNKNOWN);
6349 init_optab (vec_realign_load_optab, UNKNOWN);
6350 init_optab (movmisalign_optab, UNKNOWN);
6351 init_optab (vec_widen_umult_hi_optab, UNKNOWN);
6352 init_optab (vec_widen_umult_lo_optab, UNKNOWN);
6353 init_optab (vec_widen_smult_hi_optab, UNKNOWN);
6354 init_optab (vec_widen_smult_lo_optab, UNKNOWN);
6355 init_optab (vec_unpacks_hi_optab, UNKNOWN);
6356 init_optab (vec_unpacks_lo_optab, UNKNOWN);
6357 init_optab (vec_unpacku_hi_optab, UNKNOWN);
6358 init_optab (vec_unpacku_lo_optab, UNKNOWN);
6359 init_optab (vec_unpacks_float_hi_optab, UNKNOWN);
6360 init_optab (vec_unpacks_float_lo_optab, UNKNOWN);
6361 init_optab (vec_unpacku_float_hi_optab, UNKNOWN);
6362 init_optab (vec_unpacku_float_lo_optab, UNKNOWN);
6363 init_optab (vec_pack_trunc_optab, UNKNOWN);
6364 init_optab (vec_pack_usat_optab, UNKNOWN);
6365 init_optab (vec_pack_ssat_optab, UNKNOWN);
6366 init_optab (vec_pack_ufix_trunc_optab, UNKNOWN);
6367 init_optab (vec_pack_sfix_trunc_optab, UNKNOWN);
6369 init_optab (powi_optab, UNKNOWN);
6371 /* Conversions. */
6372 init_convert_optab (sext_optab, SIGN_EXTEND);
6373 init_convert_optab (zext_optab, ZERO_EXTEND);
6374 init_convert_optab (trunc_optab, TRUNCATE);
6375 init_convert_optab (sfix_optab, FIX);
6376 init_convert_optab (ufix_optab, UNSIGNED_FIX);
6377 init_convert_optab (sfixtrunc_optab, UNKNOWN);
6378 init_convert_optab (ufixtrunc_optab, UNKNOWN);
6379 init_convert_optab (sfloat_optab, FLOAT);
6380 init_convert_optab (ufloat_optab, UNSIGNED_FLOAT);
6381 init_convert_optab (lrint_optab, UNKNOWN);
6382 init_convert_optab (lround_optab, UNKNOWN);
6383 init_convert_optab (lfloor_optab, UNKNOWN);
6384 init_convert_optab (lceil_optab, UNKNOWN);
6386 init_convert_optab (fract_optab, FRACT_CONVERT);
6387 init_convert_optab (fractuns_optab, UNSIGNED_FRACT_CONVERT);
6388 init_convert_optab (satfract_optab, SAT_FRACT);
6389 init_convert_optab (satfractuns_optab, UNSIGNED_SAT_FRACT);
6391 for (i = 0; i < NUM_MACHINE_MODES; i++)
6393 movmem_optab[i] = CODE_FOR_nothing;
6394 cmpstr_optab[i] = CODE_FOR_nothing;
6395 cmpstrn_optab[i] = CODE_FOR_nothing;
6396 cmpmem_optab[i] = CODE_FOR_nothing;
6397 setmem_optab[i] = CODE_FOR_nothing;
6399 sync_add_optab[i] = CODE_FOR_nothing;
6400 sync_sub_optab[i] = CODE_FOR_nothing;
6401 sync_ior_optab[i] = CODE_FOR_nothing;
6402 sync_and_optab[i] = CODE_FOR_nothing;
6403 sync_xor_optab[i] = CODE_FOR_nothing;
6404 sync_nand_optab[i] = CODE_FOR_nothing;
6405 sync_old_add_optab[i] = CODE_FOR_nothing;
6406 sync_old_sub_optab[i] = CODE_FOR_nothing;
6407 sync_old_ior_optab[i] = CODE_FOR_nothing;
6408 sync_old_and_optab[i] = CODE_FOR_nothing;
6409 sync_old_xor_optab[i] = CODE_FOR_nothing;
6410 sync_old_nand_optab[i] = CODE_FOR_nothing;
6411 sync_new_add_optab[i] = CODE_FOR_nothing;
6412 sync_new_sub_optab[i] = CODE_FOR_nothing;
6413 sync_new_ior_optab[i] = CODE_FOR_nothing;
6414 sync_new_and_optab[i] = CODE_FOR_nothing;
6415 sync_new_xor_optab[i] = CODE_FOR_nothing;
6416 sync_new_nand_optab[i] = CODE_FOR_nothing;
6417 sync_compare_and_swap[i] = CODE_FOR_nothing;
6418 sync_lock_test_and_set[i] = CODE_FOR_nothing;
6419 sync_lock_release[i] = CODE_FOR_nothing;
6421 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
6424 /* Fill in the optabs with the insns we support. */
6425 init_all_optabs ();
6427 /* Initialize the optabs with the names of the library functions. */
6428 add_optab->libcall_basename = "add";
6429 add_optab->libcall_suffix = '3';
6430 add_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6431 addv_optab->libcall_basename = "add";
6432 addv_optab->libcall_suffix = '3';
6433 addv_optab->libcall_gen = gen_intv_fp_libfunc;
6434 ssadd_optab->libcall_basename = "ssadd";
6435 ssadd_optab->libcall_suffix = '3';
6436 ssadd_optab->libcall_gen = gen_signed_fixed_libfunc;
6437 usadd_optab->libcall_basename = "usadd";
6438 usadd_optab->libcall_suffix = '3';
6439 usadd_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6440 sub_optab->libcall_basename = "sub";
6441 sub_optab->libcall_suffix = '3';
6442 sub_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6443 subv_optab->libcall_basename = "sub";
6444 subv_optab->libcall_suffix = '3';
6445 subv_optab->libcall_gen = gen_intv_fp_libfunc;
6446 sssub_optab->libcall_basename = "sssub";
6447 sssub_optab->libcall_suffix = '3';
6448 sssub_optab->libcall_gen = gen_signed_fixed_libfunc;
6449 ussub_optab->libcall_basename = "ussub";
6450 ussub_optab->libcall_suffix = '3';
6451 ussub_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6452 smul_optab->libcall_basename = "mul";
6453 smul_optab->libcall_suffix = '3';
6454 smul_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6455 smulv_optab->libcall_basename = "mul";
6456 smulv_optab->libcall_suffix = '3';
6457 smulv_optab->libcall_gen = gen_intv_fp_libfunc;
6458 ssmul_optab->libcall_basename = "ssmul";
6459 ssmul_optab->libcall_suffix = '3';
6460 ssmul_optab->libcall_gen = gen_signed_fixed_libfunc;
6461 usmul_optab->libcall_basename = "usmul";
6462 usmul_optab->libcall_suffix = '3';
6463 usmul_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6464 sdiv_optab->libcall_basename = "div";
6465 sdiv_optab->libcall_suffix = '3';
6466 sdiv_optab->libcall_gen = gen_int_fp_signed_fixed_libfunc;
6467 sdivv_optab->libcall_basename = "divv";
6468 sdivv_optab->libcall_suffix = '3';
6469 sdivv_optab->libcall_gen = gen_int_libfunc;
6470 ssdiv_optab->libcall_basename = "ssdiv";
6471 ssdiv_optab->libcall_suffix = '3';
6472 ssdiv_optab->libcall_gen = gen_signed_fixed_libfunc;
6473 udiv_optab->libcall_basename = "udiv";
6474 udiv_optab->libcall_suffix = '3';
6475 udiv_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6476 usdiv_optab->libcall_basename = "usdiv";
6477 usdiv_optab->libcall_suffix = '3';
6478 usdiv_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6479 sdivmod_optab->libcall_basename = "divmod";
6480 sdivmod_optab->libcall_suffix = '4';
6481 sdivmod_optab->libcall_gen = gen_int_libfunc;
6482 udivmod_optab->libcall_basename = "udivmod";
6483 udivmod_optab->libcall_suffix = '4';
6484 udivmod_optab->libcall_gen = gen_int_libfunc;
6485 smod_optab->libcall_basename = "mod";
6486 smod_optab->libcall_suffix = '3';
6487 smod_optab->libcall_gen = gen_int_libfunc;
6488 umod_optab->libcall_basename = "umod";
6489 umod_optab->libcall_suffix = '3';
6490 umod_optab->libcall_gen = gen_int_libfunc;
6491 ftrunc_optab->libcall_basename = "ftrunc";
6492 ftrunc_optab->libcall_suffix = '2';
6493 ftrunc_optab->libcall_gen = gen_fp_libfunc;
6494 and_optab->libcall_basename = "and";
6495 and_optab->libcall_suffix = '3';
6496 and_optab->libcall_gen = gen_int_libfunc;
6497 ior_optab->libcall_basename = "ior";
6498 ior_optab->libcall_suffix = '3';
6499 ior_optab->libcall_gen = gen_int_libfunc;
6500 xor_optab->libcall_basename = "xor";
6501 xor_optab->libcall_suffix = '3';
6502 xor_optab->libcall_gen = gen_int_libfunc;
6503 ashl_optab->libcall_basename = "ashl";
6504 ashl_optab->libcall_suffix = '3';
6505 ashl_optab->libcall_gen = gen_int_fixed_libfunc;
6506 ssashl_optab->libcall_basename = "ssashl";
6507 ssashl_optab->libcall_suffix = '3';
6508 ssashl_optab->libcall_gen = gen_signed_fixed_libfunc;
6509 usashl_optab->libcall_basename = "usashl";
6510 usashl_optab->libcall_suffix = '3';
6511 usashl_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6512 ashr_optab->libcall_basename = "ashr";
6513 ashr_optab->libcall_suffix = '3';
6514 ashr_optab->libcall_gen = gen_int_signed_fixed_libfunc;
6515 lshr_optab->libcall_basename = "lshr";
6516 lshr_optab->libcall_suffix = '3';
6517 lshr_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6518 smin_optab->libcall_basename = "min";
6519 smin_optab->libcall_suffix = '3';
6520 smin_optab->libcall_gen = gen_int_fp_libfunc;
6521 smax_optab->libcall_basename = "max";
6522 smax_optab->libcall_suffix = '3';
6523 smax_optab->libcall_gen = gen_int_fp_libfunc;
6524 umin_optab->libcall_basename = "umin";
6525 umin_optab->libcall_suffix = '3';
6526 umin_optab->libcall_gen = gen_int_libfunc;
6527 umax_optab->libcall_basename = "umax";
6528 umax_optab->libcall_suffix = '3';
6529 umax_optab->libcall_gen = gen_int_libfunc;
6530 neg_optab->libcall_basename = "neg";
6531 neg_optab->libcall_suffix = '2';
6532 neg_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6533 ssneg_optab->libcall_basename = "ssneg";
6534 ssneg_optab->libcall_suffix = '2';
6535 ssneg_optab->libcall_gen = gen_signed_fixed_libfunc;
6536 usneg_optab->libcall_basename = "usneg";
6537 usneg_optab->libcall_suffix = '2';
6538 usneg_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6539 negv_optab->libcall_basename = "neg";
6540 negv_optab->libcall_suffix = '2';
6541 negv_optab->libcall_gen = gen_intv_fp_libfunc;
6542 one_cmpl_optab->libcall_basename = "one_cmpl";
6543 one_cmpl_optab->libcall_suffix = '2';
6544 one_cmpl_optab->libcall_gen = gen_int_libfunc;
6545 ffs_optab->libcall_basename = "ffs";
6546 ffs_optab->libcall_suffix = '2';
6547 ffs_optab->libcall_gen = gen_int_libfunc;
6548 clz_optab->libcall_basename = "clz";
6549 clz_optab->libcall_suffix = '2';
6550 clz_optab->libcall_gen = gen_int_libfunc;
6551 ctz_optab->libcall_basename = "ctz";
6552 ctz_optab->libcall_suffix = '2';
6553 ctz_optab->libcall_gen = gen_int_libfunc;
6554 popcount_optab->libcall_basename = "popcount";
6555 popcount_optab->libcall_suffix = '2';
6556 popcount_optab->libcall_gen = gen_int_libfunc;
6557 parity_optab->libcall_basename = "parity";
6558 parity_optab->libcall_suffix = '2';
6559 parity_optab->libcall_gen = gen_int_libfunc;
6561 /* Comparison libcalls for integers MUST come in pairs,
6562 signed/unsigned. */
6563 cmp_optab->libcall_basename = "cmp";
6564 cmp_optab->libcall_suffix = '2';
6565 cmp_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6566 ucmp_optab->libcall_basename = "ucmp";
6567 ucmp_optab->libcall_suffix = '2';
6568 ucmp_optab->libcall_gen = gen_int_libfunc;
6570 /* EQ etc are floating point only. */
6571 eq_optab->libcall_basename = "eq";
6572 eq_optab->libcall_suffix = '2';
6573 eq_optab->libcall_gen = gen_fp_libfunc;
6574 ne_optab->libcall_basename = "ne";
6575 ne_optab->libcall_suffix = '2';
6576 ne_optab->libcall_gen = gen_fp_libfunc;
6577 gt_optab->libcall_basename = "gt";
6578 gt_optab->libcall_suffix = '2';
6579 gt_optab->libcall_gen = gen_fp_libfunc;
6580 ge_optab->libcall_basename = "ge";
6581 ge_optab->libcall_suffix = '2';
6582 ge_optab->libcall_gen = gen_fp_libfunc;
6583 lt_optab->libcall_basename = "lt";
6584 lt_optab->libcall_suffix = '2';
6585 lt_optab->libcall_gen = gen_fp_libfunc;
6586 le_optab->libcall_basename = "le";
6587 le_optab->libcall_suffix = '2';
6588 le_optab->libcall_gen = gen_fp_libfunc;
6589 unord_optab->libcall_basename = "unord";
6590 unord_optab->libcall_suffix = '2';
6591 unord_optab->libcall_gen = gen_fp_libfunc;
6593 powi_optab->libcall_basename = "powi";
6594 powi_optab->libcall_suffix = '2';
6595 powi_optab->libcall_gen = gen_fp_libfunc;
6597 /* Conversions. */
6598 sfloat_optab->libcall_basename = "float";
6599 sfloat_optab->libcall_gen = gen_int_to_fp_conv_libfunc;
6600 ufloat_optab->libcall_gen = gen_ufloat_conv_libfunc;
6601 sfix_optab->libcall_basename = "fix";
6602 sfix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6603 ufix_optab->libcall_basename = "fixuns";
6604 ufix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6605 lrint_optab->libcall_basename = "lrint";
6606 lrint_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6607 lround_optab->libcall_basename = "lround";
6608 lround_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6609 lfloor_optab->libcall_basename = "lfloor";
6610 lfloor_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6611 lceil_optab->libcall_basename = "lceil";
6612 lceil_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6614 /* trunc_optab is also used for FLOAT_EXTEND. */
6615 sext_optab->libcall_basename = "extend";
6616 sext_optab->libcall_gen = gen_extend_conv_libfunc;
6617 trunc_optab->libcall_basename = "trunc";
6618 trunc_optab->libcall_gen = gen_trunc_conv_libfunc;
6620 /* Conversions for fixed-point modes and other modes. */
6621 fract_optab->libcall_basename = "fract";
6622 fract_optab->libcall_gen = gen_fract_conv_libfunc;
6623 satfract_optab->libcall_basename = "satfract";
6624 satfract_optab->libcall_gen = gen_satfract_conv_libfunc;
6625 fractuns_optab->libcall_basename = "fractuns";
6626 fractuns_optab->libcall_gen = gen_fractuns_conv_libfunc;
6627 satfractuns_optab->libcall_basename = "satfractuns";
6628 satfractuns_optab->libcall_gen = gen_satfractuns_conv_libfunc;
6630 /* The ffs function operates on `int'. Fall back on it if we do not
6631 have a libgcc2 function for that width. */
6632 if (INT_TYPE_SIZE < BITS_PER_WORD)
6633 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
6634 "ffs");
6636 /* Explicitly initialize the bswap libfuncs since we need them to be
6637 valid for things other than word_mode. */
6638 set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
6639 set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
6641 /* Use cabs for double complex abs, since systems generally have cabs.
6642 Don't define any libcall for float complex, so that cabs will be used. */
6643 if (complex_double_type_node)
6644 set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node), "cabs");
6646 abort_libfunc = init_one_libfunc ("abort");
6647 memcpy_libfunc = init_one_libfunc ("memcpy");
6648 memmove_libfunc = init_one_libfunc ("memmove");
6649 memcmp_libfunc = init_one_libfunc ("memcmp");
6650 memset_libfunc = init_one_libfunc ("memset");
6651 setbits_libfunc = init_one_libfunc ("__setbits");
6653 #ifndef DONT_USE_BUILTIN_SETJMP
6654 setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
6655 longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
6656 #else
6657 setjmp_libfunc = init_one_libfunc ("setjmp");
6658 longjmp_libfunc = init_one_libfunc ("longjmp");
6659 #endif
6660 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
6661 unwind_sjlj_unregister_libfunc
6662 = init_one_libfunc ("_Unwind_SjLj_Unregister");
6664 /* For function entry/exit instrumentation. */
6665 profile_function_entry_libfunc
6666 = init_one_libfunc ("__cyg_profile_func_enter");
6667 profile_function_exit_libfunc
6668 = init_one_libfunc ("__cyg_profile_func_exit");
6670 gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
6672 /* Allow the target to add more libcalls or rename some, etc. */
6673 targetm.init_libfuncs ();
6675 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
6676 reinit = true;
6677 #endif
6680 /* Print information about the current contents of the optabs on
6681 STDERR. */
6683 DEBUG_FUNCTION void
6684 debug_optab_libfuncs (void)
6686 int i;
6687 int j;
6688 int k;
6690 /* Dump the arithmetic optabs. */
6691 for (i = 0; i != (int) OTI_MAX; i++)
6692 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6694 optab o;
6695 rtx l;
6697 o = &optab_table[i];
6698 l = optab_libfunc (o, (enum machine_mode) j);
6699 if (l)
6701 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6702 fprintf (stderr, "%s\t%s:\t%s\n",
6703 GET_RTX_NAME (o->code),
6704 GET_MODE_NAME (j),
6705 XSTR (l, 0));
6709 /* Dump the conversion optabs. */
6710 for (i = 0; i < (int) COI_MAX; ++i)
6711 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6712 for (k = 0; k < NUM_MACHINE_MODES; ++k)
6714 convert_optab o;
6715 rtx l;
6717 o = &convert_optab_table[i];
6718 l = convert_optab_libfunc (o, (enum machine_mode) j,
6719 (enum machine_mode) k);
6720 if (l)
6722 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6723 fprintf (stderr, "%s\t%s\t%s:\t%s\n",
6724 GET_RTX_NAME (o->code),
6725 GET_MODE_NAME (j),
6726 GET_MODE_NAME (k),
6727 XSTR (l, 0));
6733 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
6734 CODE. Return 0 on failure. */
6737 gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
6739 enum machine_mode mode = GET_MODE (op1);
6740 enum insn_code icode;
6741 rtx insn;
6742 rtx trap_rtx;
6744 if (mode == VOIDmode)
6745 return 0;
6747 icode = optab_handler (ctrap_optab, mode)->insn_code;
6748 if (icode == CODE_FOR_nothing)
6749 return 0;
6751 /* Some targets only accept a zero trap code. */
6752 if (insn_data[icode].operand[3].predicate
6753 && !insn_data[icode].operand[3].predicate (tcode, VOIDmode))
6754 return 0;
6756 do_pending_stack_adjust ();
6757 start_sequence ();
6758 prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
6759 &trap_rtx, &mode);
6760 if (!trap_rtx)
6761 insn = NULL_RTX;
6762 else
6763 insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
6764 tcode);
6766 /* If that failed, then give up. */
6767 if (insn == 0)
6769 end_sequence ();
6770 return 0;
6773 emit_insn (insn);
6774 insn = get_insns ();
6775 end_sequence ();
6776 return insn;
6779 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
6780 or unsigned operation code. */
6782 static enum rtx_code
6783 get_rtx_code (enum tree_code tcode, bool unsignedp)
6785 enum rtx_code code;
6786 switch (tcode)
6788 case EQ_EXPR:
6789 code = EQ;
6790 break;
6791 case NE_EXPR:
6792 code = NE;
6793 break;
6794 case LT_EXPR:
6795 code = unsignedp ? LTU : LT;
6796 break;
6797 case LE_EXPR:
6798 code = unsignedp ? LEU : LE;
6799 break;
6800 case GT_EXPR:
6801 code = unsignedp ? GTU : GT;
6802 break;
6803 case GE_EXPR:
6804 code = unsignedp ? GEU : GE;
6805 break;
6807 case UNORDERED_EXPR:
6808 code = UNORDERED;
6809 break;
6810 case ORDERED_EXPR:
6811 code = ORDERED;
6812 break;
6813 case UNLT_EXPR:
6814 code = UNLT;
6815 break;
6816 case UNLE_EXPR:
6817 code = UNLE;
6818 break;
6819 case UNGT_EXPR:
6820 code = UNGT;
6821 break;
6822 case UNGE_EXPR:
6823 code = UNGE;
6824 break;
6825 case UNEQ_EXPR:
6826 code = UNEQ;
6827 break;
6828 case LTGT_EXPR:
6829 code = LTGT;
6830 break;
6832 default:
6833 gcc_unreachable ();
6835 return code;
6838 /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
6839 unsigned operators. Do not generate compare instruction. */
6841 static rtx
6842 vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
6844 enum rtx_code rcode;
6845 tree t_op0, t_op1;
6846 rtx rtx_op0, rtx_op1;
6848 /* This is unlikely. While generating VEC_COND_EXPR, auto vectorizer
6849 ensures that condition is a relational operation. */
6850 gcc_assert (COMPARISON_CLASS_P (cond));
6852 rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
6853 t_op0 = TREE_OPERAND (cond, 0);
6854 t_op1 = TREE_OPERAND (cond, 1);
6856 /* Expand operands. */
6857 rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
6858 EXPAND_STACK_PARM);
6859 rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
6860 EXPAND_STACK_PARM);
6862 if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
6863 && GET_MODE (rtx_op0) != VOIDmode)
6864 rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
6866 if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
6867 && GET_MODE (rtx_op1) != VOIDmode)
6868 rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
6870 return gen_rtx_fmt_ee (rcode, VOIDmode, rtx_op0, rtx_op1);
6873 /* Return insn code for TYPE, the type of a VEC_COND_EXPR. */
6875 static inline enum insn_code
6876 get_vcond_icode (tree type, enum machine_mode mode)
6878 enum insn_code icode = CODE_FOR_nothing;
6880 if (TYPE_UNSIGNED (type))
6881 icode = vcondu_gen_code[mode];
6882 else
6883 icode = vcond_gen_code[mode];
6884 return icode;
6887 /* Return TRUE iff, appropriate vector insns are available
6888 for vector cond expr with type TYPE in VMODE mode. */
6890 bool
6891 expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
6893 if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
6894 return false;
6895 return true;
6898 /* Generate insns for a VEC_COND_EXPR, given its TYPE and its
6899 three operands. */
6902 expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
6903 rtx target)
6905 enum insn_code icode;
6906 rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
6907 enum machine_mode mode = TYPE_MODE (vec_cond_type);
6908 bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
6910 icode = get_vcond_icode (vec_cond_type, mode);
6911 if (icode == CODE_FOR_nothing)
6912 return 0;
6914 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6915 target = gen_reg_rtx (mode);
6917 /* Get comparison rtx. First expand both cond expr operands. */
6918 comparison = vector_compare_rtx (op0,
6919 unsignedp, icode);
6920 cc_op0 = XEXP (comparison, 0);
6921 cc_op1 = XEXP (comparison, 1);
6922 /* Expand both operands and force them in reg, if required. */
6923 rtx_op1 = expand_normal (op1);
6924 if (!insn_data[icode].operand[1].predicate (rtx_op1, mode)
6925 && mode != VOIDmode)
6926 rtx_op1 = force_reg (mode, rtx_op1);
6928 rtx_op2 = expand_normal (op2);
6929 if (!insn_data[icode].operand[2].predicate (rtx_op2, mode)
6930 && mode != VOIDmode)
6931 rtx_op2 = force_reg (mode, rtx_op2);
6933 /* Emit instruction! */
6934 emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
6935 comparison, cc_op0, cc_op1));
6937 return target;
6941 /* This is an internal subroutine of the other compare_and_swap expanders.
6942 MEM, OLD_VAL and NEW_VAL are as you'd expect for a compare-and-swap
6943 operation. TARGET is an optional place to store the value result of
6944 the operation. ICODE is the particular instruction to expand. Return
6945 the result of the operation. */
6947 static rtx
6948 expand_val_compare_and_swap_1 (rtx mem, rtx old_val, rtx new_val,
6949 rtx target, enum insn_code icode)
6951 enum machine_mode mode = GET_MODE (mem);
6952 rtx insn;
6954 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6955 target = gen_reg_rtx (mode);
6957 if (GET_MODE (old_val) != VOIDmode && GET_MODE (old_val) != mode)
6958 old_val = convert_modes (mode, GET_MODE (old_val), old_val, 1);
6959 if (!insn_data[icode].operand[2].predicate (old_val, mode))
6960 old_val = force_reg (mode, old_val);
6962 if (GET_MODE (new_val) != VOIDmode && GET_MODE (new_val) != mode)
6963 new_val = convert_modes (mode, GET_MODE (new_val), new_val, 1);
6964 if (!insn_data[icode].operand[3].predicate (new_val, mode))
6965 new_val = force_reg (mode, new_val);
6967 insn = GEN_FCN (icode) (target, mem, old_val, new_val);
6968 if (insn == NULL_RTX)
6969 return NULL_RTX;
6970 emit_insn (insn);
6972 return target;
6975 /* Expand a compare-and-swap operation and return its value. */
6978 expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
6980 enum machine_mode mode = GET_MODE (mem);
6981 enum insn_code icode = sync_compare_and_swap[mode];
6983 if (icode == CODE_FOR_nothing)
6984 return NULL_RTX;
6986 return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode);
6989 /* Helper function to find the MODE_CC set in a sync_compare_and_swap
6990 pattern. */
6992 static void
6993 find_cc_set (rtx x, const_rtx pat, void *data)
6995 if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
6996 && GET_CODE (pat) == SET)
6998 rtx *p_cc_reg = (rtx *) data;
6999 gcc_assert (!*p_cc_reg);
7000 *p_cc_reg = x;
7004 /* Expand a compare-and-swap operation and store true into the result if
7005 the operation was successful and false otherwise. Return the result.
7006 Unlike other routines, TARGET is not optional. */
7009 expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
7011 enum machine_mode mode = GET_MODE (mem);
7012 enum insn_code icode;
7013 rtx subtarget, seq, cc_reg;
7015 /* If the target supports a compare-and-swap pattern that simultaneously
7016 sets some flag for success, then use it. Otherwise use the regular
7017 compare-and-swap and follow that immediately with a compare insn. */
7018 icode = sync_compare_and_swap[mode];
7019 if (icode == CODE_FOR_nothing)
7020 return NULL_RTX;
7024 start_sequence ();
7025 subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
7026 NULL_RTX, icode);
7027 cc_reg = NULL_RTX;
7028 if (subtarget == NULL_RTX)
7030 end_sequence ();
7031 return NULL_RTX;
7034 if (have_insn_for (COMPARE, CCmode))
7035 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
7036 seq = get_insns ();
7037 end_sequence ();
7039 /* We might be comparing against an old value. Try again. :-( */
7040 if (!cc_reg && MEM_P (old_val))
7042 seq = NULL_RTX;
7043 old_val = force_reg (mode, old_val);
7046 while (!seq);
7048 emit_insn (seq);
7049 if (cc_reg)
7050 return emit_store_flag_force (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1);
7051 else
7052 return emit_store_flag_force (target, EQ, subtarget, old_val, VOIDmode, 1, 1);
7055 /* This is a helper function for the other atomic operations. This function
7056 emits a loop that contains SEQ that iterates until a compare-and-swap
7057 operation at the end succeeds. MEM is the memory to be modified. SEQ is
7058 a set of instructions that takes a value from OLD_REG as an input and
7059 produces a value in NEW_REG as an output. Before SEQ, OLD_REG will be
7060 set to the current contents of MEM. After SEQ, a compare-and-swap will
7061 attempt to update MEM with NEW_REG. The function returns true when the
7062 loop was generated successfully. */
7064 static bool
7065 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
7067 enum machine_mode mode = GET_MODE (mem);
7068 enum insn_code icode;
7069 rtx label, cmp_reg, subtarget, cc_reg;
7071 /* The loop we want to generate looks like
7073 cmp_reg = mem;
7074 label:
7075 old_reg = cmp_reg;
7076 seq;
7077 cmp_reg = compare-and-swap(mem, old_reg, new_reg)
7078 if (cmp_reg != old_reg)
7079 goto label;
7081 Note that we only do the plain load from memory once. Subsequent
7082 iterations use the value loaded by the compare-and-swap pattern. */
7084 label = gen_label_rtx ();
7085 cmp_reg = gen_reg_rtx (mode);
7087 emit_move_insn (cmp_reg, mem);
7088 emit_label (label);
7089 emit_move_insn (old_reg, cmp_reg);
7090 if (seq)
7091 emit_insn (seq);
7093 /* If the target supports a compare-and-swap pattern that simultaneously
7094 sets some flag for success, then use it. Otherwise use the regular
7095 compare-and-swap and follow that immediately with a compare insn. */
7096 icode = sync_compare_and_swap[mode];
7097 if (icode == CODE_FOR_nothing)
7098 return false;
7100 subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
7101 cmp_reg, icode);
7102 if (subtarget == NULL_RTX)
7103 return false;
7105 cc_reg = NULL_RTX;
7106 if (have_insn_for (COMPARE, CCmode))
7107 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
7108 if (cc_reg)
7110 cmp_reg = cc_reg;
7111 old_reg = const0_rtx;
7113 else
7115 if (subtarget != cmp_reg)
7116 emit_move_insn (cmp_reg, subtarget);
7119 /* ??? Mark this jump predicted not taken? */
7120 emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, const0_rtx, GET_MODE (cmp_reg), 1,
7121 label);
7122 return true;
7125 /* This function generates the atomic operation MEM CODE= VAL. In this
7126 case, we do not care about any resulting value. Returns NULL if we
7127 cannot generate the operation. */
7130 expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
7132 enum machine_mode mode = GET_MODE (mem);
7133 enum insn_code icode;
7134 rtx insn;
7136 /* Look to see if the target supports the operation directly. */
7137 switch (code)
7139 case PLUS:
7140 icode = sync_add_optab[mode];
7141 break;
7142 case IOR:
7143 icode = sync_ior_optab[mode];
7144 break;
7145 case XOR:
7146 icode = sync_xor_optab[mode];
7147 break;
7148 case AND:
7149 icode = sync_and_optab[mode];
7150 break;
7151 case NOT:
7152 icode = sync_nand_optab[mode];
7153 break;
7155 case MINUS:
7156 icode = sync_sub_optab[mode];
7157 if (icode == CODE_FOR_nothing || CONST_INT_P (val))
7159 icode = sync_add_optab[mode];
7160 if (icode != CODE_FOR_nothing)
7162 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7163 code = PLUS;
7166 break;
7168 default:
7169 gcc_unreachable ();
7172 /* Generate the direct operation, if present. */
7173 if (icode != CODE_FOR_nothing)
7175 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7176 val = convert_modes (mode, GET_MODE (val), val, 1);
7177 if (!insn_data[icode].operand[1].predicate (val, mode))
7178 val = force_reg (mode, val);
7180 insn = GEN_FCN (icode) (mem, val);
7181 if (insn)
7183 emit_insn (insn);
7184 return const0_rtx;
7188 /* Failing that, generate a compare-and-swap loop in which we perform the
7189 operation with normal arithmetic instructions. */
7190 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7192 rtx t0 = gen_reg_rtx (mode), t1;
7194 start_sequence ();
7196 t1 = t0;
7197 if (code == NOT)
7199 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7200 true, OPTAB_LIB_WIDEN);
7201 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7203 else
7204 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7205 true, OPTAB_LIB_WIDEN);
7206 insn = get_insns ();
7207 end_sequence ();
7209 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7210 return const0_rtx;
7213 return NULL_RTX;
7216 /* This function generates the atomic operation MEM CODE= VAL. In this
7217 case, we do care about the resulting value: if AFTER is true then
7218 return the value MEM holds after the operation, if AFTER is false
7219 then return the value MEM holds before the operation. TARGET is an
7220 optional place for the result value to be stored. */
7223 expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
7224 bool after, rtx target)
7226 enum machine_mode mode = GET_MODE (mem);
7227 enum insn_code old_code, new_code, icode;
7228 bool compensate;
7229 rtx insn;
7231 /* Look to see if the target supports the operation directly. */
7232 switch (code)
7234 case PLUS:
7235 old_code = sync_old_add_optab[mode];
7236 new_code = sync_new_add_optab[mode];
7237 break;
7238 case IOR:
7239 old_code = sync_old_ior_optab[mode];
7240 new_code = sync_new_ior_optab[mode];
7241 break;
7242 case XOR:
7243 old_code = sync_old_xor_optab[mode];
7244 new_code = sync_new_xor_optab[mode];
7245 break;
7246 case AND:
7247 old_code = sync_old_and_optab[mode];
7248 new_code = sync_new_and_optab[mode];
7249 break;
7250 case NOT:
7251 old_code = sync_old_nand_optab[mode];
7252 new_code = sync_new_nand_optab[mode];
7253 break;
7255 case MINUS:
7256 old_code = sync_old_sub_optab[mode];
7257 new_code = sync_new_sub_optab[mode];
7258 if ((old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
7259 || CONST_INT_P (val))
7261 old_code = sync_old_add_optab[mode];
7262 new_code = sync_new_add_optab[mode];
7263 if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
7265 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7266 code = PLUS;
7269 break;
7271 default:
7272 gcc_unreachable ();
7275 /* If the target does supports the proper new/old operation, great. But
7276 if we only support the opposite old/new operation, check to see if we
7277 can compensate. In the case in which the old value is supported, then
7278 we can always perform the operation again with normal arithmetic. In
7279 the case in which the new value is supported, then we can only handle
7280 this in the case the operation is reversible. */
7281 compensate = false;
7282 if (after)
7284 icode = new_code;
7285 if (icode == CODE_FOR_nothing)
7287 icode = old_code;
7288 if (icode != CODE_FOR_nothing)
7289 compensate = true;
7292 else
7294 icode = old_code;
7295 if (icode == CODE_FOR_nothing
7296 && (code == PLUS || code == MINUS || code == XOR))
7298 icode = new_code;
7299 if (icode != CODE_FOR_nothing)
7300 compensate = true;
7304 /* If we found something supported, great. */
7305 if (icode != CODE_FOR_nothing)
7307 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7308 target = gen_reg_rtx (mode);
7310 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7311 val = convert_modes (mode, GET_MODE (val), val, 1);
7312 if (!insn_data[icode].operand[2].predicate (val, mode))
7313 val = force_reg (mode, val);
7315 insn = GEN_FCN (icode) (target, mem, val);
7316 if (insn)
7318 emit_insn (insn);
7320 /* If we need to compensate for using an operation with the
7321 wrong return value, do so now. */
7322 if (compensate)
7324 if (!after)
7326 if (code == PLUS)
7327 code = MINUS;
7328 else if (code == MINUS)
7329 code = PLUS;
7332 if (code == NOT)
7334 target = expand_simple_binop (mode, AND, target, val,
7335 NULL_RTX, true,
7336 OPTAB_LIB_WIDEN);
7337 target = expand_simple_unop (mode, code, target,
7338 NULL_RTX, true);
7340 else
7341 target = expand_simple_binop (mode, code, target, val,
7342 NULL_RTX, true,
7343 OPTAB_LIB_WIDEN);
7346 return target;
7350 /* Failing that, generate a compare-and-swap loop in which we perform the
7351 operation with normal arithmetic instructions. */
7352 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7354 rtx t0 = gen_reg_rtx (mode), t1;
7356 if (!target || !register_operand (target, mode))
7357 target = gen_reg_rtx (mode);
7359 start_sequence ();
7361 if (!after)
7362 emit_move_insn (target, t0);
7363 t1 = t0;
7364 if (code == NOT)
7366 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7367 true, OPTAB_LIB_WIDEN);
7368 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7370 else
7371 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7372 true, OPTAB_LIB_WIDEN);
7373 if (after)
7374 emit_move_insn (target, t1);
7376 insn = get_insns ();
7377 end_sequence ();
7379 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7380 return target;
7383 return NULL_RTX;
7386 /* This function expands a test-and-set operation. Ideally we atomically
7387 store VAL in MEM and return the previous value in MEM. Some targets
7388 may not support this operation and only support VAL with the constant 1;
7389 in this case while the return value will be 0/1, but the exact value
7390 stored in MEM is target defined. TARGET is an option place to stick
7391 the return value. */
7394 expand_sync_lock_test_and_set (rtx mem, rtx val, rtx target)
7396 enum machine_mode mode = GET_MODE (mem);
7397 enum insn_code icode;
7398 rtx insn;
7400 /* If the target supports the test-and-set directly, great. */
7401 icode = sync_lock_test_and_set[mode];
7402 if (icode != CODE_FOR_nothing)
7404 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7405 target = gen_reg_rtx (mode);
7407 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7408 val = convert_modes (mode, GET_MODE (val), val, 1);
7409 if (!insn_data[icode].operand[2].predicate (val, mode))
7410 val = force_reg (mode, val);
7412 insn = GEN_FCN (icode) (target, mem, val);
7413 if (insn)
7415 emit_insn (insn);
7416 return target;
7420 /* Otherwise, use a compare-and-swap loop for the exchange. */
7421 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7423 if (!target || !register_operand (target, mode))
7424 target = gen_reg_rtx (mode);
7425 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7426 val = convert_modes (mode, GET_MODE (val), val, 1);
7427 if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
7428 return target;
7431 return NULL_RTX;
7434 #include "gt-optabs.h"