gcc/ChangeLog:
[official-gcc.git] / gcc / optabs.c
blob26735dd2ae1a9a472dce4a6d4825edf379cb97d8
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 "diagnostic-core.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 struct target_optabs default_target_optabs;
48 struct target_libfuncs default_target_libfuncs;
49 #if SWITCHABLE_TARGET
50 struct target_optabs *this_target_optabs = &default_target_optabs;
51 struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
52 #endif
54 #define libfunc_hash \
55 (this_target_libfuncs->x_libfunc_hash)
57 /* Contains the optab used for each rtx code. */
58 optab code_to_optab[NUM_RTX_CODE + 1];
60 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
61 enum machine_mode *);
62 static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
64 /* Debug facility for use in GDB. */
65 void debug_optab_libfuncs (void);
67 /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
68 #if ENABLE_DECIMAL_BID_FORMAT
69 #define DECIMAL_PREFIX "bid_"
70 #else
71 #define DECIMAL_PREFIX "dpd_"
72 #endif
74 /* Used for libfunc_hash. */
76 static hashval_t
77 hash_libfunc (const void *p)
79 const struct libfunc_entry *const e = (const struct libfunc_entry *) p;
81 return (((int) e->mode1 + (int) e->mode2 * NUM_MACHINE_MODES)
82 ^ e->optab);
85 /* Used for libfunc_hash. */
87 static int
88 eq_libfunc (const void *p, const void *q)
90 const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p;
91 const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q;
93 return (e1->optab == e2->optab
94 && e1->mode1 == e2->mode1
95 && e1->mode2 == e2->mode2);
98 /* Return libfunc corresponding operation defined by OPTAB converting
99 from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL
100 if no libfunc is available. */
102 convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
103 enum machine_mode mode2)
105 struct libfunc_entry e;
106 struct libfunc_entry **slot;
108 e.optab = (size_t) (optab - &convert_optab_table[0]);
109 e.mode1 = mode1;
110 e.mode2 = mode2;
111 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
112 if (!slot)
114 if (optab->libcall_gen)
116 optab->libcall_gen (optab, optab->libcall_basename, mode1, mode2);
117 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
118 if (slot)
119 return (*slot)->libfunc;
120 else
121 return NULL;
123 return NULL;
125 return (*slot)->libfunc;
128 /* Return libfunc corresponding operation defined by OPTAB in MODE.
129 Trigger lazy initialization if needed, return NULL if no libfunc is
130 available. */
132 optab_libfunc (optab optab, enum machine_mode mode)
134 struct libfunc_entry e;
135 struct libfunc_entry **slot;
137 e.optab = (size_t) (optab - &optab_table[0]);
138 e.mode1 = mode;
139 e.mode2 = VOIDmode;
140 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
141 if (!slot)
143 if (optab->libcall_gen)
145 optab->libcall_gen (optab, optab->libcall_basename,
146 optab->libcall_suffix, mode);
147 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash,
148 &e, NO_INSERT);
149 if (slot)
150 return (*slot)->libfunc;
151 else
152 return NULL;
154 return NULL;
156 return (*slot)->libfunc;
160 /* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
161 the result of operation CODE applied to OP0 (and OP1 if it is a binary
162 operation).
164 If the last insn does not set TARGET, don't do anything, but return 1.
166 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
167 don't add the REG_EQUAL note but return 0. Our caller can then try
168 again, ensuring that TARGET is not one of the operands. */
170 static int
171 add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
173 rtx last_insn, insn, set;
174 rtx note;
176 gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
178 if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
179 && GET_RTX_CLASS (code) != RTX_BIN_ARITH
180 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
181 && GET_RTX_CLASS (code) != RTX_COMPARE
182 && GET_RTX_CLASS (code) != RTX_UNARY)
183 return 1;
185 if (GET_CODE (target) == ZERO_EXTRACT)
186 return 1;
188 for (last_insn = insns;
189 NEXT_INSN (last_insn) != NULL_RTX;
190 last_insn = NEXT_INSN (last_insn))
193 set = single_set (last_insn);
194 if (set == NULL_RTX)
195 return 1;
197 if (! rtx_equal_p (SET_DEST (set), target)
198 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it. */
199 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
200 || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
201 return 1;
203 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
204 besides the last insn. */
205 if (reg_overlap_mentioned_p (target, op0)
206 || (op1 && reg_overlap_mentioned_p (target, op1)))
208 insn = PREV_INSN (last_insn);
209 while (insn != NULL_RTX)
211 if (reg_set_p (target, insn))
212 return 0;
214 insn = PREV_INSN (insn);
218 if (GET_RTX_CLASS (code) == RTX_UNARY)
219 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
220 else
221 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
223 set_unique_reg_note (last_insn, REG_EQUAL, note);
225 return 1;
228 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
229 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
230 not actually do a sign-extend or zero-extend, but can leave the
231 higher-order bits of the result rtx undefined, for example, in the case
232 of logical operations, but not right shifts. */
234 static rtx
235 widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
236 int unsignedp, int no_extend)
238 rtx result;
240 /* If we don't have to extend and this is a constant, return it. */
241 if (no_extend && GET_MODE (op) == VOIDmode)
242 return op;
244 /* If we must extend do so. If OP is a SUBREG for a promoted object, also
245 extend since it will be more efficient to do so unless the signedness of
246 a promoted object differs from our extension. */
247 if (! no_extend
248 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
249 && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
250 return convert_modes (mode, oldmode, op, unsignedp);
252 /* If MODE is no wider than a single word, we return a paradoxical
253 SUBREG. */
254 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
255 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
257 /* Otherwise, get an object of MODE, clobber it, and set the low-order
258 part to OP. */
260 result = gen_reg_rtx (mode);
261 emit_clobber (result);
262 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
263 return result;
266 /* Return the optab used for computing the operation given by the tree code,
267 CODE and the tree EXP. This function is not always usable (for example, it
268 cannot give complete results for multiplication or division) but probably
269 ought to be relied on more widely throughout the expander. */
270 optab
271 optab_for_tree_code (enum tree_code code, const_tree type,
272 enum optab_subtype subtype)
274 bool trapv;
275 switch (code)
277 case BIT_AND_EXPR:
278 return and_optab;
280 case BIT_IOR_EXPR:
281 return ior_optab;
283 case BIT_NOT_EXPR:
284 return one_cmpl_optab;
286 case BIT_XOR_EXPR:
287 return xor_optab;
289 case TRUNC_MOD_EXPR:
290 case CEIL_MOD_EXPR:
291 case FLOOR_MOD_EXPR:
292 case ROUND_MOD_EXPR:
293 return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
295 case RDIV_EXPR:
296 case TRUNC_DIV_EXPR:
297 case CEIL_DIV_EXPR:
298 case FLOOR_DIV_EXPR:
299 case ROUND_DIV_EXPR:
300 case EXACT_DIV_EXPR:
301 if (TYPE_SATURATING(type))
302 return TYPE_UNSIGNED(type) ? usdiv_optab : ssdiv_optab;
303 return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
305 case LSHIFT_EXPR:
306 if (VECTOR_MODE_P (TYPE_MODE (type)))
308 if (subtype == optab_vector)
309 return TYPE_SATURATING (type) ? NULL : vashl_optab;
311 gcc_assert (subtype == optab_scalar);
313 if (TYPE_SATURATING(type))
314 return TYPE_UNSIGNED(type) ? usashl_optab : ssashl_optab;
315 return ashl_optab;
317 case RSHIFT_EXPR:
318 if (VECTOR_MODE_P (TYPE_MODE (type)))
320 if (subtype == optab_vector)
321 return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
323 gcc_assert (subtype == optab_scalar);
325 return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
327 case LROTATE_EXPR:
328 if (VECTOR_MODE_P (TYPE_MODE (type)))
330 if (subtype == optab_vector)
331 return vrotl_optab;
333 gcc_assert (subtype == optab_scalar);
335 return rotl_optab;
337 case RROTATE_EXPR:
338 if (VECTOR_MODE_P (TYPE_MODE (type)))
340 if (subtype == optab_vector)
341 return vrotr_optab;
343 gcc_assert (subtype == optab_scalar);
345 return rotr_optab;
347 case MAX_EXPR:
348 return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
350 case MIN_EXPR:
351 return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
353 case REALIGN_LOAD_EXPR:
354 return vec_realign_load_optab;
356 case WIDEN_SUM_EXPR:
357 return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
359 case DOT_PROD_EXPR:
360 return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
362 case WIDEN_MULT_PLUS_EXPR:
363 return (TYPE_UNSIGNED (type)
364 ? (TYPE_SATURATING (type)
365 ? usmadd_widen_optab : umadd_widen_optab)
366 : (TYPE_SATURATING (type)
367 ? ssmadd_widen_optab : smadd_widen_optab));
369 case WIDEN_MULT_MINUS_EXPR:
370 return (TYPE_UNSIGNED (type)
371 ? (TYPE_SATURATING (type)
372 ? usmsub_widen_optab : umsub_widen_optab)
373 : (TYPE_SATURATING (type)
374 ? ssmsub_widen_optab : smsub_widen_optab));
376 case FMA_EXPR:
377 return fma_optab;
379 case REDUC_MAX_EXPR:
380 return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab;
382 case REDUC_MIN_EXPR:
383 return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab;
385 case REDUC_PLUS_EXPR:
386 return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
388 case VEC_LSHIFT_EXPR:
389 return vec_shl_optab;
391 case VEC_RSHIFT_EXPR:
392 return vec_shr_optab;
394 case VEC_WIDEN_MULT_HI_EXPR:
395 return TYPE_UNSIGNED (type) ?
396 vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
398 case VEC_WIDEN_MULT_LO_EXPR:
399 return TYPE_UNSIGNED (type) ?
400 vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
402 case VEC_UNPACK_HI_EXPR:
403 return TYPE_UNSIGNED (type) ?
404 vec_unpacku_hi_optab : vec_unpacks_hi_optab;
406 case VEC_UNPACK_LO_EXPR:
407 return TYPE_UNSIGNED (type) ?
408 vec_unpacku_lo_optab : vec_unpacks_lo_optab;
410 case VEC_UNPACK_FLOAT_HI_EXPR:
411 /* The signedness is determined from input operand. */
412 return TYPE_UNSIGNED (type) ?
413 vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
415 case VEC_UNPACK_FLOAT_LO_EXPR:
416 /* The signedness is determined from input operand. */
417 return TYPE_UNSIGNED (type) ?
418 vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
420 case VEC_PACK_TRUNC_EXPR:
421 return vec_pack_trunc_optab;
423 case VEC_PACK_SAT_EXPR:
424 return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
426 case VEC_PACK_FIX_TRUNC_EXPR:
427 /* The signedness is determined from output operand. */
428 return TYPE_UNSIGNED (type) ?
429 vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
431 default:
432 break;
435 trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
436 switch (code)
438 case POINTER_PLUS_EXPR:
439 case PLUS_EXPR:
440 if (TYPE_SATURATING(type))
441 return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
442 return trapv ? addv_optab : add_optab;
444 case MINUS_EXPR:
445 if (TYPE_SATURATING(type))
446 return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
447 return trapv ? subv_optab : sub_optab;
449 case MULT_EXPR:
450 if (TYPE_SATURATING(type))
451 return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
452 return trapv ? smulv_optab : smul_optab;
454 case NEGATE_EXPR:
455 if (TYPE_SATURATING(type))
456 return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
457 return trapv ? negv_optab : neg_optab;
459 case ABS_EXPR:
460 return trapv ? absv_optab : abs_optab;
462 case VEC_EXTRACT_EVEN_EXPR:
463 return vec_extract_even_optab;
465 case VEC_EXTRACT_ODD_EXPR:
466 return vec_extract_odd_optab;
468 case VEC_INTERLEAVE_HIGH_EXPR:
469 return vec_interleave_high_optab;
471 case VEC_INTERLEAVE_LOW_EXPR:
472 return vec_interleave_low_optab;
474 default:
475 return NULL;
480 /* Expand vector widening operations.
482 There are two different classes of operations handled here:
483 1) Operations whose result is wider than all the arguments to the operation.
484 Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR
485 In this case OP0 and optionally OP1 would be initialized,
486 but WIDE_OP wouldn't (not relevant for this case).
487 2) Operations whose result is of the same size as the last argument to the
488 operation, but wider than all the other arguments to the operation.
489 Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR.
490 In the case WIDE_OP, OP0 and optionally OP1 would be initialized.
492 E.g, when called to expand the following operations, this is how
493 the arguments will be initialized:
494 nops OP0 OP1 WIDE_OP
495 widening-sum 2 oprnd0 - oprnd1
496 widening-dot-product 3 oprnd0 oprnd1 oprnd2
497 widening-mult 2 oprnd0 oprnd1 -
498 type-promotion (vec-unpack) 1 oprnd0 - - */
501 expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
502 rtx target, int unsignedp)
504 tree oprnd0, oprnd1, oprnd2;
505 enum machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
506 optab widen_pattern_optab;
507 int icode;
508 enum machine_mode xmode0, xmode1 = VOIDmode, wxmode = VOIDmode;
509 rtx temp;
510 rtx pat;
511 rtx xop0, xop1, wxop;
512 int nops = TREE_CODE_LENGTH (ops->code);
514 oprnd0 = ops->op0;
515 tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
516 widen_pattern_optab =
517 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
518 if (ops->code == WIDEN_MULT_PLUS_EXPR
519 || ops->code == WIDEN_MULT_MINUS_EXPR)
520 icode = (int) optab_handler (widen_pattern_optab,
521 TYPE_MODE (TREE_TYPE (ops->op2)));
522 else
523 icode = (int) optab_handler (widen_pattern_optab, tmode0);
524 gcc_assert (icode != CODE_FOR_nothing);
525 xmode0 = insn_data[icode].operand[1].mode;
527 if (nops >= 2)
529 oprnd1 = ops->op1;
530 tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
531 xmode1 = insn_data[icode].operand[2].mode;
534 /* The last operand is of a wider mode than the rest of the operands. */
535 if (nops == 2)
537 wmode = tmode1;
538 wxmode = xmode1;
540 else if (nops == 3)
542 gcc_assert (tmode1 == tmode0);
543 gcc_assert (op1);
544 oprnd2 = ops->op2;
545 wmode = TYPE_MODE (TREE_TYPE (oprnd2));
546 wxmode = insn_data[icode].operand[3].mode;
549 if (!wide_op)
550 wmode = wxmode = insn_data[icode].operand[0].mode;
552 if (!target
553 || ! (*insn_data[icode].operand[0].predicate) (target, wmode))
554 temp = gen_reg_rtx (wmode);
555 else
556 temp = target;
558 xop0 = op0;
559 xop1 = op1;
560 wxop = wide_op;
562 /* In case the insn wants input operands in modes different from
563 those of the actual operands, convert the operands. It would
564 seem that we don't need to convert CONST_INTs, but we do, so
565 that they're properly zero-extended, sign-extended or truncated
566 for their mode. */
568 if (GET_MODE (op0) != xmode0 && xmode0 != VOIDmode)
569 xop0 = convert_modes (xmode0,
570 GET_MODE (op0) != VOIDmode
571 ? GET_MODE (op0)
572 : tmode0,
573 xop0, unsignedp);
575 if (op1)
576 if (GET_MODE (op1) != xmode1 && xmode1 != VOIDmode)
577 xop1 = convert_modes (xmode1,
578 GET_MODE (op1) != VOIDmode
579 ? GET_MODE (op1)
580 : tmode1,
581 xop1, unsignedp);
583 if (wide_op)
584 if (GET_MODE (wide_op) != wxmode && wxmode != VOIDmode)
585 wxop = convert_modes (wxmode,
586 GET_MODE (wide_op) != VOIDmode
587 ? GET_MODE (wide_op)
588 : wmode,
589 wxop, unsignedp);
591 /* Now, if insn's predicates don't allow our operands, put them into
592 pseudo regs. */
594 if (! (*insn_data[icode].operand[1].predicate) (xop0, xmode0)
595 && xmode0 != VOIDmode)
596 xop0 = copy_to_mode_reg (xmode0, xop0);
598 if (op1)
600 if (! (*insn_data[icode].operand[2].predicate) (xop1, xmode1)
601 && xmode1 != VOIDmode)
602 xop1 = copy_to_mode_reg (xmode1, xop1);
604 if (wide_op)
606 if (! (*insn_data[icode].operand[3].predicate) (wxop, wxmode)
607 && wxmode != VOIDmode)
608 wxop = copy_to_mode_reg (wxmode, wxop);
610 pat = GEN_FCN (icode) (temp, xop0, xop1, wxop);
612 else
613 pat = GEN_FCN (icode) (temp, xop0, xop1);
615 else
617 if (wide_op)
619 if (! (*insn_data[icode].operand[2].predicate) (wxop, wxmode)
620 && wxmode != VOIDmode)
621 wxop = copy_to_mode_reg (wxmode, wxop);
623 pat = GEN_FCN (icode) (temp, xop0, wxop);
625 else
626 pat = GEN_FCN (icode) (temp, xop0);
629 emit_insn (pat);
630 return temp;
633 /* Generate code to perform an operation specified by TERNARY_OPTAB
634 on operands OP0, OP1 and OP2, with result having machine-mode MODE.
636 UNSIGNEDP is for the case where we have to widen the operands
637 to perform the operation. It says to use zero-extension.
639 If TARGET is nonzero, the value
640 is generated there, if it is convenient to do so.
641 In all cases an rtx is returned for the locus of the value;
642 this may or may not be TARGET. */
645 expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
646 rtx op1, rtx op2, rtx target, int unsignedp)
648 int icode = (int) optab_handler (ternary_optab, mode);
649 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
650 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
651 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
652 rtx temp;
653 rtx pat;
654 rtx xop0 = op0, xop1 = op1, xop2 = op2;
656 gcc_assert (optab_handler (ternary_optab, mode) != CODE_FOR_nothing);
658 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
659 temp = gen_reg_rtx (mode);
660 else
661 temp = target;
663 /* In case the insn wants input operands in modes different from
664 those of the actual operands, convert the operands. It would
665 seem that we don't need to convert CONST_INTs, but we do, so
666 that they're properly zero-extended, sign-extended or truncated
667 for their mode. */
669 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
670 xop0 = convert_modes (mode0,
671 GET_MODE (op0) != VOIDmode
672 ? GET_MODE (op0)
673 : mode,
674 xop0, unsignedp);
676 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
677 xop1 = convert_modes (mode1,
678 GET_MODE (op1) != VOIDmode
679 ? GET_MODE (op1)
680 : mode,
681 xop1, unsignedp);
683 if (GET_MODE (op2) != mode2 && mode2 != VOIDmode)
684 xop2 = convert_modes (mode2,
685 GET_MODE (op2) != VOIDmode
686 ? GET_MODE (op2)
687 : mode,
688 xop2, unsignedp);
690 /* Now, if insn's predicates don't allow our operands, put them into
691 pseudo regs. */
693 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
694 && mode0 != VOIDmode)
695 xop0 = copy_to_mode_reg (mode0, xop0);
697 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
698 && mode1 != VOIDmode)
699 xop1 = copy_to_mode_reg (mode1, xop1);
701 if (!insn_data[icode].operand[3].predicate (xop2, mode2)
702 && mode2 != VOIDmode)
703 xop2 = copy_to_mode_reg (mode2, xop2);
705 pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
707 emit_insn (pat);
708 return temp;
712 /* Like expand_binop, but return a constant rtx if the result can be
713 calculated at compile time. The arguments and return value are
714 otherwise the same as for expand_binop. */
716 static rtx
717 simplify_expand_binop (enum machine_mode mode, optab binoptab,
718 rtx op0, rtx op1, rtx target, int unsignedp,
719 enum optab_methods methods)
721 if (CONSTANT_P (op0) && CONSTANT_P (op1))
723 rtx x = simplify_binary_operation (binoptab->code, mode, op0, op1);
725 if (x)
726 return x;
729 return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
732 /* Like simplify_expand_binop, but always put the result in TARGET.
733 Return true if the expansion succeeded. */
735 bool
736 force_expand_binop (enum machine_mode mode, optab binoptab,
737 rtx op0, rtx op1, rtx target, int unsignedp,
738 enum optab_methods methods)
740 rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
741 target, unsignedp, methods);
742 if (x == 0)
743 return false;
744 if (x != target)
745 emit_move_insn (target, x);
746 return true;
749 /* Generate insns for VEC_LSHIFT_EXPR, VEC_RSHIFT_EXPR. */
752 expand_vec_shift_expr (sepops ops, rtx target)
754 enum insn_code icode;
755 rtx rtx_op1, rtx_op2;
756 enum machine_mode mode1;
757 enum machine_mode mode2;
758 enum machine_mode mode = TYPE_MODE (ops->type);
759 tree vec_oprnd = ops->op0;
760 tree shift_oprnd = ops->op1;
761 optab shift_optab;
762 rtx pat;
764 switch (ops->code)
766 case VEC_RSHIFT_EXPR:
767 shift_optab = vec_shr_optab;
768 break;
769 case VEC_LSHIFT_EXPR:
770 shift_optab = vec_shl_optab;
771 break;
772 default:
773 gcc_unreachable ();
776 icode = optab_handler (shift_optab, mode);
777 gcc_assert (icode != CODE_FOR_nothing);
779 mode1 = insn_data[icode].operand[1].mode;
780 mode2 = insn_data[icode].operand[2].mode;
782 rtx_op1 = expand_normal (vec_oprnd);
783 if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode1)
784 && mode1 != VOIDmode)
785 rtx_op1 = force_reg (mode1, rtx_op1);
787 rtx_op2 = expand_normal (shift_oprnd);
788 if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode2)
789 && mode2 != VOIDmode)
790 rtx_op2 = force_reg (mode2, rtx_op2);
792 if (!target
793 || ! (*insn_data[icode].operand[0].predicate) (target, mode))
794 target = gen_reg_rtx (mode);
796 /* Emit instruction */
797 pat = GEN_FCN (icode) (target, rtx_op1, rtx_op2);
798 gcc_assert (pat);
799 emit_insn (pat);
801 return target;
804 /* This subroutine of expand_doubleword_shift handles the cases in which
805 the effective shift value is >= BITS_PER_WORD. The arguments and return
806 value are the same as for the parent routine, except that SUPERWORD_OP1
807 is the shift count to use when shifting OUTOF_INPUT into INTO_TARGET.
808 INTO_TARGET may be null if the caller has decided to calculate it. */
810 static bool
811 expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
812 rtx outof_target, rtx into_target,
813 int unsignedp, enum optab_methods methods)
815 if (into_target != 0)
816 if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
817 into_target, unsignedp, methods))
818 return false;
820 if (outof_target != 0)
822 /* For a signed right shift, we must fill OUTOF_TARGET with copies
823 of the sign bit, otherwise we must fill it with zeros. */
824 if (binoptab != ashr_optab)
825 emit_move_insn (outof_target, CONST0_RTX (word_mode));
826 else
827 if (!force_expand_binop (word_mode, binoptab,
828 outof_input, GEN_INT (BITS_PER_WORD - 1),
829 outof_target, unsignedp, methods))
830 return false;
832 return true;
835 /* This subroutine of expand_doubleword_shift handles the cases in which
836 the effective shift value is < BITS_PER_WORD. The arguments and return
837 value are the same as for the parent routine. */
839 static bool
840 expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
841 rtx outof_input, rtx into_input, rtx op1,
842 rtx outof_target, rtx into_target,
843 int unsignedp, enum optab_methods methods,
844 unsigned HOST_WIDE_INT shift_mask)
846 optab reverse_unsigned_shift, unsigned_shift;
847 rtx tmp, carries;
849 reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
850 unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
852 /* The low OP1 bits of INTO_TARGET come from the high bits of OUTOF_INPUT.
853 We therefore need to shift OUTOF_INPUT by (BITS_PER_WORD - OP1) bits in
854 the opposite direction to BINOPTAB. */
855 if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
857 carries = outof_input;
858 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
859 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
860 0, true, methods);
862 else
864 /* We must avoid shifting by BITS_PER_WORD bits since that is either
865 the same as a zero shift (if shift_mask == BITS_PER_WORD - 1) or
866 has unknown behavior. Do a single shift first, then shift by the
867 remainder. It's OK to use ~OP1 as the remainder if shift counts
868 are truncated to the mode size. */
869 carries = expand_binop (word_mode, reverse_unsigned_shift,
870 outof_input, const1_rtx, 0, unsignedp, methods);
871 if (shift_mask == BITS_PER_WORD - 1)
873 tmp = immed_double_const (-1, -1, op1_mode);
874 tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
875 0, true, methods);
877 else
879 tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode);
880 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
881 0, true, methods);
884 if (tmp == 0 || carries == 0)
885 return false;
886 carries = expand_binop (word_mode, reverse_unsigned_shift,
887 carries, tmp, 0, unsignedp, methods);
888 if (carries == 0)
889 return false;
891 /* Shift INTO_INPUT logically by OP1. This is the last use of INTO_INPUT
892 so the result can go directly into INTO_TARGET if convenient. */
893 tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
894 into_target, unsignedp, methods);
895 if (tmp == 0)
896 return false;
898 /* Now OR in the bits carried over from OUTOF_INPUT. */
899 if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
900 into_target, unsignedp, methods))
901 return false;
903 /* Use a standard word_mode shift for the out-of half. */
904 if (outof_target != 0)
905 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
906 outof_target, unsignedp, methods))
907 return false;
909 return true;
913 #ifdef HAVE_conditional_move
914 /* Try implementing expand_doubleword_shift using conditional moves.
915 The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
916 otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1
917 are the shift counts to use in the former and latter case. All other
918 arguments are the same as the parent routine. */
920 static bool
921 expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
922 enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
923 rtx outof_input, rtx into_input,
924 rtx subword_op1, rtx superword_op1,
925 rtx outof_target, rtx into_target,
926 int unsignedp, enum optab_methods methods,
927 unsigned HOST_WIDE_INT shift_mask)
929 rtx outof_superword, into_superword;
931 /* Put the superword version of the output into OUTOF_SUPERWORD and
932 INTO_SUPERWORD. */
933 outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
934 if (outof_target != 0 && subword_op1 == superword_op1)
936 /* The value INTO_TARGET >> SUBWORD_OP1, which we later store in
937 OUTOF_TARGET, is the same as the value of INTO_SUPERWORD. */
938 into_superword = outof_target;
939 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
940 outof_superword, 0, unsignedp, methods))
941 return false;
943 else
945 into_superword = gen_reg_rtx (word_mode);
946 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
947 outof_superword, into_superword,
948 unsignedp, methods))
949 return false;
952 /* Put the subword version directly in OUTOF_TARGET and INTO_TARGET. */
953 if (!expand_subword_shift (op1_mode, binoptab,
954 outof_input, into_input, subword_op1,
955 outof_target, into_target,
956 unsignedp, methods, shift_mask))
957 return false;
959 /* Select between them. Do the INTO half first because INTO_SUPERWORD
960 might be the current value of OUTOF_TARGET. */
961 if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
962 into_target, into_superword, word_mode, false))
963 return false;
965 if (outof_target != 0)
966 if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
967 outof_target, outof_superword,
968 word_mode, false))
969 return false;
971 return true;
973 #endif
975 /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
976 OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
977 input operand; the shift moves bits in the direction OUTOF_INPUT->
978 INTO_TARGET. OUTOF_TARGET and INTO_TARGET are the equivalent words
979 of the target. OP1 is the shift count and OP1_MODE is its mode.
980 If OP1 is constant, it will have been truncated as appropriate
981 and is known to be nonzero.
983 If SHIFT_MASK is zero, the result of word shifts is undefined when the
984 shift count is outside the range [0, BITS_PER_WORD). This routine must
985 avoid generating such shifts for OP1s in the range [0, BITS_PER_WORD * 2).
987 If SHIFT_MASK is nonzero, all word-mode shift counts are effectively
988 masked by it and shifts in the range [BITS_PER_WORD, SHIFT_MASK) will
989 fill with zeros or sign bits as appropriate.
991 If SHIFT_MASK is BITS_PER_WORD - 1, this routine will synthesize
992 a doubleword shift whose equivalent mask is BITS_PER_WORD * 2 - 1.
993 Doing this preserves semantics required by SHIFT_COUNT_TRUNCATED.
994 In all other cases, shifts by values outside [0, BITS_PER_UNIT * 2)
995 are undefined.
997 BINOPTAB, UNSIGNEDP and METHODS are as for expand_binop. This function
998 may not use INTO_INPUT after modifying INTO_TARGET, and similarly for
999 OUTOF_INPUT and OUTOF_TARGET. OUTOF_TARGET can be null if the parent
1000 function wants to calculate it itself.
1002 Return true if the shift could be successfully synthesized. */
1004 static bool
1005 expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
1006 rtx outof_input, rtx into_input, rtx op1,
1007 rtx outof_target, rtx into_target,
1008 int unsignedp, enum optab_methods methods,
1009 unsigned HOST_WIDE_INT shift_mask)
1011 rtx superword_op1, tmp, cmp1, cmp2;
1012 rtx subword_label, done_label;
1013 enum rtx_code cmp_code;
1015 /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
1016 fill the result with sign or zero bits as appropriate. If so, the value
1017 of OUTOF_TARGET will always be (SHIFT OUTOF_INPUT OP1). Recursively call
1018 this routine to calculate INTO_TARGET (which depends on both OUTOF_INPUT
1019 and INTO_INPUT), then emit code to set up OUTOF_TARGET.
1021 This isn't worthwhile for constant shifts since the optimizers will
1022 cope better with in-range shift counts. */
1023 if (shift_mask >= BITS_PER_WORD
1024 && outof_target != 0
1025 && !CONSTANT_P (op1))
1027 if (!expand_doubleword_shift (op1_mode, binoptab,
1028 outof_input, into_input, op1,
1029 0, into_target,
1030 unsignedp, methods, shift_mask))
1031 return false;
1032 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
1033 outof_target, unsignedp, methods))
1034 return false;
1035 return true;
1038 /* Set CMP_CODE, CMP1 and CMP2 so that the rtx (CMP_CODE CMP1 CMP2)
1039 is true when the effective shift value is less than BITS_PER_WORD.
1040 Set SUPERWORD_OP1 to the shift count that should be used to shift
1041 OUTOF_INPUT into INTO_TARGET when the condition is false. */
1042 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
1043 if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
1045 /* Set CMP1 to OP1 & BITS_PER_WORD. The result is zero iff OP1
1046 is a subword shift count. */
1047 cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
1048 0, true, methods);
1049 cmp2 = CONST0_RTX (op1_mode);
1050 cmp_code = EQ;
1051 superword_op1 = op1;
1053 else
1055 /* Set CMP1 to OP1 - BITS_PER_WORD. */
1056 cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
1057 0, true, methods);
1058 cmp2 = CONST0_RTX (op1_mode);
1059 cmp_code = LT;
1060 superword_op1 = cmp1;
1062 if (cmp1 == 0)
1063 return false;
1065 /* If we can compute the condition at compile time, pick the
1066 appropriate subroutine. */
1067 tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
1068 if (tmp != 0 && CONST_INT_P (tmp))
1070 if (tmp == const0_rtx)
1071 return expand_superword_shift (binoptab, outof_input, superword_op1,
1072 outof_target, into_target,
1073 unsignedp, methods);
1074 else
1075 return expand_subword_shift (op1_mode, binoptab,
1076 outof_input, into_input, op1,
1077 outof_target, into_target,
1078 unsignedp, methods, shift_mask);
1081 #ifdef HAVE_conditional_move
1082 /* Try using conditional moves to generate straight-line code. */
1084 rtx start = get_last_insn ();
1085 if (expand_doubleword_shift_condmove (op1_mode, binoptab,
1086 cmp_code, cmp1, cmp2,
1087 outof_input, into_input,
1088 op1, superword_op1,
1089 outof_target, into_target,
1090 unsignedp, methods, shift_mask))
1091 return true;
1092 delete_insns_since (start);
1094 #endif
1096 /* As a last resort, use branches to select the correct alternative. */
1097 subword_label = gen_label_rtx ();
1098 done_label = gen_label_rtx ();
1100 NO_DEFER_POP;
1101 do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
1102 0, 0, subword_label, -1);
1103 OK_DEFER_POP;
1105 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
1106 outof_target, into_target,
1107 unsignedp, methods))
1108 return false;
1110 emit_jump_insn (gen_jump (done_label));
1111 emit_barrier ();
1112 emit_label (subword_label);
1114 if (!expand_subword_shift (op1_mode, binoptab,
1115 outof_input, into_input, op1,
1116 outof_target, into_target,
1117 unsignedp, methods, shift_mask))
1118 return false;
1120 emit_label (done_label);
1121 return true;
1124 /* Subroutine of expand_binop. Perform a double word multiplication of
1125 operands OP0 and OP1 both of mode MODE, which is exactly twice as wide
1126 as the target's word_mode. This function return NULL_RTX if anything
1127 goes wrong, in which case it may have already emitted instructions
1128 which need to be deleted.
1130 If we want to multiply two two-word values and have normal and widening
1131 multiplies of single-word values, we can do this with three smaller
1132 multiplications.
1134 The multiplication proceeds as follows:
1135 _______________________
1136 [__op0_high_|__op0_low__]
1137 _______________________
1138 * [__op1_high_|__op1_low__]
1139 _______________________________________________
1140 _______________________
1141 (1) [__op0_low__*__op1_low__]
1142 _______________________
1143 (2a) [__op0_low__*__op1_high_]
1144 _______________________
1145 (2b) [__op0_high_*__op1_low__]
1146 _______________________
1147 (3) [__op0_high_*__op1_high_]
1150 This gives a 4-word result. Since we are only interested in the
1151 lower 2 words, partial result (3) and the upper words of (2a) and
1152 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1153 calculated using non-widening multiplication.
1155 (1), however, needs to be calculated with an unsigned widening
1156 multiplication. If this operation is not directly supported we
1157 try using a signed widening multiplication and adjust the result.
1158 This adjustment works as follows:
1160 If both operands are positive then no adjustment is needed.
1162 If the operands have different signs, for example op0_low < 0 and
1163 op1_low >= 0, the instruction treats the most significant bit of
1164 op0_low as a sign bit instead of a bit with significance
1165 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1166 with 2**BITS_PER_WORD - op0_low, and two's complements the
1167 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1168 the result.
1170 Similarly, if both operands are negative, we need to add
1171 (op0_low + op1_low) * 2**BITS_PER_WORD.
1173 We use a trick to adjust quickly. We logically shift op0_low right
1174 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1175 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1176 logical shift exists, we do an arithmetic right shift and subtract
1177 the 0 or -1. */
1179 static rtx
1180 expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
1181 bool umulp, enum optab_methods methods)
1183 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1184 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1185 rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
1186 rtx product, adjust, product_high, temp;
1188 rtx op0_high = operand_subword_force (op0, high, mode);
1189 rtx op0_low = operand_subword_force (op0, low, mode);
1190 rtx op1_high = operand_subword_force (op1, high, mode);
1191 rtx op1_low = operand_subword_force (op1, low, mode);
1193 /* If we're using an unsigned multiply to directly compute the product
1194 of the low-order words of the operands and perform any required
1195 adjustments of the operands, we begin by trying two more multiplications
1196 and then computing the appropriate sum.
1198 We have checked above that the required addition is provided.
1199 Full-word addition will normally always succeed, especially if
1200 it is provided at all, so we don't worry about its failure. The
1201 multiplication may well fail, however, so we do handle that. */
1203 if (!umulp)
1205 /* ??? This could be done with emit_store_flag where available. */
1206 temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1207 NULL_RTX, 1, methods);
1208 if (temp)
1209 op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
1210 NULL_RTX, 0, OPTAB_DIRECT);
1211 else
1213 temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1214 NULL_RTX, 0, methods);
1215 if (!temp)
1216 return NULL_RTX;
1217 op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
1218 NULL_RTX, 0, OPTAB_DIRECT);
1221 if (!op0_high)
1222 return NULL_RTX;
1225 adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
1226 NULL_RTX, 0, OPTAB_DIRECT);
1227 if (!adjust)
1228 return NULL_RTX;
1230 /* OP0_HIGH should now be dead. */
1232 if (!umulp)
1234 /* ??? This could be done with emit_store_flag where available. */
1235 temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1236 NULL_RTX, 1, methods);
1237 if (temp)
1238 op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
1239 NULL_RTX, 0, OPTAB_DIRECT);
1240 else
1242 temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1243 NULL_RTX, 0, methods);
1244 if (!temp)
1245 return NULL_RTX;
1246 op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
1247 NULL_RTX, 0, OPTAB_DIRECT);
1250 if (!op1_high)
1251 return NULL_RTX;
1254 temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
1255 NULL_RTX, 0, OPTAB_DIRECT);
1256 if (!temp)
1257 return NULL_RTX;
1259 /* OP1_HIGH should now be dead. */
1261 adjust = expand_binop (word_mode, add_optab, adjust, temp,
1262 NULL_RTX, 0, OPTAB_DIRECT);
1264 if (target && !REG_P (target))
1265 target = NULL_RTX;
1267 if (umulp)
1268 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1269 target, 1, OPTAB_DIRECT);
1270 else
1271 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1272 target, 1, OPTAB_DIRECT);
1274 if (!product)
1275 return NULL_RTX;
1277 product_high = operand_subword (product, high, 1, mode);
1278 adjust = expand_binop (word_mode, add_optab, product_high, adjust,
1279 NULL_RTX, 0, OPTAB_DIRECT);
1280 emit_move_insn (product_high, adjust);
1281 return product;
1284 /* Wrapper around expand_binop which takes an rtx code to specify
1285 the operation to perform, not an optab pointer. All other
1286 arguments are the same. */
1288 expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
1289 rtx op1, rtx target, int unsignedp,
1290 enum optab_methods methods)
1292 optab binop = code_to_optab[(int) code];
1293 gcc_assert (binop);
1295 return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
1298 /* Return whether OP0 and OP1 should be swapped when expanding a commutative
1299 binop. Order them according to commutative_operand_precedence and, if
1300 possible, try to put TARGET or a pseudo first. */
1301 static bool
1302 swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
1304 int op0_prec = commutative_operand_precedence (op0);
1305 int op1_prec = commutative_operand_precedence (op1);
1307 if (op0_prec < op1_prec)
1308 return true;
1310 if (op0_prec > op1_prec)
1311 return false;
1313 /* With equal precedence, both orders are ok, but it is better if the
1314 first operand is TARGET, or if both TARGET and OP0 are pseudos. */
1315 if (target == 0 || REG_P (target))
1316 return (REG_P (op1) && !REG_P (op0)) || target == op1;
1317 else
1318 return rtx_equal_p (op1, target);
1321 /* Return true if BINOPTAB implements a shift operation. */
1323 static bool
1324 shift_optab_p (optab binoptab)
1326 switch (binoptab->code)
1328 case ASHIFT:
1329 case SS_ASHIFT:
1330 case US_ASHIFT:
1331 case ASHIFTRT:
1332 case LSHIFTRT:
1333 case ROTATE:
1334 case ROTATERT:
1335 return true;
1337 default:
1338 return false;
1342 /* Return true if BINOPTAB implements a commutative binary operation. */
1344 static bool
1345 commutative_optab_p (optab binoptab)
1347 return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
1348 || binoptab == smul_widen_optab
1349 || binoptab == umul_widen_optab
1350 || binoptab == smul_highpart_optab
1351 || binoptab == umul_highpart_optab);
1354 /* X is to be used in mode MODE as an operand to BINOPTAB. If we're
1355 optimizing, and if the operand is a constant that costs more than
1356 1 instruction, force the constant into a register and return that
1357 register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */
1359 static rtx
1360 avoid_expensive_constant (enum machine_mode mode, optab binoptab,
1361 rtx x, bool unsignedp)
1363 bool speed = optimize_insn_for_speed_p ();
1365 if (mode != VOIDmode
1366 && optimize
1367 && CONSTANT_P (x)
1368 && rtx_cost (x, binoptab->code, speed) > rtx_cost (x, SET, speed))
1370 if (CONST_INT_P (x))
1372 HOST_WIDE_INT intval = trunc_int_for_mode (INTVAL (x), mode);
1373 if (intval != INTVAL (x))
1374 x = GEN_INT (intval);
1376 else
1377 x = convert_modes (mode, VOIDmode, x, unsignedp);
1378 x = force_reg (mode, x);
1380 return x;
1383 /* Helper function for expand_binop: handle the case where there
1384 is an insn that directly implements the indicated operation.
1385 Returns null if this is not possible. */
1386 static rtx
1387 expand_binop_directly (enum machine_mode mode, optab binoptab,
1388 rtx op0, rtx op1,
1389 rtx target, int unsignedp, enum optab_methods methods,
1390 rtx last)
1392 int icode = (int) optab_handler (binoptab, mode);
1393 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
1394 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
1395 enum machine_mode tmp_mode;
1396 bool commutative_p;
1397 rtx pat;
1398 rtx xop0 = op0, xop1 = op1;
1399 rtx temp;
1400 rtx swap;
1402 if (target)
1403 temp = target;
1404 else
1405 temp = gen_reg_rtx (mode);
1407 /* If it is a commutative operator and the modes would match
1408 if we would swap the operands, we can save the conversions. */
1409 commutative_p = commutative_optab_p (binoptab);
1410 if (commutative_p
1411 && GET_MODE (xop0) != mode0 && GET_MODE (xop1) != mode1
1412 && GET_MODE (xop0) == mode1 && GET_MODE (xop1) == mode1)
1414 swap = xop0;
1415 xop0 = xop1;
1416 xop1 = swap;
1419 /* If we are optimizing, force expensive constants into a register. */
1420 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
1421 if (!shift_optab_p (binoptab))
1422 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
1424 /* In case the insn wants input operands in modes different from
1425 those of the actual operands, convert the operands. It would
1426 seem that we don't need to convert CONST_INTs, but we do, so
1427 that they're properly zero-extended, sign-extended or truncated
1428 for their mode. */
1430 if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode)
1431 xop0 = convert_modes (mode0,
1432 GET_MODE (xop0) != VOIDmode
1433 ? GET_MODE (xop0)
1434 : mode,
1435 xop0, unsignedp);
1437 if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode)
1438 xop1 = convert_modes (mode1,
1439 GET_MODE (xop1) != VOIDmode
1440 ? GET_MODE (xop1)
1441 : mode,
1442 xop1, unsignedp);
1444 /* If operation is commutative,
1445 try to make the first operand a register.
1446 Even better, try to make it the same as the target.
1447 Also try to make the last operand a constant. */
1448 if (commutative_p
1449 && swap_commutative_operands_with_target (target, xop0, xop1))
1451 swap = xop1;
1452 xop1 = xop0;
1453 xop0 = swap;
1456 /* Now, if insn's predicates don't allow our operands, put them into
1457 pseudo regs. */
1459 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
1460 && mode0 != VOIDmode)
1461 xop0 = copy_to_mode_reg (mode0, xop0);
1463 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
1464 && mode1 != VOIDmode)
1465 xop1 = copy_to_mode_reg (mode1, xop1);
1467 if (binoptab == vec_pack_trunc_optab
1468 || binoptab == vec_pack_usat_optab
1469 || binoptab == vec_pack_ssat_optab
1470 || binoptab == vec_pack_ufix_trunc_optab
1471 || binoptab == vec_pack_sfix_trunc_optab)
1473 /* The mode of the result is different then the mode of the
1474 arguments. */
1475 tmp_mode = insn_data[icode].operand[0].mode;
1476 if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
1477 return 0;
1479 else
1480 tmp_mode = mode;
1482 if (!insn_data[icode].operand[0].predicate (temp, tmp_mode))
1483 temp = gen_reg_rtx (tmp_mode);
1485 pat = GEN_FCN (icode) (temp, xop0, xop1);
1486 if (pat)
1488 /* If PAT is composed of more than one insn, try to add an appropriate
1489 REG_EQUAL note to it. If we can't because TEMP conflicts with an
1490 operand, call expand_binop again, this time without a target. */
1491 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
1492 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
1494 delete_insns_since (last);
1495 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
1496 unsignedp, methods);
1499 emit_insn (pat);
1500 return temp;
1503 delete_insns_since (last);
1504 return NULL_RTX;
1507 /* Generate code to perform an operation specified by BINOPTAB
1508 on operands OP0 and OP1, with result having machine-mode MODE.
1510 UNSIGNEDP is for the case where we have to widen the operands
1511 to perform the operation. It says to use zero-extension.
1513 If TARGET is nonzero, the value
1514 is generated there, if it is convenient to do so.
1515 In all cases an rtx is returned for the locus of the value;
1516 this may or may not be TARGET. */
1519 expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
1520 rtx target, int unsignedp, enum optab_methods methods)
1522 enum optab_methods next_methods
1523 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
1524 ? OPTAB_WIDEN : methods);
1525 enum mode_class mclass;
1526 enum machine_mode wider_mode;
1527 rtx libfunc;
1528 rtx temp;
1529 rtx entry_last = get_last_insn ();
1530 rtx last;
1532 mclass = GET_MODE_CLASS (mode);
1534 /* If subtracting an integer constant, convert this into an addition of
1535 the negated constant. */
1537 if (binoptab == sub_optab && CONST_INT_P (op1))
1539 op1 = negate_rtx (mode, op1);
1540 binoptab = add_optab;
1543 /* Record where to delete back to if we backtrack. */
1544 last = get_last_insn ();
1546 /* If we can do it with a three-operand insn, do so. */
1548 if (methods != OPTAB_MUST_WIDEN
1549 && optab_handler (binoptab, mode) != CODE_FOR_nothing)
1551 temp = expand_binop_directly (mode, binoptab, op0, op1, target,
1552 unsignedp, methods, last);
1553 if (temp)
1554 return temp;
1557 /* If we were trying to rotate, and that didn't work, try rotating
1558 the other direction before falling back to shifts and bitwise-or. */
1559 if (((binoptab == rotl_optab
1560 && optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
1561 || (binoptab == rotr_optab
1562 && optab_handler (rotl_optab, mode) != CODE_FOR_nothing))
1563 && mclass == MODE_INT)
1565 optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
1566 rtx newop1;
1567 unsigned int bits = GET_MODE_BITSIZE (mode);
1569 if (CONST_INT_P (op1))
1570 newop1 = GEN_INT (bits - INTVAL (op1));
1571 else if (targetm.shift_truncation_mask (mode) == bits - 1)
1572 newop1 = negate_rtx (GET_MODE (op1), op1);
1573 else
1574 newop1 = expand_binop (GET_MODE (op1), sub_optab,
1575 GEN_INT (bits), op1,
1576 NULL_RTX, unsignedp, OPTAB_DIRECT);
1578 temp = expand_binop_directly (mode, otheroptab, op0, newop1,
1579 target, unsignedp, methods, last);
1580 if (temp)
1581 return temp;
1584 /* If this is a multiply, see if we can do a widening operation that
1585 takes operands of this mode and makes a wider mode. */
1587 if (binoptab == smul_optab
1588 && GET_MODE_WIDER_MODE (mode) != VOIDmode
1589 && (optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab),
1590 GET_MODE_WIDER_MODE (mode))
1591 != CODE_FOR_nothing))
1593 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
1594 unsignedp ? umul_widen_optab : smul_widen_optab,
1595 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
1597 if (temp != 0)
1599 if (GET_MODE_CLASS (mode) == MODE_INT
1600 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1601 GET_MODE_BITSIZE (GET_MODE (temp))))
1602 return gen_lowpart (mode, temp);
1603 else
1604 return convert_to_mode (mode, temp, unsignedp);
1608 /* Look for a wider mode of the same class for which we think we
1609 can open-code the operation. Check for a widening multiply at the
1610 wider mode as well. */
1612 if (CLASS_HAS_WIDER_MODES_P (mclass)
1613 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
1614 for (wider_mode = GET_MODE_WIDER_MODE (mode);
1615 wider_mode != VOIDmode;
1616 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1618 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
1619 || (binoptab == smul_optab
1620 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
1621 && (optab_handler ((unsignedp ? umul_widen_optab
1622 : smul_widen_optab),
1623 GET_MODE_WIDER_MODE (wider_mode))
1624 != CODE_FOR_nothing)))
1626 rtx xop0 = op0, xop1 = op1;
1627 int no_extend = 0;
1629 /* For certain integer operations, we need not actually extend
1630 the narrow operands, as long as we will truncate
1631 the results to the same narrowness. */
1633 if ((binoptab == ior_optab || binoptab == and_optab
1634 || binoptab == xor_optab
1635 || binoptab == add_optab || binoptab == sub_optab
1636 || binoptab == smul_optab || binoptab == ashl_optab)
1637 && mclass == MODE_INT)
1639 no_extend = 1;
1640 xop0 = avoid_expensive_constant (mode, binoptab,
1641 xop0, unsignedp);
1642 if (binoptab != ashl_optab)
1643 xop1 = avoid_expensive_constant (mode, binoptab,
1644 xop1, unsignedp);
1647 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
1649 /* The second operand of a shift must always be extended. */
1650 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1651 no_extend && binoptab != ashl_optab);
1653 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1654 unsignedp, OPTAB_DIRECT);
1655 if (temp)
1657 if (mclass != MODE_INT
1658 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1659 GET_MODE_BITSIZE (wider_mode)))
1661 if (target == 0)
1662 target = gen_reg_rtx (mode);
1663 convert_move (target, temp, 0);
1664 return target;
1666 else
1667 return gen_lowpart (mode, temp);
1669 else
1670 delete_insns_since (last);
1674 /* If operation is commutative,
1675 try to make the first operand a register.
1676 Even better, try to make it the same as the target.
1677 Also try to make the last operand a constant. */
1678 if (commutative_optab_p (binoptab)
1679 && swap_commutative_operands_with_target (target, op0, op1))
1681 temp = op1;
1682 op1 = op0;
1683 op0 = temp;
1686 /* These can be done a word at a time. */
1687 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
1688 && mclass == MODE_INT
1689 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1690 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
1692 int i;
1693 rtx insns;
1695 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1696 won't be accurate, so use a new target. */
1697 if (target == 0 || target == op0 || target == op1)
1698 target = gen_reg_rtx (mode);
1700 start_sequence ();
1702 /* Do the actual arithmetic. */
1703 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1705 rtx target_piece = operand_subword (target, i, 1, mode);
1706 rtx x = expand_binop (word_mode, binoptab,
1707 operand_subword_force (op0, i, mode),
1708 operand_subword_force (op1, i, mode),
1709 target_piece, unsignedp, next_methods);
1711 if (x == 0)
1712 break;
1714 if (target_piece != x)
1715 emit_move_insn (target_piece, x);
1718 insns = get_insns ();
1719 end_sequence ();
1721 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1723 emit_insn (insns);
1724 return target;
1728 /* Synthesize double word shifts from single word shifts. */
1729 if ((binoptab == lshr_optab || binoptab == ashl_optab
1730 || binoptab == ashr_optab)
1731 && mclass == MODE_INT
1732 && (CONST_INT_P (op1) || optimize_insn_for_speed_p ())
1733 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1734 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing
1735 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1736 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
1738 unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
1739 enum machine_mode op1_mode;
1741 double_shift_mask = targetm.shift_truncation_mask (mode);
1742 shift_mask = targetm.shift_truncation_mask (word_mode);
1743 op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
1745 /* Apply the truncation to constant shifts. */
1746 if (double_shift_mask > 0 && CONST_INT_P (op1))
1747 op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
1749 if (op1 == CONST0_RTX (op1_mode))
1750 return op0;
1752 /* Make sure that this is a combination that expand_doubleword_shift
1753 can handle. See the comments there for details. */
1754 if (double_shift_mask == 0
1755 || (shift_mask == BITS_PER_WORD - 1
1756 && double_shift_mask == BITS_PER_WORD * 2 - 1))
1758 rtx insns;
1759 rtx into_target, outof_target;
1760 rtx into_input, outof_input;
1761 int left_shift, outof_word;
1763 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1764 won't be accurate, so use a new target. */
1765 if (target == 0 || target == op0 || target == op1)
1766 target = gen_reg_rtx (mode);
1768 start_sequence ();
1770 /* OUTOF_* is the word we are shifting bits away from, and
1771 INTO_* is the word that we are shifting bits towards, thus
1772 they differ depending on the direction of the shift and
1773 WORDS_BIG_ENDIAN. */
1775 left_shift = binoptab == ashl_optab;
1776 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1778 outof_target = operand_subword (target, outof_word, 1, mode);
1779 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1781 outof_input = operand_subword_force (op0, outof_word, mode);
1782 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1784 if (expand_doubleword_shift (op1_mode, binoptab,
1785 outof_input, into_input, op1,
1786 outof_target, into_target,
1787 unsignedp, next_methods, shift_mask))
1789 insns = get_insns ();
1790 end_sequence ();
1792 emit_insn (insns);
1793 return target;
1795 end_sequence ();
1799 /* Synthesize double word rotates from single word shifts. */
1800 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1801 && mclass == MODE_INT
1802 && CONST_INT_P (op1)
1803 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1804 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1805 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
1807 rtx insns;
1808 rtx into_target, outof_target;
1809 rtx into_input, outof_input;
1810 rtx inter;
1811 int shift_count, left_shift, outof_word;
1813 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1814 won't be accurate, so use a new target. Do this also if target is not
1815 a REG, first because having a register instead may open optimization
1816 opportunities, and second because if target and op0 happen to be MEMs
1817 designating the same location, we would risk clobbering it too early
1818 in the code sequence we generate below. */
1819 if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
1820 target = gen_reg_rtx (mode);
1822 start_sequence ();
1824 shift_count = INTVAL (op1);
1826 /* OUTOF_* is the word we are shifting bits away from, and
1827 INTO_* is the word that we are shifting bits towards, thus
1828 they differ depending on the direction of the shift and
1829 WORDS_BIG_ENDIAN. */
1831 left_shift = (binoptab == rotl_optab);
1832 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1834 outof_target = operand_subword (target, outof_word, 1, mode);
1835 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1837 outof_input = operand_subword_force (op0, outof_word, mode);
1838 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1840 if (shift_count == BITS_PER_WORD)
1842 /* This is just a word swap. */
1843 emit_move_insn (outof_target, into_input);
1844 emit_move_insn (into_target, outof_input);
1845 inter = const0_rtx;
1847 else
1849 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1850 rtx first_shift_count, second_shift_count;
1851 optab reverse_unsigned_shift, unsigned_shift;
1853 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1854 ? lshr_optab : ashl_optab);
1856 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1857 ? ashl_optab : lshr_optab);
1859 if (shift_count > BITS_PER_WORD)
1861 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1862 second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
1864 else
1866 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1867 second_shift_count = GEN_INT (shift_count);
1870 into_temp1 = expand_binop (word_mode, unsigned_shift,
1871 outof_input, first_shift_count,
1872 NULL_RTX, unsignedp, next_methods);
1873 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1874 into_input, second_shift_count,
1875 NULL_RTX, unsignedp, next_methods);
1877 if (into_temp1 != 0 && into_temp2 != 0)
1878 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1879 into_target, unsignedp, next_methods);
1880 else
1881 inter = 0;
1883 if (inter != 0 && inter != into_target)
1884 emit_move_insn (into_target, inter);
1886 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1887 into_input, first_shift_count,
1888 NULL_RTX, unsignedp, next_methods);
1889 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1890 outof_input, second_shift_count,
1891 NULL_RTX, unsignedp, next_methods);
1893 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1894 inter = expand_binop (word_mode, ior_optab,
1895 outof_temp1, outof_temp2,
1896 outof_target, unsignedp, next_methods);
1898 if (inter != 0 && inter != outof_target)
1899 emit_move_insn (outof_target, inter);
1902 insns = get_insns ();
1903 end_sequence ();
1905 if (inter != 0)
1907 emit_insn (insns);
1908 return target;
1912 /* These can be done a word at a time by propagating carries. */
1913 if ((binoptab == add_optab || binoptab == sub_optab)
1914 && mclass == MODE_INT
1915 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1916 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
1918 unsigned int i;
1919 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1920 const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1921 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1922 rtx xop0, xop1, xtarget;
1924 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1925 value is one of those, use it. Otherwise, use 1 since it is the
1926 one easiest to get. */
1927 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1928 int normalizep = STORE_FLAG_VALUE;
1929 #else
1930 int normalizep = 1;
1931 #endif
1933 /* Prepare the operands. */
1934 xop0 = force_reg (mode, op0);
1935 xop1 = force_reg (mode, op1);
1937 xtarget = gen_reg_rtx (mode);
1939 if (target == 0 || !REG_P (target))
1940 target = xtarget;
1942 /* Indicate for flow that the entire target reg is being set. */
1943 if (REG_P (target))
1944 emit_clobber (xtarget);
1946 /* Do the actual arithmetic. */
1947 for (i = 0; i < nwords; i++)
1949 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1950 rtx target_piece = operand_subword (xtarget, index, 1, mode);
1951 rtx op0_piece = operand_subword_force (xop0, index, mode);
1952 rtx op1_piece = operand_subword_force (xop1, index, mode);
1953 rtx x;
1955 /* Main add/subtract of the input operands. */
1956 x = expand_binop (word_mode, binoptab,
1957 op0_piece, op1_piece,
1958 target_piece, unsignedp, next_methods);
1959 if (x == 0)
1960 break;
1962 if (i + 1 < nwords)
1964 /* Store carry from main add/subtract. */
1965 carry_out = gen_reg_rtx (word_mode);
1966 carry_out = emit_store_flag_force (carry_out,
1967 (binoptab == add_optab
1968 ? LT : GT),
1969 x, op0_piece,
1970 word_mode, 1, normalizep);
1973 if (i > 0)
1975 rtx newx;
1977 /* Add/subtract previous carry to main result. */
1978 newx = expand_binop (word_mode,
1979 normalizep == 1 ? binoptab : otheroptab,
1980 x, carry_in,
1981 NULL_RTX, 1, next_methods);
1983 if (i + 1 < nwords)
1985 /* Get out carry from adding/subtracting carry in. */
1986 rtx carry_tmp = gen_reg_rtx (word_mode);
1987 carry_tmp = emit_store_flag_force (carry_tmp,
1988 (binoptab == add_optab
1989 ? LT : GT),
1990 newx, x,
1991 word_mode, 1, normalizep);
1993 /* Logical-ior the two poss. carry together. */
1994 carry_out = expand_binop (word_mode, ior_optab,
1995 carry_out, carry_tmp,
1996 carry_out, 0, next_methods);
1997 if (carry_out == 0)
1998 break;
2000 emit_move_insn (target_piece, newx);
2002 else
2004 if (x != target_piece)
2005 emit_move_insn (target_piece, x);
2008 carry_in = carry_out;
2011 if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
2013 if (optab_handler (mov_optab, mode) != CODE_FOR_nothing
2014 || ! rtx_equal_p (target, xtarget))
2016 rtx temp = emit_move_insn (target, xtarget);
2018 set_unique_reg_note (temp,
2019 REG_EQUAL,
2020 gen_rtx_fmt_ee (binoptab->code, mode,
2021 copy_rtx (xop0),
2022 copy_rtx (xop1)));
2024 else
2025 target = xtarget;
2027 return target;
2030 else
2031 delete_insns_since (last);
2034 /* Attempt to synthesize double word multiplies using a sequence of word
2035 mode multiplications. We first attempt to generate a sequence using a
2036 more efficient unsigned widening multiply, and if that fails we then
2037 try using a signed widening multiply. */
2039 if (binoptab == smul_optab
2040 && mclass == MODE_INT
2041 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
2042 && optab_handler (smul_optab, word_mode) != CODE_FOR_nothing
2043 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)
2045 rtx product = NULL_RTX;
2047 if (optab_handler (umul_widen_optab, mode) != CODE_FOR_nothing)
2049 product = expand_doubleword_mult (mode, op0, op1, target,
2050 true, methods);
2051 if (!product)
2052 delete_insns_since (last);
2055 if (product == NULL_RTX
2056 && optab_handler (smul_widen_optab, mode) != CODE_FOR_nothing)
2058 product = expand_doubleword_mult (mode, op0, op1, target,
2059 false, methods);
2060 if (!product)
2061 delete_insns_since (last);
2064 if (product != NULL_RTX)
2066 if (optab_handler (mov_optab, mode) != CODE_FOR_nothing)
2068 temp = emit_move_insn (target ? target : product, product);
2069 set_unique_reg_note (temp,
2070 REG_EQUAL,
2071 gen_rtx_fmt_ee (MULT, mode,
2072 copy_rtx (op0),
2073 copy_rtx (op1)));
2075 return product;
2079 /* It can't be open-coded in this mode.
2080 Use a library call if one is available and caller says that's ok. */
2082 libfunc = optab_libfunc (binoptab, mode);
2083 if (libfunc
2084 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
2086 rtx insns;
2087 rtx op1x = op1;
2088 enum machine_mode op1_mode = mode;
2089 rtx value;
2091 start_sequence ();
2093 if (shift_optab_p (binoptab))
2095 op1_mode = targetm.libgcc_shift_count_mode ();
2096 /* Specify unsigned here,
2097 since negative shift counts are meaningless. */
2098 op1x = convert_to_mode (op1_mode, op1, 1);
2101 if (GET_MODE (op0) != VOIDmode
2102 && GET_MODE (op0) != mode)
2103 op0 = convert_to_mode (mode, op0, unsignedp);
2105 /* Pass 1 for NO_QUEUE so we don't lose any increments
2106 if the libcall is cse'd or moved. */
2107 value = emit_library_call_value (libfunc,
2108 NULL_RTX, LCT_CONST, mode, 2,
2109 op0, mode, op1x, op1_mode);
2111 insns = get_insns ();
2112 end_sequence ();
2114 target = gen_reg_rtx (mode);
2115 emit_libcall_block (insns, target, value,
2116 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
2118 return target;
2121 delete_insns_since (last);
2123 /* It can't be done in this mode. Can we do it in a wider mode? */
2125 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
2126 || methods == OPTAB_MUST_WIDEN))
2128 /* Caller says, don't even try. */
2129 delete_insns_since (entry_last);
2130 return 0;
2133 /* Compute the value of METHODS to pass to recursive calls.
2134 Don't allow widening to be tried recursively. */
2136 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
2138 /* Look for a wider mode of the same class for which it appears we can do
2139 the operation. */
2141 if (CLASS_HAS_WIDER_MODES_P (mclass))
2143 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2144 wider_mode != VOIDmode;
2145 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2147 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
2148 || (methods == OPTAB_LIB
2149 && optab_libfunc (binoptab, wider_mode)))
2151 rtx xop0 = op0, xop1 = op1;
2152 int no_extend = 0;
2154 /* For certain integer operations, we need not actually extend
2155 the narrow operands, as long as we will truncate
2156 the results to the same narrowness. */
2158 if ((binoptab == ior_optab || binoptab == and_optab
2159 || binoptab == xor_optab
2160 || binoptab == add_optab || binoptab == sub_optab
2161 || binoptab == smul_optab || binoptab == ashl_optab)
2162 && mclass == MODE_INT)
2163 no_extend = 1;
2165 xop0 = widen_operand (xop0, wider_mode, mode,
2166 unsignedp, no_extend);
2168 /* The second operand of a shift must always be extended. */
2169 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
2170 no_extend && binoptab != ashl_optab);
2172 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
2173 unsignedp, methods);
2174 if (temp)
2176 if (mclass != MODE_INT
2177 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
2178 GET_MODE_BITSIZE (wider_mode)))
2180 if (target == 0)
2181 target = gen_reg_rtx (mode);
2182 convert_move (target, temp, 0);
2183 return target;
2185 else
2186 return gen_lowpart (mode, temp);
2188 else
2189 delete_insns_since (last);
2194 delete_insns_since (entry_last);
2195 return 0;
2198 /* Expand a binary operator which has both signed and unsigned forms.
2199 UOPTAB is the optab for unsigned operations, and SOPTAB is for
2200 signed operations.
2202 If we widen unsigned operands, we may use a signed wider operation instead
2203 of an unsigned wider operation, since the result would be the same. */
2206 sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
2207 rtx op0, rtx op1, rtx target, int unsignedp,
2208 enum optab_methods methods)
2210 rtx temp;
2211 optab direct_optab = unsignedp ? uoptab : soptab;
2212 struct optab_d wide_soptab;
2214 /* Do it without widening, if possible. */
2215 temp = expand_binop (mode, direct_optab, op0, op1, target,
2216 unsignedp, OPTAB_DIRECT);
2217 if (temp || methods == OPTAB_DIRECT)
2218 return temp;
2220 /* Try widening to a signed int. Make a fake signed optab that
2221 hides any signed insn for direct use. */
2222 wide_soptab = *soptab;
2223 set_optab_handler (&wide_soptab, mode, CODE_FOR_nothing);
2224 /* We don't want to generate new hash table entries from this fake
2225 optab. */
2226 wide_soptab.libcall_gen = NULL;
2228 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2229 unsignedp, OPTAB_WIDEN);
2231 /* For unsigned operands, try widening to an unsigned int. */
2232 if (temp == 0 && unsignedp)
2233 temp = expand_binop (mode, uoptab, op0, op1, target,
2234 unsignedp, OPTAB_WIDEN);
2235 if (temp || methods == OPTAB_WIDEN)
2236 return temp;
2238 /* Use the right width libcall if that exists. */
2239 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
2240 if (temp || methods == OPTAB_LIB)
2241 return temp;
2243 /* Must widen and use a libcall, use either signed or unsigned. */
2244 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2245 unsignedp, methods);
2246 if (temp != 0)
2247 return temp;
2248 if (unsignedp)
2249 return expand_binop (mode, uoptab, op0, op1, target,
2250 unsignedp, methods);
2251 return 0;
2254 /* Generate code to perform an operation specified by UNOPPTAB
2255 on operand OP0, with two results to TARG0 and TARG1.
2256 We assume that the order of the operands for the instruction
2257 is TARG0, TARG1, OP0.
2259 Either TARG0 or TARG1 may be zero, but what that means is that
2260 the result is not actually wanted. We will generate it into
2261 a dummy pseudo-reg and discard it. They may not both be zero.
2263 Returns 1 if this operation can be performed; 0 if not. */
2266 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
2267 int unsignedp)
2269 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2270 enum mode_class mclass;
2271 enum machine_mode wider_mode;
2272 rtx entry_last = get_last_insn ();
2273 rtx last;
2275 mclass = GET_MODE_CLASS (mode);
2277 if (!targ0)
2278 targ0 = gen_reg_rtx (mode);
2279 if (!targ1)
2280 targ1 = gen_reg_rtx (mode);
2282 /* Record where to go back to if we fail. */
2283 last = get_last_insn ();
2285 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
2287 int icode = (int) optab_handler (unoptab, mode);
2288 enum machine_mode mode0 = insn_data[icode].operand[2].mode;
2289 rtx pat;
2290 rtx xop0 = op0;
2292 if (GET_MODE (xop0) != VOIDmode
2293 && GET_MODE (xop0) != mode0)
2294 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2296 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2297 if (!insn_data[icode].operand[2].predicate (xop0, mode0))
2298 xop0 = copy_to_mode_reg (mode0, xop0);
2300 /* We could handle this, but we should always be called with a pseudo
2301 for our targets and all insns should take them as outputs. */
2302 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2303 gcc_assert (insn_data[icode].operand[1].predicate (targ1, mode));
2305 pat = GEN_FCN (icode) (targ0, targ1, xop0);
2306 if (pat)
2308 emit_insn (pat);
2309 return 1;
2311 else
2312 delete_insns_since (last);
2315 /* It can't be done in this mode. Can we do it in a wider mode? */
2317 if (CLASS_HAS_WIDER_MODES_P (mclass))
2319 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2320 wider_mode != VOIDmode;
2321 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2323 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
2325 rtx t0 = gen_reg_rtx (wider_mode);
2326 rtx t1 = gen_reg_rtx (wider_mode);
2327 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2329 if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
2331 convert_move (targ0, t0, unsignedp);
2332 convert_move (targ1, t1, unsignedp);
2333 return 1;
2335 else
2336 delete_insns_since (last);
2341 delete_insns_since (entry_last);
2342 return 0;
2345 /* Generate code to perform an operation specified by BINOPTAB
2346 on operands OP0 and OP1, with two results to TARG1 and TARG2.
2347 We assume that the order of the operands for the instruction
2348 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2349 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2351 Either TARG0 or TARG1 may be zero, but what that means is that
2352 the result is not actually wanted. We will generate it into
2353 a dummy pseudo-reg and discard it. They may not both be zero.
2355 Returns 1 if this operation can be performed; 0 if not. */
2358 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
2359 int unsignedp)
2361 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2362 enum mode_class mclass;
2363 enum machine_mode wider_mode;
2364 rtx entry_last = get_last_insn ();
2365 rtx last;
2367 mclass = GET_MODE_CLASS (mode);
2369 if (!targ0)
2370 targ0 = gen_reg_rtx (mode);
2371 if (!targ1)
2372 targ1 = gen_reg_rtx (mode);
2374 /* Record where to go back to if we fail. */
2375 last = get_last_insn ();
2377 if (optab_handler (binoptab, mode) != CODE_FOR_nothing)
2379 int icode = (int) optab_handler (binoptab, mode);
2380 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2381 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
2382 rtx pat;
2383 rtx xop0 = op0, xop1 = op1;
2385 /* If we are optimizing, force expensive constants into a register. */
2386 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
2387 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
2389 /* In case the insn wants input operands in modes different from
2390 those of the actual operands, convert the operands. It would
2391 seem that we don't need to convert CONST_INTs, but we do, so
2392 that they're properly zero-extended, sign-extended or truncated
2393 for their mode. */
2395 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
2396 xop0 = convert_modes (mode0,
2397 GET_MODE (op0) != VOIDmode
2398 ? GET_MODE (op0)
2399 : mode,
2400 xop0, unsignedp);
2402 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
2403 xop1 = convert_modes (mode1,
2404 GET_MODE (op1) != VOIDmode
2405 ? GET_MODE (op1)
2406 : mode,
2407 xop1, unsignedp);
2409 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2410 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
2411 xop0 = copy_to_mode_reg (mode0, xop0);
2413 if (!insn_data[icode].operand[2].predicate (xop1, mode1))
2414 xop1 = copy_to_mode_reg (mode1, xop1);
2416 /* We could handle this, but we should always be called with a pseudo
2417 for our targets and all insns should take them as outputs. */
2418 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2419 gcc_assert (insn_data[icode].operand[3].predicate (targ1, mode));
2421 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
2422 if (pat)
2424 emit_insn (pat);
2425 return 1;
2427 else
2428 delete_insns_since (last);
2431 /* It can't be done in this mode. Can we do it in a wider mode? */
2433 if (CLASS_HAS_WIDER_MODES_P (mclass))
2435 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2436 wider_mode != VOIDmode;
2437 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2439 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing)
2441 rtx t0 = gen_reg_rtx (wider_mode);
2442 rtx t1 = gen_reg_rtx (wider_mode);
2443 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2444 rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
2446 if (expand_twoval_binop (binoptab, cop0, cop1,
2447 t0, t1, unsignedp))
2449 convert_move (targ0, t0, unsignedp);
2450 convert_move (targ1, t1, unsignedp);
2451 return 1;
2453 else
2454 delete_insns_since (last);
2459 delete_insns_since (entry_last);
2460 return 0;
2463 /* Expand the two-valued library call indicated by BINOPTAB, but
2464 preserve only one of the values. If TARG0 is non-NULL, the first
2465 value is placed into TARG0; otherwise the second value is placed
2466 into TARG1. Exactly one of TARG0 and TARG1 must be non-NULL. The
2467 value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
2468 This routine assumes that the value returned by the library call is
2469 as if the return value was of an integral mode twice as wide as the
2470 mode of OP0. Returns 1 if the call was successful. */
2472 bool
2473 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
2474 rtx targ0, rtx targ1, enum rtx_code code)
2476 enum machine_mode mode;
2477 enum machine_mode libval_mode;
2478 rtx libval;
2479 rtx insns;
2480 rtx libfunc;
2482 /* Exactly one of TARG0 or TARG1 should be non-NULL. */
2483 gcc_assert (!targ0 != !targ1);
2485 mode = GET_MODE (op0);
2486 libfunc = optab_libfunc (binoptab, mode);
2487 if (!libfunc)
2488 return false;
2490 /* The value returned by the library function will have twice as
2491 many bits as the nominal MODE. */
2492 libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
2493 MODE_INT);
2494 start_sequence ();
2495 libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
2496 libval_mode, 2,
2497 op0, mode,
2498 op1, mode);
2499 /* Get the part of VAL containing the value that we want. */
2500 libval = simplify_gen_subreg (mode, libval, libval_mode,
2501 targ0 ? 0 : GET_MODE_SIZE (mode));
2502 insns = get_insns ();
2503 end_sequence ();
2504 /* Move the into the desired location. */
2505 emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
2506 gen_rtx_fmt_ee (code, mode, op0, op1));
2508 return true;
2512 /* Wrapper around expand_unop which takes an rtx code to specify
2513 the operation to perform, not an optab pointer. All other
2514 arguments are the same. */
2516 expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
2517 rtx target, int unsignedp)
2519 optab unop = code_to_optab[(int) code];
2520 gcc_assert (unop);
2522 return expand_unop (mode, unop, op0, target, unsignedp);
2525 /* Try calculating
2526 (clz:narrow x)
2528 (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)). */
2529 static rtx
2530 widen_clz (enum machine_mode mode, rtx op0, rtx target)
2532 enum mode_class mclass = GET_MODE_CLASS (mode);
2533 if (CLASS_HAS_WIDER_MODES_P (mclass))
2535 enum machine_mode wider_mode;
2536 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2537 wider_mode != VOIDmode;
2538 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2540 if (optab_handler (clz_optab, wider_mode) != CODE_FOR_nothing)
2542 rtx xop0, temp, last;
2544 last = get_last_insn ();
2546 if (target == 0)
2547 target = gen_reg_rtx (mode);
2548 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2549 temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
2550 if (temp != 0)
2551 temp = expand_binop (wider_mode, sub_optab, temp,
2552 GEN_INT (GET_MODE_BITSIZE (wider_mode)
2553 - GET_MODE_BITSIZE (mode)),
2554 target, true, OPTAB_DIRECT);
2555 if (temp == 0)
2556 delete_insns_since (last);
2558 return temp;
2562 return 0;
2565 /* Try calculating clz of a double-word quantity as two clz's of word-sized
2566 quantities, choosing which based on whether the high word is nonzero. */
2567 static rtx
2568 expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target)
2570 rtx xop0 = force_reg (mode, op0);
2571 rtx subhi = gen_highpart (word_mode, xop0);
2572 rtx sublo = gen_lowpart (word_mode, xop0);
2573 rtx hi0_label = gen_label_rtx ();
2574 rtx after_label = gen_label_rtx ();
2575 rtx seq, temp, result;
2577 /* If we were not given a target, use a word_mode register, not a
2578 'mode' register. The result will fit, and nobody is expecting
2579 anything bigger (the return type of __builtin_clz* is int). */
2580 if (!target)
2581 target = gen_reg_rtx (word_mode);
2583 /* In any case, write to a word_mode scratch in both branches of the
2584 conditional, so we can ensure there is a single move insn setting
2585 'target' to tag a REG_EQUAL note on. */
2586 result = gen_reg_rtx (word_mode);
2588 start_sequence ();
2590 /* If the high word is not equal to zero,
2591 then clz of the full value is clz of the high word. */
2592 emit_cmp_and_jump_insns (subhi, CONST0_RTX (word_mode), EQ, 0,
2593 word_mode, true, hi0_label);
2595 temp = expand_unop_direct (word_mode, clz_optab, subhi, result, true);
2596 if (!temp)
2597 goto fail;
2599 if (temp != result)
2600 convert_move (result, temp, true);
2602 emit_jump_insn (gen_jump (after_label));
2603 emit_barrier ();
2605 /* Else clz of the full value is clz of the low word plus the number
2606 of bits in the high word. */
2607 emit_label (hi0_label);
2609 temp = expand_unop_direct (word_mode, clz_optab, sublo, 0, true);
2610 if (!temp)
2611 goto fail;
2612 temp = expand_binop (word_mode, add_optab, temp,
2613 GEN_INT (GET_MODE_BITSIZE (word_mode)),
2614 result, true, OPTAB_DIRECT);
2615 if (!temp)
2616 goto fail;
2617 if (temp != result)
2618 convert_move (result, temp, true);
2620 emit_label (after_label);
2621 convert_move (target, result, true);
2623 seq = get_insns ();
2624 end_sequence ();
2626 add_equal_note (seq, target, CLZ, xop0, 0);
2627 emit_insn (seq);
2628 return target;
2630 fail:
2631 end_sequence ();
2632 return 0;
2635 /* Try calculating
2636 (bswap:narrow x)
2638 (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */
2639 static rtx
2640 widen_bswap (enum machine_mode mode, rtx op0, rtx target)
2642 enum mode_class mclass = GET_MODE_CLASS (mode);
2643 enum machine_mode wider_mode;
2644 rtx x, last;
2646 if (!CLASS_HAS_WIDER_MODES_P (mclass))
2647 return NULL_RTX;
2649 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2650 wider_mode != VOIDmode;
2651 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2652 if (optab_handler (bswap_optab, wider_mode) != CODE_FOR_nothing)
2653 goto found;
2654 return NULL_RTX;
2656 found:
2657 last = get_last_insn ();
2659 x = widen_operand (op0, wider_mode, mode, true, true);
2660 x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
2662 if (x != 0)
2663 x = expand_shift (RSHIFT_EXPR, wider_mode, x,
2664 size_int (GET_MODE_BITSIZE (wider_mode)
2665 - GET_MODE_BITSIZE (mode)),
2666 NULL_RTX, true);
2668 if (x != 0)
2670 if (target == 0)
2671 target = gen_reg_rtx (mode);
2672 emit_move_insn (target, gen_lowpart (mode, x));
2674 else
2675 delete_insns_since (last);
2677 return target;
2680 /* Try calculating bswap as two bswaps of two word-sized operands. */
2682 static rtx
2683 expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
2685 rtx t0, t1;
2687 t1 = expand_unop (word_mode, bswap_optab,
2688 operand_subword_force (op, 0, mode), NULL_RTX, true);
2689 t0 = expand_unop (word_mode, bswap_optab,
2690 operand_subword_force (op, 1, mode), NULL_RTX, true);
2692 if (target == 0)
2693 target = gen_reg_rtx (mode);
2694 if (REG_P (target))
2695 emit_clobber (target);
2696 emit_move_insn (operand_subword (target, 0, 1, mode), t0);
2697 emit_move_insn (operand_subword (target, 1, 1, mode), t1);
2699 return target;
2702 /* Try calculating (parity x) as (and (popcount x) 1), where
2703 popcount can also be done in a wider mode. */
2704 static rtx
2705 expand_parity (enum machine_mode mode, rtx op0, rtx target)
2707 enum mode_class mclass = GET_MODE_CLASS (mode);
2708 if (CLASS_HAS_WIDER_MODES_P (mclass))
2710 enum machine_mode wider_mode;
2711 for (wider_mode = mode; wider_mode != VOIDmode;
2712 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2714 if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
2716 rtx xop0, temp, last;
2718 last = get_last_insn ();
2720 if (target == 0)
2721 target = gen_reg_rtx (mode);
2722 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2723 temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
2724 true);
2725 if (temp != 0)
2726 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
2727 target, true, OPTAB_DIRECT);
2728 if (temp == 0)
2729 delete_insns_since (last);
2731 return temp;
2735 return 0;
2738 /* Try calculating ctz(x) as K - clz(x & -x) ,
2739 where K is GET_MODE_BITSIZE(mode) - 1.
2741 Both __builtin_ctz and __builtin_clz are undefined at zero, so we
2742 don't have to worry about what the hardware does in that case. (If
2743 the clz instruction produces the usual value at 0, which is K, the
2744 result of this code sequence will be -1; expand_ffs, below, relies
2745 on this. It might be nice to have it be K instead, for consistency
2746 with the (very few) processors that provide a ctz with a defined
2747 value, but that would take one more instruction, and it would be
2748 less convenient for expand_ffs anyway. */
2750 static rtx
2751 expand_ctz (enum machine_mode mode, rtx op0, rtx target)
2753 rtx seq, temp;
2755 if (optab_handler (clz_optab, mode) == CODE_FOR_nothing)
2756 return 0;
2758 start_sequence ();
2760 temp = expand_unop_direct (mode, neg_optab, op0, NULL_RTX, true);
2761 if (temp)
2762 temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
2763 true, OPTAB_DIRECT);
2764 if (temp)
2765 temp = expand_unop_direct (mode, clz_optab, temp, NULL_RTX, true);
2766 if (temp)
2767 temp = expand_binop (mode, sub_optab, GEN_INT (GET_MODE_BITSIZE (mode) - 1),
2768 temp, target,
2769 true, OPTAB_DIRECT);
2770 if (temp == 0)
2772 end_sequence ();
2773 return 0;
2776 seq = get_insns ();
2777 end_sequence ();
2779 add_equal_note (seq, temp, CTZ, op0, 0);
2780 emit_insn (seq);
2781 return temp;
2785 /* Try calculating ffs(x) using ctz(x) if we have that instruction, or
2786 else with the sequence used by expand_clz.
2788 The ffs builtin promises to return zero for a zero value and ctz/clz
2789 may have an undefined value in that case. If they do not give us a
2790 convenient value, we have to generate a test and branch. */
2791 static rtx
2792 expand_ffs (enum machine_mode mode, rtx op0, rtx target)
2794 HOST_WIDE_INT val = 0;
2795 bool defined_at_zero = false;
2796 rtx temp, seq;
2798 if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing)
2800 start_sequence ();
2802 temp = expand_unop_direct (mode, ctz_optab, op0, 0, true);
2803 if (!temp)
2804 goto fail;
2806 defined_at_zero = (CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2);
2808 else if (optab_handler (clz_optab, mode) != CODE_FOR_nothing)
2810 start_sequence ();
2811 temp = expand_ctz (mode, op0, 0);
2812 if (!temp)
2813 goto fail;
2815 if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
2817 defined_at_zero = true;
2818 val = (GET_MODE_BITSIZE (mode) - 1) - val;
2821 else
2822 return 0;
2824 if (defined_at_zero && val == -1)
2825 /* No correction needed at zero. */;
2826 else
2828 /* We don't try to do anything clever with the situation found
2829 on some processors (eg Alpha) where ctz(0:mode) ==
2830 bitsize(mode). If someone can think of a way to send N to -1
2831 and leave alone all values in the range 0..N-1 (where N is a
2832 power of two), cheaper than this test-and-branch, please add it.
2834 The test-and-branch is done after the operation itself, in case
2835 the operation sets condition codes that can be recycled for this.
2836 (This is true on i386, for instance.) */
2838 rtx nonzero_label = gen_label_rtx ();
2839 emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
2840 mode, true, nonzero_label);
2842 convert_move (temp, GEN_INT (-1), false);
2843 emit_label (nonzero_label);
2846 /* temp now has a value in the range -1..bitsize-1. ffs is supposed
2847 to produce a value in the range 0..bitsize. */
2848 temp = expand_binop (mode, add_optab, temp, GEN_INT (1),
2849 target, false, OPTAB_DIRECT);
2850 if (!temp)
2851 goto fail;
2853 seq = get_insns ();
2854 end_sequence ();
2856 add_equal_note (seq, temp, FFS, op0, 0);
2857 emit_insn (seq);
2858 return temp;
2860 fail:
2861 end_sequence ();
2862 return 0;
2865 /* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
2866 conditions, VAL may already be a SUBREG against which we cannot generate
2867 a further SUBREG. In this case, we expect forcing the value into a
2868 register will work around the situation. */
2870 static rtx
2871 lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
2872 enum machine_mode imode)
2874 rtx ret;
2875 ret = lowpart_subreg (omode, val, imode);
2876 if (ret == NULL)
2878 val = force_reg (imode, val);
2879 ret = lowpart_subreg (omode, val, imode);
2880 gcc_assert (ret != NULL);
2882 return ret;
2885 /* Expand a floating point absolute value or negation operation via a
2886 logical operation on the sign bit. */
2888 static rtx
2889 expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
2890 rtx op0, rtx target)
2892 const struct real_format *fmt;
2893 int bitpos, word, nwords, i;
2894 enum machine_mode imode;
2895 double_int mask;
2896 rtx temp, insns;
2898 /* The format has to have a simple sign bit. */
2899 fmt = REAL_MODE_FORMAT (mode);
2900 if (fmt == NULL)
2901 return NULL_RTX;
2903 bitpos = fmt->signbit_rw;
2904 if (bitpos < 0)
2905 return NULL_RTX;
2907 /* Don't create negative zeros if the format doesn't support them. */
2908 if (code == NEG && !fmt->has_signed_zero)
2909 return NULL_RTX;
2911 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
2913 imode = int_mode_for_mode (mode);
2914 if (imode == BLKmode)
2915 return NULL_RTX;
2916 word = 0;
2917 nwords = 1;
2919 else
2921 imode = word_mode;
2923 if (FLOAT_WORDS_BIG_ENDIAN)
2924 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
2925 else
2926 word = bitpos / BITS_PER_WORD;
2927 bitpos = bitpos % BITS_PER_WORD;
2928 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
2931 mask = double_int_setbit (double_int_zero, bitpos);
2932 if (code == ABS)
2933 mask = double_int_not (mask);
2935 if (target == 0 || target == op0)
2936 target = gen_reg_rtx (mode);
2938 if (nwords > 1)
2940 start_sequence ();
2942 for (i = 0; i < nwords; ++i)
2944 rtx targ_piece = operand_subword (target, i, 1, mode);
2945 rtx op0_piece = operand_subword_force (op0, i, mode);
2947 if (i == word)
2949 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2950 op0_piece,
2951 immed_double_int_const (mask, imode),
2952 targ_piece, 1, OPTAB_LIB_WIDEN);
2953 if (temp != targ_piece)
2954 emit_move_insn (targ_piece, temp);
2956 else
2957 emit_move_insn (targ_piece, op0_piece);
2960 insns = get_insns ();
2961 end_sequence ();
2963 emit_insn (insns);
2965 else
2967 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2968 gen_lowpart (imode, op0),
2969 immed_double_int_const (mask, imode),
2970 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
2971 target = lowpart_subreg_maybe_copy (mode, temp, imode);
2973 set_unique_reg_note (get_last_insn (), REG_EQUAL,
2974 gen_rtx_fmt_e (code, mode, copy_rtx (op0)));
2977 return target;
2980 /* As expand_unop, but will fail rather than attempt the operation in a
2981 different mode or with a libcall. */
2982 static rtx
2983 expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
2984 int unsignedp)
2986 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
2988 int icode = (int) optab_handler (unoptab, mode);
2989 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2990 rtx xop0 = op0;
2991 rtx last = get_last_insn ();
2992 rtx pat, temp;
2994 if (target)
2995 temp = target;
2996 else
2997 temp = gen_reg_rtx (mode);
2999 if (GET_MODE (xop0) != VOIDmode
3000 && GET_MODE (xop0) != mode0)
3001 xop0 = convert_to_mode (mode0, xop0, unsignedp);
3003 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
3005 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
3006 xop0 = copy_to_mode_reg (mode0, xop0);
3008 if (!insn_data[icode].operand[0].predicate (temp, mode))
3009 temp = gen_reg_rtx (mode);
3011 pat = GEN_FCN (icode) (temp, xop0);
3012 if (pat)
3014 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
3015 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
3017 delete_insns_since (last);
3018 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
3021 emit_insn (pat);
3023 return temp;
3025 else
3026 delete_insns_since (last);
3028 return 0;
3031 /* Generate code to perform an operation specified by UNOPTAB
3032 on operand OP0, with result having machine-mode MODE.
3034 UNSIGNEDP is for the case where we have to widen the operands
3035 to perform the operation. It says to use zero-extension.
3037 If TARGET is nonzero, the value
3038 is generated there, if it is convenient to do so.
3039 In all cases an rtx is returned for the locus of the value;
3040 this may or may not be TARGET. */
3043 expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3044 int unsignedp)
3046 enum mode_class mclass = GET_MODE_CLASS (mode);
3047 enum machine_mode wider_mode;
3048 rtx temp;
3049 rtx libfunc;
3051 temp = expand_unop_direct (mode, unoptab, op0, target, unsignedp);
3052 if (temp)
3053 return temp;
3055 /* It can't be done in this mode. Can we open-code it in a wider mode? */
3057 /* Widening (or narrowing) clz needs special treatment. */
3058 if (unoptab == clz_optab)
3060 temp = widen_clz (mode, op0, target);
3061 if (temp)
3062 return temp;
3064 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3065 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
3067 temp = expand_doubleword_clz (mode, op0, target);
3068 if (temp)
3069 return temp;
3072 goto try_libcall;
3075 /* Widening (or narrowing) bswap needs special treatment. */
3076 if (unoptab == bswap_optab)
3078 temp = widen_bswap (mode, op0, target);
3079 if (temp)
3080 return temp;
3082 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3083 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
3085 temp = expand_doubleword_bswap (mode, op0, target);
3086 if (temp)
3087 return temp;
3090 goto try_libcall;
3093 if (CLASS_HAS_WIDER_MODES_P (mclass))
3094 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3095 wider_mode != VOIDmode;
3096 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3098 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
3100 rtx xop0 = op0;
3101 rtx last = get_last_insn ();
3103 /* For certain operations, we need not actually extend
3104 the narrow operand, as long as we will truncate the
3105 results to the same narrowness. */
3107 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3108 (unoptab == neg_optab
3109 || unoptab == one_cmpl_optab)
3110 && mclass == MODE_INT);
3112 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3113 unsignedp);
3115 if (temp)
3117 if (mclass != MODE_INT
3118 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
3119 GET_MODE_BITSIZE (wider_mode)))
3121 if (target == 0)
3122 target = gen_reg_rtx (mode);
3123 convert_move (target, temp, 0);
3124 return target;
3126 else
3127 return gen_lowpart (mode, temp);
3129 else
3130 delete_insns_since (last);
3134 /* These can be done a word at a time. */
3135 if (unoptab == one_cmpl_optab
3136 && mclass == MODE_INT
3137 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
3138 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
3140 int i;
3141 rtx insns;
3143 if (target == 0 || target == op0)
3144 target = gen_reg_rtx (mode);
3146 start_sequence ();
3148 /* Do the actual arithmetic. */
3149 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
3151 rtx target_piece = operand_subword (target, i, 1, mode);
3152 rtx x = expand_unop (word_mode, unoptab,
3153 operand_subword_force (op0, i, mode),
3154 target_piece, unsignedp);
3156 if (target_piece != x)
3157 emit_move_insn (target_piece, x);
3160 insns = get_insns ();
3161 end_sequence ();
3163 emit_insn (insns);
3164 return target;
3167 if (unoptab->code == NEG)
3169 /* Try negating floating point values by flipping the sign bit. */
3170 if (SCALAR_FLOAT_MODE_P (mode))
3172 temp = expand_absneg_bit (NEG, mode, op0, target);
3173 if (temp)
3174 return temp;
3177 /* If there is no negation pattern, and we have no negative zero,
3178 try subtracting from zero. */
3179 if (!HONOR_SIGNED_ZEROS (mode))
3181 temp = expand_binop (mode, (unoptab == negv_optab
3182 ? subv_optab : sub_optab),
3183 CONST0_RTX (mode), op0, target,
3184 unsignedp, OPTAB_DIRECT);
3185 if (temp)
3186 return temp;
3190 /* Try calculating parity (x) as popcount (x) % 2. */
3191 if (unoptab == parity_optab)
3193 temp = expand_parity (mode, op0, target);
3194 if (temp)
3195 return temp;
3198 /* Try implementing ffs (x) in terms of clz (x). */
3199 if (unoptab == ffs_optab)
3201 temp = expand_ffs (mode, op0, target);
3202 if (temp)
3203 return temp;
3206 /* Try implementing ctz (x) in terms of clz (x). */
3207 if (unoptab == ctz_optab)
3209 temp = expand_ctz (mode, op0, target);
3210 if (temp)
3211 return temp;
3214 try_libcall:
3215 /* Now try a library call in this mode. */
3216 libfunc = optab_libfunc (unoptab, mode);
3217 if (libfunc)
3219 rtx insns;
3220 rtx value;
3221 rtx eq_value;
3222 enum machine_mode outmode = mode;
3224 /* All of these functions return small values. Thus we choose to
3225 have them return something that isn't a double-word. */
3226 if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
3227 || unoptab == popcount_optab || unoptab == parity_optab)
3228 outmode
3229 = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
3230 optab_libfunc (unoptab, mode)));
3232 start_sequence ();
3234 /* Pass 1 for NO_QUEUE so we don't lose any increments
3235 if the libcall is cse'd or moved. */
3236 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, outmode,
3237 1, op0, mode);
3238 insns = get_insns ();
3239 end_sequence ();
3241 target = gen_reg_rtx (outmode);
3242 eq_value = gen_rtx_fmt_e (unoptab->code, mode, op0);
3243 if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
3244 eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
3245 else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
3246 eq_value = simplify_gen_unary (ZERO_EXTEND, outmode, eq_value, mode);
3247 emit_libcall_block (insns, target, value, eq_value);
3249 return target;
3252 /* It can't be done in this mode. Can we do it in a wider mode? */
3254 if (CLASS_HAS_WIDER_MODES_P (mclass))
3256 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3257 wider_mode != VOIDmode;
3258 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3260 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing
3261 || optab_libfunc (unoptab, wider_mode))
3263 rtx xop0 = op0;
3264 rtx last = get_last_insn ();
3266 /* For certain operations, we need not actually extend
3267 the narrow operand, as long as we will truncate the
3268 results to the same narrowness. */
3270 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3271 (unoptab == neg_optab
3272 || unoptab == one_cmpl_optab)
3273 && mclass == MODE_INT);
3275 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3276 unsignedp);
3278 /* If we are generating clz using wider mode, adjust the
3279 result. */
3280 if (unoptab == clz_optab && temp != 0)
3281 temp = expand_binop (wider_mode, sub_optab, temp,
3282 GEN_INT (GET_MODE_BITSIZE (wider_mode)
3283 - GET_MODE_BITSIZE (mode)),
3284 target, true, OPTAB_DIRECT);
3286 if (temp)
3288 if (mclass != MODE_INT)
3290 if (target == 0)
3291 target = gen_reg_rtx (mode);
3292 convert_move (target, temp, 0);
3293 return target;
3295 else
3296 return gen_lowpart (mode, temp);
3298 else
3299 delete_insns_since (last);
3304 /* One final attempt at implementing negation via subtraction,
3305 this time allowing widening of the operand. */
3306 if (unoptab->code == NEG && !HONOR_SIGNED_ZEROS (mode))
3308 rtx temp;
3309 temp = expand_binop (mode,
3310 unoptab == negv_optab ? subv_optab : sub_optab,
3311 CONST0_RTX (mode), op0,
3312 target, unsignedp, OPTAB_LIB_WIDEN);
3313 if (temp)
3314 return temp;
3317 return 0;
3320 /* Emit code to compute the absolute value of OP0, with result to
3321 TARGET if convenient. (TARGET may be 0.) The return value says
3322 where the result actually is to be found.
3324 MODE is the mode of the operand; the mode of the result is
3325 different but can be deduced from MODE.
3330 expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
3331 int result_unsignedp)
3333 rtx temp;
3335 if (! flag_trapv)
3336 result_unsignedp = 1;
3338 /* First try to do it with a special abs instruction. */
3339 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
3340 op0, target, 0);
3341 if (temp != 0)
3342 return temp;
3344 /* For floating point modes, try clearing the sign bit. */
3345 if (SCALAR_FLOAT_MODE_P (mode))
3347 temp = expand_absneg_bit (ABS, mode, op0, target);
3348 if (temp)
3349 return temp;
3352 /* If we have a MAX insn, we can do this as MAX (x, -x). */
3353 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing
3354 && !HONOR_SIGNED_ZEROS (mode))
3356 rtx last = get_last_insn ();
3358 temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
3359 if (temp != 0)
3360 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3361 OPTAB_WIDEN);
3363 if (temp != 0)
3364 return temp;
3366 delete_insns_since (last);
3369 /* If this machine has expensive jumps, we can do integer absolute
3370 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
3371 where W is the width of MODE. */
3373 if (GET_MODE_CLASS (mode) == MODE_INT
3374 && BRANCH_COST (optimize_insn_for_speed_p (),
3375 false) >= 2)
3377 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3378 size_int (GET_MODE_BITSIZE (mode) - 1),
3379 NULL_RTX, 0);
3381 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3382 OPTAB_LIB_WIDEN);
3383 if (temp != 0)
3384 temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
3385 temp, extended, target, 0, OPTAB_LIB_WIDEN);
3387 if (temp != 0)
3388 return temp;
3391 return NULL_RTX;
3395 expand_abs (enum machine_mode mode, rtx op0, rtx target,
3396 int result_unsignedp, int safe)
3398 rtx temp, op1;
3400 if (! flag_trapv)
3401 result_unsignedp = 1;
3403 temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
3404 if (temp != 0)
3405 return temp;
3407 /* If that does not win, use conditional jump and negate. */
3409 /* It is safe to use the target if it is the same
3410 as the source if this is also a pseudo register */
3411 if (op0 == target && REG_P (op0)
3412 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
3413 safe = 1;
3415 op1 = gen_label_rtx ();
3416 if (target == 0 || ! safe
3417 || GET_MODE (target) != mode
3418 || (MEM_P (target) && MEM_VOLATILE_P (target))
3419 || (REG_P (target)
3420 && REGNO (target) < FIRST_PSEUDO_REGISTER))
3421 target = gen_reg_rtx (mode);
3423 emit_move_insn (target, op0);
3424 NO_DEFER_POP;
3426 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
3427 NULL_RTX, NULL_RTX, op1, -1);
3429 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3430 target, target, 0);
3431 if (op0 != target)
3432 emit_move_insn (target, op0);
3433 emit_label (op1);
3434 OK_DEFER_POP;
3435 return target;
3438 /* Emit code to compute the one's complement absolute value of OP0
3439 (if (OP0 < 0) OP0 = ~OP0), with result to TARGET if convenient.
3440 (TARGET may be NULL_RTX.) The return value says where the result
3441 actually is to be found.
3443 MODE is the mode of the operand; the mode of the result is
3444 different but can be deduced from MODE. */
3447 expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
3449 rtx temp;
3451 /* Not applicable for floating point modes. */
3452 if (FLOAT_MODE_P (mode))
3453 return NULL_RTX;
3455 /* If we have a MAX insn, we can do this as MAX (x, ~x). */
3456 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing)
3458 rtx last = get_last_insn ();
3460 temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
3461 if (temp != 0)
3462 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3463 OPTAB_WIDEN);
3465 if (temp != 0)
3466 return temp;
3468 delete_insns_since (last);
3471 /* If this machine has expensive jumps, we can do one's complement
3472 absolute value of X as (((signed) x >> (W-1)) ^ x). */
3474 if (GET_MODE_CLASS (mode) == MODE_INT
3475 && BRANCH_COST (optimize_insn_for_speed_p (),
3476 false) >= 2)
3478 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3479 size_int (GET_MODE_BITSIZE (mode) - 1),
3480 NULL_RTX, 0);
3482 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3483 OPTAB_LIB_WIDEN);
3485 if (temp != 0)
3486 return temp;
3489 return NULL_RTX;
3492 /* A subroutine of expand_copysign, perform the copysign operation using the
3493 abs and neg primitives advertised to exist on the target. The assumption
3494 is that we have a split register file, and leaving op0 in fp registers,
3495 and not playing with subregs so much, will help the register allocator. */
3497 static rtx
3498 expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3499 int bitpos, bool op0_is_abs)
3501 enum machine_mode imode;
3502 int icode;
3503 rtx sign, label;
3505 if (target == op1)
3506 target = NULL_RTX;
3508 /* Check if the back end provides an insn that handles signbit for the
3509 argument's mode. */
3510 icode = (int) optab_handler (signbit_optab, mode);
3511 if (icode != CODE_FOR_nothing)
3513 imode = insn_data[icode].operand[0].mode;
3514 sign = gen_reg_rtx (imode);
3515 emit_unop_insn (icode, sign, op1, UNKNOWN);
3517 else
3519 double_int mask;
3521 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3523 imode = int_mode_for_mode (mode);
3524 if (imode == BLKmode)
3525 return NULL_RTX;
3526 op1 = gen_lowpart (imode, op1);
3528 else
3530 int word;
3532 imode = word_mode;
3533 if (FLOAT_WORDS_BIG_ENDIAN)
3534 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3535 else
3536 word = bitpos / BITS_PER_WORD;
3537 bitpos = bitpos % BITS_PER_WORD;
3538 op1 = operand_subword_force (op1, word, mode);
3541 mask = double_int_setbit (double_int_zero, bitpos);
3543 sign = expand_binop (imode, and_optab, op1,
3544 immed_double_int_const (mask, imode),
3545 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3548 if (!op0_is_abs)
3550 op0 = expand_unop (mode, abs_optab, op0, target, 0);
3551 if (op0 == NULL)
3552 return NULL_RTX;
3553 target = op0;
3555 else
3557 if (target == NULL_RTX)
3558 target = copy_to_reg (op0);
3559 else
3560 emit_move_insn (target, op0);
3563 label = gen_label_rtx ();
3564 emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
3566 if (GET_CODE (op0) == CONST_DOUBLE)
3567 op0 = simplify_unary_operation (NEG, mode, op0, mode);
3568 else
3569 op0 = expand_unop (mode, neg_optab, op0, target, 0);
3570 if (op0 != target)
3571 emit_move_insn (target, op0);
3573 emit_label (label);
3575 return target;
3579 /* A subroutine of expand_copysign, perform the entire copysign operation
3580 with integer bitmasks. BITPOS is the position of the sign bit; OP0_IS_ABS
3581 is true if op0 is known to have its sign bit clear. */
3583 static rtx
3584 expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3585 int bitpos, bool op0_is_abs)
3587 enum machine_mode imode;
3588 double_int mask;
3589 int word, nwords, i;
3590 rtx temp, insns;
3592 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3594 imode = int_mode_for_mode (mode);
3595 if (imode == BLKmode)
3596 return NULL_RTX;
3597 word = 0;
3598 nwords = 1;
3600 else
3602 imode = word_mode;
3604 if (FLOAT_WORDS_BIG_ENDIAN)
3605 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3606 else
3607 word = bitpos / BITS_PER_WORD;
3608 bitpos = bitpos % BITS_PER_WORD;
3609 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
3612 mask = double_int_setbit (double_int_zero, bitpos);
3614 if (target == 0 || target == op0 || target == op1)
3615 target = gen_reg_rtx (mode);
3617 if (nwords > 1)
3619 start_sequence ();
3621 for (i = 0; i < nwords; ++i)
3623 rtx targ_piece = operand_subword (target, i, 1, mode);
3624 rtx op0_piece = operand_subword_force (op0, i, mode);
3626 if (i == word)
3628 if (!op0_is_abs)
3629 op0_piece
3630 = expand_binop (imode, and_optab, op0_piece,
3631 immed_double_int_const (double_int_not (mask),
3632 imode),
3633 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3635 op1 = expand_binop (imode, and_optab,
3636 operand_subword_force (op1, i, mode),
3637 immed_double_int_const (mask, imode),
3638 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3640 temp = expand_binop (imode, ior_optab, op0_piece, op1,
3641 targ_piece, 1, OPTAB_LIB_WIDEN);
3642 if (temp != targ_piece)
3643 emit_move_insn (targ_piece, temp);
3645 else
3646 emit_move_insn (targ_piece, op0_piece);
3649 insns = get_insns ();
3650 end_sequence ();
3652 emit_insn (insns);
3654 else
3656 op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
3657 immed_double_int_const (mask, imode),
3658 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3660 op0 = gen_lowpart (imode, op0);
3661 if (!op0_is_abs)
3662 op0 = expand_binop (imode, and_optab, op0,
3663 immed_double_int_const (double_int_not (mask),
3664 imode),
3665 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3667 temp = expand_binop (imode, ior_optab, op0, op1,
3668 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3669 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3672 return target;
3675 /* Expand the C99 copysign operation. OP0 and OP1 must be the same
3676 scalar floating point mode. Return NULL if we do not know how to
3677 expand the operation inline. */
3680 expand_copysign (rtx op0, rtx op1, rtx target)
3682 enum machine_mode mode = GET_MODE (op0);
3683 const struct real_format *fmt;
3684 bool op0_is_abs;
3685 rtx temp;
3687 gcc_assert (SCALAR_FLOAT_MODE_P (mode));
3688 gcc_assert (GET_MODE (op1) == mode);
3690 /* First try to do it with a special instruction. */
3691 temp = expand_binop (mode, copysign_optab, op0, op1,
3692 target, 0, OPTAB_DIRECT);
3693 if (temp)
3694 return temp;
3696 fmt = REAL_MODE_FORMAT (mode);
3697 if (fmt == NULL || !fmt->has_signed_zero)
3698 return NULL_RTX;
3700 op0_is_abs = false;
3701 if (GET_CODE (op0) == CONST_DOUBLE)
3703 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
3704 op0 = simplify_unary_operation (ABS, mode, op0, mode);
3705 op0_is_abs = true;
3708 if (fmt->signbit_ro >= 0
3709 && (GET_CODE (op0) == CONST_DOUBLE
3710 || (optab_handler (neg_optab, mode) != CODE_FOR_nothing
3711 && optab_handler (abs_optab, mode) != CODE_FOR_nothing)))
3713 temp = expand_copysign_absneg (mode, op0, op1, target,
3714 fmt->signbit_ro, op0_is_abs);
3715 if (temp)
3716 return temp;
3719 if (fmt->signbit_rw < 0)
3720 return NULL_RTX;
3721 return expand_copysign_bit (mode, op0, op1, target,
3722 fmt->signbit_rw, op0_is_abs);
3725 /* Generate an instruction whose insn-code is INSN_CODE,
3726 with two operands: an output TARGET and an input OP0.
3727 TARGET *must* be nonzero, and the output is always stored there.
3728 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3729 the value that is stored into TARGET.
3731 Return false if expansion failed. */
3733 bool
3734 maybe_emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3736 rtx temp;
3737 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3738 rtx pat;
3739 rtx last = get_last_insn ();
3741 temp = target;
3743 /* Now, if insn does not accept our operands, put them into pseudos. */
3745 if (!insn_data[icode].operand[1].predicate (op0, mode0))
3746 op0 = copy_to_mode_reg (mode0, op0);
3748 if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
3749 temp = gen_reg_rtx (GET_MODE (temp));
3751 pat = GEN_FCN (icode) (temp, op0);
3752 if (!pat)
3754 delete_insns_since (last);
3755 return false;
3758 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
3759 add_equal_note (pat, temp, code, op0, NULL_RTX);
3761 emit_insn (pat);
3763 if (temp != target)
3764 emit_move_insn (target, temp);
3765 return true;
3767 /* Generate an instruction whose insn-code is INSN_CODE,
3768 with two operands: an output TARGET and an input OP0.
3769 TARGET *must* be nonzero, and the output is always stored there.
3770 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3771 the value that is stored into TARGET. */
3773 void
3774 emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3776 bool ok = maybe_emit_unop_insn (icode, target, op0, code);
3777 gcc_assert (ok);
3780 struct no_conflict_data
3782 rtx target, first, insn;
3783 bool must_stay;
3786 /* Called via note_stores by emit_libcall_block. Set P->must_stay if
3787 the currently examined clobber / store has to stay in the list of
3788 insns that constitute the actual libcall block. */
3789 static void
3790 no_conflict_move_test (rtx dest, const_rtx set, void *p0)
3792 struct no_conflict_data *p= (struct no_conflict_data *) p0;
3794 /* If this inns directly contributes to setting the target, it must stay. */
3795 if (reg_overlap_mentioned_p (p->target, dest))
3796 p->must_stay = true;
3797 /* If we haven't committed to keeping any other insns in the list yet,
3798 there is nothing more to check. */
3799 else if (p->insn == p->first)
3800 return;
3801 /* If this insn sets / clobbers a register that feeds one of the insns
3802 already in the list, this insn has to stay too. */
3803 else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
3804 || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
3805 || reg_used_between_p (dest, p->first, p->insn)
3806 /* Likewise if this insn depends on a register set by a previous
3807 insn in the list, or if it sets a result (presumably a hard
3808 register) that is set or clobbered by a previous insn.
3809 N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
3810 SET_DEST perform the former check on the address, and the latter
3811 check on the MEM. */
3812 || (GET_CODE (set) == SET
3813 && (modified_in_p (SET_SRC (set), p->first)
3814 || modified_in_p (SET_DEST (set), p->first)
3815 || modified_between_p (SET_SRC (set), p->first, p->insn)
3816 || modified_between_p (SET_DEST (set), p->first, p->insn))))
3817 p->must_stay = true;
3821 /* Emit code to make a call to a constant function or a library call.
3823 INSNS is a list containing all insns emitted in the call.
3824 These insns leave the result in RESULT. Our block is to copy RESULT
3825 to TARGET, which is logically equivalent to EQUIV.
3827 We first emit any insns that set a pseudo on the assumption that these are
3828 loading constants into registers; doing so allows them to be safely cse'ed
3829 between blocks. Then we emit all the other insns in the block, followed by
3830 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
3831 note with an operand of EQUIV. */
3833 void
3834 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
3836 rtx final_dest = target;
3837 rtx next, last, insn;
3839 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
3840 into a MEM later. Protect the libcall block from this change. */
3841 if (! REG_P (target) || REG_USERVAR_P (target))
3842 target = gen_reg_rtx (GET_MODE (target));
3844 /* If we're using non-call exceptions, a libcall corresponding to an
3845 operation that may trap may also trap. */
3846 /* ??? See the comment in front of make_reg_eh_region_note. */
3847 if (cfun->can_throw_non_call_exceptions && may_trap_p (equiv))
3849 for (insn = insns; insn; insn = NEXT_INSN (insn))
3850 if (CALL_P (insn))
3852 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3853 if (note)
3855 int lp_nr = INTVAL (XEXP (note, 0));
3856 if (lp_nr == 0 || lp_nr == INT_MIN)
3857 remove_note (insn, note);
3861 else
3863 /* Look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
3864 reg note to indicate that this call cannot throw or execute a nonlocal
3865 goto (unless there is already a REG_EH_REGION note, in which case
3866 we update it). */
3867 for (insn = insns; insn; insn = NEXT_INSN (insn))
3868 if (CALL_P (insn))
3869 make_reg_eh_region_note_nothrow_nononlocal (insn);
3872 /* First emit all insns that set pseudos. Remove them from the list as
3873 we go. Avoid insns that set pseudos which were referenced in previous
3874 insns. These can be generated by move_by_pieces, for example,
3875 to update an address. Similarly, avoid insns that reference things
3876 set in previous insns. */
3878 for (insn = insns; insn; insn = next)
3880 rtx set = single_set (insn);
3882 next = NEXT_INSN (insn);
3884 if (set != 0 && REG_P (SET_DEST (set))
3885 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
3887 struct no_conflict_data data;
3889 data.target = const0_rtx;
3890 data.first = insns;
3891 data.insn = insn;
3892 data.must_stay = 0;
3893 note_stores (PATTERN (insn), no_conflict_move_test, &data);
3894 if (! data.must_stay)
3896 if (PREV_INSN (insn))
3897 NEXT_INSN (PREV_INSN (insn)) = next;
3898 else
3899 insns = next;
3901 if (next)
3902 PREV_INSN (next) = PREV_INSN (insn);
3904 add_insn (insn);
3908 /* Some ports use a loop to copy large arguments onto the stack.
3909 Don't move anything outside such a loop. */
3910 if (LABEL_P (insn))
3911 break;
3914 /* Write the remaining insns followed by the final copy. */
3915 for (insn = insns; insn; insn = next)
3917 next = NEXT_INSN (insn);
3919 add_insn (insn);
3922 last = emit_move_insn (target, result);
3923 if (optab_handler (mov_optab, GET_MODE (target)) != CODE_FOR_nothing)
3924 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
3926 if (final_dest != target)
3927 emit_move_insn (final_dest, target);
3930 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
3931 PURPOSE describes how this comparison will be used. CODE is the rtx
3932 comparison code we will be using.
3934 ??? Actually, CODE is slightly weaker than that. A target is still
3935 required to implement all of the normal bcc operations, but not
3936 required to implement all (or any) of the unordered bcc operations. */
3939 can_compare_p (enum rtx_code code, enum machine_mode mode,
3940 enum can_compare_purpose purpose)
3942 rtx test;
3943 test = gen_rtx_fmt_ee (code, mode, const0_rtx, const0_rtx);
3946 int icode;
3948 if (purpose == ccp_jump
3949 && (icode = optab_handler (cbranch_optab, mode)) != CODE_FOR_nothing
3950 && insn_data[icode].operand[0].predicate (test, mode))
3951 return 1;
3952 if (purpose == ccp_store_flag
3953 && (icode = optab_handler (cstore_optab, mode)) != CODE_FOR_nothing
3954 && insn_data[icode].operand[1].predicate (test, mode))
3955 return 1;
3956 if (purpose == ccp_cmov
3957 && optab_handler (cmov_optab, mode) != CODE_FOR_nothing)
3958 return 1;
3960 mode = GET_MODE_WIDER_MODE (mode);
3961 PUT_MODE (test, mode);
3963 while (mode != VOIDmode);
3965 return 0;
3968 /* This function is called when we are going to emit a compare instruction that
3969 compares the values found in *PX and *PY, using the rtl operator COMPARISON.
3971 *PMODE is the mode of the inputs (in case they are const_int).
3972 *PUNSIGNEDP nonzero says that the operands are unsigned;
3973 this matters if they need to be widened (as given by METHODS).
3975 If they have mode BLKmode, then SIZE specifies the size of both operands.
3977 This function performs all the setup necessary so that the caller only has
3978 to emit a single comparison insn. This setup can involve doing a BLKmode
3979 comparison or emitting a library call to perform the comparison if no insn
3980 is available to handle it.
3981 The values which are passed in through pointers can be modified; the caller
3982 should perform the comparison on the modified values. Constant
3983 comparisons must have already been folded. */
3985 static void
3986 prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
3987 int unsignedp, enum optab_methods methods,
3988 rtx *ptest, enum machine_mode *pmode)
3990 enum machine_mode mode = *pmode;
3991 rtx libfunc, test;
3992 enum machine_mode cmp_mode;
3993 enum mode_class mclass;
3995 /* The other methods are not needed. */
3996 gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
3997 || methods == OPTAB_LIB_WIDEN);
3999 /* If we are optimizing, force expensive constants into a register. */
4000 if (CONSTANT_P (x) && optimize
4001 && (rtx_cost (x, COMPARE, optimize_insn_for_speed_p ())
4002 > COSTS_N_INSNS (1)))
4003 x = force_reg (mode, x);
4005 if (CONSTANT_P (y) && optimize
4006 && (rtx_cost (y, COMPARE, optimize_insn_for_speed_p ())
4007 > COSTS_N_INSNS (1)))
4008 y = force_reg (mode, y);
4010 #ifdef HAVE_cc0
4011 /* Make sure if we have a canonical comparison. The RTL
4012 documentation states that canonical comparisons are required only
4013 for targets which have cc0. */
4014 gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
4015 #endif
4017 /* Don't let both operands fail to indicate the mode. */
4018 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
4019 x = force_reg (mode, x);
4020 if (mode == VOIDmode)
4021 mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : GET_MODE (y);
4023 /* Handle all BLKmode compares. */
4025 if (mode == BLKmode)
4027 enum machine_mode result_mode;
4028 enum insn_code cmp_code;
4029 tree length_type;
4030 rtx libfunc;
4031 rtx result;
4032 rtx opalign
4033 = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
4035 gcc_assert (size);
4037 /* Try to use a memory block compare insn - either cmpstr
4038 or cmpmem will do. */
4039 for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
4040 cmp_mode != VOIDmode;
4041 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
4043 cmp_code = direct_optab_handler (cmpmem_optab, cmp_mode);
4044 if (cmp_code == CODE_FOR_nothing)
4045 cmp_code = direct_optab_handler (cmpstr_optab, cmp_mode);
4046 if (cmp_code == CODE_FOR_nothing)
4047 cmp_code = direct_optab_handler (cmpstrn_optab, cmp_mode);
4048 if (cmp_code == CODE_FOR_nothing)
4049 continue;
4051 /* Must make sure the size fits the insn's mode. */
4052 if ((CONST_INT_P (size)
4053 && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
4054 || (GET_MODE_BITSIZE (GET_MODE (size))
4055 > GET_MODE_BITSIZE (cmp_mode)))
4056 continue;
4058 result_mode = insn_data[cmp_code].operand[0].mode;
4059 result = gen_reg_rtx (result_mode);
4060 size = convert_to_mode (cmp_mode, size, 1);
4061 emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
4063 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4064 *pmode = result_mode;
4065 return;
4068 if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
4069 goto fail;
4071 /* Otherwise call a library function, memcmp. */
4072 libfunc = memcmp_libfunc;
4073 length_type = sizetype;
4074 result_mode = TYPE_MODE (integer_type_node);
4075 cmp_mode = TYPE_MODE (length_type);
4076 size = convert_to_mode (TYPE_MODE (length_type), size,
4077 TYPE_UNSIGNED (length_type));
4079 result = emit_library_call_value (libfunc, 0, LCT_PURE,
4080 result_mode, 3,
4081 XEXP (x, 0), Pmode,
4082 XEXP (y, 0), Pmode,
4083 size, cmp_mode);
4085 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4086 *pmode = result_mode;
4087 return;
4090 /* Don't allow operands to the compare to trap, as that can put the
4091 compare and branch in different basic blocks. */
4092 if (cfun->can_throw_non_call_exceptions)
4094 if (may_trap_p (x))
4095 x = force_reg (mode, x);
4096 if (may_trap_p (y))
4097 y = force_reg (mode, y);
4100 if (GET_MODE_CLASS (mode) == MODE_CC)
4102 gcc_assert (can_compare_p (comparison, CCmode, ccp_jump));
4103 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4104 return;
4107 mclass = GET_MODE_CLASS (mode);
4108 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4109 cmp_mode = mode;
4112 enum insn_code icode;
4113 icode = optab_handler (cbranch_optab, cmp_mode);
4114 if (icode != CODE_FOR_nothing
4115 && insn_data[icode].operand[0].predicate (test, VOIDmode))
4117 rtx last = get_last_insn ();
4118 rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp);
4119 rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp);
4120 if (op0 && op1
4121 && insn_data[icode].operand[1].predicate
4122 (op0, insn_data[icode].operand[1].mode)
4123 && insn_data[icode].operand[2].predicate
4124 (op1, insn_data[icode].operand[2].mode))
4126 XEXP (test, 0) = op0;
4127 XEXP (test, 1) = op1;
4128 *ptest = test;
4129 *pmode = cmp_mode;
4130 return;
4132 delete_insns_since (last);
4135 if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
4136 break;
4137 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode);
4139 while (cmp_mode != VOIDmode);
4141 if (methods != OPTAB_LIB_WIDEN)
4142 goto fail;
4144 if (!SCALAR_FLOAT_MODE_P (mode))
4146 rtx result;
4148 /* Handle a libcall just for the mode we are using. */
4149 libfunc = optab_libfunc (cmp_optab, mode);
4150 gcc_assert (libfunc);
4152 /* If we want unsigned, and this mode has a distinct unsigned
4153 comparison routine, use that. */
4154 if (unsignedp)
4156 rtx ulibfunc = optab_libfunc (ucmp_optab, mode);
4157 if (ulibfunc)
4158 libfunc = ulibfunc;
4161 result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4162 targetm.libgcc_cmp_return_mode (),
4163 2, x, mode, y, mode);
4165 /* There are two kinds of comparison routines. Biased routines
4166 return 0/1/2, and unbiased routines return -1/0/1. Other parts
4167 of gcc expect that the comparison operation is equivalent
4168 to the modified comparison. For signed comparisons compare the
4169 result against 1 in the biased case, and zero in the unbiased
4170 case. For unsigned comparisons always compare against 1 after
4171 biasing the unbiased result by adding 1. This gives us a way to
4172 represent LTU. */
4173 x = result;
4174 y = const1_rtx;
4176 if (!TARGET_LIB_INT_CMP_BIASED)
4178 if (unsignedp)
4179 x = plus_constant (result, 1);
4180 else
4181 y = const0_rtx;
4184 *pmode = word_mode;
4185 prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods,
4186 ptest, pmode);
4188 else
4189 prepare_float_lib_cmp (x, y, comparison, ptest, pmode);
4191 return;
4193 fail:
4194 *ptest = NULL_RTX;
4197 /* Before emitting an insn with code ICODE, make sure that X, which is going
4198 to be used for operand OPNUM of the insn, is converted from mode MODE to
4199 WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
4200 that it is accepted by the operand predicate. Return the new value. */
4203 prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
4204 enum machine_mode wider_mode, int unsignedp)
4206 if (mode != wider_mode)
4207 x = convert_modes (wider_mode, mode, x, unsignedp);
4209 if (!insn_data[icode].operand[opnum].predicate
4210 (x, insn_data[icode].operand[opnum].mode))
4212 if (reload_completed)
4213 return NULL_RTX;
4214 x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
4217 return x;
4220 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
4221 we can do the branch. */
4223 static void
4224 emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label)
4226 enum machine_mode optab_mode;
4227 enum mode_class mclass;
4228 enum insn_code icode;
4230 mclass = GET_MODE_CLASS (mode);
4231 optab_mode = (mclass == MODE_CC) ? CCmode : mode;
4232 icode = optab_handler (cbranch_optab, optab_mode);
4234 gcc_assert (icode != CODE_FOR_nothing);
4235 gcc_assert (insn_data[icode].operand[0].predicate (test, VOIDmode));
4236 emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0), XEXP (test, 1), label));
4239 /* Generate code to compare X with Y so that the condition codes are
4240 set and to jump to LABEL if the condition is true. If X is a
4241 constant and Y is not a constant, then the comparison is swapped to
4242 ensure that the comparison RTL has the canonical form.
4244 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
4245 need to be widened. UNSIGNEDP is also used to select the proper
4246 branch condition code.
4248 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
4250 MODE is the mode of the inputs (in case they are const_int).
4252 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
4253 It will be potentially converted into an unsigned variant based on
4254 UNSIGNEDP to select a proper jump instruction. */
4256 void
4257 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
4258 enum machine_mode mode, int unsignedp, rtx label)
4260 rtx op0 = x, op1 = y;
4261 rtx test;
4263 /* Swap operands and condition to ensure canonical RTL. */
4264 if (swap_commutative_operands_p (x, y)
4265 && can_compare_p (swap_condition (comparison), mode, ccp_jump))
4267 op0 = y, op1 = x;
4268 comparison = swap_condition (comparison);
4271 /* If OP0 is still a constant, then both X and Y must be constants
4272 or the opposite comparison is not supported. Force X into a register
4273 to create canonical RTL. */
4274 if (CONSTANT_P (op0))
4275 op0 = force_reg (mode, op0);
4277 if (unsignedp)
4278 comparison = unsigned_condition (comparison);
4280 prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
4281 &test, &mode);
4282 emit_cmp_and_jump_insn_1 (test, mode, label);
4286 /* Emit a library call comparison between floating point X and Y.
4287 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
4289 static void
4290 prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
4291 rtx *ptest, enum machine_mode *pmode)
4293 enum rtx_code swapped = swap_condition (comparison);
4294 enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
4295 enum machine_mode orig_mode = GET_MODE (x);
4296 enum machine_mode mode, cmp_mode;
4297 rtx true_rtx, false_rtx;
4298 rtx value, target, insns, equiv;
4299 rtx libfunc = 0;
4300 bool reversed_p = false;
4301 cmp_mode = targetm.libgcc_cmp_return_mode ();
4303 for (mode = orig_mode;
4304 mode != VOIDmode;
4305 mode = GET_MODE_WIDER_MODE (mode))
4307 if (code_to_optab[comparison]
4308 && (libfunc = optab_libfunc (code_to_optab[comparison], mode)))
4309 break;
4311 if (code_to_optab[swapped]
4312 && (libfunc = optab_libfunc (code_to_optab[swapped], mode)))
4314 rtx tmp;
4315 tmp = x; x = y; y = tmp;
4316 comparison = swapped;
4317 break;
4320 if (code_to_optab[reversed]
4321 && (libfunc = optab_libfunc (code_to_optab[reversed], mode)))
4323 comparison = reversed;
4324 reversed_p = true;
4325 break;
4329 gcc_assert (mode != VOIDmode);
4331 if (mode != orig_mode)
4333 x = convert_to_mode (mode, x, 0);
4334 y = convert_to_mode (mode, y, 0);
4337 /* Attach a REG_EQUAL note describing the semantics of the libcall to
4338 the RTL. The allows the RTL optimizers to delete the libcall if the
4339 condition can be determined at compile-time. */
4340 if (comparison == UNORDERED
4341 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4343 true_rtx = const_true_rtx;
4344 false_rtx = const0_rtx;
4346 else
4348 switch (comparison)
4350 case EQ:
4351 true_rtx = const0_rtx;
4352 false_rtx = const_true_rtx;
4353 break;
4355 case NE:
4356 true_rtx = const_true_rtx;
4357 false_rtx = const0_rtx;
4358 break;
4360 case GT:
4361 true_rtx = const1_rtx;
4362 false_rtx = const0_rtx;
4363 break;
4365 case GE:
4366 true_rtx = const0_rtx;
4367 false_rtx = constm1_rtx;
4368 break;
4370 case LT:
4371 true_rtx = constm1_rtx;
4372 false_rtx = const0_rtx;
4373 break;
4375 case LE:
4376 true_rtx = const0_rtx;
4377 false_rtx = const1_rtx;
4378 break;
4380 default:
4381 gcc_unreachable ();
4385 if (comparison == UNORDERED)
4387 rtx temp = simplify_gen_relational (NE, cmp_mode, mode, x, x);
4388 equiv = simplify_gen_relational (NE, cmp_mode, mode, y, y);
4389 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4390 temp, const_true_rtx, equiv);
4392 else
4394 equiv = simplify_gen_relational (comparison, cmp_mode, mode, x, y);
4395 if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4396 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4397 equiv, true_rtx, false_rtx);
4400 start_sequence ();
4401 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4402 cmp_mode, 2, x, mode, y, mode);
4403 insns = get_insns ();
4404 end_sequence ();
4406 target = gen_reg_rtx (cmp_mode);
4407 emit_libcall_block (insns, target, value, equiv);
4409 if (comparison == UNORDERED
4410 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison)
4411 || reversed_p)
4412 *ptest = gen_rtx_fmt_ee (reversed_p ? EQ : NE, VOIDmode, target, false_rtx);
4413 else
4414 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, target, const0_rtx);
4416 *pmode = cmp_mode;
4419 /* Generate code to indirectly jump to a location given in the rtx LOC. */
4421 void
4422 emit_indirect_jump (rtx loc)
4424 if (!insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate
4425 (loc, Pmode))
4426 loc = copy_to_mode_reg (Pmode, loc);
4428 emit_jump_insn (gen_indirect_jump (loc));
4429 emit_barrier ();
4432 #ifdef HAVE_conditional_move
4434 /* Emit a conditional move instruction if the machine supports one for that
4435 condition and machine mode.
4437 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4438 the mode to use should they be constants. If it is VOIDmode, they cannot
4439 both be constants.
4441 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
4442 should be stored there. MODE is the mode to use should they be constants.
4443 If it is VOIDmode, they cannot both be constants.
4445 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4446 is not supported. */
4449 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
4450 enum machine_mode cmode, rtx op2, rtx op3,
4451 enum machine_mode mode, int unsignedp)
4453 rtx tem, subtarget, comparison, insn;
4454 enum insn_code icode;
4455 enum rtx_code reversed;
4457 /* If one operand is constant, make it the second one. Only do this
4458 if the other operand is not constant as well. */
4460 if (swap_commutative_operands_p (op0, op1))
4462 tem = op0;
4463 op0 = op1;
4464 op1 = tem;
4465 code = swap_condition (code);
4468 /* get_condition will prefer to generate LT and GT even if the old
4469 comparison was against zero, so undo that canonicalization here since
4470 comparisons against zero are cheaper. */
4471 if (code == LT && op1 == const1_rtx)
4472 code = LE, op1 = const0_rtx;
4473 else if (code == GT && op1 == constm1_rtx)
4474 code = GE, op1 = const0_rtx;
4476 if (cmode == VOIDmode)
4477 cmode = GET_MODE (op0);
4479 if (swap_commutative_operands_p (op2, op3)
4480 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4481 != UNKNOWN))
4483 tem = op2;
4484 op2 = op3;
4485 op3 = tem;
4486 code = reversed;
4489 if (mode == VOIDmode)
4490 mode = GET_MODE (op2);
4492 icode = direct_optab_handler (movcc_optab, mode);
4494 if (icode == CODE_FOR_nothing)
4495 return 0;
4497 if (!target)
4498 target = gen_reg_rtx (mode);
4500 subtarget = target;
4502 /* If the insn doesn't accept these operands, put them in pseudos. */
4504 if (!insn_data[icode].operand[0].predicate
4505 (subtarget, insn_data[icode].operand[0].mode))
4506 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4508 if (!insn_data[icode].operand[2].predicate
4509 (op2, insn_data[icode].operand[2].mode))
4510 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4512 if (!insn_data[icode].operand[3].predicate
4513 (op3, insn_data[icode].operand[3].mode))
4514 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4516 /* Everything should now be in the suitable form. */
4518 code = unsignedp ? unsigned_condition (code) : code;
4519 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4521 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4522 return NULL and let the caller figure out how best to deal with this
4523 situation. */
4524 if (!COMPARISON_P (comparison))
4525 return NULL_RTX;
4527 do_pending_stack_adjust ();
4528 start_sequence ();
4529 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4530 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4531 &comparison, &cmode);
4532 if (!comparison)
4533 insn = NULL_RTX;
4534 else
4535 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4537 /* If that failed, then give up. */
4538 if (insn == 0)
4540 end_sequence ();
4541 return 0;
4544 emit_insn (insn);
4545 insn = get_insns ();
4546 end_sequence ();
4547 emit_insn (insn);
4548 if (subtarget != target)
4549 convert_move (target, subtarget, 0);
4551 return target;
4554 /* Return nonzero if a conditional move of mode MODE is supported.
4556 This function is for combine so it can tell whether an insn that looks
4557 like a conditional move is actually supported by the hardware. If we
4558 guess wrong we lose a bit on optimization, but that's it. */
4559 /* ??? sparc64 supports conditionally moving integers values based on fp
4560 comparisons, and vice versa. How do we handle them? */
4563 can_conditionally_move_p (enum machine_mode mode)
4565 if (direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing)
4566 return 1;
4568 return 0;
4571 #endif /* HAVE_conditional_move */
4573 /* Emit a conditional addition instruction if the machine supports one for that
4574 condition and machine mode.
4576 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4577 the mode to use should they be constants. If it is VOIDmode, they cannot
4578 both be constants.
4580 OP2 should be stored in TARGET if the comparison is true, otherwise OP2+OP3
4581 should be stored there. MODE is the mode to use should they be constants.
4582 If it is VOIDmode, they cannot both be constants.
4584 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4585 is not supported. */
4588 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
4589 enum machine_mode cmode, rtx op2, rtx op3,
4590 enum machine_mode mode, int unsignedp)
4592 rtx tem, subtarget, comparison, insn;
4593 enum insn_code icode;
4594 enum rtx_code reversed;
4596 /* If one operand is constant, make it the second one. Only do this
4597 if the other operand is not constant as well. */
4599 if (swap_commutative_operands_p (op0, op1))
4601 tem = op0;
4602 op0 = op1;
4603 op1 = tem;
4604 code = swap_condition (code);
4607 /* get_condition will prefer to generate LT and GT even if the old
4608 comparison was against zero, so undo that canonicalization here since
4609 comparisons against zero are cheaper. */
4610 if (code == LT && op1 == const1_rtx)
4611 code = LE, op1 = const0_rtx;
4612 else if (code == GT && op1 == constm1_rtx)
4613 code = GE, op1 = const0_rtx;
4615 if (cmode == VOIDmode)
4616 cmode = GET_MODE (op0);
4618 if (swap_commutative_operands_p (op2, op3)
4619 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4620 != UNKNOWN))
4622 tem = op2;
4623 op2 = op3;
4624 op3 = tem;
4625 code = reversed;
4628 if (mode == VOIDmode)
4629 mode = GET_MODE (op2);
4631 icode = optab_handler (addcc_optab, mode);
4633 if (icode == CODE_FOR_nothing)
4634 return 0;
4636 if (!target)
4637 target = gen_reg_rtx (mode);
4639 /* If the insn doesn't accept these operands, put them in pseudos. */
4641 if (!insn_data[icode].operand[0].predicate
4642 (target, insn_data[icode].operand[0].mode))
4643 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4644 else
4645 subtarget = target;
4647 if (!insn_data[icode].operand[2].predicate
4648 (op2, insn_data[icode].operand[2].mode))
4649 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4651 if (!insn_data[icode].operand[3].predicate
4652 (op3, insn_data[icode].operand[3].mode))
4653 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4655 /* Everything should now be in the suitable form. */
4657 code = unsignedp ? unsigned_condition (code) : code;
4658 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4660 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4661 return NULL and let the caller figure out how best to deal with this
4662 situation. */
4663 if (!COMPARISON_P (comparison))
4664 return NULL_RTX;
4666 do_pending_stack_adjust ();
4667 start_sequence ();
4668 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4669 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4670 &comparison, &cmode);
4671 if (!comparison)
4672 insn = NULL_RTX;
4673 else
4674 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4676 /* If that failed, then give up. */
4677 if (insn == 0)
4679 end_sequence ();
4680 return 0;
4683 emit_insn (insn);
4684 insn = get_insns ();
4685 end_sequence ();
4686 emit_insn (insn);
4687 if (subtarget != target)
4688 convert_move (target, subtarget, 0);
4690 return target;
4693 /* These functions attempt to generate an insn body, rather than
4694 emitting the insn, but if the gen function already emits them, we
4695 make no attempt to turn them back into naked patterns. */
4697 /* Generate and return an insn body to add Y to X. */
4700 gen_add2_insn (rtx x, rtx y)
4702 int icode = (int) optab_handler (add_optab, GET_MODE (x));
4704 gcc_assert (insn_data[icode].operand[0].predicate
4705 (x, insn_data[icode].operand[0].mode));
4706 gcc_assert (insn_data[icode].operand[1].predicate
4707 (x, insn_data[icode].operand[1].mode));
4708 gcc_assert (insn_data[icode].operand[2].predicate
4709 (y, insn_data[icode].operand[2].mode));
4711 return GEN_FCN (icode) (x, x, y);
4714 /* Generate and return an insn body to add r1 and c,
4715 storing the result in r0. */
4718 gen_add3_insn (rtx r0, rtx r1, rtx c)
4720 int icode = (int) optab_handler (add_optab, GET_MODE (r0));
4722 if (icode == CODE_FOR_nothing
4723 || !(insn_data[icode].operand[0].predicate
4724 (r0, insn_data[icode].operand[0].mode))
4725 || !(insn_data[icode].operand[1].predicate
4726 (r1, insn_data[icode].operand[1].mode))
4727 || !(insn_data[icode].operand[2].predicate
4728 (c, insn_data[icode].operand[2].mode)))
4729 return NULL_RTX;
4731 return GEN_FCN (icode) (r0, r1, c);
4735 have_add2_insn (rtx x, rtx y)
4737 int icode;
4739 gcc_assert (GET_MODE (x) != VOIDmode);
4741 icode = (int) optab_handler (add_optab, GET_MODE (x));
4743 if (icode == CODE_FOR_nothing)
4744 return 0;
4746 if (!(insn_data[icode].operand[0].predicate
4747 (x, insn_data[icode].operand[0].mode))
4748 || !(insn_data[icode].operand[1].predicate
4749 (x, insn_data[icode].operand[1].mode))
4750 || !(insn_data[icode].operand[2].predicate
4751 (y, insn_data[icode].operand[2].mode)))
4752 return 0;
4754 return 1;
4757 /* Generate and return an insn body to subtract Y from X. */
4760 gen_sub2_insn (rtx x, rtx y)
4762 int icode = (int) optab_handler (sub_optab, GET_MODE (x));
4764 gcc_assert (insn_data[icode].operand[0].predicate
4765 (x, insn_data[icode].operand[0].mode));
4766 gcc_assert (insn_data[icode].operand[1].predicate
4767 (x, insn_data[icode].operand[1].mode));
4768 gcc_assert (insn_data[icode].operand[2].predicate
4769 (y, insn_data[icode].operand[2].mode));
4771 return GEN_FCN (icode) (x, x, y);
4774 /* Generate and return an insn body to subtract r1 and c,
4775 storing the result in r0. */
4778 gen_sub3_insn (rtx r0, rtx r1, rtx c)
4780 int icode = (int) optab_handler (sub_optab, GET_MODE (r0));
4782 if (icode == CODE_FOR_nothing
4783 || !(insn_data[icode].operand[0].predicate
4784 (r0, insn_data[icode].operand[0].mode))
4785 || !(insn_data[icode].operand[1].predicate
4786 (r1, insn_data[icode].operand[1].mode))
4787 || !(insn_data[icode].operand[2].predicate
4788 (c, insn_data[icode].operand[2].mode)))
4789 return NULL_RTX;
4791 return GEN_FCN (icode) (r0, r1, c);
4795 have_sub2_insn (rtx x, rtx y)
4797 int icode;
4799 gcc_assert (GET_MODE (x) != VOIDmode);
4801 icode = (int) optab_handler (sub_optab, GET_MODE (x));
4803 if (icode == CODE_FOR_nothing)
4804 return 0;
4806 if (!(insn_data[icode].operand[0].predicate
4807 (x, insn_data[icode].operand[0].mode))
4808 || !(insn_data[icode].operand[1].predicate
4809 (x, insn_data[icode].operand[1].mode))
4810 || !(insn_data[icode].operand[2].predicate
4811 (y, insn_data[icode].operand[2].mode)))
4812 return 0;
4814 return 1;
4817 /* Generate the body of an instruction to copy Y into X.
4818 It may be a list of insns, if one insn isn't enough. */
4821 gen_move_insn (rtx x, rtx y)
4823 rtx seq;
4825 start_sequence ();
4826 emit_move_insn_1 (x, y);
4827 seq = get_insns ();
4828 end_sequence ();
4829 return seq;
4832 /* Return the insn code used to extend FROM_MODE to TO_MODE.
4833 UNSIGNEDP specifies zero-extension instead of sign-extension. If
4834 no such operation exists, CODE_FOR_nothing will be returned. */
4836 enum insn_code
4837 can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
4838 int unsignedp)
4840 convert_optab tab;
4841 #ifdef HAVE_ptr_extend
4842 if (unsignedp < 0)
4843 return CODE_FOR_ptr_extend;
4844 #endif
4846 tab = unsignedp ? zext_optab : sext_optab;
4847 return convert_optab_handler (tab, to_mode, from_mode);
4850 /* Generate the body of an insn to extend Y (with mode MFROM)
4851 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
4854 gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
4855 enum machine_mode mfrom, int unsignedp)
4857 enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
4858 return GEN_FCN (icode) (x, y);
4861 /* can_fix_p and can_float_p say whether the target machine
4862 can directly convert a given fixed point type to
4863 a given floating point type, or vice versa.
4864 The returned value is the CODE_FOR_... value to use,
4865 or CODE_FOR_nothing if these modes cannot be directly converted.
4867 *TRUNCP_PTR is set to 1 if it is necessary to output
4868 an explicit FTRUNC insn before the fix insn; otherwise 0. */
4870 static enum insn_code
4871 can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
4872 int unsignedp, int *truncp_ptr)
4874 convert_optab tab;
4875 enum insn_code icode;
4877 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
4878 icode = convert_optab_handler (tab, fixmode, fltmode);
4879 if (icode != CODE_FOR_nothing)
4881 *truncp_ptr = 0;
4882 return icode;
4885 /* FIXME: This requires a port to define both FIX and FTRUNC pattern
4886 for this to work. We need to rework the fix* and ftrunc* patterns
4887 and documentation. */
4888 tab = unsignedp ? ufix_optab : sfix_optab;
4889 icode = convert_optab_handler (tab, fixmode, fltmode);
4890 if (icode != CODE_FOR_nothing
4891 && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
4893 *truncp_ptr = 1;
4894 return icode;
4897 *truncp_ptr = 0;
4898 return CODE_FOR_nothing;
4901 static enum insn_code
4902 can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
4903 int unsignedp)
4905 convert_optab tab;
4907 tab = unsignedp ? ufloat_optab : sfloat_optab;
4908 return convert_optab_handler (tab, fltmode, fixmode);
4911 /* Generate code to convert FROM to floating point
4912 and store in TO. FROM must be fixed point and not VOIDmode.
4913 UNSIGNEDP nonzero means regard FROM as unsigned.
4914 Normally this is done by correcting the final value
4915 if it is negative. */
4917 void
4918 expand_float (rtx to, rtx from, int unsignedp)
4920 enum insn_code icode;
4921 rtx target = to;
4922 enum machine_mode fmode, imode;
4923 bool can_do_signed = false;
4925 /* Crash now, because we won't be able to decide which mode to use. */
4926 gcc_assert (GET_MODE (from) != VOIDmode);
4928 /* Look for an insn to do the conversion. Do it in the specified
4929 modes if possible; otherwise convert either input, output or both to
4930 wider mode. If the integer mode is wider than the mode of FROM,
4931 we can do the conversion signed even if the input is unsigned. */
4933 for (fmode = GET_MODE (to); fmode != VOIDmode;
4934 fmode = GET_MODE_WIDER_MODE (fmode))
4935 for (imode = GET_MODE (from); imode != VOIDmode;
4936 imode = GET_MODE_WIDER_MODE (imode))
4938 int doing_unsigned = unsignedp;
4940 if (fmode != GET_MODE (to)
4941 && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
4942 continue;
4944 icode = can_float_p (fmode, imode, unsignedp);
4945 if (icode == CODE_FOR_nothing && unsignedp)
4947 enum insn_code scode = can_float_p (fmode, imode, 0);
4948 if (scode != CODE_FOR_nothing)
4949 can_do_signed = true;
4950 if (imode != GET_MODE (from))
4951 icode = scode, doing_unsigned = 0;
4954 if (icode != CODE_FOR_nothing)
4956 if (imode != GET_MODE (from))
4957 from = convert_to_mode (imode, from, unsignedp);
4959 if (fmode != GET_MODE (to))
4960 target = gen_reg_rtx (fmode);
4962 emit_unop_insn (icode, target, from,
4963 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
4965 if (target != to)
4966 convert_move (to, target, 0);
4967 return;
4971 /* Unsigned integer, and no way to convert directly. Convert as signed,
4972 then unconditionally adjust the result. */
4973 if (unsignedp && can_do_signed)
4975 rtx label = gen_label_rtx ();
4976 rtx temp;
4977 REAL_VALUE_TYPE offset;
4979 /* Look for a usable floating mode FMODE wider than the source and at
4980 least as wide as the target. Using FMODE will avoid rounding woes
4981 with unsigned values greater than the signed maximum value. */
4983 for (fmode = GET_MODE (to); fmode != VOIDmode;
4984 fmode = GET_MODE_WIDER_MODE (fmode))
4985 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
4986 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
4987 break;
4989 if (fmode == VOIDmode)
4991 /* There is no such mode. Pretend the target is wide enough. */
4992 fmode = GET_MODE (to);
4994 /* Avoid double-rounding when TO is narrower than FROM. */
4995 if ((significand_size (fmode) + 1)
4996 < GET_MODE_BITSIZE (GET_MODE (from)))
4998 rtx temp1;
4999 rtx neglabel = gen_label_rtx ();
5001 /* Don't use TARGET if it isn't a register, is a hard register,
5002 or is the wrong mode. */
5003 if (!REG_P (target)
5004 || REGNO (target) < FIRST_PSEUDO_REGISTER
5005 || GET_MODE (target) != fmode)
5006 target = gen_reg_rtx (fmode);
5008 imode = GET_MODE (from);
5009 do_pending_stack_adjust ();
5011 /* Test whether the sign bit is set. */
5012 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
5013 0, neglabel);
5015 /* The sign bit is not set. Convert as signed. */
5016 expand_float (target, from, 0);
5017 emit_jump_insn (gen_jump (label));
5018 emit_barrier ();
5020 /* The sign bit is set.
5021 Convert to a usable (positive signed) value by shifting right
5022 one bit, while remembering if a nonzero bit was shifted
5023 out; i.e., compute (from & 1) | (from >> 1). */
5025 emit_label (neglabel);
5026 temp = expand_binop (imode, and_optab, from, const1_rtx,
5027 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5028 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
5029 NULL_RTX, 1);
5030 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
5031 OPTAB_LIB_WIDEN);
5032 expand_float (target, temp, 0);
5034 /* Multiply by 2 to undo the shift above. */
5035 temp = expand_binop (fmode, add_optab, target, target,
5036 target, 0, OPTAB_LIB_WIDEN);
5037 if (temp != target)
5038 emit_move_insn (target, temp);
5040 do_pending_stack_adjust ();
5041 emit_label (label);
5042 goto done;
5046 /* If we are about to do some arithmetic to correct for an
5047 unsigned operand, do it in a pseudo-register. */
5049 if (GET_MODE (to) != fmode
5050 || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
5051 target = gen_reg_rtx (fmode);
5053 /* Convert as signed integer to floating. */
5054 expand_float (target, from, 0);
5056 /* If FROM is negative (and therefore TO is negative),
5057 correct its value by 2**bitwidth. */
5059 do_pending_stack_adjust ();
5060 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
5061 0, label);
5064 real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)), fmode);
5065 temp = expand_binop (fmode, add_optab, target,
5066 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
5067 target, 0, OPTAB_LIB_WIDEN);
5068 if (temp != target)
5069 emit_move_insn (target, temp);
5071 do_pending_stack_adjust ();
5072 emit_label (label);
5073 goto done;
5076 /* No hardware instruction available; call a library routine. */
5078 rtx libfunc;
5079 rtx insns;
5080 rtx value;
5081 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
5083 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
5084 from = convert_to_mode (SImode, from, unsignedp);
5086 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5087 gcc_assert (libfunc);
5089 start_sequence ();
5091 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5092 GET_MODE (to), 1, from,
5093 GET_MODE (from));
5094 insns = get_insns ();
5095 end_sequence ();
5097 emit_libcall_block (insns, target, value,
5098 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FLOAT : FLOAT,
5099 GET_MODE (to), from));
5102 done:
5104 /* Copy result to requested destination
5105 if we have been computing in a temp location. */
5107 if (target != to)
5109 if (GET_MODE (target) == GET_MODE (to))
5110 emit_move_insn (to, target);
5111 else
5112 convert_move (to, target, 0);
5116 /* Generate code to convert FROM to fixed point and store in TO. FROM
5117 must be floating point. */
5119 void
5120 expand_fix (rtx to, rtx from, int unsignedp)
5122 enum insn_code icode;
5123 rtx target = to;
5124 enum machine_mode fmode, imode;
5125 int must_trunc = 0;
5127 /* We first try to find a pair of modes, one real and one integer, at
5128 least as wide as FROM and TO, respectively, in which we can open-code
5129 this conversion. If the integer mode is wider than the mode of TO,
5130 we can do the conversion either signed or unsigned. */
5132 for (fmode = GET_MODE (from); fmode != VOIDmode;
5133 fmode = GET_MODE_WIDER_MODE (fmode))
5134 for (imode = GET_MODE (to); imode != VOIDmode;
5135 imode = GET_MODE_WIDER_MODE (imode))
5137 int doing_unsigned = unsignedp;
5139 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
5140 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
5141 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
5143 if (icode != CODE_FOR_nothing)
5145 rtx last = get_last_insn ();
5146 if (fmode != GET_MODE (from))
5147 from = convert_to_mode (fmode, from, 0);
5149 if (must_trunc)
5151 rtx temp = gen_reg_rtx (GET_MODE (from));
5152 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
5153 temp, 0);
5156 if (imode != GET_MODE (to))
5157 target = gen_reg_rtx (imode);
5159 if (maybe_emit_unop_insn (icode, target, from,
5160 doing_unsigned ? UNSIGNED_FIX : FIX))
5162 if (target != to)
5163 convert_move (to, target, unsignedp);
5164 return;
5166 delete_insns_since (last);
5170 /* For an unsigned conversion, there is one more way to do it.
5171 If we have a signed conversion, we generate code that compares
5172 the real value to the largest representable positive number. If if
5173 is smaller, the conversion is done normally. Otherwise, subtract
5174 one plus the highest signed number, convert, and add it back.
5176 We only need to check all real modes, since we know we didn't find
5177 anything with a wider integer mode.
5179 This code used to extend FP value into mode wider than the destination.
5180 This is needed for decimal float modes which cannot accurately
5181 represent one plus the highest signed number of the same size, but
5182 not for binary modes. Consider, for instance conversion from SFmode
5183 into DImode.
5185 The hot path through the code is dealing with inputs smaller than 2^63
5186 and doing just the conversion, so there is no bits to lose.
5188 In the other path we know the value is positive in the range 2^63..2^64-1
5189 inclusive. (as for other input overflow happens and result is undefined)
5190 So we know that the most important bit set in mantissa corresponds to
5191 2^63. The subtraction of 2^63 should not generate any rounding as it
5192 simply clears out that bit. The rest is trivial. */
5194 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
5195 for (fmode = GET_MODE (from); fmode != VOIDmode;
5196 fmode = GET_MODE_WIDER_MODE (fmode))
5197 if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc)
5198 && (!DECIMAL_FLOAT_MODE_P (fmode)
5199 || GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))))
5201 int bitsize;
5202 REAL_VALUE_TYPE offset;
5203 rtx limit, lab1, lab2, insn;
5205 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
5206 real_2expN (&offset, bitsize - 1, fmode);
5207 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
5208 lab1 = gen_label_rtx ();
5209 lab2 = gen_label_rtx ();
5211 if (fmode != GET_MODE (from))
5212 from = convert_to_mode (fmode, from, 0);
5214 /* See if we need to do the subtraction. */
5215 do_pending_stack_adjust ();
5216 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
5217 0, lab1);
5219 /* If not, do the signed "fix" and branch around fixup code. */
5220 expand_fix (to, from, 0);
5221 emit_jump_insn (gen_jump (lab2));
5222 emit_barrier ();
5224 /* Otherwise, subtract 2**(N-1), convert to signed number,
5225 then add 2**(N-1). Do the addition using XOR since this
5226 will often generate better code. */
5227 emit_label (lab1);
5228 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
5229 NULL_RTX, 0, OPTAB_LIB_WIDEN);
5230 expand_fix (to, target, 0);
5231 target = expand_binop (GET_MODE (to), xor_optab, to,
5232 gen_int_mode
5233 ((HOST_WIDE_INT) 1 << (bitsize - 1),
5234 GET_MODE (to)),
5235 to, 1, OPTAB_LIB_WIDEN);
5237 if (target != to)
5238 emit_move_insn (to, target);
5240 emit_label (lab2);
5242 if (optab_handler (mov_optab, GET_MODE (to)) != CODE_FOR_nothing)
5244 /* Make a place for a REG_NOTE and add it. */
5245 insn = emit_move_insn (to, to);
5246 set_unique_reg_note (insn,
5247 REG_EQUAL,
5248 gen_rtx_fmt_e (UNSIGNED_FIX,
5249 GET_MODE (to),
5250 copy_rtx (from)));
5253 return;
5256 /* We can't do it with an insn, so use a library call. But first ensure
5257 that the mode of TO is at least as wide as SImode, since those are the
5258 only library calls we know about. */
5260 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
5262 target = gen_reg_rtx (SImode);
5264 expand_fix (target, from, unsignedp);
5266 else
5268 rtx insns;
5269 rtx value;
5270 rtx libfunc;
5272 convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
5273 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5274 gcc_assert (libfunc);
5276 start_sequence ();
5278 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5279 GET_MODE (to), 1, from,
5280 GET_MODE (from));
5281 insns = get_insns ();
5282 end_sequence ();
5284 emit_libcall_block (insns, target, value,
5285 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
5286 GET_MODE (to), from));
5289 if (target != to)
5291 if (GET_MODE (to) == GET_MODE (target))
5292 emit_move_insn (to, target);
5293 else
5294 convert_move (to, target, 0);
5298 /* Generate code to convert FROM or TO a fixed-point.
5299 If UINTP is true, either TO or FROM is an unsigned integer.
5300 If SATP is true, we need to saturate the result. */
5302 void
5303 expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
5305 enum machine_mode to_mode = GET_MODE (to);
5306 enum machine_mode from_mode = GET_MODE (from);
5307 convert_optab tab;
5308 enum rtx_code this_code;
5309 enum insn_code code;
5310 rtx insns, value;
5311 rtx libfunc;
5313 if (to_mode == from_mode)
5315 emit_move_insn (to, from);
5316 return;
5319 if (uintp)
5321 tab = satp ? satfractuns_optab : fractuns_optab;
5322 this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
5324 else
5326 tab = satp ? satfract_optab : fract_optab;
5327 this_code = satp ? SAT_FRACT : FRACT_CONVERT;
5329 code = convert_optab_handler (tab, to_mode, from_mode);
5330 if (code != CODE_FOR_nothing)
5332 emit_unop_insn (code, to, from, this_code);
5333 return;
5336 libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
5337 gcc_assert (libfunc);
5339 start_sequence ();
5340 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
5341 1, from, from_mode);
5342 insns = get_insns ();
5343 end_sequence ();
5345 emit_libcall_block (insns, to, value,
5346 gen_rtx_fmt_e (tab->code, to_mode, from));
5349 /* Generate code to convert FROM to fixed point and store in TO. FROM
5350 must be floating point, TO must be signed. Use the conversion optab
5351 TAB to do the conversion. */
5353 bool
5354 expand_sfix_optab (rtx to, rtx from, convert_optab tab)
5356 enum insn_code icode;
5357 rtx target = to;
5358 enum machine_mode fmode, imode;
5360 /* We first try to find a pair of modes, one real and one integer, at
5361 least as wide as FROM and TO, respectively, in which we can open-code
5362 this conversion. If the integer mode is wider than the mode of TO,
5363 we can do the conversion either signed or unsigned. */
5365 for (fmode = GET_MODE (from); fmode != VOIDmode;
5366 fmode = GET_MODE_WIDER_MODE (fmode))
5367 for (imode = GET_MODE (to); imode != VOIDmode;
5368 imode = GET_MODE_WIDER_MODE (imode))
5370 icode = convert_optab_handler (tab, imode, fmode);
5371 if (icode != CODE_FOR_nothing)
5373 rtx last = get_last_insn ();
5374 if (fmode != GET_MODE (from))
5375 from = convert_to_mode (fmode, from, 0);
5377 if (imode != GET_MODE (to))
5378 target = gen_reg_rtx (imode);
5380 if (!maybe_emit_unop_insn (icode, target, from, UNKNOWN))
5382 delete_insns_since (last);
5383 continue;
5385 if (target != to)
5386 convert_move (to, target, 0);
5387 return true;
5391 return false;
5394 /* Report whether we have an instruction to perform the operation
5395 specified by CODE on operands of mode MODE. */
5397 have_insn_for (enum rtx_code code, enum machine_mode mode)
5399 return (code_to_optab[(int) code] != 0
5400 && (optab_handler (code_to_optab[(int) code], mode)
5401 != CODE_FOR_nothing));
5404 /* Set all insn_code fields to CODE_FOR_nothing. */
5406 static void
5407 init_insn_codes (void)
5409 memset (optab_table, 0, sizeof (optab_table));
5410 memset (convert_optab_table, 0, sizeof (convert_optab_table));
5411 memset (direct_optab_table, 0, sizeof (direct_optab_table));
5414 /* Initialize OP's code to CODE, and write it into the code_to_optab table. */
5415 static inline void
5416 init_optab (optab op, enum rtx_code code)
5418 op->code = code;
5419 code_to_optab[(int) code] = op;
5422 /* Same, but fill in its code as CODE, and do _not_ write it into
5423 the code_to_optab table. */
5424 static inline void
5425 init_optabv (optab op, enum rtx_code code)
5427 op->code = code;
5430 /* Conversion optabs never go in the code_to_optab table. */
5431 static void
5432 init_convert_optab (convert_optab op, enum rtx_code code)
5434 op->code = code;
5437 /* Initialize the libfunc fields of an entire group of entries in some
5438 optab. Each entry is set equal to a string consisting of a leading
5439 pair of underscores followed by a generic operation name followed by
5440 a mode name (downshifted to lowercase) followed by a single character
5441 representing the number of operands for the given operation (which is
5442 usually one of the characters '2', '3', or '4').
5444 OPTABLE is the table in which libfunc fields are to be initialized.
5445 OPNAME is the generic (string) name of the operation.
5446 SUFFIX is the character which specifies the number of operands for
5447 the given generic operation.
5448 MODE is the mode to generate for.
5451 static void
5452 gen_libfunc (optab optable, const char *opname, int suffix, enum machine_mode mode)
5454 unsigned opname_len = strlen (opname);
5455 const char *mname = GET_MODE_NAME (mode);
5456 unsigned mname_len = strlen (mname);
5457 char *libfunc_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5458 char *p;
5459 const char *q;
5461 p = libfunc_name;
5462 *p++ = '_';
5463 *p++ = '_';
5464 for (q = opname; *q; )
5465 *p++ = *q++;
5466 for (q = mname; *q; q++)
5467 *p++ = TOLOWER (*q);
5468 *p++ = suffix;
5469 *p = '\0';
5471 set_optab_libfunc (optable, mode,
5472 ggc_alloc_string (libfunc_name, p - libfunc_name));
5475 /* Like gen_libfunc, but verify that integer operation is involved. */
5477 static void
5478 gen_int_libfunc (optab optable, const char *opname, char suffix,
5479 enum machine_mode mode)
5481 int maxsize = 2 * BITS_PER_WORD;
5483 if (GET_MODE_CLASS (mode) != MODE_INT)
5484 return;
5485 if (maxsize < LONG_LONG_TYPE_SIZE)
5486 maxsize = LONG_LONG_TYPE_SIZE;
5487 if (GET_MODE_CLASS (mode) != MODE_INT
5488 || mode < word_mode || GET_MODE_BITSIZE (mode) > maxsize)
5489 return;
5490 gen_libfunc (optable, opname, suffix, mode);
5493 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed. */
5495 static void
5496 gen_fp_libfunc (optab optable, const char *opname, char suffix,
5497 enum machine_mode mode)
5499 char *dec_opname;
5501 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
5502 gen_libfunc (optable, opname, suffix, mode);
5503 if (DECIMAL_FLOAT_MODE_P (mode))
5505 dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
5506 /* For BID support, change the name to have either a bid_ or dpd_ prefix
5507 depending on the low level floating format used. */
5508 memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
5509 strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
5510 gen_libfunc (optable, dec_opname, suffix, mode);
5514 /* Like gen_libfunc, but verify that fixed-point operation is involved. */
5516 static void
5517 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
5518 enum machine_mode mode)
5520 if (!ALL_FIXED_POINT_MODE_P (mode))
5521 return;
5522 gen_libfunc (optable, opname, suffix, mode);
5525 /* Like gen_libfunc, but verify that signed fixed-point operation is
5526 involved. */
5528 static void
5529 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
5530 enum machine_mode mode)
5532 if (!SIGNED_FIXED_POINT_MODE_P (mode))
5533 return;
5534 gen_libfunc (optable, opname, suffix, mode);
5537 /* Like gen_libfunc, but verify that unsigned fixed-point operation is
5538 involved. */
5540 static void
5541 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
5542 enum machine_mode mode)
5544 if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
5545 return;
5546 gen_libfunc (optable, opname, suffix, mode);
5549 /* Like gen_libfunc, but verify that FP or INT operation is involved. */
5551 static void
5552 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
5553 enum machine_mode mode)
5555 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5556 gen_fp_libfunc (optable, name, suffix, mode);
5557 if (INTEGRAL_MODE_P (mode))
5558 gen_int_libfunc (optable, name, suffix, mode);
5561 /* Like gen_libfunc, but verify that FP or INT operation is involved
5562 and add 'v' suffix for integer operation. */
5564 static void
5565 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
5566 enum machine_mode mode)
5568 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5569 gen_fp_libfunc (optable, name, suffix, mode);
5570 if (GET_MODE_CLASS (mode) == MODE_INT)
5572 int len = strlen (name);
5573 char *v_name = XALLOCAVEC (char, len + 2);
5574 strcpy (v_name, name);
5575 v_name[len] = 'v';
5576 v_name[len + 1] = 0;
5577 gen_int_libfunc (optable, v_name, suffix, mode);
5581 /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
5582 involved. */
5584 static void
5585 gen_int_fp_fixed_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 (INTEGRAL_MODE_P (mode))
5591 gen_int_libfunc (optable, name, suffix, mode);
5592 if (ALL_FIXED_POINT_MODE_P (mode))
5593 gen_fixed_libfunc (optable, name, suffix, mode);
5596 /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
5597 involved. */
5599 static void
5600 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5601 enum machine_mode mode)
5603 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5604 gen_fp_libfunc (optable, name, suffix, mode);
5605 if (INTEGRAL_MODE_P (mode))
5606 gen_int_libfunc (optable, name, suffix, mode);
5607 if (SIGNED_FIXED_POINT_MODE_P (mode))
5608 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5611 /* Like gen_libfunc, but verify that INT or FIXED operation is
5612 involved. */
5614 static void
5615 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
5616 enum machine_mode mode)
5618 if (INTEGRAL_MODE_P (mode))
5619 gen_int_libfunc (optable, name, suffix, mode);
5620 if (ALL_FIXED_POINT_MODE_P (mode))
5621 gen_fixed_libfunc (optable, name, suffix, mode);
5624 /* Like gen_libfunc, but verify that INT or signed FIXED operation is
5625 involved. */
5627 static void
5628 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5629 enum machine_mode mode)
5631 if (INTEGRAL_MODE_P (mode))
5632 gen_int_libfunc (optable, name, suffix, mode);
5633 if (SIGNED_FIXED_POINT_MODE_P (mode))
5634 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5637 /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
5638 involved. */
5640 static void
5641 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
5642 enum machine_mode mode)
5644 if (INTEGRAL_MODE_P (mode))
5645 gen_int_libfunc (optable, name, suffix, mode);
5646 if (UNSIGNED_FIXED_POINT_MODE_P (mode))
5647 gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
5650 /* Initialize the libfunc fields of an entire group of entries of an
5651 inter-mode-class conversion optab. The string formation rules are
5652 similar to the ones for init_libfuncs, above, but instead of having
5653 a mode name and an operand count these functions have two mode names
5654 and no operand count. */
5656 static void
5657 gen_interclass_conv_libfunc (convert_optab tab,
5658 const char *opname,
5659 enum machine_mode tmode,
5660 enum machine_mode fmode)
5662 size_t opname_len = strlen (opname);
5663 size_t mname_len = 0;
5665 const char *fname, *tname;
5666 const char *q;
5667 char *libfunc_name, *suffix;
5668 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5669 char *p;
5671 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5672 depends on which underlying decimal floating point format is used. */
5673 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5675 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5677 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5678 nondec_name[0] = '_';
5679 nondec_name[1] = '_';
5680 memcpy (&nondec_name[2], opname, opname_len);
5681 nondec_suffix = nondec_name + opname_len + 2;
5683 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5684 dec_name[0] = '_';
5685 dec_name[1] = '_';
5686 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5687 memcpy (&dec_name[2+dec_len], opname, opname_len);
5688 dec_suffix = dec_name + dec_len + opname_len + 2;
5690 fname = GET_MODE_NAME (fmode);
5691 tname = GET_MODE_NAME (tmode);
5693 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5695 libfunc_name = dec_name;
5696 suffix = dec_suffix;
5698 else
5700 libfunc_name = nondec_name;
5701 suffix = nondec_suffix;
5704 p = suffix;
5705 for (q = fname; *q; p++, q++)
5706 *p = TOLOWER (*q);
5707 for (q = tname; *q; p++, q++)
5708 *p = TOLOWER (*q);
5710 *p = '\0';
5712 set_conv_libfunc (tab, tmode, fmode,
5713 ggc_alloc_string (libfunc_name, p - libfunc_name));
5716 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5717 int->fp conversion. */
5719 static void
5720 gen_int_to_fp_conv_libfunc (convert_optab tab,
5721 const char *opname,
5722 enum machine_mode tmode,
5723 enum machine_mode fmode)
5725 if (GET_MODE_CLASS (fmode) != MODE_INT)
5726 return;
5727 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5728 return;
5729 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5732 /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
5733 naming scheme. */
5735 static void
5736 gen_ufloat_conv_libfunc (convert_optab tab,
5737 const char *opname ATTRIBUTE_UNUSED,
5738 enum machine_mode tmode,
5739 enum machine_mode fmode)
5741 if (DECIMAL_FLOAT_MODE_P (tmode))
5742 gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
5743 else
5744 gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
5747 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5748 fp->int conversion. */
5750 static void
5751 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
5752 const char *opname,
5753 enum machine_mode tmode,
5754 enum machine_mode fmode)
5756 if (GET_MODE_CLASS (fmode) != MODE_INT)
5757 return;
5758 if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
5759 return;
5760 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5763 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5764 fp->int conversion with no decimal floating point involved. */
5766 static void
5767 gen_fp_to_int_conv_libfunc (convert_optab tab,
5768 const char *opname,
5769 enum machine_mode tmode,
5770 enum machine_mode fmode)
5772 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5773 return;
5774 if (GET_MODE_CLASS (tmode) != MODE_INT)
5775 return;
5776 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5779 /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
5780 The string formation rules are
5781 similar to the ones for init_libfunc, above. */
5783 static void
5784 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
5785 enum machine_mode tmode, enum machine_mode fmode)
5787 size_t opname_len = strlen (opname);
5788 size_t mname_len = 0;
5790 const char *fname, *tname;
5791 const char *q;
5792 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5793 char *libfunc_name, *suffix;
5794 char *p;
5796 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5797 depends on which underlying decimal floating point format is used. */
5798 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5800 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5802 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5803 nondec_name[0] = '_';
5804 nondec_name[1] = '_';
5805 memcpy (&nondec_name[2], opname, opname_len);
5806 nondec_suffix = nondec_name + opname_len + 2;
5808 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5809 dec_name[0] = '_';
5810 dec_name[1] = '_';
5811 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5812 memcpy (&dec_name[2 + dec_len], opname, opname_len);
5813 dec_suffix = dec_name + dec_len + opname_len + 2;
5815 fname = GET_MODE_NAME (fmode);
5816 tname = GET_MODE_NAME (tmode);
5818 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5820 libfunc_name = dec_name;
5821 suffix = dec_suffix;
5823 else
5825 libfunc_name = nondec_name;
5826 suffix = nondec_suffix;
5829 p = suffix;
5830 for (q = fname; *q; p++, q++)
5831 *p = TOLOWER (*q);
5832 for (q = tname; *q; p++, q++)
5833 *p = TOLOWER (*q);
5835 *p++ = '2';
5836 *p = '\0';
5838 set_conv_libfunc (tab, tmode, fmode,
5839 ggc_alloc_string (libfunc_name, p - libfunc_name));
5842 /* Pick proper libcall for trunc_optab. We need to chose if we do
5843 truncation or extension and interclass or intraclass. */
5845 static void
5846 gen_trunc_conv_libfunc (convert_optab tab,
5847 const char *opname,
5848 enum machine_mode tmode,
5849 enum machine_mode fmode)
5851 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5852 return;
5853 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5854 return;
5855 if (tmode == fmode)
5856 return;
5858 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5859 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5860 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5862 if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
5863 return;
5865 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5866 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5867 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5868 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5871 /* Pick proper libcall for extend_optab. We need to chose if we do
5872 truncation or extension and interclass or intraclass. */
5874 static void
5875 gen_extend_conv_libfunc (convert_optab tab,
5876 const char *opname ATTRIBUTE_UNUSED,
5877 enum machine_mode tmode,
5878 enum machine_mode fmode)
5880 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5881 return;
5882 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5883 return;
5884 if (tmode == fmode)
5885 return;
5887 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5888 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5889 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5891 if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
5892 return;
5894 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5895 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5896 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5897 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5900 /* Pick proper libcall for fract_optab. We need to chose if we do
5901 interclass or intraclass. */
5903 static void
5904 gen_fract_conv_libfunc (convert_optab tab,
5905 const char *opname,
5906 enum machine_mode tmode,
5907 enum machine_mode fmode)
5909 if (tmode == fmode)
5910 return;
5911 if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
5912 return;
5914 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
5915 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5916 else
5917 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5920 /* Pick proper libcall for fractuns_optab. */
5922 static void
5923 gen_fractuns_conv_libfunc (convert_optab tab,
5924 const char *opname,
5925 enum machine_mode tmode,
5926 enum machine_mode fmode)
5928 if (tmode == fmode)
5929 return;
5930 /* One mode must be a fixed-point mode, and the other must be an integer
5931 mode. */
5932 if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
5933 || (ALL_FIXED_POINT_MODE_P (fmode)
5934 && GET_MODE_CLASS (tmode) == MODE_INT)))
5935 return;
5937 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5940 /* Pick proper libcall for satfract_optab. We need to chose if we do
5941 interclass or intraclass. */
5943 static void
5944 gen_satfract_conv_libfunc (convert_optab tab,
5945 const char *opname,
5946 enum machine_mode tmode,
5947 enum machine_mode fmode)
5949 if (tmode == fmode)
5950 return;
5951 /* TMODE must be a fixed-point mode. */
5952 if (!ALL_FIXED_POINT_MODE_P (tmode))
5953 return;
5955 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
5956 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5957 else
5958 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5961 /* Pick proper libcall for satfractuns_optab. */
5963 static void
5964 gen_satfractuns_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, and FMODE must be an integer mode. */
5972 if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
5973 return;
5975 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5978 /* A table of previously-created libfuncs, hashed by name. */
5979 static GTY ((param_is (union tree_node))) htab_t libfunc_decls;
5981 /* Hashtable callbacks for libfunc_decls. */
5983 static hashval_t
5984 libfunc_decl_hash (const void *entry)
5986 return IDENTIFIER_HASH_VALUE (DECL_NAME ((const_tree) entry));
5989 static int
5990 libfunc_decl_eq (const void *entry1, const void *entry2)
5992 return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
5995 /* Build a decl for a libfunc named NAME. */
5997 tree
5998 build_libfunc_function (const char *name)
6000 tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
6001 get_identifier (name),
6002 build_function_type (integer_type_node, NULL_TREE));
6003 /* ??? We don't have any type information except for this is
6004 a function. Pretend this is "int foo()". */
6005 DECL_ARTIFICIAL (decl) = 1;
6006 DECL_EXTERNAL (decl) = 1;
6007 TREE_PUBLIC (decl) = 1;
6008 gcc_assert (DECL_ASSEMBLER_NAME (decl));
6010 /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
6011 are the flags assigned by targetm.encode_section_info. */
6012 SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
6014 return decl;
6018 init_one_libfunc (const char *name)
6020 tree id, decl;
6021 void **slot;
6022 hashval_t hash;
6024 if (libfunc_decls == NULL)
6025 libfunc_decls = htab_create_ggc (37, libfunc_decl_hash,
6026 libfunc_decl_eq, NULL);
6028 /* See if we have already created a libfunc decl for this function. */
6029 id = get_identifier (name);
6030 hash = IDENTIFIER_HASH_VALUE (id);
6031 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, INSERT);
6032 decl = (tree) *slot;
6033 if (decl == NULL)
6035 /* Create a new decl, so that it can be passed to
6036 targetm.encode_section_info. */
6037 decl = build_libfunc_function (name);
6038 *slot = decl;
6040 return XEXP (DECL_RTL (decl), 0);
6043 /* Adjust the assembler name of libfunc NAME to ASMSPEC. */
6046 set_user_assembler_libfunc (const char *name, const char *asmspec)
6048 tree id, decl;
6049 void **slot;
6050 hashval_t hash;
6052 id = get_identifier (name);
6053 hash = IDENTIFIER_HASH_VALUE (id);
6054 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, NO_INSERT);
6055 gcc_assert (slot);
6056 decl = (tree) *slot;
6057 set_user_assembler_name (decl, asmspec);
6058 return XEXP (DECL_RTL (decl), 0);
6061 /* Call this to reset the function entry for one optab (OPTABLE) in mode
6062 MODE to NAME, which should be either 0 or a string constant. */
6063 void
6064 set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
6066 rtx val;
6067 struct libfunc_entry e;
6068 struct libfunc_entry **slot;
6069 e.optab = (size_t) (optable - &optab_table[0]);
6070 e.mode1 = mode;
6071 e.mode2 = VOIDmode;
6073 if (name)
6074 val = init_one_libfunc (name);
6075 else
6076 val = 0;
6077 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6078 if (*slot == NULL)
6079 *slot = ggc_alloc_libfunc_entry ();
6080 (*slot)->optab = (size_t) (optable - &optab_table[0]);
6081 (*slot)->mode1 = mode;
6082 (*slot)->mode2 = VOIDmode;
6083 (*slot)->libfunc = val;
6086 /* Call this to reset the function entry for one conversion optab
6087 (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
6088 either 0 or a string constant. */
6089 void
6090 set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
6091 enum machine_mode fmode, const char *name)
6093 rtx val;
6094 struct libfunc_entry e;
6095 struct libfunc_entry **slot;
6096 e.optab = (size_t) (optable - &convert_optab_table[0]);
6097 e.mode1 = tmode;
6098 e.mode2 = fmode;
6100 if (name)
6101 val = init_one_libfunc (name);
6102 else
6103 val = 0;
6104 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6105 if (*slot == NULL)
6106 *slot = ggc_alloc_libfunc_entry ();
6107 (*slot)->optab = (size_t) (optable - &convert_optab_table[0]);
6108 (*slot)->mode1 = tmode;
6109 (*slot)->mode2 = fmode;
6110 (*slot)->libfunc = val;
6113 /* Call this to initialize the contents of the optabs
6114 appropriately for the current target machine. */
6116 void
6117 init_optabs (void)
6119 if (libfunc_hash)
6121 htab_empty (libfunc_hash);
6122 /* We statically initialize the insn_codes with the equivalent of
6123 CODE_FOR_nothing. Repeat the process if reinitialising. */
6124 init_insn_codes ();
6126 else
6127 libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
6129 init_optab (add_optab, PLUS);
6130 init_optabv (addv_optab, PLUS);
6131 init_optab (sub_optab, MINUS);
6132 init_optabv (subv_optab, MINUS);
6133 init_optab (ssadd_optab, SS_PLUS);
6134 init_optab (usadd_optab, US_PLUS);
6135 init_optab (sssub_optab, SS_MINUS);
6136 init_optab (ussub_optab, US_MINUS);
6137 init_optab (smul_optab, MULT);
6138 init_optab (ssmul_optab, SS_MULT);
6139 init_optab (usmul_optab, US_MULT);
6140 init_optabv (smulv_optab, MULT);
6141 init_optab (smul_highpart_optab, UNKNOWN);
6142 init_optab (umul_highpart_optab, UNKNOWN);
6143 init_optab (smul_widen_optab, UNKNOWN);
6144 init_optab (umul_widen_optab, UNKNOWN);
6145 init_optab (usmul_widen_optab, UNKNOWN);
6146 init_optab (smadd_widen_optab, UNKNOWN);
6147 init_optab (umadd_widen_optab, UNKNOWN);
6148 init_optab (ssmadd_widen_optab, UNKNOWN);
6149 init_optab (usmadd_widen_optab, UNKNOWN);
6150 init_optab (smsub_widen_optab, UNKNOWN);
6151 init_optab (umsub_widen_optab, UNKNOWN);
6152 init_optab (ssmsub_widen_optab, UNKNOWN);
6153 init_optab (usmsub_widen_optab, UNKNOWN);
6154 init_optab (sdiv_optab, DIV);
6155 init_optab (ssdiv_optab, SS_DIV);
6156 init_optab (usdiv_optab, US_DIV);
6157 init_optabv (sdivv_optab, DIV);
6158 init_optab (sdivmod_optab, UNKNOWN);
6159 init_optab (udiv_optab, UDIV);
6160 init_optab (udivmod_optab, UNKNOWN);
6161 init_optab (smod_optab, MOD);
6162 init_optab (umod_optab, UMOD);
6163 init_optab (fmod_optab, UNKNOWN);
6164 init_optab (remainder_optab, UNKNOWN);
6165 init_optab (ftrunc_optab, UNKNOWN);
6166 init_optab (and_optab, AND);
6167 init_optab (ior_optab, IOR);
6168 init_optab (xor_optab, XOR);
6169 init_optab (ashl_optab, ASHIFT);
6170 init_optab (ssashl_optab, SS_ASHIFT);
6171 init_optab (usashl_optab, US_ASHIFT);
6172 init_optab (ashr_optab, ASHIFTRT);
6173 init_optab (lshr_optab, LSHIFTRT);
6174 init_optab (rotl_optab, ROTATE);
6175 init_optab (rotr_optab, ROTATERT);
6176 init_optab (smin_optab, SMIN);
6177 init_optab (smax_optab, SMAX);
6178 init_optab (umin_optab, UMIN);
6179 init_optab (umax_optab, UMAX);
6180 init_optab (pow_optab, UNKNOWN);
6181 init_optab (atan2_optab, UNKNOWN);
6182 init_optab (fma_optab, FMA);
6183 init_optab (fms_optab, UNKNOWN);
6184 init_optab (fnma_optab, UNKNOWN);
6185 init_optab (fnms_optab, UNKNOWN);
6187 /* These three have codes assigned exclusively for the sake of
6188 have_insn_for. */
6189 init_optab (mov_optab, SET);
6190 init_optab (movstrict_optab, STRICT_LOW_PART);
6191 init_optab (cbranch_optab, COMPARE);
6193 init_optab (cmov_optab, UNKNOWN);
6194 init_optab (cstore_optab, UNKNOWN);
6195 init_optab (ctrap_optab, UNKNOWN);
6197 init_optab (storent_optab, UNKNOWN);
6199 init_optab (cmp_optab, UNKNOWN);
6200 init_optab (ucmp_optab, UNKNOWN);
6202 init_optab (eq_optab, EQ);
6203 init_optab (ne_optab, NE);
6204 init_optab (gt_optab, GT);
6205 init_optab (ge_optab, GE);
6206 init_optab (lt_optab, LT);
6207 init_optab (le_optab, LE);
6208 init_optab (unord_optab, UNORDERED);
6210 init_optab (neg_optab, NEG);
6211 init_optab (ssneg_optab, SS_NEG);
6212 init_optab (usneg_optab, US_NEG);
6213 init_optabv (negv_optab, NEG);
6214 init_optab (abs_optab, ABS);
6215 init_optabv (absv_optab, ABS);
6216 init_optab (addcc_optab, UNKNOWN);
6217 init_optab (one_cmpl_optab, NOT);
6218 init_optab (bswap_optab, BSWAP);
6219 init_optab (ffs_optab, FFS);
6220 init_optab (clz_optab, CLZ);
6221 init_optab (ctz_optab, CTZ);
6222 init_optab (popcount_optab, POPCOUNT);
6223 init_optab (parity_optab, PARITY);
6224 init_optab (sqrt_optab, SQRT);
6225 init_optab (floor_optab, UNKNOWN);
6226 init_optab (ceil_optab, UNKNOWN);
6227 init_optab (round_optab, UNKNOWN);
6228 init_optab (btrunc_optab, UNKNOWN);
6229 init_optab (nearbyint_optab, UNKNOWN);
6230 init_optab (rint_optab, UNKNOWN);
6231 init_optab (sincos_optab, UNKNOWN);
6232 init_optab (sin_optab, UNKNOWN);
6233 init_optab (asin_optab, UNKNOWN);
6234 init_optab (cos_optab, UNKNOWN);
6235 init_optab (acos_optab, UNKNOWN);
6236 init_optab (exp_optab, UNKNOWN);
6237 init_optab (exp10_optab, UNKNOWN);
6238 init_optab (exp2_optab, UNKNOWN);
6239 init_optab (expm1_optab, UNKNOWN);
6240 init_optab (ldexp_optab, UNKNOWN);
6241 init_optab (scalb_optab, UNKNOWN);
6242 init_optab (significand_optab, UNKNOWN);
6243 init_optab (logb_optab, UNKNOWN);
6244 init_optab (ilogb_optab, UNKNOWN);
6245 init_optab (log_optab, UNKNOWN);
6246 init_optab (log10_optab, UNKNOWN);
6247 init_optab (log2_optab, UNKNOWN);
6248 init_optab (log1p_optab, UNKNOWN);
6249 init_optab (tan_optab, UNKNOWN);
6250 init_optab (atan_optab, UNKNOWN);
6251 init_optab (copysign_optab, UNKNOWN);
6252 init_optab (signbit_optab, UNKNOWN);
6254 init_optab (isinf_optab, UNKNOWN);
6256 init_optab (strlen_optab, UNKNOWN);
6257 init_optab (push_optab, UNKNOWN);
6259 init_optab (reduc_smax_optab, UNKNOWN);
6260 init_optab (reduc_umax_optab, UNKNOWN);
6261 init_optab (reduc_smin_optab, UNKNOWN);
6262 init_optab (reduc_umin_optab, UNKNOWN);
6263 init_optab (reduc_splus_optab, UNKNOWN);
6264 init_optab (reduc_uplus_optab, UNKNOWN);
6266 init_optab (ssum_widen_optab, UNKNOWN);
6267 init_optab (usum_widen_optab, UNKNOWN);
6268 init_optab (sdot_prod_optab, UNKNOWN);
6269 init_optab (udot_prod_optab, UNKNOWN);
6271 init_optab (vec_extract_optab, UNKNOWN);
6272 init_optab (vec_extract_even_optab, UNKNOWN);
6273 init_optab (vec_extract_odd_optab, UNKNOWN);
6274 init_optab (vec_interleave_high_optab, UNKNOWN);
6275 init_optab (vec_interleave_low_optab, UNKNOWN);
6276 init_optab (vec_set_optab, UNKNOWN);
6277 init_optab (vec_init_optab, UNKNOWN);
6278 init_optab (vec_shl_optab, UNKNOWN);
6279 init_optab (vec_shr_optab, UNKNOWN);
6280 init_optab (vec_realign_load_optab, UNKNOWN);
6281 init_optab (movmisalign_optab, UNKNOWN);
6282 init_optab (vec_widen_umult_hi_optab, UNKNOWN);
6283 init_optab (vec_widen_umult_lo_optab, UNKNOWN);
6284 init_optab (vec_widen_smult_hi_optab, UNKNOWN);
6285 init_optab (vec_widen_smult_lo_optab, UNKNOWN);
6286 init_optab (vec_unpacks_hi_optab, UNKNOWN);
6287 init_optab (vec_unpacks_lo_optab, UNKNOWN);
6288 init_optab (vec_unpacku_hi_optab, UNKNOWN);
6289 init_optab (vec_unpacku_lo_optab, UNKNOWN);
6290 init_optab (vec_unpacks_float_hi_optab, UNKNOWN);
6291 init_optab (vec_unpacks_float_lo_optab, UNKNOWN);
6292 init_optab (vec_unpacku_float_hi_optab, UNKNOWN);
6293 init_optab (vec_unpacku_float_lo_optab, UNKNOWN);
6294 init_optab (vec_pack_trunc_optab, UNKNOWN);
6295 init_optab (vec_pack_usat_optab, UNKNOWN);
6296 init_optab (vec_pack_ssat_optab, UNKNOWN);
6297 init_optab (vec_pack_ufix_trunc_optab, UNKNOWN);
6298 init_optab (vec_pack_sfix_trunc_optab, UNKNOWN);
6300 init_optab (powi_optab, UNKNOWN);
6302 /* Conversions. */
6303 init_convert_optab (sext_optab, SIGN_EXTEND);
6304 init_convert_optab (zext_optab, ZERO_EXTEND);
6305 init_convert_optab (trunc_optab, TRUNCATE);
6306 init_convert_optab (sfix_optab, FIX);
6307 init_convert_optab (ufix_optab, UNSIGNED_FIX);
6308 init_convert_optab (sfixtrunc_optab, UNKNOWN);
6309 init_convert_optab (ufixtrunc_optab, UNKNOWN);
6310 init_convert_optab (sfloat_optab, FLOAT);
6311 init_convert_optab (ufloat_optab, UNSIGNED_FLOAT);
6312 init_convert_optab (lrint_optab, UNKNOWN);
6313 init_convert_optab (lround_optab, UNKNOWN);
6314 init_convert_optab (lfloor_optab, UNKNOWN);
6315 init_convert_optab (lceil_optab, UNKNOWN);
6317 init_convert_optab (fract_optab, FRACT_CONVERT);
6318 init_convert_optab (fractuns_optab, UNSIGNED_FRACT_CONVERT);
6319 init_convert_optab (satfract_optab, SAT_FRACT);
6320 init_convert_optab (satfractuns_optab, UNSIGNED_SAT_FRACT);
6322 /* Fill in the optabs with the insns we support. */
6323 init_all_optabs ();
6325 /* Initialize the optabs with the names of the library functions. */
6326 add_optab->libcall_basename = "add";
6327 add_optab->libcall_suffix = '3';
6328 add_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6329 addv_optab->libcall_basename = "add";
6330 addv_optab->libcall_suffix = '3';
6331 addv_optab->libcall_gen = gen_intv_fp_libfunc;
6332 ssadd_optab->libcall_basename = "ssadd";
6333 ssadd_optab->libcall_suffix = '3';
6334 ssadd_optab->libcall_gen = gen_signed_fixed_libfunc;
6335 usadd_optab->libcall_basename = "usadd";
6336 usadd_optab->libcall_suffix = '3';
6337 usadd_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6338 sub_optab->libcall_basename = "sub";
6339 sub_optab->libcall_suffix = '3';
6340 sub_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6341 subv_optab->libcall_basename = "sub";
6342 subv_optab->libcall_suffix = '3';
6343 subv_optab->libcall_gen = gen_intv_fp_libfunc;
6344 sssub_optab->libcall_basename = "sssub";
6345 sssub_optab->libcall_suffix = '3';
6346 sssub_optab->libcall_gen = gen_signed_fixed_libfunc;
6347 ussub_optab->libcall_basename = "ussub";
6348 ussub_optab->libcall_suffix = '3';
6349 ussub_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6350 smul_optab->libcall_basename = "mul";
6351 smul_optab->libcall_suffix = '3';
6352 smul_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6353 smulv_optab->libcall_basename = "mul";
6354 smulv_optab->libcall_suffix = '3';
6355 smulv_optab->libcall_gen = gen_intv_fp_libfunc;
6356 ssmul_optab->libcall_basename = "ssmul";
6357 ssmul_optab->libcall_suffix = '3';
6358 ssmul_optab->libcall_gen = gen_signed_fixed_libfunc;
6359 usmul_optab->libcall_basename = "usmul";
6360 usmul_optab->libcall_suffix = '3';
6361 usmul_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6362 sdiv_optab->libcall_basename = "div";
6363 sdiv_optab->libcall_suffix = '3';
6364 sdiv_optab->libcall_gen = gen_int_fp_signed_fixed_libfunc;
6365 sdivv_optab->libcall_basename = "divv";
6366 sdivv_optab->libcall_suffix = '3';
6367 sdivv_optab->libcall_gen = gen_int_libfunc;
6368 ssdiv_optab->libcall_basename = "ssdiv";
6369 ssdiv_optab->libcall_suffix = '3';
6370 ssdiv_optab->libcall_gen = gen_signed_fixed_libfunc;
6371 udiv_optab->libcall_basename = "udiv";
6372 udiv_optab->libcall_suffix = '3';
6373 udiv_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6374 usdiv_optab->libcall_basename = "usdiv";
6375 usdiv_optab->libcall_suffix = '3';
6376 usdiv_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6377 sdivmod_optab->libcall_basename = "divmod";
6378 sdivmod_optab->libcall_suffix = '4';
6379 sdivmod_optab->libcall_gen = gen_int_libfunc;
6380 udivmod_optab->libcall_basename = "udivmod";
6381 udivmod_optab->libcall_suffix = '4';
6382 udivmod_optab->libcall_gen = gen_int_libfunc;
6383 smod_optab->libcall_basename = "mod";
6384 smod_optab->libcall_suffix = '3';
6385 smod_optab->libcall_gen = gen_int_libfunc;
6386 umod_optab->libcall_basename = "umod";
6387 umod_optab->libcall_suffix = '3';
6388 umod_optab->libcall_gen = gen_int_libfunc;
6389 ftrunc_optab->libcall_basename = "ftrunc";
6390 ftrunc_optab->libcall_suffix = '2';
6391 ftrunc_optab->libcall_gen = gen_fp_libfunc;
6392 and_optab->libcall_basename = "and";
6393 and_optab->libcall_suffix = '3';
6394 and_optab->libcall_gen = gen_int_libfunc;
6395 ior_optab->libcall_basename = "ior";
6396 ior_optab->libcall_suffix = '3';
6397 ior_optab->libcall_gen = gen_int_libfunc;
6398 xor_optab->libcall_basename = "xor";
6399 xor_optab->libcall_suffix = '3';
6400 xor_optab->libcall_gen = gen_int_libfunc;
6401 ashl_optab->libcall_basename = "ashl";
6402 ashl_optab->libcall_suffix = '3';
6403 ashl_optab->libcall_gen = gen_int_fixed_libfunc;
6404 ssashl_optab->libcall_basename = "ssashl";
6405 ssashl_optab->libcall_suffix = '3';
6406 ssashl_optab->libcall_gen = gen_signed_fixed_libfunc;
6407 usashl_optab->libcall_basename = "usashl";
6408 usashl_optab->libcall_suffix = '3';
6409 usashl_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6410 ashr_optab->libcall_basename = "ashr";
6411 ashr_optab->libcall_suffix = '3';
6412 ashr_optab->libcall_gen = gen_int_signed_fixed_libfunc;
6413 lshr_optab->libcall_basename = "lshr";
6414 lshr_optab->libcall_suffix = '3';
6415 lshr_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6416 smin_optab->libcall_basename = "min";
6417 smin_optab->libcall_suffix = '3';
6418 smin_optab->libcall_gen = gen_int_fp_libfunc;
6419 smax_optab->libcall_basename = "max";
6420 smax_optab->libcall_suffix = '3';
6421 smax_optab->libcall_gen = gen_int_fp_libfunc;
6422 umin_optab->libcall_basename = "umin";
6423 umin_optab->libcall_suffix = '3';
6424 umin_optab->libcall_gen = gen_int_libfunc;
6425 umax_optab->libcall_basename = "umax";
6426 umax_optab->libcall_suffix = '3';
6427 umax_optab->libcall_gen = gen_int_libfunc;
6428 neg_optab->libcall_basename = "neg";
6429 neg_optab->libcall_suffix = '2';
6430 neg_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6431 ssneg_optab->libcall_basename = "ssneg";
6432 ssneg_optab->libcall_suffix = '2';
6433 ssneg_optab->libcall_gen = gen_signed_fixed_libfunc;
6434 usneg_optab->libcall_basename = "usneg";
6435 usneg_optab->libcall_suffix = '2';
6436 usneg_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6437 negv_optab->libcall_basename = "neg";
6438 negv_optab->libcall_suffix = '2';
6439 negv_optab->libcall_gen = gen_intv_fp_libfunc;
6440 one_cmpl_optab->libcall_basename = "one_cmpl";
6441 one_cmpl_optab->libcall_suffix = '2';
6442 one_cmpl_optab->libcall_gen = gen_int_libfunc;
6443 ffs_optab->libcall_basename = "ffs";
6444 ffs_optab->libcall_suffix = '2';
6445 ffs_optab->libcall_gen = gen_int_libfunc;
6446 clz_optab->libcall_basename = "clz";
6447 clz_optab->libcall_suffix = '2';
6448 clz_optab->libcall_gen = gen_int_libfunc;
6449 ctz_optab->libcall_basename = "ctz";
6450 ctz_optab->libcall_suffix = '2';
6451 ctz_optab->libcall_gen = gen_int_libfunc;
6452 popcount_optab->libcall_basename = "popcount";
6453 popcount_optab->libcall_suffix = '2';
6454 popcount_optab->libcall_gen = gen_int_libfunc;
6455 parity_optab->libcall_basename = "parity";
6456 parity_optab->libcall_suffix = '2';
6457 parity_optab->libcall_gen = gen_int_libfunc;
6459 /* Comparison libcalls for integers MUST come in pairs,
6460 signed/unsigned. */
6461 cmp_optab->libcall_basename = "cmp";
6462 cmp_optab->libcall_suffix = '2';
6463 cmp_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6464 ucmp_optab->libcall_basename = "ucmp";
6465 ucmp_optab->libcall_suffix = '2';
6466 ucmp_optab->libcall_gen = gen_int_libfunc;
6468 /* EQ etc are floating point only. */
6469 eq_optab->libcall_basename = "eq";
6470 eq_optab->libcall_suffix = '2';
6471 eq_optab->libcall_gen = gen_fp_libfunc;
6472 ne_optab->libcall_basename = "ne";
6473 ne_optab->libcall_suffix = '2';
6474 ne_optab->libcall_gen = gen_fp_libfunc;
6475 gt_optab->libcall_basename = "gt";
6476 gt_optab->libcall_suffix = '2';
6477 gt_optab->libcall_gen = gen_fp_libfunc;
6478 ge_optab->libcall_basename = "ge";
6479 ge_optab->libcall_suffix = '2';
6480 ge_optab->libcall_gen = gen_fp_libfunc;
6481 lt_optab->libcall_basename = "lt";
6482 lt_optab->libcall_suffix = '2';
6483 lt_optab->libcall_gen = gen_fp_libfunc;
6484 le_optab->libcall_basename = "le";
6485 le_optab->libcall_suffix = '2';
6486 le_optab->libcall_gen = gen_fp_libfunc;
6487 unord_optab->libcall_basename = "unord";
6488 unord_optab->libcall_suffix = '2';
6489 unord_optab->libcall_gen = gen_fp_libfunc;
6491 powi_optab->libcall_basename = "powi";
6492 powi_optab->libcall_suffix = '2';
6493 powi_optab->libcall_gen = gen_fp_libfunc;
6495 /* Conversions. */
6496 sfloat_optab->libcall_basename = "float";
6497 sfloat_optab->libcall_gen = gen_int_to_fp_conv_libfunc;
6498 ufloat_optab->libcall_gen = gen_ufloat_conv_libfunc;
6499 sfix_optab->libcall_basename = "fix";
6500 sfix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6501 ufix_optab->libcall_basename = "fixuns";
6502 ufix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6503 lrint_optab->libcall_basename = "lrint";
6504 lrint_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6505 lround_optab->libcall_basename = "lround";
6506 lround_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6507 lfloor_optab->libcall_basename = "lfloor";
6508 lfloor_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6509 lceil_optab->libcall_basename = "lceil";
6510 lceil_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6512 /* trunc_optab is also used for FLOAT_EXTEND. */
6513 sext_optab->libcall_basename = "extend";
6514 sext_optab->libcall_gen = gen_extend_conv_libfunc;
6515 trunc_optab->libcall_basename = "trunc";
6516 trunc_optab->libcall_gen = gen_trunc_conv_libfunc;
6518 /* Conversions for fixed-point modes and other modes. */
6519 fract_optab->libcall_basename = "fract";
6520 fract_optab->libcall_gen = gen_fract_conv_libfunc;
6521 satfract_optab->libcall_basename = "satfract";
6522 satfract_optab->libcall_gen = gen_satfract_conv_libfunc;
6523 fractuns_optab->libcall_basename = "fractuns";
6524 fractuns_optab->libcall_gen = gen_fractuns_conv_libfunc;
6525 satfractuns_optab->libcall_basename = "satfractuns";
6526 satfractuns_optab->libcall_gen = gen_satfractuns_conv_libfunc;
6528 /* The ffs function operates on `int'. Fall back on it if we do not
6529 have a libgcc2 function for that width. */
6530 if (INT_TYPE_SIZE < BITS_PER_WORD)
6531 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
6532 "ffs");
6534 /* Explicitly initialize the bswap libfuncs since we need them to be
6535 valid for things other than word_mode. */
6536 set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
6537 set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
6539 /* Use cabs for double complex abs, since systems generally have cabs.
6540 Don't define any libcall for float complex, so that cabs will be used. */
6541 if (complex_double_type_node)
6542 set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node), "cabs");
6544 abort_libfunc = init_one_libfunc ("abort");
6545 memcpy_libfunc = init_one_libfunc ("memcpy");
6546 memmove_libfunc = init_one_libfunc ("memmove");
6547 memcmp_libfunc = init_one_libfunc ("memcmp");
6548 memset_libfunc = init_one_libfunc ("memset");
6549 setbits_libfunc = init_one_libfunc ("__setbits");
6551 #ifndef DONT_USE_BUILTIN_SETJMP
6552 setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
6553 longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
6554 #else
6555 setjmp_libfunc = init_one_libfunc ("setjmp");
6556 longjmp_libfunc = init_one_libfunc ("longjmp");
6557 #endif
6558 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
6559 unwind_sjlj_unregister_libfunc
6560 = init_one_libfunc ("_Unwind_SjLj_Unregister");
6562 /* For function entry/exit instrumentation. */
6563 profile_function_entry_libfunc
6564 = init_one_libfunc ("__cyg_profile_func_enter");
6565 profile_function_exit_libfunc
6566 = init_one_libfunc ("__cyg_profile_func_exit");
6568 gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
6570 /* Allow the target to add more libcalls or rename some, etc. */
6571 targetm.init_libfuncs ();
6574 /* Print information about the current contents of the optabs on
6575 STDERR. */
6577 DEBUG_FUNCTION void
6578 debug_optab_libfuncs (void)
6580 int i;
6581 int j;
6582 int k;
6584 /* Dump the arithmetic optabs. */
6585 for (i = 0; i != (int) OTI_MAX; i++)
6586 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6588 optab o;
6589 rtx l;
6591 o = &optab_table[i];
6592 l = optab_libfunc (o, (enum machine_mode) j);
6593 if (l)
6595 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6596 fprintf (stderr, "%s\t%s:\t%s\n",
6597 GET_RTX_NAME (o->code),
6598 GET_MODE_NAME (j),
6599 XSTR (l, 0));
6603 /* Dump the conversion optabs. */
6604 for (i = 0; i < (int) COI_MAX; ++i)
6605 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6606 for (k = 0; k < NUM_MACHINE_MODES; ++k)
6608 convert_optab o;
6609 rtx l;
6611 o = &convert_optab_table[i];
6612 l = convert_optab_libfunc (o, (enum machine_mode) j,
6613 (enum machine_mode) k);
6614 if (l)
6616 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6617 fprintf (stderr, "%s\t%s\t%s:\t%s\n",
6618 GET_RTX_NAME (o->code),
6619 GET_MODE_NAME (j),
6620 GET_MODE_NAME (k),
6621 XSTR (l, 0));
6627 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
6628 CODE. Return 0 on failure. */
6631 gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
6633 enum machine_mode mode = GET_MODE (op1);
6634 enum insn_code icode;
6635 rtx insn;
6636 rtx trap_rtx;
6638 if (mode == VOIDmode)
6639 return 0;
6641 icode = optab_handler (ctrap_optab, mode);
6642 if (icode == CODE_FOR_nothing)
6643 return 0;
6645 /* Some targets only accept a zero trap code. */
6646 if (insn_data[icode].operand[3].predicate
6647 && !insn_data[icode].operand[3].predicate (tcode, VOIDmode))
6648 return 0;
6650 do_pending_stack_adjust ();
6651 start_sequence ();
6652 prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
6653 &trap_rtx, &mode);
6654 if (!trap_rtx)
6655 insn = NULL_RTX;
6656 else
6657 insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
6658 tcode);
6660 /* If that failed, then give up. */
6661 if (insn == 0)
6663 end_sequence ();
6664 return 0;
6667 emit_insn (insn);
6668 insn = get_insns ();
6669 end_sequence ();
6670 return insn;
6673 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
6674 or unsigned operation code. */
6676 static enum rtx_code
6677 get_rtx_code (enum tree_code tcode, bool unsignedp)
6679 enum rtx_code code;
6680 switch (tcode)
6682 case EQ_EXPR:
6683 code = EQ;
6684 break;
6685 case NE_EXPR:
6686 code = NE;
6687 break;
6688 case LT_EXPR:
6689 code = unsignedp ? LTU : LT;
6690 break;
6691 case LE_EXPR:
6692 code = unsignedp ? LEU : LE;
6693 break;
6694 case GT_EXPR:
6695 code = unsignedp ? GTU : GT;
6696 break;
6697 case GE_EXPR:
6698 code = unsignedp ? GEU : GE;
6699 break;
6701 case UNORDERED_EXPR:
6702 code = UNORDERED;
6703 break;
6704 case ORDERED_EXPR:
6705 code = ORDERED;
6706 break;
6707 case UNLT_EXPR:
6708 code = UNLT;
6709 break;
6710 case UNLE_EXPR:
6711 code = UNLE;
6712 break;
6713 case UNGT_EXPR:
6714 code = UNGT;
6715 break;
6716 case UNGE_EXPR:
6717 code = UNGE;
6718 break;
6719 case UNEQ_EXPR:
6720 code = UNEQ;
6721 break;
6722 case LTGT_EXPR:
6723 code = LTGT;
6724 break;
6726 default:
6727 gcc_unreachable ();
6729 return code;
6732 /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
6733 unsigned operators. Do not generate compare instruction. */
6735 static rtx
6736 vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
6738 enum rtx_code rcode;
6739 tree t_op0, t_op1;
6740 rtx rtx_op0, rtx_op1;
6742 /* This is unlikely. While generating VEC_COND_EXPR, auto vectorizer
6743 ensures that condition is a relational operation. */
6744 gcc_assert (COMPARISON_CLASS_P (cond));
6746 rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
6747 t_op0 = TREE_OPERAND (cond, 0);
6748 t_op1 = TREE_OPERAND (cond, 1);
6750 /* Expand operands. */
6751 rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
6752 EXPAND_STACK_PARM);
6753 rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
6754 EXPAND_STACK_PARM);
6756 if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
6757 && GET_MODE (rtx_op0) != VOIDmode)
6758 rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
6760 if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
6761 && GET_MODE (rtx_op1) != VOIDmode)
6762 rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
6764 return gen_rtx_fmt_ee (rcode, VOIDmode, rtx_op0, rtx_op1);
6767 /* Return insn code for TYPE, the type of a VEC_COND_EXPR. */
6769 static inline enum insn_code
6770 get_vcond_icode (tree type, enum machine_mode mode)
6772 enum insn_code icode = CODE_FOR_nothing;
6774 if (TYPE_UNSIGNED (type))
6775 icode = direct_optab_handler (vcondu_optab, mode);
6776 else
6777 icode = direct_optab_handler (vcond_optab, mode);
6778 return icode;
6781 /* Return TRUE iff, appropriate vector insns are available
6782 for vector cond expr with type TYPE in VMODE mode. */
6784 bool
6785 expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
6787 if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
6788 return false;
6789 return true;
6792 /* Generate insns for a VEC_COND_EXPR, given its TYPE and its
6793 three operands. */
6796 expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
6797 rtx target)
6799 enum insn_code icode;
6800 rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
6801 enum machine_mode mode = TYPE_MODE (vec_cond_type);
6802 bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
6804 icode = get_vcond_icode (vec_cond_type, mode);
6805 if (icode == CODE_FOR_nothing)
6806 return 0;
6808 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6809 target = gen_reg_rtx (mode);
6811 /* Get comparison rtx. First expand both cond expr operands. */
6812 comparison = vector_compare_rtx (op0,
6813 unsignedp, icode);
6814 cc_op0 = XEXP (comparison, 0);
6815 cc_op1 = XEXP (comparison, 1);
6816 /* Expand both operands and force them in reg, if required. */
6817 rtx_op1 = expand_normal (op1);
6818 if (!insn_data[icode].operand[1].predicate (rtx_op1, mode)
6819 && mode != VOIDmode)
6820 rtx_op1 = force_reg (mode, rtx_op1);
6822 rtx_op2 = expand_normal (op2);
6823 if (!insn_data[icode].operand[2].predicate (rtx_op2, mode)
6824 && mode != VOIDmode)
6825 rtx_op2 = force_reg (mode, rtx_op2);
6827 /* Emit instruction! */
6828 emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
6829 comparison, cc_op0, cc_op1));
6831 return target;
6835 /* This is an internal subroutine of the other compare_and_swap expanders.
6836 MEM, OLD_VAL and NEW_VAL are as you'd expect for a compare-and-swap
6837 operation. TARGET is an optional place to store the value result of
6838 the operation. ICODE is the particular instruction to expand. Return
6839 the result of the operation. */
6841 static rtx
6842 expand_val_compare_and_swap_1 (rtx mem, rtx old_val, rtx new_val,
6843 rtx target, enum insn_code icode)
6845 enum machine_mode mode = GET_MODE (mem);
6846 rtx insn;
6848 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6849 target = gen_reg_rtx (mode);
6851 if (GET_MODE (old_val) != VOIDmode && GET_MODE (old_val) != mode)
6852 old_val = convert_modes (mode, GET_MODE (old_val), old_val, 1);
6853 if (!insn_data[icode].operand[2].predicate (old_val, mode))
6854 old_val = force_reg (mode, old_val);
6856 if (GET_MODE (new_val) != VOIDmode && GET_MODE (new_val) != mode)
6857 new_val = convert_modes (mode, GET_MODE (new_val), new_val, 1);
6858 if (!insn_data[icode].operand[3].predicate (new_val, mode))
6859 new_val = force_reg (mode, new_val);
6861 insn = GEN_FCN (icode) (target, mem, old_val, new_val);
6862 if (insn == NULL_RTX)
6863 return NULL_RTX;
6864 emit_insn (insn);
6866 return target;
6869 /* Expand a compare-and-swap operation and return its value. */
6872 expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
6874 enum machine_mode mode = GET_MODE (mem);
6875 enum insn_code icode
6876 = direct_optab_handler (sync_compare_and_swap_optab, mode);
6878 if (icode == CODE_FOR_nothing)
6879 return NULL_RTX;
6881 return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode);
6884 /* Helper function to find the MODE_CC set in a sync_compare_and_swap
6885 pattern. */
6887 static void
6888 find_cc_set (rtx x, const_rtx pat, void *data)
6890 if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
6891 && GET_CODE (pat) == SET)
6893 rtx *p_cc_reg = (rtx *) data;
6894 gcc_assert (!*p_cc_reg);
6895 *p_cc_reg = x;
6899 /* Expand a compare-and-swap operation and store true into the result if
6900 the operation was successful and false otherwise. Return the result.
6901 Unlike other routines, TARGET is not optional. */
6904 expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
6906 enum machine_mode mode = GET_MODE (mem);
6907 enum insn_code icode;
6908 rtx subtarget, seq, cc_reg;
6910 /* If the target supports a compare-and-swap pattern that simultaneously
6911 sets some flag for success, then use it. Otherwise use the regular
6912 compare-and-swap and follow that immediately with a compare insn. */
6913 icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
6914 if (icode == CODE_FOR_nothing)
6915 return NULL_RTX;
6917 do_pending_stack_adjust ();
6920 start_sequence ();
6921 subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
6922 NULL_RTX, icode);
6923 cc_reg = NULL_RTX;
6924 if (subtarget == NULL_RTX)
6926 end_sequence ();
6927 return NULL_RTX;
6930 if (have_insn_for (COMPARE, CCmode))
6931 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
6932 seq = get_insns ();
6933 end_sequence ();
6935 /* We might be comparing against an old value. Try again. :-( */
6936 if (!cc_reg && MEM_P (old_val))
6938 seq = NULL_RTX;
6939 old_val = force_reg (mode, old_val);
6942 while (!seq);
6944 emit_insn (seq);
6945 if (cc_reg)
6946 return emit_store_flag_force (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1);
6947 else
6948 return emit_store_flag_force (target, EQ, subtarget, old_val, VOIDmode, 1, 1);
6951 /* This is a helper function for the other atomic operations. This function
6952 emits a loop that contains SEQ that iterates until a compare-and-swap
6953 operation at the end succeeds. MEM is the memory to be modified. SEQ is
6954 a set of instructions that takes a value from OLD_REG as an input and
6955 produces a value in NEW_REG as an output. Before SEQ, OLD_REG will be
6956 set to the current contents of MEM. After SEQ, a compare-and-swap will
6957 attempt to update MEM with NEW_REG. The function returns true when the
6958 loop was generated successfully. */
6960 static bool
6961 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
6963 enum machine_mode mode = GET_MODE (mem);
6964 enum insn_code icode;
6965 rtx label, cmp_reg, subtarget, cc_reg;
6967 /* The loop we want to generate looks like
6969 cmp_reg = mem;
6970 label:
6971 old_reg = cmp_reg;
6972 seq;
6973 cmp_reg = compare-and-swap(mem, old_reg, new_reg)
6974 if (cmp_reg != old_reg)
6975 goto label;
6977 Note that we only do the plain load from memory once. Subsequent
6978 iterations use the value loaded by the compare-and-swap pattern. */
6980 label = gen_label_rtx ();
6981 cmp_reg = gen_reg_rtx (mode);
6983 emit_move_insn (cmp_reg, mem);
6984 emit_label (label);
6985 emit_move_insn (old_reg, cmp_reg);
6986 if (seq)
6987 emit_insn (seq);
6989 /* If the target supports a compare-and-swap pattern that simultaneously
6990 sets some flag for success, then use it. Otherwise use the regular
6991 compare-and-swap and follow that immediately with a compare insn. */
6992 icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
6993 if (icode == CODE_FOR_nothing)
6994 return false;
6996 subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
6997 cmp_reg, icode);
6998 if (subtarget == NULL_RTX)
6999 return false;
7001 cc_reg = NULL_RTX;
7002 if (have_insn_for (COMPARE, CCmode))
7003 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
7004 if (cc_reg)
7006 cmp_reg = cc_reg;
7007 old_reg = const0_rtx;
7009 else
7011 if (subtarget != cmp_reg)
7012 emit_move_insn (cmp_reg, subtarget);
7015 /* ??? Mark this jump predicted not taken? */
7016 emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, const0_rtx, GET_MODE (cmp_reg), 1,
7017 label);
7018 return true;
7021 /* This function generates the atomic operation MEM CODE= VAL. In this
7022 case, we do not care about any resulting value. Returns NULL if we
7023 cannot generate the operation. */
7026 expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
7028 enum machine_mode mode = GET_MODE (mem);
7029 enum insn_code icode;
7030 rtx insn;
7032 /* Look to see if the target supports the operation directly. */
7033 switch (code)
7035 case PLUS:
7036 icode = direct_optab_handler (sync_add_optab, mode);
7037 break;
7038 case IOR:
7039 icode = direct_optab_handler (sync_ior_optab, mode);
7040 break;
7041 case XOR:
7042 icode = direct_optab_handler (sync_xor_optab, mode);
7043 break;
7044 case AND:
7045 icode = direct_optab_handler (sync_and_optab, mode);
7046 break;
7047 case NOT:
7048 icode = direct_optab_handler (sync_nand_optab, mode);
7049 break;
7051 case MINUS:
7052 icode = direct_optab_handler (sync_sub_optab, mode);
7053 if (icode == CODE_FOR_nothing || CONST_INT_P (val))
7055 icode = direct_optab_handler (sync_add_optab, mode);
7056 if (icode != CODE_FOR_nothing)
7058 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7059 code = PLUS;
7062 break;
7064 default:
7065 gcc_unreachable ();
7068 /* Generate the direct operation, if present. */
7069 if (icode != CODE_FOR_nothing)
7071 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7072 val = convert_modes (mode, GET_MODE (val), val, 1);
7073 if (!insn_data[icode].operand[1].predicate (val, mode))
7074 val = force_reg (mode, val);
7076 insn = GEN_FCN (icode) (mem, val);
7077 if (insn)
7079 emit_insn (insn);
7080 return const0_rtx;
7084 /* Failing that, generate a compare-and-swap loop in which we perform the
7085 operation with normal arithmetic instructions. */
7086 if (direct_optab_handler (sync_compare_and_swap_optab, mode)
7087 != CODE_FOR_nothing)
7089 rtx t0 = gen_reg_rtx (mode), t1;
7091 start_sequence ();
7093 t1 = t0;
7094 if (code == NOT)
7096 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7097 true, OPTAB_LIB_WIDEN);
7098 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7100 else
7101 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7102 true, OPTAB_LIB_WIDEN);
7103 insn = get_insns ();
7104 end_sequence ();
7106 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7107 return const0_rtx;
7110 return NULL_RTX;
7113 /* This function generates the atomic operation MEM CODE= VAL. In this
7114 case, we do care about the resulting value: if AFTER is true then
7115 return the value MEM holds after the operation, if AFTER is false
7116 then return the value MEM holds before the operation. TARGET is an
7117 optional place for the result value to be stored. */
7120 expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
7121 bool after, rtx target)
7123 enum machine_mode mode = GET_MODE (mem);
7124 enum insn_code old_code, new_code, icode;
7125 bool compensate;
7126 rtx insn;
7128 /* Look to see if the target supports the operation directly. */
7129 switch (code)
7131 case PLUS:
7132 old_code = direct_optab_handler (sync_old_add_optab, mode);
7133 new_code = direct_optab_handler (sync_new_add_optab, mode);
7134 break;
7135 case IOR:
7136 old_code = direct_optab_handler (sync_old_ior_optab, mode);
7137 new_code = direct_optab_handler (sync_new_ior_optab, mode);
7138 break;
7139 case XOR:
7140 old_code = direct_optab_handler (sync_old_xor_optab, mode);
7141 new_code = direct_optab_handler (sync_new_xor_optab, mode);
7142 break;
7143 case AND:
7144 old_code = direct_optab_handler (sync_old_and_optab, mode);
7145 new_code = direct_optab_handler (sync_new_and_optab, mode);
7146 break;
7147 case NOT:
7148 old_code = direct_optab_handler (sync_old_nand_optab, mode);
7149 new_code = direct_optab_handler (sync_new_nand_optab, mode);
7150 break;
7152 case MINUS:
7153 old_code = direct_optab_handler (sync_old_sub_optab, mode);
7154 new_code = direct_optab_handler (sync_new_sub_optab, mode);
7155 if ((old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
7156 || CONST_INT_P (val))
7158 old_code = direct_optab_handler (sync_old_add_optab, mode);
7159 new_code = direct_optab_handler (sync_new_add_optab, mode);
7160 if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
7162 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7163 code = PLUS;
7166 break;
7168 default:
7169 gcc_unreachable ();
7172 /* If the target does supports the proper new/old operation, great. But
7173 if we only support the opposite old/new operation, check to see if we
7174 can compensate. In the case in which the old value is supported, then
7175 we can always perform the operation again with normal arithmetic. In
7176 the case in which the new value is supported, then we can only handle
7177 this in the case the operation is reversible. */
7178 compensate = false;
7179 if (after)
7181 icode = new_code;
7182 if (icode == CODE_FOR_nothing)
7184 icode = old_code;
7185 if (icode != CODE_FOR_nothing)
7186 compensate = true;
7189 else
7191 icode = old_code;
7192 if (icode == CODE_FOR_nothing
7193 && (code == PLUS || code == MINUS || code == XOR))
7195 icode = new_code;
7196 if (icode != CODE_FOR_nothing)
7197 compensate = true;
7201 /* If we found something supported, great. */
7202 if (icode != CODE_FOR_nothing)
7204 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7205 target = gen_reg_rtx (mode);
7207 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7208 val = convert_modes (mode, GET_MODE (val), val, 1);
7209 if (!insn_data[icode].operand[2].predicate (val, mode))
7210 val = force_reg (mode, val);
7212 insn = GEN_FCN (icode) (target, mem, val);
7213 if (insn)
7215 emit_insn (insn);
7217 /* If we need to compensate for using an operation with the
7218 wrong return value, do so now. */
7219 if (compensate)
7221 if (!after)
7223 if (code == PLUS)
7224 code = MINUS;
7225 else if (code == MINUS)
7226 code = PLUS;
7229 if (code == NOT)
7231 target = expand_simple_binop (mode, AND, target, val,
7232 NULL_RTX, true,
7233 OPTAB_LIB_WIDEN);
7234 target = expand_simple_unop (mode, code, target,
7235 NULL_RTX, true);
7237 else
7238 target = expand_simple_binop (mode, code, target, val,
7239 NULL_RTX, true,
7240 OPTAB_LIB_WIDEN);
7243 return target;
7247 /* Failing that, generate a compare-and-swap loop in which we perform the
7248 operation with normal arithmetic instructions. */
7249 if (direct_optab_handler (sync_compare_and_swap_optab, mode)
7250 != CODE_FOR_nothing)
7252 rtx t0 = gen_reg_rtx (mode), t1;
7254 if (!target || !register_operand (target, mode))
7255 target = gen_reg_rtx (mode);
7257 start_sequence ();
7259 if (!after)
7260 emit_move_insn (target, t0);
7261 t1 = t0;
7262 if (code == NOT)
7264 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7265 true, OPTAB_LIB_WIDEN);
7266 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7268 else
7269 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7270 true, OPTAB_LIB_WIDEN);
7271 if (after)
7272 emit_move_insn (target, t1);
7274 insn = get_insns ();
7275 end_sequence ();
7277 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7278 return target;
7281 return NULL_RTX;
7284 /* This function expands a test-and-set operation. Ideally we atomically
7285 store VAL in MEM and return the previous value in MEM. Some targets
7286 may not support this operation and only support VAL with the constant 1;
7287 in this case while the return value will be 0/1, but the exact value
7288 stored in MEM is target defined. TARGET is an option place to stick
7289 the return value. */
7292 expand_sync_lock_test_and_set (rtx mem, rtx val, rtx target)
7294 enum machine_mode mode = GET_MODE (mem);
7295 enum insn_code icode;
7296 rtx insn;
7298 /* If the target supports the test-and-set directly, great. */
7299 icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
7300 if (icode != CODE_FOR_nothing)
7302 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7303 target = gen_reg_rtx (mode);
7305 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7306 val = convert_modes (mode, GET_MODE (val), val, 1);
7307 if (!insn_data[icode].operand[2].predicate (val, mode))
7308 val = force_reg (mode, val);
7310 insn = GEN_FCN (icode) (target, mem, val);
7311 if (insn)
7313 emit_insn (insn);
7314 return target;
7318 /* Otherwise, use a compare-and-swap loop for the exchange. */
7319 if (direct_optab_handler (sync_compare_and_swap_optab, mode)
7320 != CODE_FOR_nothing)
7322 if (!target || !register_operand (target, mode))
7323 target = gen_reg_rtx (mode);
7324 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7325 val = convert_modes (mode, GET_MODE (val), val, 1);
7326 if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
7327 return target;
7330 return NULL_RTX;
7333 #include "gt-optabs.h"