* gcc.target/powerpc/altivec-volatile.c: Adjust expected warning.
[official-gcc.git] / gcc / optabs.c
blob1b1a8699eaaabc467dca0f04b2d4dd7d022070d9
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 struct optab_d optab_table[OTI_MAX];
58 rtx libfunc_table[LTI_MAX];
60 /* Tables of patterns for converting one mode to another. */
61 struct convert_optab_d convert_optab_table[COI_MAX];
63 /* Tables of patterns for direct optabs (i.e. those which cannot be
64 implemented using a libcall). */
65 struct direct_optab_d direct_optab_table[(int) DOI_MAX];
67 /* Contains the optab used for each rtx code. */
68 optab code_to_optab[NUM_RTX_CODE + 1];
70 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
71 enum machine_mode *);
72 static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
74 /* Debug facility for use in GDB. */
75 void debug_optab_libfuncs (void);
77 /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
78 #if ENABLE_DECIMAL_BID_FORMAT
79 #define DECIMAL_PREFIX "bid_"
80 #else
81 #define DECIMAL_PREFIX "dpd_"
82 #endif
85 /* Info about libfunc. We use same hashtable for normal optabs and conversion
86 optab. In the first case mode2 is unused. */
87 struct GTY(()) libfunc_entry {
88 size_t optab;
89 enum machine_mode mode1, mode2;
90 rtx libfunc;
93 /* Hash table used to convert declarations into nodes. */
94 static GTY((param_is (struct libfunc_entry))) htab_t libfunc_hash;
96 /* Used for attribute_hash. */
98 static hashval_t
99 hash_libfunc (const void *p)
101 const struct libfunc_entry *const e = (const struct libfunc_entry *) p;
103 return (((int) e->mode1 + (int) e->mode2 * NUM_MACHINE_MODES)
104 ^ e->optab);
107 /* Used for optab_hash. */
109 static int
110 eq_libfunc (const void *p, const void *q)
112 const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p;
113 const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q;
115 return (e1->optab == e2->optab
116 && e1->mode1 == e2->mode1
117 && e1->mode2 == e2->mode2);
120 /* Return libfunc corresponding operation defined by OPTAB converting
121 from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL
122 if no libfunc is available. */
124 convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
125 enum machine_mode mode2)
127 struct libfunc_entry e;
128 struct libfunc_entry **slot;
130 e.optab = (size_t) (optab - &convert_optab_table[0]);
131 e.mode1 = mode1;
132 e.mode2 = mode2;
133 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
134 if (!slot)
136 if (optab->libcall_gen)
138 optab->libcall_gen (optab, optab->libcall_basename, mode1, mode2);
139 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
140 if (slot)
141 return (*slot)->libfunc;
142 else
143 return NULL;
145 return NULL;
147 return (*slot)->libfunc;
150 /* Return libfunc corresponding operation defined by OPTAB in MODE.
151 Trigger lazy initialization if needed, return NULL if no libfunc is
152 available. */
154 optab_libfunc (optab optab, enum machine_mode mode)
156 struct libfunc_entry e;
157 struct libfunc_entry **slot;
159 e.optab = (size_t) (optab - &optab_table[0]);
160 e.mode1 = mode;
161 e.mode2 = VOIDmode;
162 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
163 if (!slot)
165 if (optab->libcall_gen)
167 optab->libcall_gen (optab, optab->libcall_basename,
168 optab->libcall_suffix, mode);
169 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash,
170 &e, NO_INSERT);
171 if (slot)
172 return (*slot)->libfunc;
173 else
174 return NULL;
176 return NULL;
178 return (*slot)->libfunc;
182 /* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
183 the result of operation CODE applied to OP0 (and OP1 if it is a binary
184 operation).
186 If the last insn does not set TARGET, don't do anything, but return 1.
188 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
189 don't add the REG_EQUAL note but return 0. Our caller can then try
190 again, ensuring that TARGET is not one of the operands. */
192 static int
193 add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
195 rtx last_insn, insn, set;
196 rtx note;
198 gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
200 if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
201 && GET_RTX_CLASS (code) != RTX_BIN_ARITH
202 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
203 && GET_RTX_CLASS (code) != RTX_COMPARE
204 && GET_RTX_CLASS (code) != RTX_UNARY)
205 return 1;
207 if (GET_CODE (target) == ZERO_EXTRACT)
208 return 1;
210 for (last_insn = insns;
211 NEXT_INSN (last_insn) != NULL_RTX;
212 last_insn = NEXT_INSN (last_insn))
215 set = single_set (last_insn);
216 if (set == NULL_RTX)
217 return 1;
219 if (! rtx_equal_p (SET_DEST (set), target)
220 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it. */
221 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
222 || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
223 return 1;
225 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
226 besides the last insn. */
227 if (reg_overlap_mentioned_p (target, op0)
228 || (op1 && reg_overlap_mentioned_p (target, op1)))
230 insn = PREV_INSN (last_insn);
231 while (insn != NULL_RTX)
233 if (reg_set_p (target, insn))
234 return 0;
236 insn = PREV_INSN (insn);
240 if (GET_RTX_CLASS (code) == RTX_UNARY)
241 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
242 else
243 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
245 set_unique_reg_note (last_insn, REG_EQUAL, note);
247 return 1;
250 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
251 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
252 not actually do a sign-extend or zero-extend, but can leave the
253 higher-order bits of the result rtx undefined, for example, in the case
254 of logical operations, but not right shifts. */
256 static rtx
257 widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
258 int unsignedp, int no_extend)
260 rtx result;
262 /* If we don't have to extend and this is a constant, return it. */
263 if (no_extend && GET_MODE (op) == VOIDmode)
264 return op;
266 /* If we must extend do so. If OP is a SUBREG for a promoted object, also
267 extend since it will be more efficient to do so unless the signedness of
268 a promoted object differs from our extension. */
269 if (! no_extend
270 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
271 && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
272 return convert_modes (mode, oldmode, op, unsignedp);
274 /* If MODE is no wider than a single word, we return a paradoxical
275 SUBREG. */
276 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
277 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
279 /* Otherwise, get an object of MODE, clobber it, and set the low-order
280 part to OP. */
282 result = gen_reg_rtx (mode);
283 emit_clobber (result);
284 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
285 return result;
288 /* Return the optab used for computing the operation given by the tree code,
289 CODE and the tree EXP. This function is not always usable (for example, it
290 cannot give complete results for multiplication or division) but probably
291 ought to be relied on more widely throughout the expander. */
292 optab
293 optab_for_tree_code (enum tree_code code, const_tree type,
294 enum optab_subtype subtype)
296 bool trapv;
297 switch (code)
299 case BIT_AND_EXPR:
300 return and_optab;
302 case BIT_IOR_EXPR:
303 return ior_optab;
305 case BIT_NOT_EXPR:
306 return one_cmpl_optab;
308 case BIT_XOR_EXPR:
309 return xor_optab;
311 case TRUNC_MOD_EXPR:
312 case CEIL_MOD_EXPR:
313 case FLOOR_MOD_EXPR:
314 case ROUND_MOD_EXPR:
315 return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
317 case RDIV_EXPR:
318 case TRUNC_DIV_EXPR:
319 case CEIL_DIV_EXPR:
320 case FLOOR_DIV_EXPR:
321 case ROUND_DIV_EXPR:
322 case EXACT_DIV_EXPR:
323 if (TYPE_SATURATING(type))
324 return TYPE_UNSIGNED(type) ? usdiv_optab : ssdiv_optab;
325 return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
327 case LSHIFT_EXPR:
328 if (VECTOR_MODE_P (TYPE_MODE (type)))
330 if (subtype == optab_vector)
331 return TYPE_SATURATING (type) ? NULL : vashl_optab;
333 gcc_assert (subtype == optab_scalar);
335 if (TYPE_SATURATING(type))
336 return TYPE_UNSIGNED(type) ? usashl_optab : ssashl_optab;
337 return ashl_optab;
339 case RSHIFT_EXPR:
340 if (VECTOR_MODE_P (TYPE_MODE (type)))
342 if (subtype == optab_vector)
343 return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
345 gcc_assert (subtype == optab_scalar);
347 return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
349 case LROTATE_EXPR:
350 if (VECTOR_MODE_P (TYPE_MODE (type)))
352 if (subtype == optab_vector)
353 return vrotl_optab;
355 gcc_assert (subtype == optab_scalar);
357 return rotl_optab;
359 case RROTATE_EXPR:
360 if (VECTOR_MODE_P (TYPE_MODE (type)))
362 if (subtype == optab_vector)
363 return vrotr_optab;
365 gcc_assert (subtype == optab_scalar);
367 return rotr_optab;
369 case MAX_EXPR:
370 return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
372 case MIN_EXPR:
373 return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
375 case REALIGN_LOAD_EXPR:
376 return vec_realign_load_optab;
378 case WIDEN_SUM_EXPR:
379 return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
381 case DOT_PROD_EXPR:
382 return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
384 case WIDEN_MULT_PLUS_EXPR:
385 return (TYPE_UNSIGNED (type)
386 ? (TYPE_SATURATING (type)
387 ? usmadd_widen_optab : umadd_widen_optab)
388 : (TYPE_SATURATING (type)
389 ? ssmadd_widen_optab : smadd_widen_optab));
391 case WIDEN_MULT_MINUS_EXPR:
392 return (TYPE_UNSIGNED (type)
393 ? (TYPE_SATURATING (type)
394 ? usmsub_widen_optab : umsub_widen_optab)
395 : (TYPE_SATURATING (type)
396 ? ssmsub_widen_optab : smsub_widen_optab));
398 case REDUC_MAX_EXPR:
399 return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab;
401 case REDUC_MIN_EXPR:
402 return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab;
404 case REDUC_PLUS_EXPR:
405 return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
407 case VEC_LSHIFT_EXPR:
408 return vec_shl_optab;
410 case VEC_RSHIFT_EXPR:
411 return vec_shr_optab;
413 case VEC_WIDEN_MULT_HI_EXPR:
414 return TYPE_UNSIGNED (type) ?
415 vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
417 case VEC_WIDEN_MULT_LO_EXPR:
418 return TYPE_UNSIGNED (type) ?
419 vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
421 case VEC_UNPACK_HI_EXPR:
422 return TYPE_UNSIGNED (type) ?
423 vec_unpacku_hi_optab : vec_unpacks_hi_optab;
425 case VEC_UNPACK_LO_EXPR:
426 return TYPE_UNSIGNED (type) ?
427 vec_unpacku_lo_optab : vec_unpacks_lo_optab;
429 case VEC_UNPACK_FLOAT_HI_EXPR:
430 /* The signedness is determined from input operand. */
431 return TYPE_UNSIGNED (type) ?
432 vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
434 case VEC_UNPACK_FLOAT_LO_EXPR:
435 /* The signedness is determined from input operand. */
436 return TYPE_UNSIGNED (type) ?
437 vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
439 case VEC_PACK_TRUNC_EXPR:
440 return vec_pack_trunc_optab;
442 case VEC_PACK_SAT_EXPR:
443 return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
445 case VEC_PACK_FIX_TRUNC_EXPR:
446 /* The signedness is determined from output operand. */
447 return TYPE_UNSIGNED (type) ?
448 vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
450 default:
451 break;
454 trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
455 switch (code)
457 case POINTER_PLUS_EXPR:
458 case PLUS_EXPR:
459 if (TYPE_SATURATING(type))
460 return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
461 return trapv ? addv_optab : add_optab;
463 case MINUS_EXPR:
464 if (TYPE_SATURATING(type))
465 return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
466 return trapv ? subv_optab : sub_optab;
468 case MULT_EXPR:
469 if (TYPE_SATURATING(type))
470 return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
471 return trapv ? smulv_optab : smul_optab;
473 case NEGATE_EXPR:
474 if (TYPE_SATURATING(type))
475 return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
476 return trapv ? negv_optab : neg_optab;
478 case ABS_EXPR:
479 return trapv ? absv_optab : abs_optab;
481 case VEC_EXTRACT_EVEN_EXPR:
482 return vec_extract_even_optab;
484 case VEC_EXTRACT_ODD_EXPR:
485 return vec_extract_odd_optab;
487 case VEC_INTERLEAVE_HIGH_EXPR:
488 return vec_interleave_high_optab;
490 case VEC_INTERLEAVE_LOW_EXPR:
491 return vec_interleave_low_optab;
493 default:
494 return NULL;
499 /* Expand vector widening operations.
501 There are two different classes of operations handled here:
502 1) Operations whose result is wider than all the arguments to the operation.
503 Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR
504 In this case OP0 and optionally OP1 would be initialized,
505 but WIDE_OP wouldn't (not relevant for this case).
506 2) Operations whose result is of the same size as the last argument to the
507 operation, but wider than all the other arguments to the operation.
508 Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR.
509 In the case WIDE_OP, OP0 and optionally OP1 would be initialized.
511 E.g, when called to expand the following operations, this is how
512 the arguments will be initialized:
513 nops OP0 OP1 WIDE_OP
514 widening-sum 2 oprnd0 - oprnd1
515 widening-dot-product 3 oprnd0 oprnd1 oprnd2
516 widening-mult 2 oprnd0 oprnd1 -
517 type-promotion (vec-unpack) 1 oprnd0 - - */
520 expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
521 rtx target, int unsignedp)
523 tree oprnd0, oprnd1, oprnd2;
524 enum machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
525 optab widen_pattern_optab;
526 int icode;
527 enum machine_mode xmode0, xmode1 = VOIDmode, wxmode = VOIDmode;
528 rtx temp;
529 rtx pat;
530 rtx xop0, xop1, wxop;
531 int nops = TREE_CODE_LENGTH (ops->code);
533 oprnd0 = ops->op0;
534 tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
535 widen_pattern_optab =
536 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
537 if (ops->code == WIDEN_MULT_PLUS_EXPR
538 || ops->code == WIDEN_MULT_MINUS_EXPR)
539 icode = (int) optab_handler (widen_pattern_optab,
540 TYPE_MODE (TREE_TYPE (ops->op2)));
541 else
542 icode = (int) optab_handler (widen_pattern_optab, tmode0);
543 gcc_assert (icode != CODE_FOR_nothing);
544 xmode0 = insn_data[icode].operand[1].mode;
546 if (nops >= 2)
548 oprnd1 = ops->op1;
549 tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
550 xmode1 = insn_data[icode].operand[2].mode;
553 /* The last operand is of a wider mode than the rest of the operands. */
554 if (nops == 2)
556 wmode = tmode1;
557 wxmode = xmode1;
559 else if (nops == 3)
561 gcc_assert (tmode1 == tmode0);
562 gcc_assert (op1);
563 oprnd2 = ops->op2;
564 wmode = TYPE_MODE (TREE_TYPE (oprnd2));
565 wxmode = insn_data[icode].operand[3].mode;
568 if (!wide_op)
569 wmode = wxmode = insn_data[icode].operand[0].mode;
571 if (!target
572 || ! (*insn_data[icode].operand[0].predicate) (target, wmode))
573 temp = gen_reg_rtx (wmode);
574 else
575 temp = target;
577 xop0 = op0;
578 xop1 = op1;
579 wxop = wide_op;
581 /* In case the insn wants input operands in modes different from
582 those of the actual operands, convert the operands. It would
583 seem that we don't need to convert CONST_INTs, but we do, so
584 that they're properly zero-extended, sign-extended or truncated
585 for their mode. */
587 if (GET_MODE (op0) != xmode0 && xmode0 != VOIDmode)
588 xop0 = convert_modes (xmode0,
589 GET_MODE (op0) != VOIDmode
590 ? GET_MODE (op0)
591 : tmode0,
592 xop0, unsignedp);
594 if (op1)
595 if (GET_MODE (op1) != xmode1 && xmode1 != VOIDmode)
596 xop1 = convert_modes (xmode1,
597 GET_MODE (op1) != VOIDmode
598 ? GET_MODE (op1)
599 : tmode1,
600 xop1, unsignedp);
602 if (wide_op)
603 if (GET_MODE (wide_op) != wxmode && wxmode != VOIDmode)
604 wxop = convert_modes (wxmode,
605 GET_MODE (wide_op) != VOIDmode
606 ? GET_MODE (wide_op)
607 : wmode,
608 wxop, unsignedp);
610 /* Now, if insn's predicates don't allow our operands, put them into
611 pseudo regs. */
613 if (! (*insn_data[icode].operand[1].predicate) (xop0, xmode0)
614 && xmode0 != VOIDmode)
615 xop0 = copy_to_mode_reg (xmode0, xop0);
617 if (op1)
619 if (! (*insn_data[icode].operand[2].predicate) (xop1, xmode1)
620 && xmode1 != VOIDmode)
621 xop1 = copy_to_mode_reg (xmode1, xop1);
623 if (wide_op)
625 if (! (*insn_data[icode].operand[3].predicate) (wxop, wxmode)
626 && wxmode != VOIDmode)
627 wxop = copy_to_mode_reg (wxmode, wxop);
629 pat = GEN_FCN (icode) (temp, xop0, xop1, wxop);
631 else
632 pat = GEN_FCN (icode) (temp, xop0, xop1);
634 else
636 if (wide_op)
638 if (! (*insn_data[icode].operand[2].predicate) (wxop, wxmode)
639 && wxmode != VOIDmode)
640 wxop = copy_to_mode_reg (wxmode, wxop);
642 pat = GEN_FCN (icode) (temp, xop0, wxop);
644 else
645 pat = GEN_FCN (icode) (temp, xop0);
648 emit_insn (pat);
649 return temp;
652 /* Generate code to perform an operation specified by TERNARY_OPTAB
653 on operands OP0, OP1 and OP2, with result having machine-mode MODE.
655 UNSIGNEDP is for the case where we have to widen the operands
656 to perform the operation. It says to use zero-extension.
658 If TARGET is nonzero, the value
659 is generated there, if it is convenient to do so.
660 In all cases an rtx is returned for the locus of the value;
661 this may or may not be TARGET. */
664 expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
665 rtx op1, rtx op2, rtx target, int unsignedp)
667 int icode = (int) optab_handler (ternary_optab, mode);
668 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
669 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
670 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
671 rtx temp;
672 rtx pat;
673 rtx xop0 = op0, xop1 = op1, xop2 = op2;
675 gcc_assert (optab_handler (ternary_optab, mode) != CODE_FOR_nothing);
677 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
678 temp = gen_reg_rtx (mode);
679 else
680 temp = target;
682 /* In case the insn wants input operands in modes different from
683 those of the actual operands, convert the operands. It would
684 seem that we don't need to convert CONST_INTs, but we do, so
685 that they're properly zero-extended, sign-extended or truncated
686 for their mode. */
688 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
689 xop0 = convert_modes (mode0,
690 GET_MODE (op0) != VOIDmode
691 ? GET_MODE (op0)
692 : mode,
693 xop0, unsignedp);
695 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
696 xop1 = convert_modes (mode1,
697 GET_MODE (op1) != VOIDmode
698 ? GET_MODE (op1)
699 : mode,
700 xop1, unsignedp);
702 if (GET_MODE (op2) != mode2 && mode2 != VOIDmode)
703 xop2 = convert_modes (mode2,
704 GET_MODE (op2) != VOIDmode
705 ? GET_MODE (op2)
706 : mode,
707 xop2, unsignedp);
709 /* Now, if insn's predicates don't allow our operands, put them into
710 pseudo regs. */
712 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
713 && mode0 != VOIDmode)
714 xop0 = copy_to_mode_reg (mode0, xop0);
716 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
717 && mode1 != VOIDmode)
718 xop1 = copy_to_mode_reg (mode1, xop1);
720 if (!insn_data[icode].operand[3].predicate (xop2, mode2)
721 && mode2 != VOIDmode)
722 xop2 = copy_to_mode_reg (mode2, xop2);
724 pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
726 emit_insn (pat);
727 return temp;
731 /* Like expand_binop, but return a constant rtx if the result can be
732 calculated at compile time. The arguments and return value are
733 otherwise the same as for expand_binop. */
735 static rtx
736 simplify_expand_binop (enum machine_mode mode, optab binoptab,
737 rtx op0, rtx op1, rtx target, int unsignedp,
738 enum optab_methods methods)
740 if (CONSTANT_P (op0) && CONSTANT_P (op1))
742 rtx x = simplify_binary_operation (binoptab->code, mode, op0, op1);
744 if (x)
745 return x;
748 return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
751 /* Like simplify_expand_binop, but always put the result in TARGET.
752 Return true if the expansion succeeded. */
754 bool
755 force_expand_binop (enum machine_mode mode, optab binoptab,
756 rtx op0, rtx op1, rtx target, int unsignedp,
757 enum optab_methods methods)
759 rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
760 target, unsignedp, methods);
761 if (x == 0)
762 return false;
763 if (x != target)
764 emit_move_insn (target, x);
765 return true;
768 /* Generate insns for VEC_LSHIFT_EXPR, VEC_RSHIFT_EXPR. */
771 expand_vec_shift_expr (sepops ops, rtx target)
773 enum insn_code icode;
774 rtx rtx_op1, rtx_op2;
775 enum machine_mode mode1;
776 enum machine_mode mode2;
777 enum machine_mode mode = TYPE_MODE (ops->type);
778 tree vec_oprnd = ops->op0;
779 tree shift_oprnd = ops->op1;
780 optab shift_optab;
781 rtx pat;
783 switch (ops->code)
785 case VEC_RSHIFT_EXPR:
786 shift_optab = vec_shr_optab;
787 break;
788 case VEC_LSHIFT_EXPR:
789 shift_optab = vec_shl_optab;
790 break;
791 default:
792 gcc_unreachable ();
795 icode = optab_handler (shift_optab, mode);
796 gcc_assert (icode != CODE_FOR_nothing);
798 mode1 = insn_data[icode].operand[1].mode;
799 mode2 = insn_data[icode].operand[2].mode;
801 rtx_op1 = expand_normal (vec_oprnd);
802 if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode1)
803 && mode1 != VOIDmode)
804 rtx_op1 = force_reg (mode1, rtx_op1);
806 rtx_op2 = expand_normal (shift_oprnd);
807 if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode2)
808 && mode2 != VOIDmode)
809 rtx_op2 = force_reg (mode2, rtx_op2);
811 if (!target
812 || ! (*insn_data[icode].operand[0].predicate) (target, mode))
813 target = gen_reg_rtx (mode);
815 /* Emit instruction */
816 pat = GEN_FCN (icode) (target, rtx_op1, rtx_op2);
817 gcc_assert (pat);
818 emit_insn (pat);
820 return target;
823 /* This subroutine of expand_doubleword_shift handles the cases in which
824 the effective shift value is >= BITS_PER_WORD. The arguments and return
825 value are the same as for the parent routine, except that SUPERWORD_OP1
826 is the shift count to use when shifting OUTOF_INPUT into INTO_TARGET.
827 INTO_TARGET may be null if the caller has decided to calculate it. */
829 static bool
830 expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
831 rtx outof_target, rtx into_target,
832 int unsignedp, enum optab_methods methods)
834 if (into_target != 0)
835 if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
836 into_target, unsignedp, methods))
837 return false;
839 if (outof_target != 0)
841 /* For a signed right shift, we must fill OUTOF_TARGET with copies
842 of the sign bit, otherwise we must fill it with zeros. */
843 if (binoptab != ashr_optab)
844 emit_move_insn (outof_target, CONST0_RTX (word_mode));
845 else
846 if (!force_expand_binop (word_mode, binoptab,
847 outof_input, GEN_INT (BITS_PER_WORD - 1),
848 outof_target, unsignedp, methods))
849 return false;
851 return true;
854 /* This subroutine of expand_doubleword_shift handles the cases in which
855 the effective shift value is < BITS_PER_WORD. The arguments and return
856 value are the same as for the parent routine. */
858 static bool
859 expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
860 rtx outof_input, rtx into_input, rtx op1,
861 rtx outof_target, rtx into_target,
862 int unsignedp, enum optab_methods methods,
863 unsigned HOST_WIDE_INT shift_mask)
865 optab reverse_unsigned_shift, unsigned_shift;
866 rtx tmp, carries;
868 reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
869 unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
871 /* The low OP1 bits of INTO_TARGET come from the high bits of OUTOF_INPUT.
872 We therefore need to shift OUTOF_INPUT by (BITS_PER_WORD - OP1) bits in
873 the opposite direction to BINOPTAB. */
874 if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
876 carries = outof_input;
877 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
878 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
879 0, true, methods);
881 else
883 /* We must avoid shifting by BITS_PER_WORD bits since that is either
884 the same as a zero shift (if shift_mask == BITS_PER_WORD - 1) or
885 has unknown behavior. Do a single shift first, then shift by the
886 remainder. It's OK to use ~OP1 as the remainder if shift counts
887 are truncated to the mode size. */
888 carries = expand_binop (word_mode, reverse_unsigned_shift,
889 outof_input, const1_rtx, 0, unsignedp, methods);
890 if (shift_mask == BITS_PER_WORD - 1)
892 tmp = immed_double_const (-1, -1, op1_mode);
893 tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
894 0, true, methods);
896 else
898 tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode);
899 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
900 0, true, methods);
903 if (tmp == 0 || carries == 0)
904 return false;
905 carries = expand_binop (word_mode, reverse_unsigned_shift,
906 carries, tmp, 0, unsignedp, methods);
907 if (carries == 0)
908 return false;
910 /* Shift INTO_INPUT logically by OP1. This is the last use of INTO_INPUT
911 so the result can go directly into INTO_TARGET if convenient. */
912 tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
913 into_target, unsignedp, methods);
914 if (tmp == 0)
915 return false;
917 /* Now OR in the bits carried over from OUTOF_INPUT. */
918 if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
919 into_target, unsignedp, methods))
920 return false;
922 /* Use a standard word_mode shift for the out-of half. */
923 if (outof_target != 0)
924 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
925 outof_target, unsignedp, methods))
926 return false;
928 return true;
932 #ifdef HAVE_conditional_move
933 /* Try implementing expand_doubleword_shift using conditional moves.
934 The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
935 otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1
936 are the shift counts to use in the former and latter case. All other
937 arguments are the same as the parent routine. */
939 static bool
940 expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
941 enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
942 rtx outof_input, rtx into_input,
943 rtx subword_op1, rtx superword_op1,
944 rtx outof_target, rtx into_target,
945 int unsignedp, enum optab_methods methods,
946 unsigned HOST_WIDE_INT shift_mask)
948 rtx outof_superword, into_superword;
950 /* Put the superword version of the output into OUTOF_SUPERWORD and
951 INTO_SUPERWORD. */
952 outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
953 if (outof_target != 0 && subword_op1 == superword_op1)
955 /* The value INTO_TARGET >> SUBWORD_OP1, which we later store in
956 OUTOF_TARGET, is the same as the value of INTO_SUPERWORD. */
957 into_superword = outof_target;
958 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
959 outof_superword, 0, unsignedp, methods))
960 return false;
962 else
964 into_superword = gen_reg_rtx (word_mode);
965 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
966 outof_superword, into_superword,
967 unsignedp, methods))
968 return false;
971 /* Put the subword version directly in OUTOF_TARGET and INTO_TARGET. */
972 if (!expand_subword_shift (op1_mode, binoptab,
973 outof_input, into_input, subword_op1,
974 outof_target, into_target,
975 unsignedp, methods, shift_mask))
976 return false;
978 /* Select between them. Do the INTO half first because INTO_SUPERWORD
979 might be the current value of OUTOF_TARGET. */
980 if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
981 into_target, into_superword, word_mode, false))
982 return false;
984 if (outof_target != 0)
985 if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
986 outof_target, outof_superword,
987 word_mode, false))
988 return false;
990 return true;
992 #endif
994 /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
995 OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
996 input operand; the shift moves bits in the direction OUTOF_INPUT->
997 INTO_TARGET. OUTOF_TARGET and INTO_TARGET are the equivalent words
998 of the target. OP1 is the shift count and OP1_MODE is its mode.
999 If OP1 is constant, it will have been truncated as appropriate
1000 and is known to be nonzero.
1002 If SHIFT_MASK is zero, the result of word shifts is undefined when the
1003 shift count is outside the range [0, BITS_PER_WORD). This routine must
1004 avoid generating such shifts for OP1s in the range [0, BITS_PER_WORD * 2).
1006 If SHIFT_MASK is nonzero, all word-mode shift counts are effectively
1007 masked by it and shifts in the range [BITS_PER_WORD, SHIFT_MASK) will
1008 fill with zeros or sign bits as appropriate.
1010 If SHIFT_MASK is BITS_PER_WORD - 1, this routine will synthesize
1011 a doubleword shift whose equivalent mask is BITS_PER_WORD * 2 - 1.
1012 Doing this preserves semantics required by SHIFT_COUNT_TRUNCATED.
1013 In all other cases, shifts by values outside [0, BITS_PER_UNIT * 2)
1014 are undefined.
1016 BINOPTAB, UNSIGNEDP and METHODS are as for expand_binop. This function
1017 may not use INTO_INPUT after modifying INTO_TARGET, and similarly for
1018 OUTOF_INPUT and OUTOF_TARGET. OUTOF_TARGET can be null if the parent
1019 function wants to calculate it itself.
1021 Return true if the shift could be successfully synthesized. */
1023 static bool
1024 expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
1025 rtx outof_input, rtx into_input, rtx op1,
1026 rtx outof_target, rtx into_target,
1027 int unsignedp, enum optab_methods methods,
1028 unsigned HOST_WIDE_INT shift_mask)
1030 rtx superword_op1, tmp, cmp1, cmp2;
1031 rtx subword_label, done_label;
1032 enum rtx_code cmp_code;
1034 /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
1035 fill the result with sign or zero bits as appropriate. If so, the value
1036 of OUTOF_TARGET will always be (SHIFT OUTOF_INPUT OP1). Recursively call
1037 this routine to calculate INTO_TARGET (which depends on both OUTOF_INPUT
1038 and INTO_INPUT), then emit code to set up OUTOF_TARGET.
1040 This isn't worthwhile for constant shifts since the optimizers will
1041 cope better with in-range shift counts. */
1042 if (shift_mask >= BITS_PER_WORD
1043 && outof_target != 0
1044 && !CONSTANT_P (op1))
1046 if (!expand_doubleword_shift (op1_mode, binoptab,
1047 outof_input, into_input, op1,
1048 0, into_target,
1049 unsignedp, methods, shift_mask))
1050 return false;
1051 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
1052 outof_target, unsignedp, methods))
1053 return false;
1054 return true;
1057 /* Set CMP_CODE, CMP1 and CMP2 so that the rtx (CMP_CODE CMP1 CMP2)
1058 is true when the effective shift value is less than BITS_PER_WORD.
1059 Set SUPERWORD_OP1 to the shift count that should be used to shift
1060 OUTOF_INPUT into INTO_TARGET when the condition is false. */
1061 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
1062 if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
1064 /* Set CMP1 to OP1 & BITS_PER_WORD. The result is zero iff OP1
1065 is a subword shift count. */
1066 cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
1067 0, true, methods);
1068 cmp2 = CONST0_RTX (op1_mode);
1069 cmp_code = EQ;
1070 superword_op1 = op1;
1072 else
1074 /* Set CMP1 to OP1 - BITS_PER_WORD. */
1075 cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
1076 0, true, methods);
1077 cmp2 = CONST0_RTX (op1_mode);
1078 cmp_code = LT;
1079 superword_op1 = cmp1;
1081 if (cmp1 == 0)
1082 return false;
1084 /* If we can compute the condition at compile time, pick the
1085 appropriate subroutine. */
1086 tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
1087 if (tmp != 0 && CONST_INT_P (tmp))
1089 if (tmp == const0_rtx)
1090 return expand_superword_shift (binoptab, outof_input, superword_op1,
1091 outof_target, into_target,
1092 unsignedp, methods);
1093 else
1094 return expand_subword_shift (op1_mode, binoptab,
1095 outof_input, into_input, op1,
1096 outof_target, into_target,
1097 unsignedp, methods, shift_mask);
1100 #ifdef HAVE_conditional_move
1101 /* Try using conditional moves to generate straight-line code. */
1103 rtx start = get_last_insn ();
1104 if (expand_doubleword_shift_condmove (op1_mode, binoptab,
1105 cmp_code, cmp1, cmp2,
1106 outof_input, into_input,
1107 op1, superword_op1,
1108 outof_target, into_target,
1109 unsignedp, methods, shift_mask))
1110 return true;
1111 delete_insns_since (start);
1113 #endif
1115 /* As a last resort, use branches to select the correct alternative. */
1116 subword_label = gen_label_rtx ();
1117 done_label = gen_label_rtx ();
1119 NO_DEFER_POP;
1120 do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
1121 0, 0, subword_label, -1);
1122 OK_DEFER_POP;
1124 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
1125 outof_target, into_target,
1126 unsignedp, methods))
1127 return false;
1129 emit_jump_insn (gen_jump (done_label));
1130 emit_barrier ();
1131 emit_label (subword_label);
1133 if (!expand_subword_shift (op1_mode, binoptab,
1134 outof_input, into_input, op1,
1135 outof_target, into_target,
1136 unsignedp, methods, shift_mask))
1137 return false;
1139 emit_label (done_label);
1140 return true;
1143 /* Subroutine of expand_binop. Perform a double word multiplication of
1144 operands OP0 and OP1 both of mode MODE, which is exactly twice as wide
1145 as the target's word_mode. This function return NULL_RTX if anything
1146 goes wrong, in which case it may have already emitted instructions
1147 which need to be deleted.
1149 If we want to multiply two two-word values and have normal and widening
1150 multiplies of single-word values, we can do this with three smaller
1151 multiplications.
1153 The multiplication proceeds as follows:
1154 _______________________
1155 [__op0_high_|__op0_low__]
1156 _______________________
1157 * [__op1_high_|__op1_low__]
1158 _______________________________________________
1159 _______________________
1160 (1) [__op0_low__*__op1_low__]
1161 _______________________
1162 (2a) [__op0_low__*__op1_high_]
1163 _______________________
1164 (2b) [__op0_high_*__op1_low__]
1165 _______________________
1166 (3) [__op0_high_*__op1_high_]
1169 This gives a 4-word result. Since we are only interested in the
1170 lower 2 words, partial result (3) and the upper words of (2a) and
1171 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1172 calculated using non-widening multiplication.
1174 (1), however, needs to be calculated with an unsigned widening
1175 multiplication. If this operation is not directly supported we
1176 try using a signed widening multiplication and adjust the result.
1177 This adjustment works as follows:
1179 If both operands are positive then no adjustment is needed.
1181 If the operands have different signs, for example op0_low < 0 and
1182 op1_low >= 0, the instruction treats the most significant bit of
1183 op0_low as a sign bit instead of a bit with significance
1184 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1185 with 2**BITS_PER_WORD - op0_low, and two's complements the
1186 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1187 the result.
1189 Similarly, if both operands are negative, we need to add
1190 (op0_low + op1_low) * 2**BITS_PER_WORD.
1192 We use a trick to adjust quickly. We logically shift op0_low right
1193 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1194 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1195 logical shift exists, we do an arithmetic right shift and subtract
1196 the 0 or -1. */
1198 static rtx
1199 expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
1200 bool umulp, enum optab_methods methods)
1202 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1203 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1204 rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
1205 rtx product, adjust, product_high, temp;
1207 rtx op0_high = operand_subword_force (op0, high, mode);
1208 rtx op0_low = operand_subword_force (op0, low, mode);
1209 rtx op1_high = operand_subword_force (op1, high, mode);
1210 rtx op1_low = operand_subword_force (op1, low, mode);
1212 /* If we're using an unsigned multiply to directly compute the product
1213 of the low-order words of the operands and perform any required
1214 adjustments of the operands, we begin by trying two more multiplications
1215 and then computing the appropriate sum.
1217 We have checked above that the required addition is provided.
1218 Full-word addition will normally always succeed, especially if
1219 it is provided at all, so we don't worry about its failure. The
1220 multiplication may well fail, however, so we do handle that. */
1222 if (!umulp)
1224 /* ??? This could be done with emit_store_flag where available. */
1225 temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1226 NULL_RTX, 1, methods);
1227 if (temp)
1228 op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
1229 NULL_RTX, 0, OPTAB_DIRECT);
1230 else
1232 temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1233 NULL_RTX, 0, methods);
1234 if (!temp)
1235 return NULL_RTX;
1236 op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
1237 NULL_RTX, 0, OPTAB_DIRECT);
1240 if (!op0_high)
1241 return NULL_RTX;
1244 adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
1245 NULL_RTX, 0, OPTAB_DIRECT);
1246 if (!adjust)
1247 return NULL_RTX;
1249 /* OP0_HIGH should now be dead. */
1251 if (!umulp)
1253 /* ??? This could be done with emit_store_flag where available. */
1254 temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1255 NULL_RTX, 1, methods);
1256 if (temp)
1257 op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
1258 NULL_RTX, 0, OPTAB_DIRECT);
1259 else
1261 temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1262 NULL_RTX, 0, methods);
1263 if (!temp)
1264 return NULL_RTX;
1265 op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
1266 NULL_RTX, 0, OPTAB_DIRECT);
1269 if (!op1_high)
1270 return NULL_RTX;
1273 temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
1274 NULL_RTX, 0, OPTAB_DIRECT);
1275 if (!temp)
1276 return NULL_RTX;
1278 /* OP1_HIGH should now be dead. */
1280 adjust = expand_binop (word_mode, add_optab, adjust, temp,
1281 adjust, 0, OPTAB_DIRECT);
1283 if (target && !REG_P (target))
1284 target = NULL_RTX;
1286 if (umulp)
1287 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1288 target, 1, OPTAB_DIRECT);
1289 else
1290 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1291 target, 1, OPTAB_DIRECT);
1293 if (!product)
1294 return NULL_RTX;
1296 product_high = operand_subword (product, high, 1, mode);
1297 adjust = expand_binop (word_mode, add_optab, product_high, adjust,
1298 REG_P (product_high) ? product_high : adjust,
1299 0, OPTAB_DIRECT);
1300 emit_move_insn (product_high, adjust);
1301 return product;
1304 /* Wrapper around expand_binop which takes an rtx code to specify
1305 the operation to perform, not an optab pointer. All other
1306 arguments are the same. */
1308 expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
1309 rtx op1, rtx target, int unsignedp,
1310 enum optab_methods methods)
1312 optab binop = code_to_optab[(int) code];
1313 gcc_assert (binop);
1315 return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
1318 /* Return whether OP0 and OP1 should be swapped when expanding a commutative
1319 binop. Order them according to commutative_operand_precedence and, if
1320 possible, try to put TARGET or a pseudo first. */
1321 static bool
1322 swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
1324 int op0_prec = commutative_operand_precedence (op0);
1325 int op1_prec = commutative_operand_precedence (op1);
1327 if (op0_prec < op1_prec)
1328 return true;
1330 if (op0_prec > op1_prec)
1331 return false;
1333 /* With equal precedence, both orders are ok, but it is better if the
1334 first operand is TARGET, or if both TARGET and OP0 are pseudos. */
1335 if (target == 0 || REG_P (target))
1336 return (REG_P (op1) && !REG_P (op0)) || target == op1;
1337 else
1338 return rtx_equal_p (op1, target);
1341 /* Return true if BINOPTAB implements a shift operation. */
1343 static bool
1344 shift_optab_p (optab binoptab)
1346 switch (binoptab->code)
1348 case ASHIFT:
1349 case SS_ASHIFT:
1350 case US_ASHIFT:
1351 case ASHIFTRT:
1352 case LSHIFTRT:
1353 case ROTATE:
1354 case ROTATERT:
1355 return true;
1357 default:
1358 return false;
1362 /* Return true if BINOPTAB implements a commutative binary operation. */
1364 static bool
1365 commutative_optab_p (optab binoptab)
1367 return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
1368 || binoptab == smul_widen_optab
1369 || binoptab == umul_widen_optab
1370 || binoptab == smul_highpart_optab
1371 || binoptab == umul_highpart_optab);
1374 /* X is to be used in mode MODE as an operand to BINOPTAB. If we're
1375 optimizing, and if the operand is a constant that costs more than
1376 1 instruction, force the constant into a register and return that
1377 register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */
1379 static rtx
1380 avoid_expensive_constant (enum machine_mode mode, optab binoptab,
1381 rtx x, bool unsignedp)
1383 bool speed = optimize_insn_for_speed_p ();
1385 if (mode != VOIDmode
1386 && optimize
1387 && CONSTANT_P (x)
1388 && rtx_cost (x, binoptab->code, speed) > rtx_cost (x, SET, speed))
1390 if (CONST_INT_P (x))
1392 HOST_WIDE_INT intval = trunc_int_for_mode (INTVAL (x), mode);
1393 if (intval != INTVAL (x))
1394 x = GEN_INT (intval);
1396 else
1397 x = convert_modes (mode, VOIDmode, x, unsignedp);
1398 x = force_reg (mode, x);
1400 return x;
1403 /* Helper function for expand_binop: handle the case where there
1404 is an insn that directly implements the indicated operation.
1405 Returns null if this is not possible. */
1406 static rtx
1407 expand_binop_directly (enum machine_mode mode, optab binoptab,
1408 rtx op0, rtx op1,
1409 rtx target, int unsignedp, enum optab_methods methods,
1410 rtx last)
1412 int icode = (int) optab_handler (binoptab, mode);
1413 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
1414 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
1415 enum machine_mode tmp_mode;
1416 bool commutative_p;
1417 rtx pat;
1418 rtx xop0 = op0, xop1 = op1;
1419 rtx temp;
1420 rtx swap;
1422 if (target)
1423 temp = target;
1424 else
1425 temp = gen_reg_rtx (mode);
1427 /* If it is a commutative operator and the modes would match
1428 if we would swap the operands, we can save the conversions. */
1429 commutative_p = commutative_optab_p (binoptab);
1430 if (commutative_p
1431 && GET_MODE (xop0) != mode0 && GET_MODE (xop1) != mode1
1432 && GET_MODE (xop0) == mode1 && GET_MODE (xop1) == mode1)
1434 swap = xop0;
1435 xop0 = xop1;
1436 xop1 = swap;
1439 /* If we are optimizing, force expensive constants into a register. */
1440 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
1441 if (!shift_optab_p (binoptab))
1442 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
1444 /* In case the insn wants input operands in modes different from
1445 those of the actual operands, convert the operands. It would
1446 seem that we don't need to convert CONST_INTs, but we do, so
1447 that they're properly zero-extended, sign-extended or truncated
1448 for their mode. */
1450 if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode)
1451 xop0 = convert_modes (mode0,
1452 GET_MODE (xop0) != VOIDmode
1453 ? GET_MODE (xop0)
1454 : mode,
1455 xop0, unsignedp);
1457 if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode)
1458 xop1 = convert_modes (mode1,
1459 GET_MODE (xop1) != VOIDmode
1460 ? GET_MODE (xop1)
1461 : mode,
1462 xop1, unsignedp);
1464 /* If operation is commutative,
1465 try to make the first operand a register.
1466 Even better, try to make it the same as the target.
1467 Also try to make the last operand a constant. */
1468 if (commutative_p
1469 && swap_commutative_operands_with_target (target, xop0, xop1))
1471 swap = xop1;
1472 xop1 = xop0;
1473 xop0 = swap;
1476 /* Now, if insn's predicates don't allow our operands, put them into
1477 pseudo regs. */
1479 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
1480 && mode0 != VOIDmode)
1481 xop0 = copy_to_mode_reg (mode0, xop0);
1483 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
1484 && mode1 != VOIDmode)
1485 xop1 = copy_to_mode_reg (mode1, xop1);
1487 if (binoptab == vec_pack_trunc_optab
1488 || binoptab == vec_pack_usat_optab
1489 || binoptab == vec_pack_ssat_optab
1490 || binoptab == vec_pack_ufix_trunc_optab
1491 || binoptab == vec_pack_sfix_trunc_optab)
1493 /* The mode of the result is different then the mode of the
1494 arguments. */
1495 tmp_mode = insn_data[icode].operand[0].mode;
1496 if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
1497 return 0;
1499 else
1500 tmp_mode = mode;
1502 if (!insn_data[icode].operand[0].predicate (temp, tmp_mode))
1503 temp = gen_reg_rtx (tmp_mode);
1505 pat = GEN_FCN (icode) (temp, xop0, xop1);
1506 if (pat)
1508 /* If PAT is composed of more than one insn, try to add an appropriate
1509 REG_EQUAL note to it. If we can't because TEMP conflicts with an
1510 operand, call expand_binop again, this time without a target. */
1511 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
1512 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
1514 delete_insns_since (last);
1515 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
1516 unsignedp, methods);
1519 emit_insn (pat);
1520 return temp;
1523 delete_insns_since (last);
1524 return NULL_RTX;
1527 /* Generate code to perform an operation specified by BINOPTAB
1528 on operands OP0 and OP1, with result having machine-mode MODE.
1530 UNSIGNEDP is for the case where we have to widen the operands
1531 to perform the operation. It says to use zero-extension.
1533 If TARGET is nonzero, the value
1534 is generated there, if it is convenient to do so.
1535 In all cases an rtx is returned for the locus of the value;
1536 this may or may not be TARGET. */
1539 expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
1540 rtx target, int unsignedp, enum optab_methods methods)
1542 enum optab_methods next_methods
1543 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
1544 ? OPTAB_WIDEN : methods);
1545 enum mode_class mclass;
1546 enum machine_mode wider_mode;
1547 rtx libfunc;
1548 rtx temp;
1549 rtx entry_last = get_last_insn ();
1550 rtx last;
1552 mclass = GET_MODE_CLASS (mode);
1554 /* If subtracting an integer constant, convert this into an addition of
1555 the negated constant. */
1557 if (binoptab == sub_optab && CONST_INT_P (op1))
1559 op1 = negate_rtx (mode, op1);
1560 binoptab = add_optab;
1563 /* Record where to delete back to if we backtrack. */
1564 last = get_last_insn ();
1566 /* If we can do it with a three-operand insn, do so. */
1568 if (methods != OPTAB_MUST_WIDEN
1569 && optab_handler (binoptab, mode) != CODE_FOR_nothing)
1571 temp = expand_binop_directly (mode, binoptab, op0, op1, target,
1572 unsignedp, methods, last);
1573 if (temp)
1574 return temp;
1577 /* If we were trying to rotate, and that didn't work, try rotating
1578 the other direction before falling back to shifts and bitwise-or. */
1579 if (((binoptab == rotl_optab
1580 && optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
1581 || (binoptab == rotr_optab
1582 && optab_handler (rotl_optab, mode) != CODE_FOR_nothing))
1583 && mclass == MODE_INT)
1585 optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
1586 rtx newop1;
1587 unsigned int bits = GET_MODE_BITSIZE (mode);
1589 if (CONST_INT_P (op1))
1590 newop1 = GEN_INT (bits - INTVAL (op1));
1591 else if (targetm.shift_truncation_mask (mode) == bits - 1)
1592 newop1 = negate_rtx (GET_MODE (op1), op1);
1593 else
1594 newop1 = expand_binop (GET_MODE (op1), sub_optab,
1595 GEN_INT (bits), op1,
1596 NULL_RTX, unsignedp, OPTAB_DIRECT);
1598 temp = expand_binop_directly (mode, otheroptab, op0, newop1,
1599 target, unsignedp, methods, last);
1600 if (temp)
1601 return temp;
1604 /* If this is a multiply, see if we can do a widening operation that
1605 takes operands of this mode and makes a wider mode. */
1607 if (binoptab == smul_optab
1608 && GET_MODE_WIDER_MODE (mode) != VOIDmode
1609 && (optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab),
1610 GET_MODE_WIDER_MODE (mode))
1611 != CODE_FOR_nothing))
1613 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
1614 unsignedp ? umul_widen_optab : smul_widen_optab,
1615 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
1617 if (temp != 0)
1619 if (GET_MODE_CLASS (mode) == MODE_INT
1620 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1621 GET_MODE_BITSIZE (GET_MODE (temp))))
1622 return gen_lowpart (mode, temp);
1623 else
1624 return convert_to_mode (mode, temp, unsignedp);
1628 /* Look for a wider mode of the same class for which we think we
1629 can open-code the operation. Check for a widening multiply at the
1630 wider mode as well. */
1632 if (CLASS_HAS_WIDER_MODES_P (mclass)
1633 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
1634 for (wider_mode = GET_MODE_WIDER_MODE (mode);
1635 wider_mode != VOIDmode;
1636 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1638 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
1639 || (binoptab == smul_optab
1640 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
1641 && (optab_handler ((unsignedp ? umul_widen_optab
1642 : smul_widen_optab),
1643 GET_MODE_WIDER_MODE (wider_mode))
1644 != CODE_FOR_nothing)))
1646 rtx xop0 = op0, xop1 = op1;
1647 int no_extend = 0;
1649 /* For certain integer operations, we need not actually extend
1650 the narrow operands, as long as we will truncate
1651 the results to the same narrowness. */
1653 if ((binoptab == ior_optab || binoptab == and_optab
1654 || binoptab == xor_optab
1655 || binoptab == add_optab || binoptab == sub_optab
1656 || binoptab == smul_optab || binoptab == ashl_optab)
1657 && mclass == MODE_INT)
1659 no_extend = 1;
1660 xop0 = avoid_expensive_constant (mode, binoptab,
1661 xop0, unsignedp);
1662 if (binoptab != ashl_optab)
1663 xop1 = avoid_expensive_constant (mode, binoptab,
1664 xop1, unsignedp);
1667 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
1669 /* The second operand of a shift must always be extended. */
1670 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1671 no_extend && binoptab != ashl_optab);
1673 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1674 unsignedp, OPTAB_DIRECT);
1675 if (temp)
1677 if (mclass != MODE_INT
1678 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1679 GET_MODE_BITSIZE (wider_mode)))
1681 if (target == 0)
1682 target = gen_reg_rtx (mode);
1683 convert_move (target, temp, 0);
1684 return target;
1686 else
1687 return gen_lowpart (mode, temp);
1689 else
1690 delete_insns_since (last);
1694 /* If operation is commutative,
1695 try to make the first operand a register.
1696 Even better, try to make it the same as the target.
1697 Also try to make the last operand a constant. */
1698 if (commutative_optab_p (binoptab)
1699 && swap_commutative_operands_with_target (target, op0, op1))
1701 temp = op1;
1702 op1 = op0;
1703 op0 = temp;
1706 /* These can be done a word at a time. */
1707 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
1708 && mclass == MODE_INT
1709 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1710 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
1712 int i;
1713 rtx insns;
1715 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1716 won't be accurate, so use a new target. */
1717 if (target == 0 || target == op0 || target == op1)
1718 target = gen_reg_rtx (mode);
1720 start_sequence ();
1722 /* Do the actual arithmetic. */
1723 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1725 rtx target_piece = operand_subword (target, i, 1, mode);
1726 rtx x = expand_binop (word_mode, binoptab,
1727 operand_subword_force (op0, i, mode),
1728 operand_subword_force (op1, i, mode),
1729 target_piece, unsignedp, next_methods);
1731 if (x == 0)
1732 break;
1734 if (target_piece != x)
1735 emit_move_insn (target_piece, x);
1738 insns = get_insns ();
1739 end_sequence ();
1741 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1743 emit_insn (insns);
1744 return target;
1748 /* Synthesize double word shifts from single word shifts. */
1749 if ((binoptab == lshr_optab || binoptab == ashl_optab
1750 || binoptab == ashr_optab)
1751 && mclass == MODE_INT
1752 && (CONST_INT_P (op1) || optimize_insn_for_speed_p ())
1753 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1754 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing
1755 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1756 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
1758 unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
1759 enum machine_mode op1_mode;
1761 double_shift_mask = targetm.shift_truncation_mask (mode);
1762 shift_mask = targetm.shift_truncation_mask (word_mode);
1763 op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
1765 /* Apply the truncation to constant shifts. */
1766 if (double_shift_mask > 0 && CONST_INT_P (op1))
1767 op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
1769 if (op1 == CONST0_RTX (op1_mode))
1770 return op0;
1772 /* Make sure that this is a combination that expand_doubleword_shift
1773 can handle. See the comments there for details. */
1774 if (double_shift_mask == 0
1775 || (shift_mask == BITS_PER_WORD - 1
1776 && double_shift_mask == BITS_PER_WORD * 2 - 1))
1778 rtx insns;
1779 rtx into_target, outof_target;
1780 rtx into_input, outof_input;
1781 int left_shift, outof_word;
1783 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1784 won't be accurate, so use a new target. */
1785 if (target == 0 || target == op0 || target == op1)
1786 target = gen_reg_rtx (mode);
1788 start_sequence ();
1790 /* OUTOF_* is the word we are shifting bits away from, and
1791 INTO_* is the word that we are shifting bits towards, thus
1792 they differ depending on the direction of the shift and
1793 WORDS_BIG_ENDIAN. */
1795 left_shift = binoptab == ashl_optab;
1796 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1798 outof_target = operand_subword (target, outof_word, 1, mode);
1799 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1801 outof_input = operand_subword_force (op0, outof_word, mode);
1802 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1804 if (expand_doubleword_shift (op1_mode, binoptab,
1805 outof_input, into_input, op1,
1806 outof_target, into_target,
1807 unsignedp, next_methods, shift_mask))
1809 insns = get_insns ();
1810 end_sequence ();
1812 emit_insn (insns);
1813 return target;
1815 end_sequence ();
1819 /* Synthesize double word rotates from single word shifts. */
1820 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1821 && mclass == MODE_INT
1822 && CONST_INT_P (op1)
1823 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1824 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1825 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
1827 rtx insns;
1828 rtx into_target, outof_target;
1829 rtx into_input, outof_input;
1830 rtx inter;
1831 int shift_count, left_shift, outof_word;
1833 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1834 won't be accurate, so use a new target. Do this also if target is not
1835 a REG, first because having a register instead may open optimization
1836 opportunities, and second because if target and op0 happen to be MEMs
1837 designating the same location, we would risk clobbering it too early
1838 in the code sequence we generate below. */
1839 if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
1840 target = gen_reg_rtx (mode);
1842 start_sequence ();
1844 shift_count = INTVAL (op1);
1846 /* OUTOF_* is the word we are shifting bits away from, and
1847 INTO_* is the word that we are shifting bits towards, thus
1848 they differ depending on the direction of the shift and
1849 WORDS_BIG_ENDIAN. */
1851 left_shift = (binoptab == rotl_optab);
1852 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1854 outof_target = operand_subword (target, outof_word, 1, mode);
1855 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1857 outof_input = operand_subword_force (op0, outof_word, mode);
1858 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1860 if (shift_count == BITS_PER_WORD)
1862 /* This is just a word swap. */
1863 emit_move_insn (outof_target, into_input);
1864 emit_move_insn (into_target, outof_input);
1865 inter = const0_rtx;
1867 else
1869 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1870 rtx first_shift_count, second_shift_count;
1871 optab reverse_unsigned_shift, unsigned_shift;
1873 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1874 ? lshr_optab : ashl_optab);
1876 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1877 ? ashl_optab : lshr_optab);
1879 if (shift_count > BITS_PER_WORD)
1881 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1882 second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
1884 else
1886 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1887 second_shift_count = GEN_INT (shift_count);
1890 into_temp1 = expand_binop (word_mode, unsigned_shift,
1891 outof_input, first_shift_count,
1892 NULL_RTX, unsignedp, next_methods);
1893 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1894 into_input, second_shift_count,
1895 NULL_RTX, unsignedp, next_methods);
1897 if (into_temp1 != 0 && into_temp2 != 0)
1898 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1899 into_target, unsignedp, next_methods);
1900 else
1901 inter = 0;
1903 if (inter != 0 && inter != into_target)
1904 emit_move_insn (into_target, inter);
1906 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1907 into_input, first_shift_count,
1908 NULL_RTX, unsignedp, next_methods);
1909 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1910 outof_input, second_shift_count,
1911 NULL_RTX, unsignedp, next_methods);
1913 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1914 inter = expand_binop (word_mode, ior_optab,
1915 outof_temp1, outof_temp2,
1916 outof_target, unsignedp, next_methods);
1918 if (inter != 0 && inter != outof_target)
1919 emit_move_insn (outof_target, inter);
1922 insns = get_insns ();
1923 end_sequence ();
1925 if (inter != 0)
1927 emit_insn (insns);
1928 return target;
1932 /* These can be done a word at a time by propagating carries. */
1933 if ((binoptab == add_optab || binoptab == sub_optab)
1934 && mclass == MODE_INT
1935 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1936 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
1938 unsigned int i;
1939 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1940 const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1941 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1942 rtx xop0, xop1, xtarget;
1944 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1945 value is one of those, use it. Otherwise, use 1 since it is the
1946 one easiest to get. */
1947 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1948 int normalizep = STORE_FLAG_VALUE;
1949 #else
1950 int normalizep = 1;
1951 #endif
1953 /* Prepare the operands. */
1954 xop0 = force_reg (mode, op0);
1955 xop1 = force_reg (mode, op1);
1957 xtarget = gen_reg_rtx (mode);
1959 if (target == 0 || !REG_P (target))
1960 target = xtarget;
1962 /* Indicate for flow that the entire target reg is being set. */
1963 if (REG_P (target))
1964 emit_clobber (xtarget);
1966 /* Do the actual arithmetic. */
1967 for (i = 0; i < nwords; i++)
1969 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1970 rtx target_piece = operand_subword (xtarget, index, 1, mode);
1971 rtx op0_piece = operand_subword_force (xop0, index, mode);
1972 rtx op1_piece = operand_subword_force (xop1, index, mode);
1973 rtx x;
1975 /* Main add/subtract of the input operands. */
1976 x = expand_binop (word_mode, binoptab,
1977 op0_piece, op1_piece,
1978 target_piece, unsignedp, next_methods);
1979 if (x == 0)
1980 break;
1982 if (i + 1 < nwords)
1984 /* Store carry from main add/subtract. */
1985 carry_out = gen_reg_rtx (word_mode);
1986 carry_out = emit_store_flag_force (carry_out,
1987 (binoptab == add_optab
1988 ? LT : GT),
1989 x, op0_piece,
1990 word_mode, 1, normalizep);
1993 if (i > 0)
1995 rtx newx;
1997 /* Add/subtract previous carry to main result. */
1998 newx = expand_binop (word_mode,
1999 normalizep == 1 ? binoptab : otheroptab,
2000 x, carry_in,
2001 NULL_RTX, 1, next_methods);
2003 if (i + 1 < nwords)
2005 /* Get out carry from adding/subtracting carry in. */
2006 rtx carry_tmp = gen_reg_rtx (word_mode);
2007 carry_tmp = emit_store_flag_force (carry_tmp,
2008 (binoptab == add_optab
2009 ? LT : GT),
2010 newx, x,
2011 word_mode, 1, normalizep);
2013 /* Logical-ior the two poss. carry together. */
2014 carry_out = expand_binop (word_mode, ior_optab,
2015 carry_out, carry_tmp,
2016 carry_out, 0, next_methods);
2017 if (carry_out == 0)
2018 break;
2020 emit_move_insn (target_piece, newx);
2022 else
2024 if (x != target_piece)
2025 emit_move_insn (target_piece, x);
2028 carry_in = carry_out;
2031 if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
2033 if (optab_handler (mov_optab, mode) != CODE_FOR_nothing
2034 || ! rtx_equal_p (target, xtarget))
2036 rtx temp = emit_move_insn (target, xtarget);
2038 set_unique_reg_note (temp,
2039 REG_EQUAL,
2040 gen_rtx_fmt_ee (binoptab->code, mode,
2041 copy_rtx (xop0),
2042 copy_rtx (xop1)));
2044 else
2045 target = xtarget;
2047 return target;
2050 else
2051 delete_insns_since (last);
2054 /* Attempt to synthesize double word multiplies using a sequence of word
2055 mode multiplications. We first attempt to generate a sequence using a
2056 more efficient unsigned widening multiply, and if that fails we then
2057 try using a signed widening multiply. */
2059 if (binoptab == smul_optab
2060 && mclass == MODE_INT
2061 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
2062 && optab_handler (smul_optab, word_mode) != CODE_FOR_nothing
2063 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)
2065 rtx product = NULL_RTX;
2067 if (optab_handler (umul_widen_optab, mode) != CODE_FOR_nothing)
2069 product = expand_doubleword_mult (mode, op0, op1, target,
2070 true, methods);
2071 if (!product)
2072 delete_insns_since (last);
2075 if (product == NULL_RTX
2076 && optab_handler (smul_widen_optab, mode) != CODE_FOR_nothing)
2078 product = expand_doubleword_mult (mode, op0, op1, target,
2079 false, methods);
2080 if (!product)
2081 delete_insns_since (last);
2084 if (product != NULL_RTX)
2086 if (optab_handler (mov_optab, mode) != CODE_FOR_nothing)
2088 temp = emit_move_insn (target ? target : product, product);
2089 set_unique_reg_note (temp,
2090 REG_EQUAL,
2091 gen_rtx_fmt_ee (MULT, mode,
2092 copy_rtx (op0),
2093 copy_rtx (op1)));
2095 return product;
2099 /* It can't be open-coded in this mode.
2100 Use a library call if one is available and caller says that's ok. */
2102 libfunc = optab_libfunc (binoptab, mode);
2103 if (libfunc
2104 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
2106 rtx insns;
2107 rtx op1x = op1;
2108 enum machine_mode op1_mode = mode;
2109 rtx value;
2111 start_sequence ();
2113 if (shift_optab_p (binoptab))
2115 op1_mode = targetm.libgcc_shift_count_mode ();
2116 /* Specify unsigned here,
2117 since negative shift counts are meaningless. */
2118 op1x = convert_to_mode (op1_mode, op1, 1);
2121 if (GET_MODE (op0) != VOIDmode
2122 && GET_MODE (op0) != mode)
2123 op0 = convert_to_mode (mode, op0, unsignedp);
2125 /* Pass 1 for NO_QUEUE so we don't lose any increments
2126 if the libcall is cse'd or moved. */
2127 value = emit_library_call_value (libfunc,
2128 NULL_RTX, LCT_CONST, mode, 2,
2129 op0, mode, op1x, op1_mode);
2131 insns = get_insns ();
2132 end_sequence ();
2134 target = gen_reg_rtx (mode);
2135 emit_libcall_block (insns, target, value,
2136 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
2138 return target;
2141 delete_insns_since (last);
2143 /* It can't be done in this mode. Can we do it in a wider mode? */
2145 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
2146 || methods == OPTAB_MUST_WIDEN))
2148 /* Caller says, don't even try. */
2149 delete_insns_since (entry_last);
2150 return 0;
2153 /* Compute the value of METHODS to pass to recursive calls.
2154 Don't allow widening to be tried recursively. */
2156 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
2158 /* Look for a wider mode of the same class for which it appears we can do
2159 the operation. */
2161 if (CLASS_HAS_WIDER_MODES_P (mclass))
2163 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2164 wider_mode != VOIDmode;
2165 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2167 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
2168 || (methods == OPTAB_LIB
2169 && optab_libfunc (binoptab, wider_mode)))
2171 rtx xop0 = op0, xop1 = op1;
2172 int no_extend = 0;
2174 /* For certain integer operations, we need not actually extend
2175 the narrow operands, as long as we will truncate
2176 the results to the same narrowness. */
2178 if ((binoptab == ior_optab || binoptab == and_optab
2179 || binoptab == xor_optab
2180 || binoptab == add_optab || binoptab == sub_optab
2181 || binoptab == smul_optab || binoptab == ashl_optab)
2182 && mclass == MODE_INT)
2183 no_extend = 1;
2185 xop0 = widen_operand (xop0, wider_mode, mode,
2186 unsignedp, no_extend);
2188 /* The second operand of a shift must always be extended. */
2189 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
2190 no_extend && binoptab != ashl_optab);
2192 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
2193 unsignedp, methods);
2194 if (temp)
2196 if (mclass != MODE_INT
2197 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
2198 GET_MODE_BITSIZE (wider_mode)))
2200 if (target == 0)
2201 target = gen_reg_rtx (mode);
2202 convert_move (target, temp, 0);
2203 return target;
2205 else
2206 return gen_lowpart (mode, temp);
2208 else
2209 delete_insns_since (last);
2214 delete_insns_since (entry_last);
2215 return 0;
2218 /* Expand a binary operator which has both signed and unsigned forms.
2219 UOPTAB is the optab for unsigned operations, and SOPTAB is for
2220 signed operations.
2222 If we widen unsigned operands, we may use a signed wider operation instead
2223 of an unsigned wider operation, since the result would be the same. */
2226 sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
2227 rtx op0, rtx op1, rtx target, int unsignedp,
2228 enum optab_methods methods)
2230 rtx temp;
2231 optab direct_optab = unsignedp ? uoptab : soptab;
2232 struct optab_d wide_soptab;
2234 /* Do it without widening, if possible. */
2235 temp = expand_binop (mode, direct_optab, op0, op1, target,
2236 unsignedp, OPTAB_DIRECT);
2237 if (temp || methods == OPTAB_DIRECT)
2238 return temp;
2240 /* Try widening to a signed int. Make a fake signed optab that
2241 hides any signed insn for direct use. */
2242 wide_soptab = *soptab;
2243 set_optab_handler (&wide_soptab, mode, CODE_FOR_nothing);
2244 /* We don't want to generate new hash table entries from this fake
2245 optab. */
2246 wide_soptab.libcall_gen = NULL;
2248 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2249 unsignedp, OPTAB_WIDEN);
2251 /* For unsigned operands, try widening to an unsigned int. */
2252 if (temp == 0 && unsignedp)
2253 temp = expand_binop (mode, uoptab, op0, op1, target,
2254 unsignedp, OPTAB_WIDEN);
2255 if (temp || methods == OPTAB_WIDEN)
2256 return temp;
2258 /* Use the right width libcall if that exists. */
2259 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
2260 if (temp || methods == OPTAB_LIB)
2261 return temp;
2263 /* Must widen and use a libcall, use either signed or unsigned. */
2264 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2265 unsignedp, methods);
2266 if (temp != 0)
2267 return temp;
2268 if (unsignedp)
2269 return expand_binop (mode, uoptab, op0, op1, target,
2270 unsignedp, methods);
2271 return 0;
2274 /* Generate code to perform an operation specified by UNOPPTAB
2275 on operand OP0, with two results to TARG0 and TARG1.
2276 We assume that the order of the operands for the instruction
2277 is TARG0, TARG1, OP0.
2279 Either TARG0 or TARG1 may be zero, but what that means is that
2280 the result is not actually wanted. We will generate it into
2281 a dummy pseudo-reg and discard it. They may not both be zero.
2283 Returns 1 if this operation can be performed; 0 if not. */
2286 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
2287 int unsignedp)
2289 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2290 enum mode_class mclass;
2291 enum machine_mode wider_mode;
2292 rtx entry_last = get_last_insn ();
2293 rtx last;
2295 mclass = GET_MODE_CLASS (mode);
2297 if (!targ0)
2298 targ0 = gen_reg_rtx (mode);
2299 if (!targ1)
2300 targ1 = gen_reg_rtx (mode);
2302 /* Record where to go back to if we fail. */
2303 last = get_last_insn ();
2305 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
2307 int icode = (int) optab_handler (unoptab, mode);
2308 enum machine_mode mode0 = insn_data[icode].operand[2].mode;
2309 rtx pat;
2310 rtx xop0 = op0;
2312 if (GET_MODE (xop0) != VOIDmode
2313 && GET_MODE (xop0) != mode0)
2314 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2316 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2317 if (!insn_data[icode].operand[2].predicate (xop0, mode0))
2318 xop0 = copy_to_mode_reg (mode0, xop0);
2320 /* We could handle this, but we should always be called with a pseudo
2321 for our targets and all insns should take them as outputs. */
2322 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2323 gcc_assert (insn_data[icode].operand[1].predicate (targ1, mode));
2325 pat = GEN_FCN (icode) (targ0, targ1, xop0);
2326 if (pat)
2328 emit_insn (pat);
2329 return 1;
2331 else
2332 delete_insns_since (last);
2335 /* It can't be done in this mode. Can we do it in a wider mode? */
2337 if (CLASS_HAS_WIDER_MODES_P (mclass))
2339 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2340 wider_mode != VOIDmode;
2341 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2343 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
2345 rtx t0 = gen_reg_rtx (wider_mode);
2346 rtx t1 = gen_reg_rtx (wider_mode);
2347 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2349 if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
2351 convert_move (targ0, t0, unsignedp);
2352 convert_move (targ1, t1, unsignedp);
2353 return 1;
2355 else
2356 delete_insns_since (last);
2361 delete_insns_since (entry_last);
2362 return 0;
2365 /* Generate code to perform an operation specified by BINOPTAB
2366 on operands OP0 and OP1, with two results to TARG1 and TARG2.
2367 We assume that the order of the operands for the instruction
2368 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2369 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2371 Either TARG0 or TARG1 may be zero, but what that means is that
2372 the result is not actually wanted. We will generate it into
2373 a dummy pseudo-reg and discard it. They may not both be zero.
2375 Returns 1 if this operation can be performed; 0 if not. */
2378 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
2379 int unsignedp)
2381 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2382 enum mode_class mclass;
2383 enum machine_mode wider_mode;
2384 rtx entry_last = get_last_insn ();
2385 rtx last;
2387 mclass = GET_MODE_CLASS (mode);
2389 if (!targ0)
2390 targ0 = gen_reg_rtx (mode);
2391 if (!targ1)
2392 targ1 = gen_reg_rtx (mode);
2394 /* Record where to go back to if we fail. */
2395 last = get_last_insn ();
2397 if (optab_handler (binoptab, mode) != CODE_FOR_nothing)
2399 int icode = (int) optab_handler (binoptab, mode);
2400 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2401 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
2402 rtx pat;
2403 rtx xop0 = op0, xop1 = op1;
2405 /* If we are optimizing, force expensive constants into a register. */
2406 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
2407 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
2409 /* In case the insn wants input operands in modes different from
2410 those of the actual operands, convert the operands. It would
2411 seem that we don't need to convert CONST_INTs, but we do, so
2412 that they're properly zero-extended, sign-extended or truncated
2413 for their mode. */
2415 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
2416 xop0 = convert_modes (mode0,
2417 GET_MODE (op0) != VOIDmode
2418 ? GET_MODE (op0)
2419 : mode,
2420 xop0, unsignedp);
2422 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
2423 xop1 = convert_modes (mode1,
2424 GET_MODE (op1) != VOIDmode
2425 ? GET_MODE (op1)
2426 : mode,
2427 xop1, unsignedp);
2429 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2430 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
2431 xop0 = copy_to_mode_reg (mode0, xop0);
2433 if (!insn_data[icode].operand[2].predicate (xop1, mode1))
2434 xop1 = copy_to_mode_reg (mode1, xop1);
2436 /* We could handle this, but we should always be called with a pseudo
2437 for our targets and all insns should take them as outputs. */
2438 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2439 gcc_assert (insn_data[icode].operand[3].predicate (targ1, mode));
2441 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
2442 if (pat)
2444 emit_insn (pat);
2445 return 1;
2447 else
2448 delete_insns_since (last);
2451 /* It can't be done in this mode. Can we do it in a wider mode? */
2453 if (CLASS_HAS_WIDER_MODES_P (mclass))
2455 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2456 wider_mode != VOIDmode;
2457 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2459 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing)
2461 rtx t0 = gen_reg_rtx (wider_mode);
2462 rtx t1 = gen_reg_rtx (wider_mode);
2463 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2464 rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
2466 if (expand_twoval_binop (binoptab, cop0, cop1,
2467 t0, t1, unsignedp))
2469 convert_move (targ0, t0, unsignedp);
2470 convert_move (targ1, t1, unsignedp);
2471 return 1;
2473 else
2474 delete_insns_since (last);
2479 delete_insns_since (entry_last);
2480 return 0;
2483 /* Expand the two-valued library call indicated by BINOPTAB, but
2484 preserve only one of the values. If TARG0 is non-NULL, the first
2485 value is placed into TARG0; otherwise the second value is placed
2486 into TARG1. Exactly one of TARG0 and TARG1 must be non-NULL. The
2487 value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
2488 This routine assumes that the value returned by the library call is
2489 as if the return value was of an integral mode twice as wide as the
2490 mode of OP0. Returns 1 if the call was successful. */
2492 bool
2493 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
2494 rtx targ0, rtx targ1, enum rtx_code code)
2496 enum machine_mode mode;
2497 enum machine_mode libval_mode;
2498 rtx libval;
2499 rtx insns;
2500 rtx libfunc;
2502 /* Exactly one of TARG0 or TARG1 should be non-NULL. */
2503 gcc_assert (!targ0 != !targ1);
2505 mode = GET_MODE (op0);
2506 libfunc = optab_libfunc (binoptab, mode);
2507 if (!libfunc)
2508 return false;
2510 /* The value returned by the library function will have twice as
2511 many bits as the nominal MODE. */
2512 libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
2513 MODE_INT);
2514 start_sequence ();
2515 libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
2516 libval_mode, 2,
2517 op0, mode,
2518 op1, mode);
2519 /* Get the part of VAL containing the value that we want. */
2520 libval = simplify_gen_subreg (mode, libval, libval_mode,
2521 targ0 ? 0 : GET_MODE_SIZE (mode));
2522 insns = get_insns ();
2523 end_sequence ();
2524 /* Move the into the desired location. */
2525 emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
2526 gen_rtx_fmt_ee (code, mode, op0, op1));
2528 return true;
2532 /* Wrapper around expand_unop which takes an rtx code to specify
2533 the operation to perform, not an optab pointer. All other
2534 arguments are the same. */
2536 expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
2537 rtx target, int unsignedp)
2539 optab unop = code_to_optab[(int) code];
2540 gcc_assert (unop);
2542 return expand_unop (mode, unop, op0, target, unsignedp);
2545 /* Try calculating
2546 (clz:narrow x)
2548 (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)). */
2549 static rtx
2550 widen_clz (enum machine_mode mode, rtx op0, rtx target)
2552 enum mode_class mclass = GET_MODE_CLASS (mode);
2553 if (CLASS_HAS_WIDER_MODES_P (mclass))
2555 enum machine_mode wider_mode;
2556 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2557 wider_mode != VOIDmode;
2558 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2560 if (optab_handler (clz_optab, wider_mode) != CODE_FOR_nothing)
2562 rtx xop0, temp, last;
2564 last = get_last_insn ();
2566 if (target == 0)
2567 target = gen_reg_rtx (mode);
2568 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2569 temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
2570 if (temp != 0)
2571 temp = expand_binop (wider_mode, sub_optab, temp,
2572 GEN_INT (GET_MODE_BITSIZE (wider_mode)
2573 - GET_MODE_BITSIZE (mode)),
2574 target, true, OPTAB_DIRECT);
2575 if (temp == 0)
2576 delete_insns_since (last);
2578 return temp;
2582 return 0;
2585 /* Try calculating clz of a double-word quantity as two clz's of word-sized
2586 quantities, choosing which based on whether the high word is nonzero. */
2587 static rtx
2588 expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target)
2590 rtx xop0 = force_reg (mode, op0);
2591 rtx subhi = gen_highpart (word_mode, xop0);
2592 rtx sublo = gen_lowpart (word_mode, xop0);
2593 rtx hi0_label = gen_label_rtx ();
2594 rtx after_label = gen_label_rtx ();
2595 rtx seq, temp, result;
2597 /* If we were not given a target, use a word_mode register, not a
2598 'mode' register. The result will fit, and nobody is expecting
2599 anything bigger (the return type of __builtin_clz* is int). */
2600 if (!target)
2601 target = gen_reg_rtx (word_mode);
2603 /* In any case, write to a word_mode scratch in both branches of the
2604 conditional, so we can ensure there is a single move insn setting
2605 'target' to tag a REG_EQUAL note on. */
2606 result = gen_reg_rtx (word_mode);
2608 start_sequence ();
2610 /* If the high word is not equal to zero,
2611 then clz of the full value is clz of the high word. */
2612 emit_cmp_and_jump_insns (subhi, CONST0_RTX (word_mode), EQ, 0,
2613 word_mode, true, hi0_label);
2615 temp = expand_unop_direct (word_mode, clz_optab, subhi, result, true);
2616 if (!temp)
2617 goto fail;
2619 if (temp != result)
2620 convert_move (result, temp, true);
2622 emit_jump_insn (gen_jump (after_label));
2623 emit_barrier ();
2625 /* Else clz of the full value is clz of the low word plus the number
2626 of bits in the high word. */
2627 emit_label (hi0_label);
2629 temp = expand_unop_direct (word_mode, clz_optab, sublo, 0, true);
2630 if (!temp)
2631 goto fail;
2632 temp = expand_binop (word_mode, add_optab, temp,
2633 GEN_INT (GET_MODE_BITSIZE (word_mode)),
2634 result, true, OPTAB_DIRECT);
2635 if (!temp)
2636 goto fail;
2637 if (temp != result)
2638 convert_move (result, temp, true);
2640 emit_label (after_label);
2641 convert_move (target, result, true);
2643 seq = get_insns ();
2644 end_sequence ();
2646 add_equal_note (seq, target, CLZ, xop0, 0);
2647 emit_insn (seq);
2648 return target;
2650 fail:
2651 end_sequence ();
2652 return 0;
2655 /* Try calculating
2656 (bswap:narrow x)
2658 (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */
2659 static rtx
2660 widen_bswap (enum machine_mode mode, rtx op0, rtx target)
2662 enum mode_class mclass = GET_MODE_CLASS (mode);
2663 enum machine_mode wider_mode;
2664 rtx x, last;
2666 if (!CLASS_HAS_WIDER_MODES_P (mclass))
2667 return NULL_RTX;
2669 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2670 wider_mode != VOIDmode;
2671 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2672 if (optab_handler (bswap_optab, wider_mode) != CODE_FOR_nothing)
2673 goto found;
2674 return NULL_RTX;
2676 found:
2677 last = get_last_insn ();
2679 x = widen_operand (op0, wider_mode, mode, true, true);
2680 x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
2682 if (x != 0)
2683 x = expand_shift (RSHIFT_EXPR, wider_mode, x,
2684 size_int (GET_MODE_BITSIZE (wider_mode)
2685 - GET_MODE_BITSIZE (mode)),
2686 NULL_RTX, true);
2688 if (x != 0)
2690 if (target == 0)
2691 target = gen_reg_rtx (mode);
2692 emit_move_insn (target, gen_lowpart (mode, x));
2694 else
2695 delete_insns_since (last);
2697 return target;
2700 /* Try calculating bswap as two bswaps of two word-sized operands. */
2702 static rtx
2703 expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
2705 rtx t0, t1;
2707 t1 = expand_unop (word_mode, bswap_optab,
2708 operand_subword_force (op, 0, mode), NULL_RTX, true);
2709 t0 = expand_unop (word_mode, bswap_optab,
2710 operand_subword_force (op, 1, mode), NULL_RTX, true);
2712 if (target == 0)
2713 target = gen_reg_rtx (mode);
2714 if (REG_P (target))
2715 emit_clobber (target);
2716 emit_move_insn (operand_subword (target, 0, 1, mode), t0);
2717 emit_move_insn (operand_subword (target, 1, 1, mode), t1);
2719 return target;
2722 /* Try calculating (parity x) as (and (popcount x) 1), where
2723 popcount can also be done in a wider mode. */
2724 static rtx
2725 expand_parity (enum machine_mode mode, rtx op0, rtx target)
2727 enum mode_class mclass = GET_MODE_CLASS (mode);
2728 if (CLASS_HAS_WIDER_MODES_P (mclass))
2730 enum machine_mode wider_mode;
2731 for (wider_mode = mode; wider_mode != VOIDmode;
2732 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2734 if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
2736 rtx xop0, temp, last;
2738 last = get_last_insn ();
2740 if (target == 0)
2741 target = gen_reg_rtx (mode);
2742 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2743 temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
2744 true);
2745 if (temp != 0)
2746 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
2747 target, true, OPTAB_DIRECT);
2748 if (temp == 0)
2749 delete_insns_since (last);
2751 return temp;
2755 return 0;
2758 /* Try calculating ctz(x) as K - clz(x & -x) ,
2759 where K is GET_MODE_BITSIZE(mode) - 1.
2761 Both __builtin_ctz and __builtin_clz are undefined at zero, so we
2762 don't have to worry about what the hardware does in that case. (If
2763 the clz instruction produces the usual value at 0, which is K, the
2764 result of this code sequence will be -1; expand_ffs, below, relies
2765 on this. It might be nice to have it be K instead, for consistency
2766 with the (very few) processors that provide a ctz with a defined
2767 value, but that would take one more instruction, and it would be
2768 less convenient for expand_ffs anyway. */
2770 static rtx
2771 expand_ctz (enum machine_mode mode, rtx op0, rtx target)
2773 rtx seq, temp;
2775 if (optab_handler (clz_optab, mode) == CODE_FOR_nothing)
2776 return 0;
2778 start_sequence ();
2780 temp = expand_unop_direct (mode, neg_optab, op0, NULL_RTX, true);
2781 if (temp)
2782 temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
2783 true, OPTAB_DIRECT);
2784 if (temp)
2785 temp = expand_unop_direct (mode, clz_optab, temp, NULL_RTX, true);
2786 if (temp)
2787 temp = expand_binop (mode, sub_optab, GEN_INT (GET_MODE_BITSIZE (mode) - 1),
2788 temp, target,
2789 true, OPTAB_DIRECT);
2790 if (temp == 0)
2792 end_sequence ();
2793 return 0;
2796 seq = get_insns ();
2797 end_sequence ();
2799 add_equal_note (seq, temp, CTZ, op0, 0);
2800 emit_insn (seq);
2801 return temp;
2805 /* Try calculating ffs(x) using ctz(x) if we have that instruction, or
2806 else with the sequence used by expand_clz.
2808 The ffs builtin promises to return zero for a zero value and ctz/clz
2809 may have an undefined value in that case. If they do not give us a
2810 convenient value, we have to generate a test and branch. */
2811 static rtx
2812 expand_ffs (enum machine_mode mode, rtx op0, rtx target)
2814 HOST_WIDE_INT val = 0;
2815 bool defined_at_zero = false;
2816 rtx temp, seq;
2818 if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing)
2820 start_sequence ();
2822 temp = expand_unop_direct (mode, ctz_optab, op0, 0, true);
2823 if (!temp)
2824 goto fail;
2826 defined_at_zero = (CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2);
2828 else if (optab_handler (clz_optab, mode) != CODE_FOR_nothing)
2830 start_sequence ();
2831 temp = expand_ctz (mode, op0, 0);
2832 if (!temp)
2833 goto fail;
2835 if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
2837 defined_at_zero = true;
2838 val = (GET_MODE_BITSIZE (mode) - 1) - val;
2841 else
2842 return 0;
2844 if (defined_at_zero && val == -1)
2845 /* No correction needed at zero. */;
2846 else
2848 /* We don't try to do anything clever with the situation found
2849 on some processors (eg Alpha) where ctz(0:mode) ==
2850 bitsize(mode). If someone can think of a way to send N to -1
2851 and leave alone all values in the range 0..N-1 (where N is a
2852 power of two), cheaper than this test-and-branch, please add it.
2854 The test-and-branch is done after the operation itself, in case
2855 the operation sets condition codes that can be recycled for this.
2856 (This is true on i386, for instance.) */
2858 rtx nonzero_label = gen_label_rtx ();
2859 emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
2860 mode, true, nonzero_label);
2862 convert_move (temp, GEN_INT (-1), false);
2863 emit_label (nonzero_label);
2866 /* temp now has a value in the range -1..bitsize-1. ffs is supposed
2867 to produce a value in the range 0..bitsize. */
2868 temp = expand_binop (mode, add_optab, temp, GEN_INT (1),
2869 target, false, OPTAB_DIRECT);
2870 if (!temp)
2871 goto fail;
2873 seq = get_insns ();
2874 end_sequence ();
2876 add_equal_note (seq, temp, FFS, op0, 0);
2877 emit_insn (seq);
2878 return temp;
2880 fail:
2881 end_sequence ();
2882 return 0;
2885 /* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
2886 conditions, VAL may already be a SUBREG against which we cannot generate
2887 a further SUBREG. In this case, we expect forcing the value into a
2888 register will work around the situation. */
2890 static rtx
2891 lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
2892 enum machine_mode imode)
2894 rtx ret;
2895 ret = lowpart_subreg (omode, val, imode);
2896 if (ret == NULL)
2898 val = force_reg (imode, val);
2899 ret = lowpart_subreg (omode, val, imode);
2900 gcc_assert (ret != NULL);
2902 return ret;
2905 /* Expand a floating point absolute value or negation operation via a
2906 logical operation on the sign bit. */
2908 static rtx
2909 expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
2910 rtx op0, rtx target)
2912 const struct real_format *fmt;
2913 int bitpos, word, nwords, i;
2914 enum machine_mode imode;
2915 double_int mask;
2916 rtx temp, insns;
2918 /* The format has to have a simple sign bit. */
2919 fmt = REAL_MODE_FORMAT (mode);
2920 if (fmt == NULL)
2921 return NULL_RTX;
2923 bitpos = fmt->signbit_rw;
2924 if (bitpos < 0)
2925 return NULL_RTX;
2927 /* Don't create negative zeros if the format doesn't support them. */
2928 if (code == NEG && !fmt->has_signed_zero)
2929 return NULL_RTX;
2931 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
2933 imode = int_mode_for_mode (mode);
2934 if (imode == BLKmode)
2935 return NULL_RTX;
2936 word = 0;
2937 nwords = 1;
2939 else
2941 imode = word_mode;
2943 if (FLOAT_WORDS_BIG_ENDIAN)
2944 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
2945 else
2946 word = bitpos / BITS_PER_WORD;
2947 bitpos = bitpos % BITS_PER_WORD;
2948 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
2951 mask = double_int_setbit (double_int_zero, bitpos);
2952 if (code == ABS)
2953 mask = double_int_not (mask);
2955 if (target == 0 || target == op0)
2956 target = gen_reg_rtx (mode);
2958 if (nwords > 1)
2960 start_sequence ();
2962 for (i = 0; i < nwords; ++i)
2964 rtx targ_piece = operand_subword (target, i, 1, mode);
2965 rtx op0_piece = operand_subword_force (op0, i, mode);
2967 if (i == word)
2969 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2970 op0_piece,
2971 immed_double_int_const (mask, imode),
2972 targ_piece, 1, OPTAB_LIB_WIDEN);
2973 if (temp != targ_piece)
2974 emit_move_insn (targ_piece, temp);
2976 else
2977 emit_move_insn (targ_piece, op0_piece);
2980 insns = get_insns ();
2981 end_sequence ();
2983 emit_insn (insns);
2985 else
2987 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2988 gen_lowpart (imode, op0),
2989 immed_double_int_const (mask, imode),
2990 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
2991 target = lowpart_subreg_maybe_copy (mode, temp, imode);
2993 set_unique_reg_note (get_last_insn (), REG_EQUAL,
2994 gen_rtx_fmt_e (code, mode, copy_rtx (op0)));
2997 return target;
3000 /* As expand_unop, but will fail rather than attempt the operation in a
3001 different mode or with a libcall. */
3002 static rtx
3003 expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3004 int unsignedp)
3006 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
3008 int icode = (int) optab_handler (unoptab, mode);
3009 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3010 rtx xop0 = op0;
3011 rtx last = get_last_insn ();
3012 rtx pat, temp;
3014 if (target)
3015 temp = target;
3016 else
3017 temp = gen_reg_rtx (mode);
3019 if (GET_MODE (xop0) != VOIDmode
3020 && GET_MODE (xop0) != mode0)
3021 xop0 = convert_to_mode (mode0, xop0, unsignedp);
3023 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
3025 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
3026 xop0 = copy_to_mode_reg (mode0, xop0);
3028 if (!insn_data[icode].operand[0].predicate (temp, mode))
3029 temp = gen_reg_rtx (mode);
3031 pat = GEN_FCN (icode) (temp, xop0);
3032 if (pat)
3034 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
3035 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
3037 delete_insns_since (last);
3038 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
3041 emit_insn (pat);
3043 return temp;
3045 else
3046 delete_insns_since (last);
3048 return 0;
3051 /* Generate code to perform an operation specified by UNOPTAB
3052 on operand OP0, with result having machine-mode MODE.
3054 UNSIGNEDP is for the case where we have to widen the operands
3055 to perform the operation. It says to use zero-extension.
3057 If TARGET is nonzero, the value
3058 is generated there, if it is convenient to do so.
3059 In all cases an rtx is returned for the locus of the value;
3060 this may or may not be TARGET. */
3063 expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3064 int unsignedp)
3066 enum mode_class mclass = GET_MODE_CLASS (mode);
3067 enum machine_mode wider_mode;
3068 rtx temp;
3069 rtx libfunc;
3071 temp = expand_unop_direct (mode, unoptab, op0, target, unsignedp);
3072 if (temp)
3073 return temp;
3075 /* It can't be done in this mode. Can we open-code it in a wider mode? */
3077 /* Widening (or narrowing) clz needs special treatment. */
3078 if (unoptab == clz_optab)
3080 temp = widen_clz (mode, op0, target);
3081 if (temp)
3082 return temp;
3084 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3085 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
3087 temp = expand_doubleword_clz (mode, op0, target);
3088 if (temp)
3089 return temp;
3092 goto try_libcall;
3095 /* Widening (or narrowing) bswap needs special treatment. */
3096 if (unoptab == bswap_optab)
3098 temp = widen_bswap (mode, op0, target);
3099 if (temp)
3100 return temp;
3102 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3103 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
3105 temp = expand_doubleword_bswap (mode, op0, target);
3106 if (temp)
3107 return temp;
3110 goto try_libcall;
3113 if (CLASS_HAS_WIDER_MODES_P (mclass))
3114 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3115 wider_mode != VOIDmode;
3116 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3118 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
3120 rtx xop0 = op0;
3121 rtx last = get_last_insn ();
3123 /* For certain operations, we need not actually extend
3124 the narrow operand, as long as we will truncate the
3125 results to the same narrowness. */
3127 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3128 (unoptab == neg_optab
3129 || unoptab == one_cmpl_optab)
3130 && mclass == MODE_INT);
3132 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3133 unsignedp);
3135 if (temp)
3137 if (mclass != MODE_INT
3138 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
3139 GET_MODE_BITSIZE (wider_mode)))
3141 if (target == 0)
3142 target = gen_reg_rtx (mode);
3143 convert_move (target, temp, 0);
3144 return target;
3146 else
3147 return gen_lowpart (mode, temp);
3149 else
3150 delete_insns_since (last);
3154 /* These can be done a word at a time. */
3155 if (unoptab == one_cmpl_optab
3156 && mclass == MODE_INT
3157 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
3158 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
3160 int i;
3161 rtx insns;
3163 if (target == 0 || target == op0)
3164 target = gen_reg_rtx (mode);
3166 start_sequence ();
3168 /* Do the actual arithmetic. */
3169 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
3171 rtx target_piece = operand_subword (target, i, 1, mode);
3172 rtx x = expand_unop (word_mode, unoptab,
3173 operand_subword_force (op0, i, mode),
3174 target_piece, unsignedp);
3176 if (target_piece != x)
3177 emit_move_insn (target_piece, x);
3180 insns = get_insns ();
3181 end_sequence ();
3183 emit_insn (insns);
3184 return target;
3187 if (unoptab->code == NEG)
3189 /* Try negating floating point values by flipping the sign bit. */
3190 if (SCALAR_FLOAT_MODE_P (mode))
3192 temp = expand_absneg_bit (NEG, mode, op0, target);
3193 if (temp)
3194 return temp;
3197 /* If there is no negation pattern, and we have no negative zero,
3198 try subtracting from zero. */
3199 if (!HONOR_SIGNED_ZEROS (mode))
3201 temp = expand_binop (mode, (unoptab == negv_optab
3202 ? subv_optab : sub_optab),
3203 CONST0_RTX (mode), op0, target,
3204 unsignedp, OPTAB_DIRECT);
3205 if (temp)
3206 return temp;
3210 /* Try calculating parity (x) as popcount (x) % 2. */
3211 if (unoptab == parity_optab)
3213 temp = expand_parity (mode, op0, target);
3214 if (temp)
3215 return temp;
3218 /* Try implementing ffs (x) in terms of clz (x). */
3219 if (unoptab == ffs_optab)
3221 temp = expand_ffs (mode, op0, target);
3222 if (temp)
3223 return temp;
3226 /* Try implementing ctz (x) in terms of clz (x). */
3227 if (unoptab == ctz_optab)
3229 temp = expand_ctz (mode, op0, target);
3230 if (temp)
3231 return temp;
3234 try_libcall:
3235 /* Now try a library call in this mode. */
3236 libfunc = optab_libfunc (unoptab, mode);
3237 if (libfunc)
3239 rtx insns;
3240 rtx value;
3241 rtx eq_value;
3242 enum machine_mode outmode = mode;
3244 /* All of these functions return small values. Thus we choose to
3245 have them return something that isn't a double-word. */
3246 if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
3247 || unoptab == popcount_optab || unoptab == parity_optab)
3248 outmode
3249 = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
3250 optab_libfunc (unoptab, mode)));
3252 start_sequence ();
3254 /* Pass 1 for NO_QUEUE so we don't lose any increments
3255 if the libcall is cse'd or moved. */
3256 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, outmode,
3257 1, op0, mode);
3258 insns = get_insns ();
3259 end_sequence ();
3261 target = gen_reg_rtx (outmode);
3262 eq_value = gen_rtx_fmt_e (unoptab->code, mode, op0);
3263 if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
3264 eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
3265 else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
3266 eq_value = simplify_gen_unary (ZERO_EXTEND, outmode, eq_value, mode);
3267 emit_libcall_block (insns, target, value, eq_value);
3269 return target;
3272 /* It can't be done in this mode. Can we do it in a wider mode? */
3274 if (CLASS_HAS_WIDER_MODES_P (mclass))
3276 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3277 wider_mode != VOIDmode;
3278 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3280 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing
3281 || optab_libfunc (unoptab, wider_mode))
3283 rtx xop0 = op0;
3284 rtx last = get_last_insn ();
3286 /* For certain operations, we need not actually extend
3287 the narrow operand, as long as we will truncate the
3288 results to the same narrowness. */
3290 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3291 (unoptab == neg_optab
3292 || unoptab == one_cmpl_optab)
3293 && mclass == MODE_INT);
3295 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3296 unsignedp);
3298 /* If we are generating clz using wider mode, adjust the
3299 result. */
3300 if (unoptab == clz_optab && temp != 0)
3301 temp = expand_binop (wider_mode, sub_optab, temp,
3302 GEN_INT (GET_MODE_BITSIZE (wider_mode)
3303 - GET_MODE_BITSIZE (mode)),
3304 target, true, OPTAB_DIRECT);
3306 if (temp)
3308 if (mclass != MODE_INT)
3310 if (target == 0)
3311 target = gen_reg_rtx (mode);
3312 convert_move (target, temp, 0);
3313 return target;
3315 else
3316 return gen_lowpart (mode, temp);
3318 else
3319 delete_insns_since (last);
3324 /* One final attempt at implementing negation via subtraction,
3325 this time allowing widening of the operand. */
3326 if (unoptab->code == NEG && !HONOR_SIGNED_ZEROS (mode))
3328 rtx temp;
3329 temp = expand_binop (mode,
3330 unoptab == negv_optab ? subv_optab : sub_optab,
3331 CONST0_RTX (mode), op0,
3332 target, unsignedp, OPTAB_LIB_WIDEN);
3333 if (temp)
3334 return temp;
3337 return 0;
3340 /* Emit code to compute the absolute value of OP0, with result to
3341 TARGET if convenient. (TARGET may be 0.) The return value says
3342 where the result actually is to be found.
3344 MODE is the mode of the operand; the mode of the result is
3345 different but can be deduced from MODE.
3350 expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
3351 int result_unsignedp)
3353 rtx temp;
3355 if (! flag_trapv)
3356 result_unsignedp = 1;
3358 /* First try to do it with a special abs instruction. */
3359 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
3360 op0, target, 0);
3361 if (temp != 0)
3362 return temp;
3364 /* For floating point modes, try clearing the sign bit. */
3365 if (SCALAR_FLOAT_MODE_P (mode))
3367 temp = expand_absneg_bit (ABS, mode, op0, target);
3368 if (temp)
3369 return temp;
3372 /* If we have a MAX insn, we can do this as MAX (x, -x). */
3373 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing
3374 && !HONOR_SIGNED_ZEROS (mode))
3376 rtx last = get_last_insn ();
3378 temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
3379 if (temp != 0)
3380 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3381 OPTAB_WIDEN);
3383 if (temp != 0)
3384 return temp;
3386 delete_insns_since (last);
3389 /* If this machine has expensive jumps, we can do integer absolute
3390 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
3391 where W is the width of MODE. */
3393 if (GET_MODE_CLASS (mode) == MODE_INT
3394 && BRANCH_COST (optimize_insn_for_speed_p (),
3395 false) >= 2)
3397 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3398 size_int (GET_MODE_BITSIZE (mode) - 1),
3399 NULL_RTX, 0);
3401 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3402 OPTAB_LIB_WIDEN);
3403 if (temp != 0)
3404 temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
3405 temp, extended, target, 0, OPTAB_LIB_WIDEN);
3407 if (temp != 0)
3408 return temp;
3411 return NULL_RTX;
3415 expand_abs (enum machine_mode mode, rtx op0, rtx target,
3416 int result_unsignedp, int safe)
3418 rtx temp, op1;
3420 if (! flag_trapv)
3421 result_unsignedp = 1;
3423 temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
3424 if (temp != 0)
3425 return temp;
3427 /* If that does not win, use conditional jump and negate. */
3429 /* It is safe to use the target if it is the same
3430 as the source if this is also a pseudo register */
3431 if (op0 == target && REG_P (op0)
3432 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
3433 safe = 1;
3435 op1 = gen_label_rtx ();
3436 if (target == 0 || ! safe
3437 || GET_MODE (target) != mode
3438 || (MEM_P (target) && MEM_VOLATILE_P (target))
3439 || (REG_P (target)
3440 && REGNO (target) < FIRST_PSEUDO_REGISTER))
3441 target = gen_reg_rtx (mode);
3443 emit_move_insn (target, op0);
3444 NO_DEFER_POP;
3446 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
3447 NULL_RTX, NULL_RTX, op1, -1);
3449 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3450 target, target, 0);
3451 if (op0 != target)
3452 emit_move_insn (target, op0);
3453 emit_label (op1);
3454 OK_DEFER_POP;
3455 return target;
3458 /* Emit code to compute the one's complement absolute value of OP0
3459 (if (OP0 < 0) OP0 = ~OP0), with result to TARGET if convenient.
3460 (TARGET may be NULL_RTX.) The return value says where the result
3461 actually is to be found.
3463 MODE is the mode of the operand; the mode of the result is
3464 different but can be deduced from MODE. */
3467 expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
3469 rtx temp;
3471 /* Not applicable for floating point modes. */
3472 if (FLOAT_MODE_P (mode))
3473 return NULL_RTX;
3475 /* If we have a MAX insn, we can do this as MAX (x, ~x). */
3476 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing)
3478 rtx last = get_last_insn ();
3480 temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
3481 if (temp != 0)
3482 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3483 OPTAB_WIDEN);
3485 if (temp != 0)
3486 return temp;
3488 delete_insns_since (last);
3491 /* If this machine has expensive jumps, we can do one's complement
3492 absolute value of X as (((signed) x >> (W-1)) ^ x). */
3494 if (GET_MODE_CLASS (mode) == MODE_INT
3495 && BRANCH_COST (optimize_insn_for_speed_p (),
3496 false) >= 2)
3498 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3499 size_int (GET_MODE_BITSIZE (mode) - 1),
3500 NULL_RTX, 0);
3502 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3503 OPTAB_LIB_WIDEN);
3505 if (temp != 0)
3506 return temp;
3509 return NULL_RTX;
3512 /* A subroutine of expand_copysign, perform the copysign operation using the
3513 abs and neg primitives advertised to exist on the target. The assumption
3514 is that we have a split register file, and leaving op0 in fp registers,
3515 and not playing with subregs so much, will help the register allocator. */
3517 static rtx
3518 expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3519 int bitpos, bool op0_is_abs)
3521 enum machine_mode imode;
3522 int icode;
3523 rtx sign, label;
3525 if (target == op1)
3526 target = NULL_RTX;
3528 /* Check if the back end provides an insn that handles signbit for the
3529 argument's mode. */
3530 icode = (int) optab_handler (signbit_optab, mode);
3531 if (icode != CODE_FOR_nothing)
3533 imode = insn_data[icode].operand[0].mode;
3534 sign = gen_reg_rtx (imode);
3535 emit_unop_insn (icode, sign, op1, UNKNOWN);
3537 else
3539 double_int mask;
3541 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3543 imode = int_mode_for_mode (mode);
3544 if (imode == BLKmode)
3545 return NULL_RTX;
3546 op1 = gen_lowpart (imode, op1);
3548 else
3550 int word;
3552 imode = word_mode;
3553 if (FLOAT_WORDS_BIG_ENDIAN)
3554 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3555 else
3556 word = bitpos / BITS_PER_WORD;
3557 bitpos = bitpos % BITS_PER_WORD;
3558 op1 = operand_subword_force (op1, word, mode);
3561 mask = double_int_setbit (double_int_zero, bitpos);
3563 sign = expand_binop (imode, and_optab, op1,
3564 immed_double_int_const (mask, imode),
3565 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3568 if (!op0_is_abs)
3570 op0 = expand_unop (mode, abs_optab, op0, target, 0);
3571 if (op0 == NULL)
3572 return NULL_RTX;
3573 target = op0;
3575 else
3577 if (target == NULL_RTX)
3578 target = copy_to_reg (op0);
3579 else
3580 emit_move_insn (target, op0);
3583 label = gen_label_rtx ();
3584 emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
3586 if (GET_CODE (op0) == CONST_DOUBLE)
3587 op0 = simplify_unary_operation (NEG, mode, op0, mode);
3588 else
3589 op0 = expand_unop (mode, neg_optab, op0, target, 0);
3590 if (op0 != target)
3591 emit_move_insn (target, op0);
3593 emit_label (label);
3595 return target;
3599 /* A subroutine of expand_copysign, perform the entire copysign operation
3600 with integer bitmasks. BITPOS is the position of the sign bit; OP0_IS_ABS
3601 is true if op0 is known to have its sign bit clear. */
3603 static rtx
3604 expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3605 int bitpos, bool op0_is_abs)
3607 enum machine_mode imode;
3608 double_int mask;
3609 int word, nwords, i;
3610 rtx temp, insns;
3612 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3614 imode = int_mode_for_mode (mode);
3615 if (imode == BLKmode)
3616 return NULL_RTX;
3617 word = 0;
3618 nwords = 1;
3620 else
3622 imode = word_mode;
3624 if (FLOAT_WORDS_BIG_ENDIAN)
3625 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3626 else
3627 word = bitpos / BITS_PER_WORD;
3628 bitpos = bitpos % BITS_PER_WORD;
3629 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
3632 mask = double_int_setbit (double_int_zero, bitpos);
3634 if (target == 0 || target == op0 || target == op1)
3635 target = gen_reg_rtx (mode);
3637 if (nwords > 1)
3639 start_sequence ();
3641 for (i = 0; i < nwords; ++i)
3643 rtx targ_piece = operand_subword (target, i, 1, mode);
3644 rtx op0_piece = operand_subword_force (op0, i, mode);
3646 if (i == word)
3648 if (!op0_is_abs)
3649 op0_piece
3650 = expand_binop (imode, and_optab, op0_piece,
3651 immed_double_int_const (double_int_not (mask),
3652 imode),
3653 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3655 op1 = expand_binop (imode, and_optab,
3656 operand_subword_force (op1, i, mode),
3657 immed_double_int_const (mask, imode),
3658 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3660 temp = expand_binop (imode, ior_optab, op0_piece, op1,
3661 targ_piece, 1, OPTAB_LIB_WIDEN);
3662 if (temp != targ_piece)
3663 emit_move_insn (targ_piece, temp);
3665 else
3666 emit_move_insn (targ_piece, op0_piece);
3669 insns = get_insns ();
3670 end_sequence ();
3672 emit_insn (insns);
3674 else
3676 op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
3677 immed_double_int_const (mask, imode),
3678 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3680 op0 = gen_lowpart (imode, op0);
3681 if (!op0_is_abs)
3682 op0 = expand_binop (imode, and_optab, op0,
3683 immed_double_int_const (double_int_not (mask),
3684 imode),
3685 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3687 temp = expand_binop (imode, ior_optab, op0, op1,
3688 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3689 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3692 return target;
3695 /* Expand the C99 copysign operation. OP0 and OP1 must be the same
3696 scalar floating point mode. Return NULL if we do not know how to
3697 expand the operation inline. */
3700 expand_copysign (rtx op0, rtx op1, rtx target)
3702 enum machine_mode mode = GET_MODE (op0);
3703 const struct real_format *fmt;
3704 bool op0_is_abs;
3705 rtx temp;
3707 gcc_assert (SCALAR_FLOAT_MODE_P (mode));
3708 gcc_assert (GET_MODE (op1) == mode);
3710 /* First try to do it with a special instruction. */
3711 temp = expand_binop (mode, copysign_optab, op0, op1,
3712 target, 0, OPTAB_DIRECT);
3713 if (temp)
3714 return temp;
3716 fmt = REAL_MODE_FORMAT (mode);
3717 if (fmt == NULL || !fmt->has_signed_zero)
3718 return NULL_RTX;
3720 op0_is_abs = false;
3721 if (GET_CODE (op0) == CONST_DOUBLE)
3723 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
3724 op0 = simplify_unary_operation (ABS, mode, op0, mode);
3725 op0_is_abs = true;
3728 if (fmt->signbit_ro >= 0
3729 && (GET_CODE (op0) == CONST_DOUBLE
3730 || (optab_handler (neg_optab, mode) != CODE_FOR_nothing
3731 && optab_handler (abs_optab, mode) != CODE_FOR_nothing)))
3733 temp = expand_copysign_absneg (mode, op0, op1, target,
3734 fmt->signbit_ro, op0_is_abs);
3735 if (temp)
3736 return temp;
3739 if (fmt->signbit_rw < 0)
3740 return NULL_RTX;
3741 return expand_copysign_bit (mode, op0, op1, target,
3742 fmt->signbit_rw, op0_is_abs);
3745 /* Generate an instruction whose insn-code is INSN_CODE,
3746 with two operands: an output TARGET and an input OP0.
3747 TARGET *must* be nonzero, and the output is always stored there.
3748 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3749 the value that is stored into TARGET.
3751 Return false if expansion failed. */
3753 bool
3754 maybe_emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3756 rtx temp;
3757 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3758 rtx pat;
3759 rtx last = get_last_insn ();
3761 temp = target;
3763 /* Now, if insn does not accept our operands, put them into pseudos. */
3765 if (!insn_data[icode].operand[1].predicate (op0, mode0))
3766 op0 = copy_to_mode_reg (mode0, op0);
3768 if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
3769 temp = gen_reg_rtx (GET_MODE (temp));
3771 pat = GEN_FCN (icode) (temp, op0);
3772 if (!pat)
3774 delete_insns_since (last);
3775 return false;
3778 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
3779 add_equal_note (pat, temp, code, op0, NULL_RTX);
3781 emit_insn (pat);
3783 if (temp != target)
3784 emit_move_insn (target, temp);
3785 return true;
3787 /* Generate an instruction whose insn-code is INSN_CODE,
3788 with two operands: an output TARGET and an input OP0.
3789 TARGET *must* be nonzero, and the output is always stored there.
3790 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3791 the value that is stored into TARGET. */
3793 void
3794 emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3796 bool ok = maybe_emit_unop_insn (icode, target, op0, code);
3797 gcc_assert (ok);
3800 struct no_conflict_data
3802 rtx target, first, insn;
3803 bool must_stay;
3806 /* Called via note_stores by emit_libcall_block. Set P->must_stay if
3807 the currently examined clobber / store has to stay in the list of
3808 insns that constitute the actual libcall block. */
3809 static void
3810 no_conflict_move_test (rtx dest, const_rtx set, void *p0)
3812 struct no_conflict_data *p= (struct no_conflict_data *) p0;
3814 /* If this inns directly contributes to setting the target, it must stay. */
3815 if (reg_overlap_mentioned_p (p->target, dest))
3816 p->must_stay = true;
3817 /* If we haven't committed to keeping any other insns in the list yet,
3818 there is nothing more to check. */
3819 else if (p->insn == p->first)
3820 return;
3821 /* If this insn sets / clobbers a register that feeds one of the insns
3822 already in the list, this insn has to stay too. */
3823 else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
3824 || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
3825 || reg_used_between_p (dest, p->first, p->insn)
3826 /* Likewise if this insn depends on a register set by a previous
3827 insn in the list, or if it sets a result (presumably a hard
3828 register) that is set or clobbered by a previous insn.
3829 N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
3830 SET_DEST perform the former check on the address, and the latter
3831 check on the MEM. */
3832 || (GET_CODE (set) == SET
3833 && (modified_in_p (SET_SRC (set), p->first)
3834 || modified_in_p (SET_DEST (set), p->first)
3835 || modified_between_p (SET_SRC (set), p->first, p->insn)
3836 || modified_between_p (SET_DEST (set), p->first, p->insn))))
3837 p->must_stay = true;
3841 /* Emit code to make a call to a constant function or a library call.
3843 INSNS is a list containing all insns emitted in the call.
3844 These insns leave the result in RESULT. Our block is to copy RESULT
3845 to TARGET, which is logically equivalent to EQUIV.
3847 We first emit any insns that set a pseudo on the assumption that these are
3848 loading constants into registers; doing so allows them to be safely cse'ed
3849 between blocks. Then we emit all the other insns in the block, followed by
3850 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
3851 note with an operand of EQUIV. */
3853 void
3854 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
3856 rtx final_dest = target;
3857 rtx next, last, insn;
3859 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
3860 into a MEM later. Protect the libcall block from this change. */
3861 if (! REG_P (target) || REG_USERVAR_P (target))
3862 target = gen_reg_rtx (GET_MODE (target));
3864 /* If we're using non-call exceptions, a libcall corresponding to an
3865 operation that may trap may also trap. */
3866 /* ??? See the comment in front of make_reg_eh_region_note. */
3867 if (cfun->can_throw_non_call_exceptions && may_trap_p (equiv))
3869 for (insn = insns; insn; insn = NEXT_INSN (insn))
3870 if (CALL_P (insn))
3872 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3873 if (note)
3875 int lp_nr = INTVAL (XEXP (note, 0));
3876 if (lp_nr == 0 || lp_nr == INT_MIN)
3877 remove_note (insn, note);
3881 else
3883 /* Look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
3884 reg note to indicate that this call cannot throw or execute a nonlocal
3885 goto (unless there is already a REG_EH_REGION note, in which case
3886 we update it). */
3887 for (insn = insns; insn; insn = NEXT_INSN (insn))
3888 if (CALL_P (insn))
3889 make_reg_eh_region_note_nothrow_nononlocal (insn);
3892 /* First emit all insns that set pseudos. Remove them from the list as
3893 we go. Avoid insns that set pseudos which were referenced in previous
3894 insns. These can be generated by move_by_pieces, for example,
3895 to update an address. Similarly, avoid insns that reference things
3896 set in previous insns. */
3898 for (insn = insns; insn; insn = next)
3900 rtx set = single_set (insn);
3902 next = NEXT_INSN (insn);
3904 if (set != 0 && REG_P (SET_DEST (set))
3905 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
3907 struct no_conflict_data data;
3909 data.target = const0_rtx;
3910 data.first = insns;
3911 data.insn = insn;
3912 data.must_stay = 0;
3913 note_stores (PATTERN (insn), no_conflict_move_test, &data);
3914 if (! data.must_stay)
3916 if (PREV_INSN (insn))
3917 NEXT_INSN (PREV_INSN (insn)) = next;
3918 else
3919 insns = next;
3921 if (next)
3922 PREV_INSN (next) = PREV_INSN (insn);
3924 add_insn (insn);
3928 /* Some ports use a loop to copy large arguments onto the stack.
3929 Don't move anything outside such a loop. */
3930 if (LABEL_P (insn))
3931 break;
3934 /* Write the remaining insns followed by the final copy. */
3935 for (insn = insns; insn; insn = next)
3937 next = NEXT_INSN (insn);
3939 add_insn (insn);
3942 last = emit_move_insn (target, result);
3943 if (optab_handler (mov_optab, GET_MODE (target)) != CODE_FOR_nothing)
3944 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
3946 if (final_dest != target)
3947 emit_move_insn (final_dest, target);
3950 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
3951 PURPOSE describes how this comparison will be used. CODE is the rtx
3952 comparison code we will be using.
3954 ??? Actually, CODE is slightly weaker than that. A target is still
3955 required to implement all of the normal bcc operations, but not
3956 required to implement all (or any) of the unordered bcc operations. */
3959 can_compare_p (enum rtx_code code, enum machine_mode mode,
3960 enum can_compare_purpose purpose)
3962 rtx test;
3963 test = gen_rtx_fmt_ee (code, mode, const0_rtx, const0_rtx);
3966 int icode;
3968 if (purpose == ccp_jump
3969 && (icode = optab_handler (cbranch_optab, mode)) != CODE_FOR_nothing
3970 && insn_data[icode].operand[0].predicate (test, mode))
3971 return 1;
3972 if (purpose == ccp_store_flag
3973 && (icode = optab_handler (cstore_optab, mode)) != CODE_FOR_nothing
3974 && insn_data[icode].operand[1].predicate (test, mode))
3975 return 1;
3976 if (purpose == ccp_cmov
3977 && optab_handler (cmov_optab, mode) != CODE_FOR_nothing)
3978 return 1;
3980 mode = GET_MODE_WIDER_MODE (mode);
3981 PUT_MODE (test, mode);
3983 while (mode != VOIDmode);
3985 return 0;
3988 /* This function is called when we are going to emit a compare instruction that
3989 compares the values found in *PX and *PY, using the rtl operator COMPARISON.
3991 *PMODE is the mode of the inputs (in case they are const_int).
3992 *PUNSIGNEDP nonzero says that the operands are unsigned;
3993 this matters if they need to be widened (as given by METHODS).
3995 If they have mode BLKmode, then SIZE specifies the size of both operands.
3997 This function performs all the setup necessary so that the caller only has
3998 to emit a single comparison insn. This setup can involve doing a BLKmode
3999 comparison or emitting a library call to perform the comparison if no insn
4000 is available to handle it.
4001 The values which are passed in through pointers can be modified; the caller
4002 should perform the comparison on the modified values. Constant
4003 comparisons must have already been folded. */
4005 static void
4006 prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
4007 int unsignedp, enum optab_methods methods,
4008 rtx *ptest, enum machine_mode *pmode)
4010 enum machine_mode mode = *pmode;
4011 rtx libfunc, test;
4012 enum machine_mode cmp_mode;
4013 enum mode_class mclass;
4015 /* The other methods are not needed. */
4016 gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
4017 || methods == OPTAB_LIB_WIDEN);
4019 /* If we are optimizing, force expensive constants into a register. */
4020 if (CONSTANT_P (x) && optimize
4021 && (rtx_cost (x, COMPARE, optimize_insn_for_speed_p ())
4022 > COSTS_N_INSNS (1)))
4023 x = force_reg (mode, x);
4025 if (CONSTANT_P (y) && optimize
4026 && (rtx_cost (y, COMPARE, optimize_insn_for_speed_p ())
4027 > COSTS_N_INSNS (1)))
4028 y = force_reg (mode, y);
4030 #ifdef HAVE_cc0
4031 /* Make sure if we have a canonical comparison. The RTL
4032 documentation states that canonical comparisons are required only
4033 for targets which have cc0. */
4034 gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
4035 #endif
4037 /* Don't let both operands fail to indicate the mode. */
4038 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
4039 x = force_reg (mode, x);
4040 if (mode == VOIDmode)
4041 mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : GET_MODE (y);
4043 /* Handle all BLKmode compares. */
4045 if (mode == BLKmode)
4047 enum machine_mode result_mode;
4048 enum insn_code cmp_code;
4049 tree length_type;
4050 rtx libfunc;
4051 rtx result;
4052 rtx opalign
4053 = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
4055 gcc_assert (size);
4057 /* Try to use a memory block compare insn - either cmpstr
4058 or cmpmem will do. */
4059 for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
4060 cmp_mode != VOIDmode;
4061 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
4063 cmp_code = direct_optab_handler (cmpmem_optab, cmp_mode);
4064 if (cmp_code == CODE_FOR_nothing)
4065 cmp_code = direct_optab_handler (cmpstr_optab, cmp_mode);
4066 if (cmp_code == CODE_FOR_nothing)
4067 cmp_code = direct_optab_handler (cmpstrn_optab, cmp_mode);
4068 if (cmp_code == CODE_FOR_nothing)
4069 continue;
4071 /* Must make sure the size fits the insn's mode. */
4072 if ((CONST_INT_P (size)
4073 && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
4074 || (GET_MODE_BITSIZE (GET_MODE (size))
4075 > GET_MODE_BITSIZE (cmp_mode)))
4076 continue;
4078 result_mode = insn_data[cmp_code].operand[0].mode;
4079 result = gen_reg_rtx (result_mode);
4080 size = convert_to_mode (cmp_mode, size, 1);
4081 emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
4083 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4084 *pmode = result_mode;
4085 return;
4088 if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
4089 goto fail;
4091 /* Otherwise call a library function, memcmp. */
4092 libfunc = memcmp_libfunc;
4093 length_type = sizetype;
4094 result_mode = TYPE_MODE (integer_type_node);
4095 cmp_mode = TYPE_MODE (length_type);
4096 size = convert_to_mode (TYPE_MODE (length_type), size,
4097 TYPE_UNSIGNED (length_type));
4099 result = emit_library_call_value (libfunc, 0, LCT_PURE,
4100 result_mode, 3,
4101 XEXP (x, 0), Pmode,
4102 XEXP (y, 0), Pmode,
4103 size, cmp_mode);
4105 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4106 *pmode = result_mode;
4107 return;
4110 /* Don't allow operands to the compare to trap, as that can put the
4111 compare and branch in different basic blocks. */
4112 if (cfun->can_throw_non_call_exceptions)
4114 if (may_trap_p (x))
4115 x = force_reg (mode, x);
4116 if (may_trap_p (y))
4117 y = force_reg (mode, y);
4120 if (GET_MODE_CLASS (mode) == MODE_CC)
4122 gcc_assert (can_compare_p (comparison, CCmode, ccp_jump));
4123 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4124 return;
4127 mclass = GET_MODE_CLASS (mode);
4128 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4129 cmp_mode = mode;
4132 enum insn_code icode;
4133 icode = optab_handler (cbranch_optab, cmp_mode);
4134 if (icode != CODE_FOR_nothing
4135 && insn_data[icode].operand[0].predicate (test, VOIDmode))
4137 rtx last = get_last_insn ();
4138 rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp);
4139 rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp);
4140 if (op0 && op1
4141 && insn_data[icode].operand[1].predicate
4142 (op0, insn_data[icode].operand[1].mode)
4143 && insn_data[icode].operand[2].predicate
4144 (op1, insn_data[icode].operand[2].mode))
4146 XEXP (test, 0) = op0;
4147 XEXP (test, 1) = op1;
4148 *ptest = test;
4149 *pmode = cmp_mode;
4150 return;
4152 delete_insns_since (last);
4155 if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
4156 break;
4157 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode);
4159 while (cmp_mode != VOIDmode);
4161 if (methods != OPTAB_LIB_WIDEN)
4162 goto fail;
4164 if (!SCALAR_FLOAT_MODE_P (mode))
4166 rtx result;
4168 /* Handle a libcall just for the mode we are using. */
4169 libfunc = optab_libfunc (cmp_optab, mode);
4170 gcc_assert (libfunc);
4172 /* If we want unsigned, and this mode has a distinct unsigned
4173 comparison routine, use that. */
4174 if (unsignedp)
4176 rtx ulibfunc = optab_libfunc (ucmp_optab, mode);
4177 if (ulibfunc)
4178 libfunc = ulibfunc;
4181 result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4182 targetm.libgcc_cmp_return_mode (),
4183 2, x, mode, y, mode);
4185 /* There are two kinds of comparison routines. Biased routines
4186 return 0/1/2, and unbiased routines return -1/0/1. Other parts
4187 of gcc expect that the comparison operation is equivalent
4188 to the modified comparison. For signed comparisons compare the
4189 result against 1 in the biased case, and zero in the unbiased
4190 case. For unsigned comparisons always compare against 1 after
4191 biasing the unbiased result by adding 1. This gives us a way to
4192 represent LTU. */
4193 x = result;
4194 y = const1_rtx;
4196 if (!TARGET_LIB_INT_CMP_BIASED)
4198 if (unsignedp)
4199 x = plus_constant (result, 1);
4200 else
4201 y = const0_rtx;
4204 *pmode = word_mode;
4205 prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods,
4206 ptest, pmode);
4208 else
4209 prepare_float_lib_cmp (x, y, comparison, ptest, pmode);
4211 return;
4213 fail:
4214 *ptest = NULL_RTX;
4217 /* Before emitting an insn with code ICODE, make sure that X, which is going
4218 to be used for operand OPNUM of the insn, is converted from mode MODE to
4219 WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
4220 that it is accepted by the operand predicate. Return the new value. */
4223 prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
4224 enum machine_mode wider_mode, int unsignedp)
4226 if (mode != wider_mode)
4227 x = convert_modes (wider_mode, mode, x, unsignedp);
4229 if (!insn_data[icode].operand[opnum].predicate
4230 (x, insn_data[icode].operand[opnum].mode))
4232 if (reload_completed)
4233 return NULL_RTX;
4234 x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
4237 return x;
4240 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
4241 we can do the branch. */
4243 static void
4244 emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label)
4246 enum machine_mode optab_mode;
4247 enum mode_class mclass;
4248 enum insn_code icode;
4250 mclass = GET_MODE_CLASS (mode);
4251 optab_mode = (mclass == MODE_CC) ? CCmode : mode;
4252 icode = optab_handler (cbranch_optab, optab_mode);
4254 gcc_assert (icode != CODE_FOR_nothing);
4255 gcc_assert (insn_data[icode].operand[0].predicate (test, VOIDmode));
4256 emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0), XEXP (test, 1), label));
4259 /* Generate code to compare X with Y so that the condition codes are
4260 set and to jump to LABEL if the condition is true. If X is a
4261 constant and Y is not a constant, then the comparison is swapped to
4262 ensure that the comparison RTL has the canonical form.
4264 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
4265 need to be widened. UNSIGNEDP is also used to select the proper
4266 branch condition code.
4268 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
4270 MODE is the mode of the inputs (in case they are const_int).
4272 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
4273 It will be potentially converted into an unsigned variant based on
4274 UNSIGNEDP to select a proper jump instruction. */
4276 void
4277 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
4278 enum machine_mode mode, int unsignedp, rtx label)
4280 rtx op0 = x, op1 = y;
4281 rtx test;
4283 /* Swap operands and condition to ensure canonical RTL. */
4284 if (swap_commutative_operands_p (x, y)
4285 && can_compare_p (swap_condition (comparison), mode, ccp_jump))
4287 op0 = y, op1 = x;
4288 comparison = swap_condition (comparison);
4291 /* If OP0 is still a constant, then both X and Y must be constants
4292 or the opposite comparison is not supported. Force X into a register
4293 to create canonical RTL. */
4294 if (CONSTANT_P (op0))
4295 op0 = force_reg (mode, op0);
4297 if (unsignedp)
4298 comparison = unsigned_condition (comparison);
4300 prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
4301 &test, &mode);
4302 emit_cmp_and_jump_insn_1 (test, mode, label);
4306 /* Emit a library call comparison between floating point X and Y.
4307 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
4309 static void
4310 prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
4311 rtx *ptest, enum machine_mode *pmode)
4313 enum rtx_code swapped = swap_condition (comparison);
4314 enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
4315 enum machine_mode orig_mode = GET_MODE (x);
4316 enum machine_mode mode, cmp_mode;
4317 rtx true_rtx, false_rtx;
4318 rtx value, target, insns, equiv;
4319 rtx libfunc = 0;
4320 bool reversed_p = false;
4321 cmp_mode = targetm.libgcc_cmp_return_mode ();
4323 for (mode = orig_mode;
4324 mode != VOIDmode;
4325 mode = GET_MODE_WIDER_MODE (mode))
4327 if (code_to_optab[comparison]
4328 && (libfunc = optab_libfunc (code_to_optab[comparison], mode)))
4329 break;
4331 if (code_to_optab[swapped]
4332 && (libfunc = optab_libfunc (code_to_optab[swapped], mode)))
4334 rtx tmp;
4335 tmp = x; x = y; y = tmp;
4336 comparison = swapped;
4337 break;
4340 if (code_to_optab[reversed]
4341 && (libfunc = optab_libfunc (code_to_optab[reversed], mode)))
4343 comparison = reversed;
4344 reversed_p = true;
4345 break;
4349 gcc_assert (mode != VOIDmode);
4351 if (mode != orig_mode)
4353 x = convert_to_mode (mode, x, 0);
4354 y = convert_to_mode (mode, y, 0);
4357 /* Attach a REG_EQUAL note describing the semantics of the libcall to
4358 the RTL. The allows the RTL optimizers to delete the libcall if the
4359 condition can be determined at compile-time. */
4360 if (comparison == UNORDERED
4361 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4363 true_rtx = const_true_rtx;
4364 false_rtx = const0_rtx;
4366 else
4368 switch (comparison)
4370 case EQ:
4371 true_rtx = const0_rtx;
4372 false_rtx = const_true_rtx;
4373 break;
4375 case NE:
4376 true_rtx = const_true_rtx;
4377 false_rtx = const0_rtx;
4378 break;
4380 case GT:
4381 true_rtx = const1_rtx;
4382 false_rtx = const0_rtx;
4383 break;
4385 case GE:
4386 true_rtx = const0_rtx;
4387 false_rtx = constm1_rtx;
4388 break;
4390 case LT:
4391 true_rtx = constm1_rtx;
4392 false_rtx = const0_rtx;
4393 break;
4395 case LE:
4396 true_rtx = const0_rtx;
4397 false_rtx = const1_rtx;
4398 break;
4400 default:
4401 gcc_unreachable ();
4405 if (comparison == UNORDERED)
4407 rtx temp = simplify_gen_relational (NE, cmp_mode, mode, x, x);
4408 equiv = simplify_gen_relational (NE, cmp_mode, mode, y, y);
4409 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4410 temp, const_true_rtx, equiv);
4412 else
4414 equiv = simplify_gen_relational (comparison, cmp_mode, mode, x, y);
4415 if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4416 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4417 equiv, true_rtx, false_rtx);
4420 start_sequence ();
4421 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4422 cmp_mode, 2, x, mode, y, mode);
4423 insns = get_insns ();
4424 end_sequence ();
4426 target = gen_reg_rtx (cmp_mode);
4427 emit_libcall_block (insns, target, value, equiv);
4429 if (comparison == UNORDERED
4430 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison)
4431 || reversed_p)
4432 *ptest = gen_rtx_fmt_ee (reversed_p ? EQ : NE, VOIDmode, target, false_rtx);
4433 else
4434 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, target, const0_rtx);
4436 *pmode = cmp_mode;
4439 /* Generate code to indirectly jump to a location given in the rtx LOC. */
4441 void
4442 emit_indirect_jump (rtx loc)
4444 if (!insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate
4445 (loc, Pmode))
4446 loc = copy_to_mode_reg (Pmode, loc);
4448 emit_jump_insn (gen_indirect_jump (loc));
4449 emit_barrier ();
4452 #ifdef HAVE_conditional_move
4454 /* Emit a conditional move instruction if the machine supports one for that
4455 condition and machine mode.
4457 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4458 the mode to use should they be constants. If it is VOIDmode, they cannot
4459 both be constants.
4461 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
4462 should be stored there. MODE is the mode to use should they be constants.
4463 If it is VOIDmode, they cannot both be constants.
4465 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4466 is not supported. */
4469 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
4470 enum machine_mode cmode, rtx op2, rtx op3,
4471 enum machine_mode mode, int unsignedp)
4473 rtx tem, subtarget, comparison, insn;
4474 enum insn_code icode;
4475 enum rtx_code reversed;
4477 /* If one operand is constant, make it the second one. Only do this
4478 if the other operand is not constant as well. */
4480 if (swap_commutative_operands_p (op0, op1))
4482 tem = op0;
4483 op0 = op1;
4484 op1 = tem;
4485 code = swap_condition (code);
4488 /* get_condition will prefer to generate LT and GT even if the old
4489 comparison was against zero, so undo that canonicalization here since
4490 comparisons against zero are cheaper. */
4491 if (code == LT && op1 == const1_rtx)
4492 code = LE, op1 = const0_rtx;
4493 else if (code == GT && op1 == constm1_rtx)
4494 code = GE, op1 = const0_rtx;
4496 if (cmode == VOIDmode)
4497 cmode = GET_MODE (op0);
4499 if (swap_commutative_operands_p (op2, op3)
4500 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4501 != UNKNOWN))
4503 tem = op2;
4504 op2 = op3;
4505 op3 = tem;
4506 code = reversed;
4509 if (mode == VOIDmode)
4510 mode = GET_MODE (op2);
4512 icode = direct_optab_handler (movcc_optab, mode);
4514 if (icode == CODE_FOR_nothing)
4515 return 0;
4517 if (!target)
4518 target = gen_reg_rtx (mode);
4520 subtarget = target;
4522 /* If the insn doesn't accept these operands, put them in pseudos. */
4524 if (!insn_data[icode].operand[0].predicate
4525 (subtarget, insn_data[icode].operand[0].mode))
4526 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4528 if (!insn_data[icode].operand[2].predicate
4529 (op2, insn_data[icode].operand[2].mode))
4530 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4532 if (!insn_data[icode].operand[3].predicate
4533 (op3, insn_data[icode].operand[3].mode))
4534 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4536 /* Everything should now be in the suitable form. */
4538 code = unsignedp ? unsigned_condition (code) : code;
4539 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4541 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4542 return NULL and let the caller figure out how best to deal with this
4543 situation. */
4544 if (!COMPARISON_P (comparison))
4545 return NULL_RTX;
4547 do_pending_stack_adjust ();
4548 start_sequence ();
4549 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4550 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4551 &comparison, &cmode);
4552 if (!comparison)
4553 insn = NULL_RTX;
4554 else
4555 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4557 /* If that failed, then give up. */
4558 if (insn == 0)
4560 end_sequence ();
4561 return 0;
4564 emit_insn (insn);
4565 insn = get_insns ();
4566 end_sequence ();
4567 emit_insn (insn);
4568 if (subtarget != target)
4569 convert_move (target, subtarget, 0);
4571 return target;
4574 /* Return nonzero if a conditional move of mode MODE is supported.
4576 This function is for combine so it can tell whether an insn that looks
4577 like a conditional move is actually supported by the hardware. If we
4578 guess wrong we lose a bit on optimization, but that's it. */
4579 /* ??? sparc64 supports conditionally moving integers values based on fp
4580 comparisons, and vice versa. How do we handle them? */
4583 can_conditionally_move_p (enum machine_mode mode)
4585 if (direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing)
4586 return 1;
4588 return 0;
4591 #endif /* HAVE_conditional_move */
4593 /* Emit a conditional addition instruction if the machine supports one for that
4594 condition and machine mode.
4596 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4597 the mode to use should they be constants. If it is VOIDmode, they cannot
4598 both be constants.
4600 OP2 should be stored in TARGET if the comparison is true, otherwise OP2+OP3
4601 should be stored there. MODE is the mode to use should they be constants.
4602 If it is VOIDmode, they cannot both be constants.
4604 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4605 is not supported. */
4608 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
4609 enum machine_mode cmode, rtx op2, rtx op3,
4610 enum machine_mode mode, int unsignedp)
4612 rtx tem, subtarget, comparison, insn;
4613 enum insn_code icode;
4614 enum rtx_code reversed;
4616 /* If one operand is constant, make it the second one. Only do this
4617 if the other operand is not constant as well. */
4619 if (swap_commutative_operands_p (op0, op1))
4621 tem = op0;
4622 op0 = op1;
4623 op1 = tem;
4624 code = swap_condition (code);
4627 /* get_condition will prefer to generate LT and GT even if the old
4628 comparison was against zero, so undo that canonicalization here since
4629 comparisons against zero are cheaper. */
4630 if (code == LT && op1 == const1_rtx)
4631 code = LE, op1 = const0_rtx;
4632 else if (code == GT && op1 == constm1_rtx)
4633 code = GE, op1 = const0_rtx;
4635 if (cmode == VOIDmode)
4636 cmode = GET_MODE (op0);
4638 if (swap_commutative_operands_p (op2, op3)
4639 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4640 != UNKNOWN))
4642 tem = op2;
4643 op2 = op3;
4644 op3 = tem;
4645 code = reversed;
4648 if (mode == VOIDmode)
4649 mode = GET_MODE (op2);
4651 icode = optab_handler (addcc_optab, mode);
4653 if (icode == CODE_FOR_nothing)
4654 return 0;
4656 if (!target)
4657 target = gen_reg_rtx (mode);
4659 /* If the insn doesn't accept these operands, put them in pseudos. */
4661 if (!insn_data[icode].operand[0].predicate
4662 (target, insn_data[icode].operand[0].mode))
4663 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4664 else
4665 subtarget = target;
4667 if (!insn_data[icode].operand[2].predicate
4668 (op2, insn_data[icode].operand[2].mode))
4669 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4671 if (!insn_data[icode].operand[3].predicate
4672 (op3, insn_data[icode].operand[3].mode))
4673 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4675 /* Everything should now be in the suitable form. */
4677 code = unsignedp ? unsigned_condition (code) : code;
4678 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4680 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4681 return NULL and let the caller figure out how best to deal with this
4682 situation. */
4683 if (!COMPARISON_P (comparison))
4684 return NULL_RTX;
4686 do_pending_stack_adjust ();
4687 start_sequence ();
4688 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4689 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4690 &comparison, &cmode);
4691 if (!comparison)
4692 insn = NULL_RTX;
4693 else
4694 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4696 /* If that failed, then give up. */
4697 if (insn == 0)
4699 end_sequence ();
4700 return 0;
4703 emit_insn (insn);
4704 insn = get_insns ();
4705 end_sequence ();
4706 emit_insn (insn);
4707 if (subtarget != target)
4708 convert_move (target, subtarget, 0);
4710 return target;
4713 /* These functions attempt to generate an insn body, rather than
4714 emitting the insn, but if the gen function already emits them, we
4715 make no attempt to turn them back into naked patterns. */
4717 /* Generate and return an insn body to add Y to X. */
4720 gen_add2_insn (rtx x, rtx y)
4722 int icode = (int) optab_handler (add_optab, GET_MODE (x));
4724 gcc_assert (insn_data[icode].operand[0].predicate
4725 (x, insn_data[icode].operand[0].mode));
4726 gcc_assert (insn_data[icode].operand[1].predicate
4727 (x, insn_data[icode].operand[1].mode));
4728 gcc_assert (insn_data[icode].operand[2].predicate
4729 (y, insn_data[icode].operand[2].mode));
4731 return GEN_FCN (icode) (x, x, y);
4734 /* Generate and return an insn body to add r1 and c,
4735 storing the result in r0. */
4738 gen_add3_insn (rtx r0, rtx r1, rtx c)
4740 int icode = (int) optab_handler (add_optab, GET_MODE (r0));
4742 if (icode == CODE_FOR_nothing
4743 || !(insn_data[icode].operand[0].predicate
4744 (r0, insn_data[icode].operand[0].mode))
4745 || !(insn_data[icode].operand[1].predicate
4746 (r1, insn_data[icode].operand[1].mode))
4747 || !(insn_data[icode].operand[2].predicate
4748 (c, insn_data[icode].operand[2].mode)))
4749 return NULL_RTX;
4751 return GEN_FCN (icode) (r0, r1, c);
4755 have_add2_insn (rtx x, rtx y)
4757 int icode;
4759 gcc_assert (GET_MODE (x) != VOIDmode);
4761 icode = (int) optab_handler (add_optab, GET_MODE (x));
4763 if (icode == CODE_FOR_nothing)
4764 return 0;
4766 if (!(insn_data[icode].operand[0].predicate
4767 (x, insn_data[icode].operand[0].mode))
4768 || !(insn_data[icode].operand[1].predicate
4769 (x, insn_data[icode].operand[1].mode))
4770 || !(insn_data[icode].operand[2].predicate
4771 (y, insn_data[icode].operand[2].mode)))
4772 return 0;
4774 return 1;
4777 /* Generate and return an insn body to subtract Y from X. */
4780 gen_sub2_insn (rtx x, rtx y)
4782 int icode = (int) optab_handler (sub_optab, GET_MODE (x));
4784 gcc_assert (insn_data[icode].operand[0].predicate
4785 (x, insn_data[icode].operand[0].mode));
4786 gcc_assert (insn_data[icode].operand[1].predicate
4787 (x, insn_data[icode].operand[1].mode));
4788 gcc_assert (insn_data[icode].operand[2].predicate
4789 (y, insn_data[icode].operand[2].mode));
4791 return GEN_FCN (icode) (x, x, y);
4794 /* Generate and return an insn body to subtract r1 and c,
4795 storing the result in r0. */
4798 gen_sub3_insn (rtx r0, rtx r1, rtx c)
4800 int icode = (int) optab_handler (sub_optab, GET_MODE (r0));
4802 if (icode == CODE_FOR_nothing
4803 || !(insn_data[icode].operand[0].predicate
4804 (r0, insn_data[icode].operand[0].mode))
4805 || !(insn_data[icode].operand[1].predicate
4806 (r1, insn_data[icode].operand[1].mode))
4807 || !(insn_data[icode].operand[2].predicate
4808 (c, insn_data[icode].operand[2].mode)))
4809 return NULL_RTX;
4811 return GEN_FCN (icode) (r0, r1, c);
4815 have_sub2_insn (rtx x, rtx y)
4817 int icode;
4819 gcc_assert (GET_MODE (x) != VOIDmode);
4821 icode = (int) optab_handler (sub_optab, GET_MODE (x));
4823 if (icode == CODE_FOR_nothing)
4824 return 0;
4826 if (!(insn_data[icode].operand[0].predicate
4827 (x, insn_data[icode].operand[0].mode))
4828 || !(insn_data[icode].operand[1].predicate
4829 (x, insn_data[icode].operand[1].mode))
4830 || !(insn_data[icode].operand[2].predicate
4831 (y, insn_data[icode].operand[2].mode)))
4832 return 0;
4834 return 1;
4837 /* Generate the body of an instruction to copy Y into X.
4838 It may be a list of insns, if one insn isn't enough. */
4841 gen_move_insn (rtx x, rtx y)
4843 rtx seq;
4845 start_sequence ();
4846 emit_move_insn_1 (x, y);
4847 seq = get_insns ();
4848 end_sequence ();
4849 return seq;
4852 /* Return the insn code used to extend FROM_MODE to TO_MODE.
4853 UNSIGNEDP specifies zero-extension instead of sign-extension. If
4854 no such operation exists, CODE_FOR_nothing will be returned. */
4856 enum insn_code
4857 can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
4858 int unsignedp)
4860 convert_optab tab;
4861 #ifdef HAVE_ptr_extend
4862 if (unsignedp < 0)
4863 return CODE_FOR_ptr_extend;
4864 #endif
4866 tab = unsignedp ? zext_optab : sext_optab;
4867 return convert_optab_handler (tab, to_mode, from_mode);
4870 /* Generate the body of an insn to extend Y (with mode MFROM)
4871 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
4874 gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
4875 enum machine_mode mfrom, int unsignedp)
4877 enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
4878 return GEN_FCN (icode) (x, y);
4881 /* can_fix_p and can_float_p say whether the target machine
4882 can directly convert a given fixed point type to
4883 a given floating point type, or vice versa.
4884 The returned value is the CODE_FOR_... value to use,
4885 or CODE_FOR_nothing if these modes cannot be directly converted.
4887 *TRUNCP_PTR is set to 1 if it is necessary to output
4888 an explicit FTRUNC insn before the fix insn; otherwise 0. */
4890 static enum insn_code
4891 can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
4892 int unsignedp, int *truncp_ptr)
4894 convert_optab tab;
4895 enum insn_code icode;
4897 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
4898 icode = convert_optab_handler (tab, fixmode, fltmode);
4899 if (icode != CODE_FOR_nothing)
4901 *truncp_ptr = 0;
4902 return icode;
4905 /* FIXME: This requires a port to define both FIX and FTRUNC pattern
4906 for this to work. We need to rework the fix* and ftrunc* patterns
4907 and documentation. */
4908 tab = unsignedp ? ufix_optab : sfix_optab;
4909 icode = convert_optab_handler (tab, fixmode, fltmode);
4910 if (icode != CODE_FOR_nothing
4911 && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
4913 *truncp_ptr = 1;
4914 return icode;
4917 *truncp_ptr = 0;
4918 return CODE_FOR_nothing;
4921 static enum insn_code
4922 can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
4923 int unsignedp)
4925 convert_optab tab;
4927 tab = unsignedp ? ufloat_optab : sfloat_optab;
4928 return convert_optab_handler (tab, fltmode, fixmode);
4931 /* Generate code to convert FROM to floating point
4932 and store in TO. FROM must be fixed point and not VOIDmode.
4933 UNSIGNEDP nonzero means regard FROM as unsigned.
4934 Normally this is done by correcting the final value
4935 if it is negative. */
4937 void
4938 expand_float (rtx to, rtx from, int unsignedp)
4940 enum insn_code icode;
4941 rtx target = to;
4942 enum machine_mode fmode, imode;
4943 bool can_do_signed = false;
4945 /* Crash now, because we won't be able to decide which mode to use. */
4946 gcc_assert (GET_MODE (from) != VOIDmode);
4948 /* Look for an insn to do the conversion. Do it in the specified
4949 modes if possible; otherwise convert either input, output or both to
4950 wider mode. If the integer mode is wider than the mode of FROM,
4951 we can do the conversion signed even if the input is unsigned. */
4953 for (fmode = GET_MODE (to); fmode != VOIDmode;
4954 fmode = GET_MODE_WIDER_MODE (fmode))
4955 for (imode = GET_MODE (from); imode != VOIDmode;
4956 imode = GET_MODE_WIDER_MODE (imode))
4958 int doing_unsigned = unsignedp;
4960 if (fmode != GET_MODE (to)
4961 && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
4962 continue;
4964 icode = can_float_p (fmode, imode, unsignedp);
4965 if (icode == CODE_FOR_nothing && unsignedp)
4967 enum insn_code scode = can_float_p (fmode, imode, 0);
4968 if (scode != CODE_FOR_nothing)
4969 can_do_signed = true;
4970 if (imode != GET_MODE (from))
4971 icode = scode, doing_unsigned = 0;
4974 if (icode != CODE_FOR_nothing)
4976 if (imode != GET_MODE (from))
4977 from = convert_to_mode (imode, from, unsignedp);
4979 if (fmode != GET_MODE (to))
4980 target = gen_reg_rtx (fmode);
4982 emit_unop_insn (icode, target, from,
4983 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
4985 if (target != to)
4986 convert_move (to, target, 0);
4987 return;
4991 /* Unsigned integer, and no way to convert directly. Convert as signed,
4992 then unconditionally adjust the result. */
4993 if (unsignedp && can_do_signed)
4995 rtx label = gen_label_rtx ();
4996 rtx temp;
4997 REAL_VALUE_TYPE offset;
4999 /* Look for a usable floating mode FMODE wider than the source and at
5000 least as wide as the target. Using FMODE will avoid rounding woes
5001 with unsigned values greater than the signed maximum value. */
5003 for (fmode = GET_MODE (to); fmode != VOIDmode;
5004 fmode = GET_MODE_WIDER_MODE (fmode))
5005 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
5006 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
5007 break;
5009 if (fmode == VOIDmode)
5011 /* There is no such mode. Pretend the target is wide enough. */
5012 fmode = GET_MODE (to);
5014 /* Avoid double-rounding when TO is narrower than FROM. */
5015 if ((significand_size (fmode) + 1)
5016 < GET_MODE_BITSIZE (GET_MODE (from)))
5018 rtx temp1;
5019 rtx neglabel = gen_label_rtx ();
5021 /* Don't use TARGET if it isn't a register, is a hard register,
5022 or is the wrong mode. */
5023 if (!REG_P (target)
5024 || REGNO (target) < FIRST_PSEUDO_REGISTER
5025 || GET_MODE (target) != fmode)
5026 target = gen_reg_rtx (fmode);
5028 imode = GET_MODE (from);
5029 do_pending_stack_adjust ();
5031 /* Test whether the sign bit is set. */
5032 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
5033 0, neglabel);
5035 /* The sign bit is not set. Convert as signed. */
5036 expand_float (target, from, 0);
5037 emit_jump_insn (gen_jump (label));
5038 emit_barrier ();
5040 /* The sign bit is set.
5041 Convert to a usable (positive signed) value by shifting right
5042 one bit, while remembering if a nonzero bit was shifted
5043 out; i.e., compute (from & 1) | (from >> 1). */
5045 emit_label (neglabel);
5046 temp = expand_binop (imode, and_optab, from, const1_rtx,
5047 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5048 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
5049 NULL_RTX, 1);
5050 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
5051 OPTAB_LIB_WIDEN);
5052 expand_float (target, temp, 0);
5054 /* Multiply by 2 to undo the shift above. */
5055 temp = expand_binop (fmode, add_optab, target, target,
5056 target, 0, OPTAB_LIB_WIDEN);
5057 if (temp != target)
5058 emit_move_insn (target, temp);
5060 do_pending_stack_adjust ();
5061 emit_label (label);
5062 goto done;
5066 /* If we are about to do some arithmetic to correct for an
5067 unsigned operand, do it in a pseudo-register. */
5069 if (GET_MODE (to) != fmode
5070 || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
5071 target = gen_reg_rtx (fmode);
5073 /* Convert as signed integer to floating. */
5074 expand_float (target, from, 0);
5076 /* If FROM is negative (and therefore TO is negative),
5077 correct its value by 2**bitwidth. */
5079 do_pending_stack_adjust ();
5080 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
5081 0, label);
5084 real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)), fmode);
5085 temp = expand_binop (fmode, add_optab, target,
5086 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
5087 target, 0, OPTAB_LIB_WIDEN);
5088 if (temp != target)
5089 emit_move_insn (target, temp);
5091 do_pending_stack_adjust ();
5092 emit_label (label);
5093 goto done;
5096 /* No hardware instruction available; call a library routine. */
5098 rtx libfunc;
5099 rtx insns;
5100 rtx value;
5101 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
5103 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
5104 from = convert_to_mode (SImode, from, unsignedp);
5106 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5107 gcc_assert (libfunc);
5109 start_sequence ();
5111 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5112 GET_MODE (to), 1, from,
5113 GET_MODE (from));
5114 insns = get_insns ();
5115 end_sequence ();
5117 emit_libcall_block (insns, target, value,
5118 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FLOAT : FLOAT,
5119 GET_MODE (to), from));
5122 done:
5124 /* Copy result to requested destination
5125 if we have been computing in a temp location. */
5127 if (target != to)
5129 if (GET_MODE (target) == GET_MODE (to))
5130 emit_move_insn (to, target);
5131 else
5132 convert_move (to, target, 0);
5136 /* Generate code to convert FROM to fixed point and store in TO. FROM
5137 must be floating point. */
5139 void
5140 expand_fix (rtx to, rtx from, int unsignedp)
5142 enum insn_code icode;
5143 rtx target = to;
5144 enum machine_mode fmode, imode;
5145 int must_trunc = 0;
5147 /* We first try to find a pair of modes, one real and one integer, at
5148 least as wide as FROM and TO, respectively, in which we can open-code
5149 this conversion. If the integer mode is wider than the mode of TO,
5150 we can do the conversion either signed or unsigned. */
5152 for (fmode = GET_MODE (from); fmode != VOIDmode;
5153 fmode = GET_MODE_WIDER_MODE (fmode))
5154 for (imode = GET_MODE (to); imode != VOIDmode;
5155 imode = GET_MODE_WIDER_MODE (imode))
5157 int doing_unsigned = unsignedp;
5159 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
5160 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
5161 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
5163 if (icode != CODE_FOR_nothing)
5165 rtx last = get_last_insn ();
5166 if (fmode != GET_MODE (from))
5167 from = convert_to_mode (fmode, from, 0);
5169 if (must_trunc)
5171 rtx temp = gen_reg_rtx (GET_MODE (from));
5172 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
5173 temp, 0);
5176 if (imode != GET_MODE (to))
5177 target = gen_reg_rtx (imode);
5179 if (maybe_emit_unop_insn (icode, target, from,
5180 doing_unsigned ? UNSIGNED_FIX : FIX))
5182 if (target != to)
5183 convert_move (to, target, unsignedp);
5184 return;
5186 delete_insns_since (last);
5190 /* For an unsigned conversion, there is one more way to do it.
5191 If we have a signed conversion, we generate code that compares
5192 the real value to the largest representable positive number. If if
5193 is smaller, the conversion is done normally. Otherwise, subtract
5194 one plus the highest signed number, convert, and add it back.
5196 We only need to check all real modes, since we know we didn't find
5197 anything with a wider integer mode.
5199 This code used to extend FP value into mode wider than the destination.
5200 This is needed for decimal float modes which cannot accurately
5201 represent one plus the highest signed number of the same size, but
5202 not for binary modes. Consider, for instance conversion from SFmode
5203 into DImode.
5205 The hot path through the code is dealing with inputs smaller than 2^63
5206 and doing just the conversion, so there is no bits to lose.
5208 In the other path we know the value is positive in the range 2^63..2^64-1
5209 inclusive. (as for other input overflow happens and result is undefined)
5210 So we know that the most important bit set in mantissa corresponds to
5211 2^63. The subtraction of 2^63 should not generate any rounding as it
5212 simply clears out that bit. The rest is trivial. */
5214 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
5215 for (fmode = GET_MODE (from); fmode != VOIDmode;
5216 fmode = GET_MODE_WIDER_MODE (fmode))
5217 if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc)
5218 && (!DECIMAL_FLOAT_MODE_P (fmode)
5219 || GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))))
5221 int bitsize;
5222 REAL_VALUE_TYPE offset;
5223 rtx limit, lab1, lab2, insn;
5225 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
5226 real_2expN (&offset, bitsize - 1, fmode);
5227 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
5228 lab1 = gen_label_rtx ();
5229 lab2 = gen_label_rtx ();
5231 if (fmode != GET_MODE (from))
5232 from = convert_to_mode (fmode, from, 0);
5234 /* See if we need to do the subtraction. */
5235 do_pending_stack_adjust ();
5236 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
5237 0, lab1);
5239 /* If not, do the signed "fix" and branch around fixup code. */
5240 expand_fix (to, from, 0);
5241 emit_jump_insn (gen_jump (lab2));
5242 emit_barrier ();
5244 /* Otherwise, subtract 2**(N-1), convert to signed number,
5245 then add 2**(N-1). Do the addition using XOR since this
5246 will often generate better code. */
5247 emit_label (lab1);
5248 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
5249 NULL_RTX, 0, OPTAB_LIB_WIDEN);
5250 expand_fix (to, target, 0);
5251 target = expand_binop (GET_MODE (to), xor_optab, to,
5252 gen_int_mode
5253 ((HOST_WIDE_INT) 1 << (bitsize - 1),
5254 GET_MODE (to)),
5255 to, 1, OPTAB_LIB_WIDEN);
5257 if (target != to)
5258 emit_move_insn (to, target);
5260 emit_label (lab2);
5262 if (optab_handler (mov_optab, GET_MODE (to)) != CODE_FOR_nothing)
5264 /* Make a place for a REG_NOTE and add it. */
5265 insn = emit_move_insn (to, to);
5266 set_unique_reg_note (insn,
5267 REG_EQUAL,
5268 gen_rtx_fmt_e (UNSIGNED_FIX,
5269 GET_MODE (to),
5270 copy_rtx (from)));
5273 return;
5276 /* We can't do it with an insn, so use a library call. But first ensure
5277 that the mode of TO is at least as wide as SImode, since those are the
5278 only library calls we know about. */
5280 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
5282 target = gen_reg_rtx (SImode);
5284 expand_fix (target, from, unsignedp);
5286 else
5288 rtx insns;
5289 rtx value;
5290 rtx libfunc;
5292 convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
5293 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5294 gcc_assert (libfunc);
5296 start_sequence ();
5298 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5299 GET_MODE (to), 1, from,
5300 GET_MODE (from));
5301 insns = get_insns ();
5302 end_sequence ();
5304 emit_libcall_block (insns, target, value,
5305 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
5306 GET_MODE (to), from));
5309 if (target != to)
5311 if (GET_MODE (to) == GET_MODE (target))
5312 emit_move_insn (to, target);
5313 else
5314 convert_move (to, target, 0);
5318 /* Generate code to convert FROM or TO a fixed-point.
5319 If UINTP is true, either TO or FROM is an unsigned integer.
5320 If SATP is true, we need to saturate the result. */
5322 void
5323 expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
5325 enum machine_mode to_mode = GET_MODE (to);
5326 enum machine_mode from_mode = GET_MODE (from);
5327 convert_optab tab;
5328 enum rtx_code this_code;
5329 enum insn_code code;
5330 rtx insns, value;
5331 rtx libfunc;
5333 if (to_mode == from_mode)
5335 emit_move_insn (to, from);
5336 return;
5339 if (uintp)
5341 tab = satp ? satfractuns_optab : fractuns_optab;
5342 this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
5344 else
5346 tab = satp ? satfract_optab : fract_optab;
5347 this_code = satp ? SAT_FRACT : FRACT_CONVERT;
5349 code = convert_optab_handler (tab, to_mode, from_mode);
5350 if (code != CODE_FOR_nothing)
5352 emit_unop_insn (code, to, from, this_code);
5353 return;
5356 libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
5357 gcc_assert (libfunc);
5359 start_sequence ();
5360 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
5361 1, from, from_mode);
5362 insns = get_insns ();
5363 end_sequence ();
5365 emit_libcall_block (insns, to, value,
5366 gen_rtx_fmt_e (tab->code, to_mode, from));
5369 /* Generate code to convert FROM to fixed point and store in TO. FROM
5370 must be floating point, TO must be signed. Use the conversion optab
5371 TAB to do the conversion. */
5373 bool
5374 expand_sfix_optab (rtx to, rtx from, convert_optab tab)
5376 enum insn_code icode;
5377 rtx target = to;
5378 enum machine_mode fmode, imode;
5380 /* We first try to find a pair of modes, one real and one integer, at
5381 least as wide as FROM and TO, respectively, in which we can open-code
5382 this conversion. If the integer mode is wider than the mode of TO,
5383 we can do the conversion either signed or unsigned. */
5385 for (fmode = GET_MODE (from); fmode != VOIDmode;
5386 fmode = GET_MODE_WIDER_MODE (fmode))
5387 for (imode = GET_MODE (to); imode != VOIDmode;
5388 imode = GET_MODE_WIDER_MODE (imode))
5390 icode = convert_optab_handler (tab, imode, fmode);
5391 if (icode != CODE_FOR_nothing)
5393 rtx last = get_last_insn ();
5394 if (fmode != GET_MODE (from))
5395 from = convert_to_mode (fmode, from, 0);
5397 if (imode != GET_MODE (to))
5398 target = gen_reg_rtx (imode);
5400 if (!maybe_emit_unop_insn (icode, target, from, UNKNOWN))
5402 delete_insns_since (last);
5403 continue;
5405 if (target != to)
5406 convert_move (to, target, 0);
5407 return true;
5411 return false;
5414 /* Report whether we have an instruction to perform the operation
5415 specified by CODE on operands of mode MODE. */
5417 have_insn_for (enum rtx_code code, enum machine_mode mode)
5419 return (code_to_optab[(int) code] != 0
5420 && (optab_handler (code_to_optab[(int) code], mode)
5421 != CODE_FOR_nothing));
5424 /* Set all insn_code fields to CODE_FOR_nothing. */
5426 static void
5427 init_insn_codes (void)
5429 memset (optab_table, 0, sizeof (optab_table));
5430 memset (convert_optab_table, 0, sizeof (convert_optab_table));
5431 memset (direct_optab_table, 0, sizeof (direct_optab_table));
5434 /* Initialize OP's code to CODE, and write it into the code_to_optab table. */
5435 static inline void
5436 init_optab (optab op, enum rtx_code code)
5438 op->code = code;
5439 code_to_optab[(int) code] = op;
5442 /* Same, but fill in its code as CODE, and do _not_ write it into
5443 the code_to_optab table. */
5444 static inline void
5445 init_optabv (optab op, enum rtx_code code)
5447 op->code = code;
5450 /* Conversion optabs never go in the code_to_optab table. */
5451 static void
5452 init_convert_optab (convert_optab op, enum rtx_code code)
5454 op->code = code;
5457 /* Initialize the libfunc fields of an entire group of entries in some
5458 optab. Each entry is set equal to a string consisting of a leading
5459 pair of underscores followed by a generic operation name followed by
5460 a mode name (downshifted to lowercase) followed by a single character
5461 representing the number of operands for the given operation (which is
5462 usually one of the characters '2', '3', or '4').
5464 OPTABLE is the table in which libfunc fields are to be initialized.
5465 OPNAME is the generic (string) name of the operation.
5466 SUFFIX is the character which specifies the number of operands for
5467 the given generic operation.
5468 MODE is the mode to generate for.
5471 static void
5472 gen_libfunc (optab optable, const char *opname, int suffix, enum machine_mode mode)
5474 unsigned opname_len = strlen (opname);
5475 const char *mname = GET_MODE_NAME (mode);
5476 unsigned mname_len = strlen (mname);
5477 char *libfunc_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5478 char *p;
5479 const char *q;
5481 p = libfunc_name;
5482 *p++ = '_';
5483 *p++ = '_';
5484 for (q = opname; *q; )
5485 *p++ = *q++;
5486 for (q = mname; *q; q++)
5487 *p++ = TOLOWER (*q);
5488 *p++ = suffix;
5489 *p = '\0';
5491 set_optab_libfunc (optable, mode,
5492 ggc_alloc_string (libfunc_name, p - libfunc_name));
5495 /* Like gen_libfunc, but verify that integer operation is involved. */
5497 static void
5498 gen_int_libfunc (optab optable, const char *opname, char suffix,
5499 enum machine_mode mode)
5501 int maxsize = 2 * BITS_PER_WORD;
5503 if (GET_MODE_CLASS (mode) != MODE_INT)
5504 return;
5505 if (maxsize < LONG_LONG_TYPE_SIZE)
5506 maxsize = LONG_LONG_TYPE_SIZE;
5507 if (GET_MODE_CLASS (mode) != MODE_INT
5508 || mode < word_mode || GET_MODE_BITSIZE (mode) > maxsize)
5509 return;
5510 gen_libfunc (optable, opname, suffix, mode);
5513 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed. */
5515 static void
5516 gen_fp_libfunc (optab optable, const char *opname, char suffix,
5517 enum machine_mode mode)
5519 char *dec_opname;
5521 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
5522 gen_libfunc (optable, opname, suffix, mode);
5523 if (DECIMAL_FLOAT_MODE_P (mode))
5525 dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
5526 /* For BID support, change the name to have either a bid_ or dpd_ prefix
5527 depending on the low level floating format used. */
5528 memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
5529 strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
5530 gen_libfunc (optable, dec_opname, suffix, mode);
5534 /* Like gen_libfunc, but verify that fixed-point operation is involved. */
5536 static void
5537 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
5538 enum machine_mode mode)
5540 if (!ALL_FIXED_POINT_MODE_P (mode))
5541 return;
5542 gen_libfunc (optable, opname, suffix, mode);
5545 /* Like gen_libfunc, but verify that signed fixed-point operation is
5546 involved. */
5548 static void
5549 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
5550 enum machine_mode mode)
5552 if (!SIGNED_FIXED_POINT_MODE_P (mode))
5553 return;
5554 gen_libfunc (optable, opname, suffix, mode);
5557 /* Like gen_libfunc, but verify that unsigned fixed-point operation is
5558 involved. */
5560 static void
5561 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
5562 enum machine_mode mode)
5564 if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
5565 return;
5566 gen_libfunc (optable, opname, suffix, mode);
5569 /* Like gen_libfunc, but verify that FP or INT operation is involved. */
5571 static void
5572 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
5573 enum machine_mode mode)
5575 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5576 gen_fp_libfunc (optable, name, suffix, mode);
5577 if (INTEGRAL_MODE_P (mode))
5578 gen_int_libfunc (optable, name, suffix, mode);
5581 /* Like gen_libfunc, but verify that FP or INT operation is involved
5582 and add 'v' suffix for integer operation. */
5584 static void
5585 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
5586 enum machine_mode mode)
5588 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5589 gen_fp_libfunc (optable, name, suffix, mode);
5590 if (GET_MODE_CLASS (mode) == MODE_INT)
5592 int len = strlen (name);
5593 char *v_name = XALLOCAVEC (char, len + 2);
5594 strcpy (v_name, name);
5595 v_name[len] = 'v';
5596 v_name[len + 1] = 0;
5597 gen_int_libfunc (optable, v_name, suffix, mode);
5601 /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
5602 involved. */
5604 static void
5605 gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
5606 enum machine_mode mode)
5608 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5609 gen_fp_libfunc (optable, name, suffix, mode);
5610 if (INTEGRAL_MODE_P (mode))
5611 gen_int_libfunc (optable, name, suffix, mode);
5612 if (ALL_FIXED_POINT_MODE_P (mode))
5613 gen_fixed_libfunc (optable, name, suffix, mode);
5616 /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
5617 involved. */
5619 static void
5620 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5621 enum machine_mode mode)
5623 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5624 gen_fp_libfunc (optable, name, suffix, mode);
5625 if (INTEGRAL_MODE_P (mode))
5626 gen_int_libfunc (optable, name, suffix, mode);
5627 if (SIGNED_FIXED_POINT_MODE_P (mode))
5628 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5631 /* Like gen_libfunc, but verify that INT or FIXED operation is
5632 involved. */
5634 static void
5635 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
5636 enum machine_mode mode)
5638 if (INTEGRAL_MODE_P (mode))
5639 gen_int_libfunc (optable, name, suffix, mode);
5640 if (ALL_FIXED_POINT_MODE_P (mode))
5641 gen_fixed_libfunc (optable, name, suffix, mode);
5644 /* Like gen_libfunc, but verify that INT or signed FIXED operation is
5645 involved. */
5647 static void
5648 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5649 enum machine_mode mode)
5651 if (INTEGRAL_MODE_P (mode))
5652 gen_int_libfunc (optable, name, suffix, mode);
5653 if (SIGNED_FIXED_POINT_MODE_P (mode))
5654 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5657 /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
5658 involved. */
5660 static void
5661 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
5662 enum machine_mode mode)
5664 if (INTEGRAL_MODE_P (mode))
5665 gen_int_libfunc (optable, name, suffix, mode);
5666 if (UNSIGNED_FIXED_POINT_MODE_P (mode))
5667 gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
5670 /* Initialize the libfunc fields of an entire group of entries of an
5671 inter-mode-class conversion optab. The string formation rules are
5672 similar to the ones for init_libfuncs, above, but instead of having
5673 a mode name and an operand count these functions have two mode names
5674 and no operand count. */
5676 static void
5677 gen_interclass_conv_libfunc (convert_optab tab,
5678 const char *opname,
5679 enum machine_mode tmode,
5680 enum machine_mode fmode)
5682 size_t opname_len = strlen (opname);
5683 size_t mname_len = 0;
5685 const char *fname, *tname;
5686 const char *q;
5687 char *libfunc_name, *suffix;
5688 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5689 char *p;
5691 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5692 depends on which underlying decimal floating point format is used. */
5693 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5695 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5697 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5698 nondec_name[0] = '_';
5699 nondec_name[1] = '_';
5700 memcpy (&nondec_name[2], opname, opname_len);
5701 nondec_suffix = nondec_name + opname_len + 2;
5703 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5704 dec_name[0] = '_';
5705 dec_name[1] = '_';
5706 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5707 memcpy (&dec_name[2+dec_len], opname, opname_len);
5708 dec_suffix = dec_name + dec_len + opname_len + 2;
5710 fname = GET_MODE_NAME (fmode);
5711 tname = GET_MODE_NAME (tmode);
5713 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5715 libfunc_name = dec_name;
5716 suffix = dec_suffix;
5718 else
5720 libfunc_name = nondec_name;
5721 suffix = nondec_suffix;
5724 p = suffix;
5725 for (q = fname; *q; p++, q++)
5726 *p = TOLOWER (*q);
5727 for (q = tname; *q; p++, q++)
5728 *p = TOLOWER (*q);
5730 *p = '\0';
5732 set_conv_libfunc (tab, tmode, fmode,
5733 ggc_alloc_string (libfunc_name, p - libfunc_name));
5736 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5737 int->fp conversion. */
5739 static void
5740 gen_int_to_fp_conv_libfunc (convert_optab tab,
5741 const char *opname,
5742 enum machine_mode tmode,
5743 enum machine_mode fmode)
5745 if (GET_MODE_CLASS (fmode) != MODE_INT)
5746 return;
5747 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5748 return;
5749 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5752 /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
5753 naming scheme. */
5755 static void
5756 gen_ufloat_conv_libfunc (convert_optab tab,
5757 const char *opname ATTRIBUTE_UNUSED,
5758 enum machine_mode tmode,
5759 enum machine_mode fmode)
5761 if (DECIMAL_FLOAT_MODE_P (tmode))
5762 gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
5763 else
5764 gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
5767 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5768 fp->int conversion. */
5770 static void
5771 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
5772 const char *opname,
5773 enum machine_mode tmode,
5774 enum machine_mode fmode)
5776 if (GET_MODE_CLASS (fmode) != MODE_INT)
5777 return;
5778 if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
5779 return;
5780 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5783 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5784 fp->int conversion with no decimal floating point involved. */
5786 static void
5787 gen_fp_to_int_conv_libfunc (convert_optab tab,
5788 const char *opname,
5789 enum machine_mode tmode,
5790 enum machine_mode fmode)
5792 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5793 return;
5794 if (GET_MODE_CLASS (tmode) != MODE_INT)
5795 return;
5796 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5799 /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
5800 The string formation rules are
5801 similar to the ones for init_libfunc, above. */
5803 static void
5804 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
5805 enum machine_mode tmode, enum machine_mode fmode)
5807 size_t opname_len = strlen (opname);
5808 size_t mname_len = 0;
5810 const char *fname, *tname;
5811 const char *q;
5812 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5813 char *libfunc_name, *suffix;
5814 char *p;
5816 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5817 depends on which underlying decimal floating point format is used. */
5818 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5820 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5822 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5823 nondec_name[0] = '_';
5824 nondec_name[1] = '_';
5825 memcpy (&nondec_name[2], opname, opname_len);
5826 nondec_suffix = nondec_name + opname_len + 2;
5828 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5829 dec_name[0] = '_';
5830 dec_name[1] = '_';
5831 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5832 memcpy (&dec_name[2 + dec_len], opname, opname_len);
5833 dec_suffix = dec_name + dec_len + opname_len + 2;
5835 fname = GET_MODE_NAME (fmode);
5836 tname = GET_MODE_NAME (tmode);
5838 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5840 libfunc_name = dec_name;
5841 suffix = dec_suffix;
5843 else
5845 libfunc_name = nondec_name;
5846 suffix = nondec_suffix;
5849 p = suffix;
5850 for (q = fname; *q; p++, q++)
5851 *p = TOLOWER (*q);
5852 for (q = tname; *q; p++, q++)
5853 *p = TOLOWER (*q);
5855 *p++ = '2';
5856 *p = '\0';
5858 set_conv_libfunc (tab, tmode, fmode,
5859 ggc_alloc_string (libfunc_name, p - libfunc_name));
5862 /* Pick proper libcall for trunc_optab. We need to chose if we do
5863 truncation or extension and interclass or intraclass. */
5865 static void
5866 gen_trunc_conv_libfunc (convert_optab tab,
5867 const char *opname,
5868 enum machine_mode tmode,
5869 enum machine_mode fmode)
5871 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5872 return;
5873 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5874 return;
5875 if (tmode == fmode)
5876 return;
5878 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5879 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5880 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5882 if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
5883 return;
5885 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5886 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5887 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5888 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5891 /* Pick proper libcall for extend_optab. We need to chose if we do
5892 truncation or extension and interclass or intraclass. */
5894 static void
5895 gen_extend_conv_libfunc (convert_optab tab,
5896 const char *opname ATTRIBUTE_UNUSED,
5897 enum machine_mode tmode,
5898 enum machine_mode fmode)
5900 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5901 return;
5902 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5903 return;
5904 if (tmode == fmode)
5905 return;
5907 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5908 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5909 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5911 if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
5912 return;
5914 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5915 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5916 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5917 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5920 /* Pick proper libcall for fract_optab. We need to chose if we do
5921 interclass or intraclass. */
5923 static void
5924 gen_fract_conv_libfunc (convert_optab tab,
5925 const char *opname,
5926 enum machine_mode tmode,
5927 enum machine_mode fmode)
5929 if (tmode == fmode)
5930 return;
5931 if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
5932 return;
5934 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
5935 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5936 else
5937 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5940 /* Pick proper libcall for fractuns_optab. */
5942 static void
5943 gen_fractuns_conv_libfunc (convert_optab tab,
5944 const char *opname,
5945 enum machine_mode tmode,
5946 enum machine_mode fmode)
5948 if (tmode == fmode)
5949 return;
5950 /* One mode must be a fixed-point mode, and the other must be an integer
5951 mode. */
5952 if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
5953 || (ALL_FIXED_POINT_MODE_P (fmode)
5954 && GET_MODE_CLASS (tmode) == MODE_INT)))
5955 return;
5957 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5960 /* Pick proper libcall for satfract_optab. We need to chose if we do
5961 interclass or intraclass. */
5963 static void
5964 gen_satfract_conv_libfunc (convert_optab tab,
5965 const char *opname,
5966 enum machine_mode tmode,
5967 enum machine_mode fmode)
5969 if (tmode == fmode)
5970 return;
5971 /* TMODE must be a fixed-point mode. */
5972 if (!ALL_FIXED_POINT_MODE_P (tmode))
5973 return;
5975 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
5976 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5977 else
5978 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5981 /* Pick proper libcall for satfractuns_optab. */
5983 static void
5984 gen_satfractuns_conv_libfunc (convert_optab tab,
5985 const char *opname,
5986 enum machine_mode tmode,
5987 enum machine_mode fmode)
5989 if (tmode == fmode)
5990 return;
5991 /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
5992 if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
5993 return;
5995 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5998 /* A table of previously-created libfuncs, hashed by name. */
5999 static GTY ((param_is (union tree_node))) htab_t libfunc_decls;
6001 /* Hashtable callbacks for libfunc_decls. */
6003 static hashval_t
6004 libfunc_decl_hash (const void *entry)
6006 return IDENTIFIER_HASH_VALUE (DECL_NAME ((const_tree) entry));
6009 static int
6010 libfunc_decl_eq (const void *entry1, const void *entry2)
6012 return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
6015 /* Build a decl for a libfunc named NAME. */
6017 tree
6018 build_libfunc_function (const char *name)
6020 tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
6021 get_identifier (name),
6022 build_function_type (integer_type_node, NULL_TREE));
6023 /* ??? We don't have any type information except for this is
6024 a function. Pretend this is "int foo()". */
6025 DECL_ARTIFICIAL (decl) = 1;
6026 DECL_EXTERNAL (decl) = 1;
6027 TREE_PUBLIC (decl) = 1;
6028 gcc_assert (DECL_ASSEMBLER_NAME (decl));
6030 /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
6031 are the flags assigned by targetm.encode_section_info. */
6032 SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
6034 return decl;
6038 init_one_libfunc (const char *name)
6040 tree id, decl;
6041 void **slot;
6042 hashval_t hash;
6044 if (libfunc_decls == NULL)
6045 libfunc_decls = htab_create_ggc (37, libfunc_decl_hash,
6046 libfunc_decl_eq, NULL);
6048 /* See if we have already created a libfunc decl for this function. */
6049 id = get_identifier (name);
6050 hash = IDENTIFIER_HASH_VALUE (id);
6051 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, INSERT);
6052 decl = (tree) *slot;
6053 if (decl == NULL)
6055 /* Create a new decl, so that it can be passed to
6056 targetm.encode_section_info. */
6057 decl = build_libfunc_function (name);
6058 *slot = decl;
6060 return XEXP (DECL_RTL (decl), 0);
6063 /* Adjust the assembler name of libfunc NAME to ASMSPEC. */
6066 set_user_assembler_libfunc (const char *name, const char *asmspec)
6068 tree id, decl;
6069 void **slot;
6070 hashval_t hash;
6072 id = get_identifier (name);
6073 hash = IDENTIFIER_HASH_VALUE (id);
6074 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, NO_INSERT);
6075 gcc_assert (slot);
6076 decl = (tree) *slot;
6077 set_user_assembler_name (decl, asmspec);
6078 return XEXP (DECL_RTL (decl), 0);
6081 /* Call this to reset the function entry for one optab (OPTABLE) in mode
6082 MODE to NAME, which should be either 0 or a string constant. */
6083 void
6084 set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
6086 rtx val;
6087 struct libfunc_entry e;
6088 struct libfunc_entry **slot;
6089 e.optab = (size_t) (optable - &optab_table[0]);
6090 e.mode1 = mode;
6091 e.mode2 = VOIDmode;
6093 if (name)
6094 val = init_one_libfunc (name);
6095 else
6096 val = 0;
6097 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6098 if (*slot == NULL)
6099 *slot = ggc_alloc_libfunc_entry ();
6100 (*slot)->optab = (size_t) (optable - &optab_table[0]);
6101 (*slot)->mode1 = mode;
6102 (*slot)->mode2 = VOIDmode;
6103 (*slot)->libfunc = val;
6106 /* Call this to reset the function entry for one conversion optab
6107 (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
6108 either 0 or a string constant. */
6109 void
6110 set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
6111 enum machine_mode fmode, const char *name)
6113 rtx val;
6114 struct libfunc_entry e;
6115 struct libfunc_entry **slot;
6116 e.optab = (size_t) (optable - &convert_optab_table[0]);
6117 e.mode1 = tmode;
6118 e.mode2 = fmode;
6120 if (name)
6121 val = init_one_libfunc (name);
6122 else
6123 val = 0;
6124 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6125 if (*slot == NULL)
6126 *slot = ggc_alloc_libfunc_entry ();
6127 (*slot)->optab = (size_t) (optable - &convert_optab_table[0]);
6128 (*slot)->mode1 = tmode;
6129 (*slot)->mode2 = fmode;
6130 (*slot)->libfunc = val;
6133 /* Call this to initialize the contents of the optabs
6134 appropriately for the current target machine. */
6136 void
6137 init_optabs (void)
6139 static bool reinit;
6141 libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
6143 /* We statically initialize the insn_codes with the equivalent of
6144 CODE_FOR_nothing. Repeat the process if reinitialising. */
6145 if (reinit)
6146 init_insn_codes ();
6148 init_optab (add_optab, PLUS);
6149 init_optabv (addv_optab, PLUS);
6150 init_optab (sub_optab, MINUS);
6151 init_optabv (subv_optab, MINUS);
6152 init_optab (ssadd_optab, SS_PLUS);
6153 init_optab (usadd_optab, US_PLUS);
6154 init_optab (sssub_optab, SS_MINUS);
6155 init_optab (ussub_optab, US_MINUS);
6156 init_optab (smul_optab, MULT);
6157 init_optab (ssmul_optab, SS_MULT);
6158 init_optab (usmul_optab, US_MULT);
6159 init_optabv (smulv_optab, MULT);
6160 init_optab (smul_highpart_optab, UNKNOWN);
6161 init_optab (umul_highpart_optab, UNKNOWN);
6162 init_optab (smul_widen_optab, UNKNOWN);
6163 init_optab (umul_widen_optab, UNKNOWN);
6164 init_optab (usmul_widen_optab, UNKNOWN);
6165 init_optab (smadd_widen_optab, UNKNOWN);
6166 init_optab (umadd_widen_optab, UNKNOWN);
6167 init_optab (ssmadd_widen_optab, UNKNOWN);
6168 init_optab (usmadd_widen_optab, UNKNOWN);
6169 init_optab (smsub_widen_optab, UNKNOWN);
6170 init_optab (umsub_widen_optab, UNKNOWN);
6171 init_optab (ssmsub_widen_optab, UNKNOWN);
6172 init_optab (usmsub_widen_optab, UNKNOWN);
6173 init_optab (sdiv_optab, DIV);
6174 init_optab (ssdiv_optab, SS_DIV);
6175 init_optab (usdiv_optab, US_DIV);
6176 init_optabv (sdivv_optab, DIV);
6177 init_optab (sdivmod_optab, UNKNOWN);
6178 init_optab (udiv_optab, UDIV);
6179 init_optab (udivmod_optab, UNKNOWN);
6180 init_optab (smod_optab, MOD);
6181 init_optab (umod_optab, UMOD);
6182 init_optab (fmod_optab, UNKNOWN);
6183 init_optab (remainder_optab, UNKNOWN);
6184 init_optab (ftrunc_optab, UNKNOWN);
6185 init_optab (and_optab, AND);
6186 init_optab (ior_optab, IOR);
6187 init_optab (xor_optab, XOR);
6188 init_optab (ashl_optab, ASHIFT);
6189 init_optab (ssashl_optab, SS_ASHIFT);
6190 init_optab (usashl_optab, US_ASHIFT);
6191 init_optab (ashr_optab, ASHIFTRT);
6192 init_optab (lshr_optab, LSHIFTRT);
6193 init_optab (rotl_optab, ROTATE);
6194 init_optab (rotr_optab, ROTATERT);
6195 init_optab (smin_optab, SMIN);
6196 init_optab (smax_optab, SMAX);
6197 init_optab (umin_optab, UMIN);
6198 init_optab (umax_optab, UMAX);
6199 init_optab (pow_optab, UNKNOWN);
6200 init_optab (atan2_optab, UNKNOWN);
6202 /* These three have codes assigned exclusively for the sake of
6203 have_insn_for. */
6204 init_optab (mov_optab, SET);
6205 init_optab (movstrict_optab, STRICT_LOW_PART);
6206 init_optab (cbranch_optab, COMPARE);
6208 init_optab (cmov_optab, UNKNOWN);
6209 init_optab (cstore_optab, UNKNOWN);
6210 init_optab (ctrap_optab, UNKNOWN);
6212 init_optab (storent_optab, UNKNOWN);
6214 init_optab (cmp_optab, UNKNOWN);
6215 init_optab (ucmp_optab, UNKNOWN);
6217 init_optab (eq_optab, EQ);
6218 init_optab (ne_optab, NE);
6219 init_optab (gt_optab, GT);
6220 init_optab (ge_optab, GE);
6221 init_optab (lt_optab, LT);
6222 init_optab (le_optab, LE);
6223 init_optab (unord_optab, UNORDERED);
6225 init_optab (neg_optab, NEG);
6226 init_optab (ssneg_optab, SS_NEG);
6227 init_optab (usneg_optab, US_NEG);
6228 init_optabv (negv_optab, NEG);
6229 init_optab (abs_optab, ABS);
6230 init_optabv (absv_optab, ABS);
6231 init_optab (addcc_optab, UNKNOWN);
6232 init_optab (one_cmpl_optab, NOT);
6233 init_optab (bswap_optab, BSWAP);
6234 init_optab (ffs_optab, FFS);
6235 init_optab (clz_optab, CLZ);
6236 init_optab (ctz_optab, CTZ);
6237 init_optab (popcount_optab, POPCOUNT);
6238 init_optab (parity_optab, PARITY);
6239 init_optab (sqrt_optab, SQRT);
6240 init_optab (floor_optab, UNKNOWN);
6241 init_optab (ceil_optab, UNKNOWN);
6242 init_optab (round_optab, UNKNOWN);
6243 init_optab (btrunc_optab, UNKNOWN);
6244 init_optab (nearbyint_optab, UNKNOWN);
6245 init_optab (rint_optab, UNKNOWN);
6246 init_optab (sincos_optab, UNKNOWN);
6247 init_optab (sin_optab, UNKNOWN);
6248 init_optab (asin_optab, UNKNOWN);
6249 init_optab (cos_optab, UNKNOWN);
6250 init_optab (acos_optab, UNKNOWN);
6251 init_optab (exp_optab, UNKNOWN);
6252 init_optab (exp10_optab, UNKNOWN);
6253 init_optab (exp2_optab, UNKNOWN);
6254 init_optab (expm1_optab, UNKNOWN);
6255 init_optab (ldexp_optab, UNKNOWN);
6256 init_optab (scalb_optab, UNKNOWN);
6257 init_optab (significand_optab, UNKNOWN);
6258 init_optab (logb_optab, UNKNOWN);
6259 init_optab (ilogb_optab, UNKNOWN);
6260 init_optab (log_optab, UNKNOWN);
6261 init_optab (log10_optab, UNKNOWN);
6262 init_optab (log2_optab, UNKNOWN);
6263 init_optab (log1p_optab, UNKNOWN);
6264 init_optab (tan_optab, UNKNOWN);
6265 init_optab (atan_optab, UNKNOWN);
6266 init_optab (copysign_optab, UNKNOWN);
6267 init_optab (signbit_optab, UNKNOWN);
6269 init_optab (isinf_optab, UNKNOWN);
6271 init_optab (strlen_optab, UNKNOWN);
6272 init_optab (push_optab, UNKNOWN);
6274 init_optab (reduc_smax_optab, UNKNOWN);
6275 init_optab (reduc_umax_optab, UNKNOWN);
6276 init_optab (reduc_smin_optab, UNKNOWN);
6277 init_optab (reduc_umin_optab, UNKNOWN);
6278 init_optab (reduc_splus_optab, UNKNOWN);
6279 init_optab (reduc_uplus_optab, UNKNOWN);
6281 init_optab (ssum_widen_optab, UNKNOWN);
6282 init_optab (usum_widen_optab, UNKNOWN);
6283 init_optab (sdot_prod_optab, UNKNOWN);
6284 init_optab (udot_prod_optab, UNKNOWN);
6286 init_optab (vec_extract_optab, UNKNOWN);
6287 init_optab (vec_extract_even_optab, UNKNOWN);
6288 init_optab (vec_extract_odd_optab, UNKNOWN);
6289 init_optab (vec_interleave_high_optab, UNKNOWN);
6290 init_optab (vec_interleave_low_optab, UNKNOWN);
6291 init_optab (vec_set_optab, UNKNOWN);
6292 init_optab (vec_init_optab, UNKNOWN);
6293 init_optab (vec_shl_optab, UNKNOWN);
6294 init_optab (vec_shr_optab, UNKNOWN);
6295 init_optab (vec_realign_load_optab, UNKNOWN);
6296 init_optab (movmisalign_optab, UNKNOWN);
6297 init_optab (vec_widen_umult_hi_optab, UNKNOWN);
6298 init_optab (vec_widen_umult_lo_optab, UNKNOWN);
6299 init_optab (vec_widen_smult_hi_optab, UNKNOWN);
6300 init_optab (vec_widen_smult_lo_optab, UNKNOWN);
6301 init_optab (vec_unpacks_hi_optab, UNKNOWN);
6302 init_optab (vec_unpacks_lo_optab, UNKNOWN);
6303 init_optab (vec_unpacku_hi_optab, UNKNOWN);
6304 init_optab (vec_unpacku_lo_optab, UNKNOWN);
6305 init_optab (vec_unpacks_float_hi_optab, UNKNOWN);
6306 init_optab (vec_unpacks_float_lo_optab, UNKNOWN);
6307 init_optab (vec_unpacku_float_hi_optab, UNKNOWN);
6308 init_optab (vec_unpacku_float_lo_optab, UNKNOWN);
6309 init_optab (vec_pack_trunc_optab, UNKNOWN);
6310 init_optab (vec_pack_usat_optab, UNKNOWN);
6311 init_optab (vec_pack_ssat_optab, UNKNOWN);
6312 init_optab (vec_pack_ufix_trunc_optab, UNKNOWN);
6313 init_optab (vec_pack_sfix_trunc_optab, UNKNOWN);
6315 init_optab (powi_optab, UNKNOWN);
6317 /* Conversions. */
6318 init_convert_optab (sext_optab, SIGN_EXTEND);
6319 init_convert_optab (zext_optab, ZERO_EXTEND);
6320 init_convert_optab (trunc_optab, TRUNCATE);
6321 init_convert_optab (sfix_optab, FIX);
6322 init_convert_optab (ufix_optab, UNSIGNED_FIX);
6323 init_convert_optab (sfixtrunc_optab, UNKNOWN);
6324 init_convert_optab (ufixtrunc_optab, UNKNOWN);
6325 init_convert_optab (sfloat_optab, FLOAT);
6326 init_convert_optab (ufloat_optab, UNSIGNED_FLOAT);
6327 init_convert_optab (lrint_optab, UNKNOWN);
6328 init_convert_optab (lround_optab, UNKNOWN);
6329 init_convert_optab (lfloor_optab, UNKNOWN);
6330 init_convert_optab (lceil_optab, UNKNOWN);
6332 init_convert_optab (fract_optab, FRACT_CONVERT);
6333 init_convert_optab (fractuns_optab, UNSIGNED_FRACT_CONVERT);
6334 init_convert_optab (satfract_optab, SAT_FRACT);
6335 init_convert_optab (satfractuns_optab, UNSIGNED_SAT_FRACT);
6337 /* Fill in the optabs with the insns we support. */
6338 init_all_optabs ();
6340 /* Initialize the optabs with the names of the library functions. */
6341 add_optab->libcall_basename = "add";
6342 add_optab->libcall_suffix = '3';
6343 add_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6344 addv_optab->libcall_basename = "add";
6345 addv_optab->libcall_suffix = '3';
6346 addv_optab->libcall_gen = gen_intv_fp_libfunc;
6347 ssadd_optab->libcall_basename = "ssadd";
6348 ssadd_optab->libcall_suffix = '3';
6349 ssadd_optab->libcall_gen = gen_signed_fixed_libfunc;
6350 usadd_optab->libcall_basename = "usadd";
6351 usadd_optab->libcall_suffix = '3';
6352 usadd_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6353 sub_optab->libcall_basename = "sub";
6354 sub_optab->libcall_suffix = '3';
6355 sub_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6356 subv_optab->libcall_basename = "sub";
6357 subv_optab->libcall_suffix = '3';
6358 subv_optab->libcall_gen = gen_intv_fp_libfunc;
6359 sssub_optab->libcall_basename = "sssub";
6360 sssub_optab->libcall_suffix = '3';
6361 sssub_optab->libcall_gen = gen_signed_fixed_libfunc;
6362 ussub_optab->libcall_basename = "ussub";
6363 ussub_optab->libcall_suffix = '3';
6364 ussub_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6365 smul_optab->libcall_basename = "mul";
6366 smul_optab->libcall_suffix = '3';
6367 smul_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6368 smulv_optab->libcall_basename = "mul";
6369 smulv_optab->libcall_suffix = '3';
6370 smulv_optab->libcall_gen = gen_intv_fp_libfunc;
6371 ssmul_optab->libcall_basename = "ssmul";
6372 ssmul_optab->libcall_suffix = '3';
6373 ssmul_optab->libcall_gen = gen_signed_fixed_libfunc;
6374 usmul_optab->libcall_basename = "usmul";
6375 usmul_optab->libcall_suffix = '3';
6376 usmul_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6377 sdiv_optab->libcall_basename = "div";
6378 sdiv_optab->libcall_suffix = '3';
6379 sdiv_optab->libcall_gen = gen_int_fp_signed_fixed_libfunc;
6380 sdivv_optab->libcall_basename = "divv";
6381 sdivv_optab->libcall_suffix = '3';
6382 sdivv_optab->libcall_gen = gen_int_libfunc;
6383 ssdiv_optab->libcall_basename = "ssdiv";
6384 ssdiv_optab->libcall_suffix = '3';
6385 ssdiv_optab->libcall_gen = gen_signed_fixed_libfunc;
6386 udiv_optab->libcall_basename = "udiv";
6387 udiv_optab->libcall_suffix = '3';
6388 udiv_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6389 usdiv_optab->libcall_basename = "usdiv";
6390 usdiv_optab->libcall_suffix = '3';
6391 usdiv_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6392 sdivmod_optab->libcall_basename = "divmod";
6393 sdivmod_optab->libcall_suffix = '4';
6394 sdivmod_optab->libcall_gen = gen_int_libfunc;
6395 udivmod_optab->libcall_basename = "udivmod";
6396 udivmod_optab->libcall_suffix = '4';
6397 udivmod_optab->libcall_gen = gen_int_libfunc;
6398 smod_optab->libcall_basename = "mod";
6399 smod_optab->libcall_suffix = '3';
6400 smod_optab->libcall_gen = gen_int_libfunc;
6401 umod_optab->libcall_basename = "umod";
6402 umod_optab->libcall_suffix = '3';
6403 umod_optab->libcall_gen = gen_int_libfunc;
6404 ftrunc_optab->libcall_basename = "ftrunc";
6405 ftrunc_optab->libcall_suffix = '2';
6406 ftrunc_optab->libcall_gen = gen_fp_libfunc;
6407 and_optab->libcall_basename = "and";
6408 and_optab->libcall_suffix = '3';
6409 and_optab->libcall_gen = gen_int_libfunc;
6410 ior_optab->libcall_basename = "ior";
6411 ior_optab->libcall_suffix = '3';
6412 ior_optab->libcall_gen = gen_int_libfunc;
6413 xor_optab->libcall_basename = "xor";
6414 xor_optab->libcall_suffix = '3';
6415 xor_optab->libcall_gen = gen_int_libfunc;
6416 ashl_optab->libcall_basename = "ashl";
6417 ashl_optab->libcall_suffix = '3';
6418 ashl_optab->libcall_gen = gen_int_fixed_libfunc;
6419 ssashl_optab->libcall_basename = "ssashl";
6420 ssashl_optab->libcall_suffix = '3';
6421 ssashl_optab->libcall_gen = gen_signed_fixed_libfunc;
6422 usashl_optab->libcall_basename = "usashl";
6423 usashl_optab->libcall_suffix = '3';
6424 usashl_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6425 ashr_optab->libcall_basename = "ashr";
6426 ashr_optab->libcall_suffix = '3';
6427 ashr_optab->libcall_gen = gen_int_signed_fixed_libfunc;
6428 lshr_optab->libcall_basename = "lshr";
6429 lshr_optab->libcall_suffix = '3';
6430 lshr_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6431 smin_optab->libcall_basename = "min";
6432 smin_optab->libcall_suffix = '3';
6433 smin_optab->libcall_gen = gen_int_fp_libfunc;
6434 smax_optab->libcall_basename = "max";
6435 smax_optab->libcall_suffix = '3';
6436 smax_optab->libcall_gen = gen_int_fp_libfunc;
6437 umin_optab->libcall_basename = "umin";
6438 umin_optab->libcall_suffix = '3';
6439 umin_optab->libcall_gen = gen_int_libfunc;
6440 umax_optab->libcall_basename = "umax";
6441 umax_optab->libcall_suffix = '3';
6442 umax_optab->libcall_gen = gen_int_libfunc;
6443 neg_optab->libcall_basename = "neg";
6444 neg_optab->libcall_suffix = '2';
6445 neg_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6446 ssneg_optab->libcall_basename = "ssneg";
6447 ssneg_optab->libcall_suffix = '2';
6448 ssneg_optab->libcall_gen = gen_signed_fixed_libfunc;
6449 usneg_optab->libcall_basename = "usneg";
6450 usneg_optab->libcall_suffix = '2';
6451 usneg_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6452 negv_optab->libcall_basename = "neg";
6453 negv_optab->libcall_suffix = '2';
6454 negv_optab->libcall_gen = gen_intv_fp_libfunc;
6455 one_cmpl_optab->libcall_basename = "one_cmpl";
6456 one_cmpl_optab->libcall_suffix = '2';
6457 one_cmpl_optab->libcall_gen = gen_int_libfunc;
6458 ffs_optab->libcall_basename = "ffs";
6459 ffs_optab->libcall_suffix = '2';
6460 ffs_optab->libcall_gen = gen_int_libfunc;
6461 clz_optab->libcall_basename = "clz";
6462 clz_optab->libcall_suffix = '2';
6463 clz_optab->libcall_gen = gen_int_libfunc;
6464 ctz_optab->libcall_basename = "ctz";
6465 ctz_optab->libcall_suffix = '2';
6466 ctz_optab->libcall_gen = gen_int_libfunc;
6467 popcount_optab->libcall_basename = "popcount";
6468 popcount_optab->libcall_suffix = '2';
6469 popcount_optab->libcall_gen = gen_int_libfunc;
6470 parity_optab->libcall_basename = "parity";
6471 parity_optab->libcall_suffix = '2';
6472 parity_optab->libcall_gen = gen_int_libfunc;
6474 /* Comparison libcalls for integers MUST come in pairs,
6475 signed/unsigned. */
6476 cmp_optab->libcall_basename = "cmp";
6477 cmp_optab->libcall_suffix = '2';
6478 cmp_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6479 ucmp_optab->libcall_basename = "ucmp";
6480 ucmp_optab->libcall_suffix = '2';
6481 ucmp_optab->libcall_gen = gen_int_libfunc;
6483 /* EQ etc are floating point only. */
6484 eq_optab->libcall_basename = "eq";
6485 eq_optab->libcall_suffix = '2';
6486 eq_optab->libcall_gen = gen_fp_libfunc;
6487 ne_optab->libcall_basename = "ne";
6488 ne_optab->libcall_suffix = '2';
6489 ne_optab->libcall_gen = gen_fp_libfunc;
6490 gt_optab->libcall_basename = "gt";
6491 gt_optab->libcall_suffix = '2';
6492 gt_optab->libcall_gen = gen_fp_libfunc;
6493 ge_optab->libcall_basename = "ge";
6494 ge_optab->libcall_suffix = '2';
6495 ge_optab->libcall_gen = gen_fp_libfunc;
6496 lt_optab->libcall_basename = "lt";
6497 lt_optab->libcall_suffix = '2';
6498 lt_optab->libcall_gen = gen_fp_libfunc;
6499 le_optab->libcall_basename = "le";
6500 le_optab->libcall_suffix = '2';
6501 le_optab->libcall_gen = gen_fp_libfunc;
6502 unord_optab->libcall_basename = "unord";
6503 unord_optab->libcall_suffix = '2';
6504 unord_optab->libcall_gen = gen_fp_libfunc;
6506 powi_optab->libcall_basename = "powi";
6507 powi_optab->libcall_suffix = '2';
6508 powi_optab->libcall_gen = gen_fp_libfunc;
6510 /* Conversions. */
6511 sfloat_optab->libcall_basename = "float";
6512 sfloat_optab->libcall_gen = gen_int_to_fp_conv_libfunc;
6513 ufloat_optab->libcall_gen = gen_ufloat_conv_libfunc;
6514 sfix_optab->libcall_basename = "fix";
6515 sfix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6516 ufix_optab->libcall_basename = "fixuns";
6517 ufix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6518 lrint_optab->libcall_basename = "lrint";
6519 lrint_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6520 lround_optab->libcall_basename = "lround";
6521 lround_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6522 lfloor_optab->libcall_basename = "lfloor";
6523 lfloor_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6524 lceil_optab->libcall_basename = "lceil";
6525 lceil_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6527 /* trunc_optab is also used for FLOAT_EXTEND. */
6528 sext_optab->libcall_basename = "extend";
6529 sext_optab->libcall_gen = gen_extend_conv_libfunc;
6530 trunc_optab->libcall_basename = "trunc";
6531 trunc_optab->libcall_gen = gen_trunc_conv_libfunc;
6533 /* Conversions for fixed-point modes and other modes. */
6534 fract_optab->libcall_basename = "fract";
6535 fract_optab->libcall_gen = gen_fract_conv_libfunc;
6536 satfract_optab->libcall_basename = "satfract";
6537 satfract_optab->libcall_gen = gen_satfract_conv_libfunc;
6538 fractuns_optab->libcall_basename = "fractuns";
6539 fractuns_optab->libcall_gen = gen_fractuns_conv_libfunc;
6540 satfractuns_optab->libcall_basename = "satfractuns";
6541 satfractuns_optab->libcall_gen = gen_satfractuns_conv_libfunc;
6543 /* The ffs function operates on `int'. Fall back on it if we do not
6544 have a libgcc2 function for that width. */
6545 if (INT_TYPE_SIZE < BITS_PER_WORD)
6546 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
6547 "ffs");
6549 /* Explicitly initialize the bswap libfuncs since we need them to be
6550 valid for things other than word_mode. */
6551 set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
6552 set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
6554 /* Use cabs for double complex abs, since systems generally have cabs.
6555 Don't define any libcall for float complex, so that cabs will be used. */
6556 if (complex_double_type_node)
6557 set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node), "cabs");
6559 abort_libfunc = init_one_libfunc ("abort");
6560 memcpy_libfunc = init_one_libfunc ("memcpy");
6561 memmove_libfunc = init_one_libfunc ("memmove");
6562 memcmp_libfunc = init_one_libfunc ("memcmp");
6563 memset_libfunc = init_one_libfunc ("memset");
6564 setbits_libfunc = init_one_libfunc ("__setbits");
6566 #ifndef DONT_USE_BUILTIN_SETJMP
6567 setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
6568 longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
6569 #else
6570 setjmp_libfunc = init_one_libfunc ("setjmp");
6571 longjmp_libfunc = init_one_libfunc ("longjmp");
6572 #endif
6573 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
6574 unwind_sjlj_unregister_libfunc
6575 = init_one_libfunc ("_Unwind_SjLj_Unregister");
6577 /* For function entry/exit instrumentation. */
6578 profile_function_entry_libfunc
6579 = init_one_libfunc ("__cyg_profile_func_enter");
6580 profile_function_exit_libfunc
6581 = init_one_libfunc ("__cyg_profile_func_exit");
6583 gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
6585 /* Allow the target to add more libcalls or rename some, etc. */
6586 targetm.init_libfuncs ();
6588 reinit = true;
6591 /* Print information about the current contents of the optabs on
6592 STDERR. */
6594 DEBUG_FUNCTION void
6595 debug_optab_libfuncs (void)
6597 int i;
6598 int j;
6599 int k;
6601 /* Dump the arithmetic optabs. */
6602 for (i = 0; i != (int) OTI_MAX; i++)
6603 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6605 optab o;
6606 rtx l;
6608 o = &optab_table[i];
6609 l = optab_libfunc (o, (enum machine_mode) j);
6610 if (l)
6612 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6613 fprintf (stderr, "%s\t%s:\t%s\n",
6614 GET_RTX_NAME (o->code),
6615 GET_MODE_NAME (j),
6616 XSTR (l, 0));
6620 /* Dump the conversion optabs. */
6621 for (i = 0; i < (int) COI_MAX; ++i)
6622 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6623 for (k = 0; k < NUM_MACHINE_MODES; ++k)
6625 convert_optab o;
6626 rtx l;
6628 o = &convert_optab_table[i];
6629 l = convert_optab_libfunc (o, (enum machine_mode) j,
6630 (enum machine_mode) k);
6631 if (l)
6633 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6634 fprintf (stderr, "%s\t%s\t%s:\t%s\n",
6635 GET_RTX_NAME (o->code),
6636 GET_MODE_NAME (j),
6637 GET_MODE_NAME (k),
6638 XSTR (l, 0));
6644 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
6645 CODE. Return 0 on failure. */
6648 gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
6650 enum machine_mode mode = GET_MODE (op1);
6651 enum insn_code icode;
6652 rtx insn;
6653 rtx trap_rtx;
6655 if (mode == VOIDmode)
6656 return 0;
6658 icode = optab_handler (ctrap_optab, mode);
6659 if (icode == CODE_FOR_nothing)
6660 return 0;
6662 /* Some targets only accept a zero trap code. */
6663 if (insn_data[icode].operand[3].predicate
6664 && !insn_data[icode].operand[3].predicate (tcode, VOIDmode))
6665 return 0;
6667 do_pending_stack_adjust ();
6668 start_sequence ();
6669 prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
6670 &trap_rtx, &mode);
6671 if (!trap_rtx)
6672 insn = NULL_RTX;
6673 else
6674 insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
6675 tcode);
6677 /* If that failed, then give up. */
6678 if (insn == 0)
6680 end_sequence ();
6681 return 0;
6684 emit_insn (insn);
6685 insn = get_insns ();
6686 end_sequence ();
6687 return insn;
6690 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
6691 or unsigned operation code. */
6693 static enum rtx_code
6694 get_rtx_code (enum tree_code tcode, bool unsignedp)
6696 enum rtx_code code;
6697 switch (tcode)
6699 case EQ_EXPR:
6700 code = EQ;
6701 break;
6702 case NE_EXPR:
6703 code = NE;
6704 break;
6705 case LT_EXPR:
6706 code = unsignedp ? LTU : LT;
6707 break;
6708 case LE_EXPR:
6709 code = unsignedp ? LEU : LE;
6710 break;
6711 case GT_EXPR:
6712 code = unsignedp ? GTU : GT;
6713 break;
6714 case GE_EXPR:
6715 code = unsignedp ? GEU : GE;
6716 break;
6718 case UNORDERED_EXPR:
6719 code = UNORDERED;
6720 break;
6721 case ORDERED_EXPR:
6722 code = ORDERED;
6723 break;
6724 case UNLT_EXPR:
6725 code = UNLT;
6726 break;
6727 case UNLE_EXPR:
6728 code = UNLE;
6729 break;
6730 case UNGT_EXPR:
6731 code = UNGT;
6732 break;
6733 case UNGE_EXPR:
6734 code = UNGE;
6735 break;
6736 case UNEQ_EXPR:
6737 code = UNEQ;
6738 break;
6739 case LTGT_EXPR:
6740 code = LTGT;
6741 break;
6743 default:
6744 gcc_unreachable ();
6746 return code;
6749 /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
6750 unsigned operators. Do not generate compare instruction. */
6752 static rtx
6753 vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
6755 enum rtx_code rcode;
6756 tree t_op0, t_op1;
6757 rtx rtx_op0, rtx_op1;
6759 /* This is unlikely. While generating VEC_COND_EXPR, auto vectorizer
6760 ensures that condition is a relational operation. */
6761 gcc_assert (COMPARISON_CLASS_P (cond));
6763 rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
6764 t_op0 = TREE_OPERAND (cond, 0);
6765 t_op1 = TREE_OPERAND (cond, 1);
6767 /* Expand operands. */
6768 rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
6769 EXPAND_STACK_PARM);
6770 rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
6771 EXPAND_STACK_PARM);
6773 if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
6774 && GET_MODE (rtx_op0) != VOIDmode)
6775 rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
6777 if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
6778 && GET_MODE (rtx_op1) != VOIDmode)
6779 rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
6781 return gen_rtx_fmt_ee (rcode, VOIDmode, rtx_op0, rtx_op1);
6784 /* Return insn code for TYPE, the type of a VEC_COND_EXPR. */
6786 static inline enum insn_code
6787 get_vcond_icode (tree type, enum machine_mode mode)
6789 enum insn_code icode = CODE_FOR_nothing;
6791 if (TYPE_UNSIGNED (type))
6792 icode = direct_optab_handler (vcondu_optab, mode);
6793 else
6794 icode = direct_optab_handler (vcond_optab, mode);
6795 return icode;
6798 /* Return TRUE iff, appropriate vector insns are available
6799 for vector cond expr with type TYPE in VMODE mode. */
6801 bool
6802 expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
6804 if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
6805 return false;
6806 return true;
6809 /* Generate insns for a VEC_COND_EXPR, given its TYPE and its
6810 three operands. */
6813 expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
6814 rtx target)
6816 enum insn_code icode;
6817 rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
6818 enum machine_mode mode = TYPE_MODE (vec_cond_type);
6819 bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
6821 icode = get_vcond_icode (vec_cond_type, mode);
6822 if (icode == CODE_FOR_nothing)
6823 return 0;
6825 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6826 target = gen_reg_rtx (mode);
6828 /* Get comparison rtx. First expand both cond expr operands. */
6829 comparison = vector_compare_rtx (op0,
6830 unsignedp, icode);
6831 cc_op0 = XEXP (comparison, 0);
6832 cc_op1 = XEXP (comparison, 1);
6833 /* Expand both operands and force them in reg, if required. */
6834 rtx_op1 = expand_normal (op1);
6835 if (!insn_data[icode].operand[1].predicate (rtx_op1, mode)
6836 && mode != VOIDmode)
6837 rtx_op1 = force_reg (mode, rtx_op1);
6839 rtx_op2 = expand_normal (op2);
6840 if (!insn_data[icode].operand[2].predicate (rtx_op2, mode)
6841 && mode != VOIDmode)
6842 rtx_op2 = force_reg (mode, rtx_op2);
6844 /* Emit instruction! */
6845 emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
6846 comparison, cc_op0, cc_op1));
6848 return target;
6852 /* This is an internal subroutine of the other compare_and_swap expanders.
6853 MEM, OLD_VAL and NEW_VAL are as you'd expect for a compare-and-swap
6854 operation. TARGET is an optional place to store the value result of
6855 the operation. ICODE is the particular instruction to expand. Return
6856 the result of the operation. */
6858 static rtx
6859 expand_val_compare_and_swap_1 (rtx mem, rtx old_val, rtx new_val,
6860 rtx target, enum insn_code icode)
6862 enum machine_mode mode = GET_MODE (mem);
6863 rtx insn;
6865 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6866 target = gen_reg_rtx (mode);
6868 if (GET_MODE (old_val) != VOIDmode && GET_MODE (old_val) != mode)
6869 old_val = convert_modes (mode, GET_MODE (old_val), old_val, 1);
6870 if (!insn_data[icode].operand[2].predicate (old_val, mode))
6871 old_val = force_reg (mode, old_val);
6873 if (GET_MODE (new_val) != VOIDmode && GET_MODE (new_val) != mode)
6874 new_val = convert_modes (mode, GET_MODE (new_val), new_val, 1);
6875 if (!insn_data[icode].operand[3].predicate (new_val, mode))
6876 new_val = force_reg (mode, new_val);
6878 insn = GEN_FCN (icode) (target, mem, old_val, new_val);
6879 if (insn == NULL_RTX)
6880 return NULL_RTX;
6881 emit_insn (insn);
6883 return target;
6886 /* Expand a compare-and-swap operation and return its value. */
6889 expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
6891 enum machine_mode mode = GET_MODE (mem);
6892 enum insn_code icode
6893 = direct_optab_handler (sync_compare_and_swap_optab, mode);
6895 if (icode == CODE_FOR_nothing)
6896 return NULL_RTX;
6898 return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode);
6901 /* Helper function to find the MODE_CC set in a sync_compare_and_swap
6902 pattern. */
6904 static void
6905 find_cc_set (rtx x, const_rtx pat, void *data)
6907 if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
6908 && GET_CODE (pat) == SET)
6910 rtx *p_cc_reg = (rtx *) data;
6911 gcc_assert (!*p_cc_reg);
6912 *p_cc_reg = x;
6916 /* Expand a compare-and-swap operation and store true into the result if
6917 the operation was successful and false otherwise. Return the result.
6918 Unlike other routines, TARGET is not optional. */
6921 expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
6923 enum machine_mode mode = GET_MODE (mem);
6924 enum insn_code icode;
6925 rtx subtarget, seq, cc_reg;
6927 /* If the target supports a compare-and-swap pattern that simultaneously
6928 sets some flag for success, then use it. Otherwise use the regular
6929 compare-and-swap and follow that immediately with a compare insn. */
6930 icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
6931 if (icode == CODE_FOR_nothing)
6932 return NULL_RTX;
6936 start_sequence ();
6937 subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
6938 NULL_RTX, icode);
6939 cc_reg = NULL_RTX;
6940 if (subtarget == NULL_RTX)
6942 end_sequence ();
6943 return NULL_RTX;
6946 if (have_insn_for (COMPARE, CCmode))
6947 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
6948 seq = get_insns ();
6949 end_sequence ();
6951 /* We might be comparing against an old value. Try again. :-( */
6952 if (!cc_reg && MEM_P (old_val))
6954 seq = NULL_RTX;
6955 old_val = force_reg (mode, old_val);
6958 while (!seq);
6960 emit_insn (seq);
6961 if (cc_reg)
6962 return emit_store_flag_force (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1);
6963 else
6964 return emit_store_flag_force (target, EQ, subtarget, old_val, VOIDmode, 1, 1);
6967 /* This is a helper function for the other atomic operations. This function
6968 emits a loop that contains SEQ that iterates until a compare-and-swap
6969 operation at the end succeeds. MEM is the memory to be modified. SEQ is
6970 a set of instructions that takes a value from OLD_REG as an input and
6971 produces a value in NEW_REG as an output. Before SEQ, OLD_REG will be
6972 set to the current contents of MEM. After SEQ, a compare-and-swap will
6973 attempt to update MEM with NEW_REG. The function returns true when the
6974 loop was generated successfully. */
6976 static bool
6977 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
6979 enum machine_mode mode = GET_MODE (mem);
6980 enum insn_code icode;
6981 rtx label, cmp_reg, subtarget, cc_reg;
6983 /* The loop we want to generate looks like
6985 cmp_reg = mem;
6986 label:
6987 old_reg = cmp_reg;
6988 seq;
6989 cmp_reg = compare-and-swap(mem, old_reg, new_reg)
6990 if (cmp_reg != old_reg)
6991 goto label;
6993 Note that we only do the plain load from memory once. Subsequent
6994 iterations use the value loaded by the compare-and-swap pattern. */
6996 label = gen_label_rtx ();
6997 cmp_reg = gen_reg_rtx (mode);
6999 emit_move_insn (cmp_reg, mem);
7000 emit_label (label);
7001 emit_move_insn (old_reg, cmp_reg);
7002 if (seq)
7003 emit_insn (seq);
7005 /* If the target supports a compare-and-swap pattern that simultaneously
7006 sets some flag for success, then use it. Otherwise use the regular
7007 compare-and-swap and follow that immediately with a compare insn. */
7008 icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
7009 if (icode == CODE_FOR_nothing)
7010 return false;
7012 subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
7013 cmp_reg, icode);
7014 if (subtarget == NULL_RTX)
7015 return false;
7017 cc_reg = NULL_RTX;
7018 if (have_insn_for (COMPARE, CCmode))
7019 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
7020 if (cc_reg)
7022 cmp_reg = cc_reg;
7023 old_reg = const0_rtx;
7025 else
7027 if (subtarget != cmp_reg)
7028 emit_move_insn (cmp_reg, subtarget);
7031 /* ??? Mark this jump predicted not taken? */
7032 emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, const0_rtx, GET_MODE (cmp_reg), 1,
7033 label);
7034 return true;
7037 /* This function generates the atomic operation MEM CODE= VAL. In this
7038 case, we do not care about any resulting value. Returns NULL if we
7039 cannot generate the operation. */
7042 expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
7044 enum machine_mode mode = GET_MODE (mem);
7045 enum insn_code icode;
7046 rtx insn;
7048 /* Look to see if the target supports the operation directly. */
7049 switch (code)
7051 case PLUS:
7052 icode = direct_optab_handler (sync_add_optab, mode);
7053 break;
7054 case IOR:
7055 icode = direct_optab_handler (sync_ior_optab, mode);
7056 break;
7057 case XOR:
7058 icode = direct_optab_handler (sync_xor_optab, mode);
7059 break;
7060 case AND:
7061 icode = direct_optab_handler (sync_and_optab, mode);
7062 break;
7063 case NOT:
7064 icode = direct_optab_handler (sync_nand_optab, mode);
7065 break;
7067 case MINUS:
7068 icode = direct_optab_handler (sync_sub_optab, mode);
7069 if (icode == CODE_FOR_nothing || CONST_INT_P (val))
7071 icode = direct_optab_handler (sync_add_optab, mode);
7072 if (icode != CODE_FOR_nothing)
7074 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7075 code = PLUS;
7078 break;
7080 default:
7081 gcc_unreachable ();
7084 /* Generate the direct operation, if present. */
7085 if (icode != CODE_FOR_nothing)
7087 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7088 val = convert_modes (mode, GET_MODE (val), val, 1);
7089 if (!insn_data[icode].operand[1].predicate (val, mode))
7090 val = force_reg (mode, val);
7092 insn = GEN_FCN (icode) (mem, val);
7093 if (insn)
7095 emit_insn (insn);
7096 return const0_rtx;
7100 /* Failing that, generate a compare-and-swap loop in which we perform the
7101 operation with normal arithmetic instructions. */
7102 if (direct_optab_handler (sync_compare_and_swap_optab, mode)
7103 != CODE_FOR_nothing)
7105 rtx t0 = gen_reg_rtx (mode), t1;
7107 start_sequence ();
7109 t1 = t0;
7110 if (code == NOT)
7112 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7113 true, OPTAB_LIB_WIDEN);
7114 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7116 else
7117 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7118 true, OPTAB_LIB_WIDEN);
7119 insn = get_insns ();
7120 end_sequence ();
7122 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7123 return const0_rtx;
7126 return NULL_RTX;
7129 /* This function generates the atomic operation MEM CODE= VAL. In this
7130 case, we do care about the resulting value: if AFTER is true then
7131 return the value MEM holds after the operation, if AFTER is false
7132 then return the value MEM holds before the operation. TARGET is an
7133 optional place for the result value to be stored. */
7136 expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
7137 bool after, rtx target)
7139 enum machine_mode mode = GET_MODE (mem);
7140 enum insn_code old_code, new_code, icode;
7141 bool compensate;
7142 rtx insn;
7144 /* Look to see if the target supports the operation directly. */
7145 switch (code)
7147 case PLUS:
7148 old_code = direct_optab_handler (sync_old_add_optab, mode);
7149 new_code = direct_optab_handler (sync_new_add_optab, mode);
7150 break;
7151 case IOR:
7152 old_code = direct_optab_handler (sync_old_ior_optab, mode);
7153 new_code = direct_optab_handler (sync_new_ior_optab, mode);
7154 break;
7155 case XOR:
7156 old_code = direct_optab_handler (sync_old_xor_optab, mode);
7157 new_code = direct_optab_handler (sync_new_xor_optab, mode);
7158 break;
7159 case AND:
7160 old_code = direct_optab_handler (sync_old_and_optab, mode);
7161 new_code = direct_optab_handler (sync_new_and_optab, mode);
7162 break;
7163 case NOT:
7164 old_code = direct_optab_handler (sync_old_nand_optab, mode);
7165 new_code = direct_optab_handler (sync_new_nand_optab, mode);
7166 break;
7168 case MINUS:
7169 old_code = direct_optab_handler (sync_old_sub_optab, mode);
7170 new_code = direct_optab_handler (sync_new_sub_optab, mode);
7171 if ((old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
7172 || CONST_INT_P (val))
7174 old_code = direct_optab_handler (sync_old_add_optab, mode);
7175 new_code = direct_optab_handler (sync_new_add_optab, mode);
7176 if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
7178 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7179 code = PLUS;
7182 break;
7184 default:
7185 gcc_unreachable ();
7188 /* If the target does supports the proper new/old operation, great. But
7189 if we only support the opposite old/new operation, check to see if we
7190 can compensate. In the case in which the old value is supported, then
7191 we can always perform the operation again with normal arithmetic. In
7192 the case in which the new value is supported, then we can only handle
7193 this in the case the operation is reversible. */
7194 compensate = false;
7195 if (after)
7197 icode = new_code;
7198 if (icode == CODE_FOR_nothing)
7200 icode = old_code;
7201 if (icode != CODE_FOR_nothing)
7202 compensate = true;
7205 else
7207 icode = old_code;
7208 if (icode == CODE_FOR_nothing
7209 && (code == PLUS || code == MINUS || code == XOR))
7211 icode = new_code;
7212 if (icode != CODE_FOR_nothing)
7213 compensate = true;
7217 /* If we found something supported, great. */
7218 if (icode != CODE_FOR_nothing)
7220 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7221 target = gen_reg_rtx (mode);
7223 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7224 val = convert_modes (mode, GET_MODE (val), val, 1);
7225 if (!insn_data[icode].operand[2].predicate (val, mode))
7226 val = force_reg (mode, val);
7228 insn = GEN_FCN (icode) (target, mem, val);
7229 if (insn)
7231 emit_insn (insn);
7233 /* If we need to compensate for using an operation with the
7234 wrong return value, do so now. */
7235 if (compensate)
7237 if (!after)
7239 if (code == PLUS)
7240 code = MINUS;
7241 else if (code == MINUS)
7242 code = PLUS;
7245 if (code == NOT)
7247 target = expand_simple_binop (mode, AND, target, val,
7248 NULL_RTX, true,
7249 OPTAB_LIB_WIDEN);
7250 target = expand_simple_unop (mode, code, target,
7251 NULL_RTX, true);
7253 else
7254 target = expand_simple_binop (mode, code, target, val,
7255 NULL_RTX, true,
7256 OPTAB_LIB_WIDEN);
7259 return target;
7263 /* Failing that, generate a compare-and-swap loop in which we perform the
7264 operation with normal arithmetic instructions. */
7265 if (direct_optab_handler (sync_compare_and_swap_optab, mode)
7266 != CODE_FOR_nothing)
7268 rtx t0 = gen_reg_rtx (mode), t1;
7270 if (!target || !register_operand (target, mode))
7271 target = gen_reg_rtx (mode);
7273 start_sequence ();
7275 if (!after)
7276 emit_move_insn (target, t0);
7277 t1 = t0;
7278 if (code == NOT)
7280 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7281 true, OPTAB_LIB_WIDEN);
7282 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7284 else
7285 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7286 true, OPTAB_LIB_WIDEN);
7287 if (after)
7288 emit_move_insn (target, t1);
7290 insn = get_insns ();
7291 end_sequence ();
7293 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7294 return target;
7297 return NULL_RTX;
7300 /* This function expands a test-and-set operation. Ideally we atomically
7301 store VAL in MEM and return the previous value in MEM. Some targets
7302 may not support this operation and only support VAL with the constant 1;
7303 in this case while the return value will be 0/1, but the exact value
7304 stored in MEM is target defined. TARGET is an option place to stick
7305 the return value. */
7308 expand_sync_lock_test_and_set (rtx mem, rtx val, rtx target)
7310 enum machine_mode mode = GET_MODE (mem);
7311 enum insn_code icode;
7312 rtx insn;
7314 /* If the target supports the test-and-set directly, great. */
7315 icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
7316 if (icode != CODE_FOR_nothing)
7318 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7319 target = gen_reg_rtx (mode);
7321 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7322 val = convert_modes (mode, GET_MODE (val), val, 1);
7323 if (!insn_data[icode].operand[2].predicate (val, mode))
7324 val = force_reg (mode, val);
7326 insn = GEN_FCN (icode) (target, mem, val);
7327 if (insn)
7329 emit_insn (insn);
7330 return target;
7334 /* Otherwise, use a compare-and-swap loop for the exchange. */
7335 if (direct_optab_handler (sync_compare_and_swap_optab, mode)
7336 != CODE_FOR_nothing)
7338 if (!target || !register_operand (target, mode))
7339 target = gen_reg_rtx (mode);
7340 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7341 val = convert_modes (mode, GET_MODE (val), val, 1);
7342 if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
7343 return target;
7346 return NULL_RTX;
7349 #include "gt-optabs.h"