Print SCoPs under CLooG format.
[official-gcc/graphite-test-results.git] / gcc / optabs.c
blob747166b18d38b8d278a1f42ea4f22419698c143a
1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "toplev.h"
29 /* Include insn-config.h before expr.h so that HAVE_conditional_move
30 is properly defined. */
31 #include "insn-config.h"
32 #include "rtl.h"
33 #include "tree.h"
34 #include "tm_p.h"
35 #include "flags.h"
36 #include "function.h"
37 #include "except.h"
38 #include "expr.h"
39 #include "optabs.h"
40 #include "libfuncs.h"
41 #include "recog.h"
42 #include "reload.h"
43 #include "ggc.h"
44 #include "real.h"
45 #include "basic-block.h"
46 #include "target.h"
48 /* Each optab contains info on how this target machine
49 can perform a particular operation
50 for all sizes and kinds of operands.
52 The operation to be performed is often specified
53 by passing one of these optabs as an argument.
55 See expr.h for documentation of these optabs. */
57 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
58 __extension__ struct optab_d optab_table[OTI_MAX]
59 = { [0 ... OTI_MAX - 1].handlers[0 ... NUM_MACHINE_MODES - 1].insn_code
60 = CODE_FOR_nothing };
61 #else
62 /* init_insn_codes will do runtime initialization otherwise. */
63 struct optab_d optab_table[OTI_MAX];
64 #endif
66 rtx libfunc_table[LTI_MAX];
68 /* Tables of patterns for converting one mode to another. */
69 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
70 __extension__ struct convert_optab_d convert_optab_table[COI_MAX]
71 = { [0 ... COI_MAX - 1].handlers[0 ... NUM_MACHINE_MODES - 1]
72 [0 ... NUM_MACHINE_MODES - 1].insn_code
73 = CODE_FOR_nothing };
74 #else
75 /* init_convert_optab will do runtime initialization otherwise. */
76 struct convert_optab_d convert_optab_table[COI_MAX];
77 #endif
79 /* Contains the optab used for each rtx code. */
80 optab code_to_optab[NUM_RTX_CODE + 1];
82 #ifdef HAVE_conditional_move
83 /* Indexed by the machine mode, gives the insn code to make a conditional
84 move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
85 setcc_gen_code to cut down on the number of named patterns. Consider a day
86 when a lot more rtx codes are conditional (eg: for the ARM). */
88 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
89 #endif
91 /* Indexed by the machine mode, gives the insn code for vector conditional
92 operation. */
94 enum insn_code vcond_gen_code[NUM_MACHINE_MODES];
95 enum insn_code vcondu_gen_code[NUM_MACHINE_MODES];
97 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
98 enum machine_mode *);
99 static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
101 /* Debug facility for use in GDB. */
102 void debug_optab_libfuncs (void);
104 /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
105 #if ENABLE_DECIMAL_BID_FORMAT
106 #define DECIMAL_PREFIX "bid_"
107 #else
108 #define DECIMAL_PREFIX "dpd_"
109 #endif
112 /* Info about libfunc. We use same hashtable for normal optabs and conversion
113 optab. In the first case mode2 is unused. */
114 struct GTY(()) libfunc_entry {
115 size_t optab;
116 enum machine_mode mode1, mode2;
117 rtx libfunc;
120 /* Hash table used to convert declarations into nodes. */
121 static GTY((param_is (struct libfunc_entry))) htab_t libfunc_hash;
123 /* Used for attribute_hash. */
125 static hashval_t
126 hash_libfunc (const void *p)
128 const struct libfunc_entry *const e = (const struct libfunc_entry *) p;
130 return (((int) e->mode1 + (int) e->mode2 * NUM_MACHINE_MODES)
131 ^ e->optab);
134 /* Used for optab_hash. */
136 static int
137 eq_libfunc (const void *p, const void *q)
139 const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p;
140 const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q;
142 return (e1->optab == e2->optab
143 && e1->mode1 == e2->mode1
144 && e1->mode2 == e2->mode2);
147 /* Return libfunc corresponding operation defined by OPTAB converting
148 from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL
149 if no libfunc is available. */
151 convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
152 enum machine_mode mode2)
154 struct libfunc_entry e;
155 struct libfunc_entry **slot;
157 e.optab = (size_t) (optab - &convert_optab_table[0]);
158 e.mode1 = mode1;
159 e.mode2 = mode2;
160 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
161 if (!slot)
163 if (optab->libcall_gen)
165 optab->libcall_gen (optab, optab->libcall_basename, mode1, mode2);
166 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
167 if (slot)
168 return (*slot)->libfunc;
169 else
170 return NULL;
172 return NULL;
174 return (*slot)->libfunc;
177 /* Return libfunc corresponding operation defined by OPTAB in MODE.
178 Trigger lazy initialization if needed, return NULL if no libfunc is
179 available. */
181 optab_libfunc (optab optab, enum machine_mode mode)
183 struct libfunc_entry e;
184 struct libfunc_entry **slot;
186 e.optab = (size_t) (optab - &optab_table[0]);
187 e.mode1 = mode;
188 e.mode2 = VOIDmode;
189 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
190 if (!slot)
192 if (optab->libcall_gen)
194 optab->libcall_gen (optab, optab->libcall_basename,
195 optab->libcall_suffix, mode);
196 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash,
197 &e, NO_INSERT);
198 if (slot)
199 return (*slot)->libfunc;
200 else
201 return NULL;
203 return NULL;
205 return (*slot)->libfunc;
209 /* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
210 the result of operation CODE applied to OP0 (and OP1 if it is a binary
211 operation).
213 If the last insn does not set TARGET, don't do anything, but return 1.
215 If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
216 don't add the REG_EQUAL note but return 0. Our caller can then try
217 again, ensuring that TARGET is not one of the operands. */
219 static int
220 add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
222 rtx last_insn, insn, set;
223 rtx note;
225 gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
227 if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
228 && GET_RTX_CLASS (code) != RTX_BIN_ARITH
229 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
230 && GET_RTX_CLASS (code) != RTX_COMPARE
231 && GET_RTX_CLASS (code) != RTX_UNARY)
232 return 1;
234 if (GET_CODE (target) == ZERO_EXTRACT)
235 return 1;
237 for (last_insn = insns;
238 NEXT_INSN (last_insn) != NULL_RTX;
239 last_insn = NEXT_INSN (last_insn))
242 set = single_set (last_insn);
243 if (set == NULL_RTX)
244 return 1;
246 if (! rtx_equal_p (SET_DEST (set), target)
247 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it. */
248 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
249 || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
250 return 1;
252 /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
253 besides the last insn. */
254 if (reg_overlap_mentioned_p (target, op0)
255 || (op1 && reg_overlap_mentioned_p (target, op1)))
257 insn = PREV_INSN (last_insn);
258 while (insn != NULL_RTX)
260 if (reg_set_p (target, insn))
261 return 0;
263 insn = PREV_INSN (insn);
267 if (GET_RTX_CLASS (code) == RTX_UNARY)
268 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
269 else
270 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
272 set_unique_reg_note (last_insn, REG_EQUAL, note);
274 return 1;
277 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
278 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
279 not actually do a sign-extend or zero-extend, but can leave the
280 higher-order bits of the result rtx undefined, for example, in the case
281 of logical operations, but not right shifts. */
283 static rtx
284 widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
285 int unsignedp, int no_extend)
287 rtx result;
289 /* If we don't have to extend and this is a constant, return it. */
290 if (no_extend && GET_MODE (op) == VOIDmode)
291 return op;
293 /* If we must extend do so. If OP is a SUBREG for a promoted object, also
294 extend since it will be more efficient to do so unless the signedness of
295 a promoted object differs from our extension. */
296 if (! no_extend
297 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
298 && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
299 return convert_modes (mode, oldmode, op, unsignedp);
301 /* If MODE is no wider than a single word, we return a paradoxical
302 SUBREG. */
303 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
304 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
306 /* Otherwise, get an object of MODE, clobber it, and set the low-order
307 part to OP. */
309 result = gen_reg_rtx (mode);
310 emit_clobber (result);
311 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
312 return result;
315 /* Return the optab used for computing the operation given by the tree code,
316 CODE and the tree EXP. This function is not always usable (for example, it
317 cannot give complete results for multiplication or division) but probably
318 ought to be relied on more widely throughout the expander. */
319 optab
320 optab_for_tree_code (enum tree_code code, const_tree type,
321 enum optab_subtype subtype)
323 bool trapv;
324 switch (code)
326 case BIT_AND_EXPR:
327 return and_optab;
329 case BIT_IOR_EXPR:
330 return ior_optab;
332 case BIT_NOT_EXPR:
333 return one_cmpl_optab;
335 case BIT_XOR_EXPR:
336 return xor_optab;
338 case TRUNC_MOD_EXPR:
339 case CEIL_MOD_EXPR:
340 case FLOOR_MOD_EXPR:
341 case ROUND_MOD_EXPR:
342 return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
344 case RDIV_EXPR:
345 case TRUNC_DIV_EXPR:
346 case CEIL_DIV_EXPR:
347 case FLOOR_DIV_EXPR:
348 case ROUND_DIV_EXPR:
349 case EXACT_DIV_EXPR:
350 if (TYPE_SATURATING(type))
351 return TYPE_UNSIGNED(type) ? usdiv_optab : ssdiv_optab;
352 return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
354 case LSHIFT_EXPR:
355 if (VECTOR_MODE_P (TYPE_MODE (type)))
357 if (subtype == optab_vector)
358 return TYPE_SATURATING (type) ? NULL : vashl_optab;
360 gcc_assert (subtype == optab_scalar);
362 if (TYPE_SATURATING(type))
363 return TYPE_UNSIGNED(type) ? usashl_optab : ssashl_optab;
364 return ashl_optab;
366 case RSHIFT_EXPR:
367 if (VECTOR_MODE_P (TYPE_MODE (type)))
369 if (subtype == optab_vector)
370 return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
372 gcc_assert (subtype == optab_scalar);
374 return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
376 case LROTATE_EXPR:
377 if (VECTOR_MODE_P (TYPE_MODE (type)))
379 if (subtype == optab_vector)
380 return vrotl_optab;
382 gcc_assert (subtype == optab_scalar);
384 return rotl_optab;
386 case RROTATE_EXPR:
387 if (VECTOR_MODE_P (TYPE_MODE (type)))
389 if (subtype == optab_vector)
390 return vrotr_optab;
392 gcc_assert (subtype == optab_scalar);
394 return rotr_optab;
396 case MAX_EXPR:
397 return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
399 case MIN_EXPR:
400 return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
402 case REALIGN_LOAD_EXPR:
403 return vec_realign_load_optab;
405 case WIDEN_SUM_EXPR:
406 return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
408 case DOT_PROD_EXPR:
409 return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
411 case REDUC_MAX_EXPR:
412 return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab;
414 case REDUC_MIN_EXPR:
415 return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab;
417 case REDUC_PLUS_EXPR:
418 return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
420 case VEC_LSHIFT_EXPR:
421 return vec_shl_optab;
423 case VEC_RSHIFT_EXPR:
424 return vec_shr_optab;
426 case VEC_WIDEN_MULT_HI_EXPR:
427 return TYPE_UNSIGNED (type) ?
428 vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
430 case VEC_WIDEN_MULT_LO_EXPR:
431 return TYPE_UNSIGNED (type) ?
432 vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
434 case VEC_UNPACK_HI_EXPR:
435 return TYPE_UNSIGNED (type) ?
436 vec_unpacku_hi_optab : vec_unpacks_hi_optab;
438 case VEC_UNPACK_LO_EXPR:
439 return TYPE_UNSIGNED (type) ?
440 vec_unpacku_lo_optab : vec_unpacks_lo_optab;
442 case VEC_UNPACK_FLOAT_HI_EXPR:
443 /* The signedness is determined from input operand. */
444 return TYPE_UNSIGNED (type) ?
445 vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
447 case VEC_UNPACK_FLOAT_LO_EXPR:
448 /* The signedness is determined from input operand. */
449 return TYPE_UNSIGNED (type) ?
450 vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
452 case VEC_PACK_TRUNC_EXPR:
453 return vec_pack_trunc_optab;
455 case VEC_PACK_SAT_EXPR:
456 return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
458 case VEC_PACK_FIX_TRUNC_EXPR:
459 /* The signedness is determined from output operand. */
460 return TYPE_UNSIGNED (type) ?
461 vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
463 default:
464 break;
467 trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
468 switch (code)
470 case POINTER_PLUS_EXPR:
471 case PLUS_EXPR:
472 if (TYPE_SATURATING(type))
473 return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
474 return trapv ? addv_optab : add_optab;
476 case MINUS_EXPR:
477 if (TYPE_SATURATING(type))
478 return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
479 return trapv ? subv_optab : sub_optab;
481 case MULT_EXPR:
482 if (TYPE_SATURATING(type))
483 return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
484 return trapv ? smulv_optab : smul_optab;
486 case NEGATE_EXPR:
487 if (TYPE_SATURATING(type))
488 return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
489 return trapv ? negv_optab : neg_optab;
491 case ABS_EXPR:
492 return trapv ? absv_optab : abs_optab;
494 case VEC_EXTRACT_EVEN_EXPR:
495 return vec_extract_even_optab;
497 case VEC_EXTRACT_ODD_EXPR:
498 return vec_extract_odd_optab;
500 case VEC_INTERLEAVE_HIGH_EXPR:
501 return vec_interleave_high_optab;
503 case VEC_INTERLEAVE_LOW_EXPR:
504 return vec_interleave_low_optab;
506 default:
507 return NULL;
512 /* Expand vector widening operations.
514 There are two different classes of operations handled here:
515 1) Operations whose result is wider than all the arguments to the operation.
516 Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR
517 In this case OP0 and optionally OP1 would be initialized,
518 but WIDE_OP wouldn't (not relevant for this case).
519 2) Operations whose result is of the same size as the last argument to the
520 operation, but wider than all the other arguments to the operation.
521 Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR.
522 In the case WIDE_OP, OP0 and optionally OP1 would be initialized.
524 E.g, when called to expand the following operations, this is how
525 the arguments will be initialized:
526 nops OP0 OP1 WIDE_OP
527 widening-sum 2 oprnd0 - oprnd1
528 widening-dot-product 3 oprnd0 oprnd1 oprnd2
529 widening-mult 2 oprnd0 oprnd1 -
530 type-promotion (vec-unpack) 1 oprnd0 - - */
533 expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
534 rtx target, int unsignedp)
536 tree oprnd0, oprnd1, oprnd2;
537 enum machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
538 optab widen_pattern_optab;
539 int icode;
540 enum machine_mode xmode0, xmode1 = VOIDmode, wxmode = VOIDmode;
541 rtx temp;
542 rtx pat;
543 rtx xop0, xop1, wxop;
544 int nops = TREE_CODE_LENGTH (ops->code);
546 oprnd0 = ops->op0;
547 tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
548 widen_pattern_optab =
549 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
550 icode = (int) optab_handler (widen_pattern_optab, tmode0)->insn_code;
551 gcc_assert (icode != CODE_FOR_nothing);
552 xmode0 = insn_data[icode].operand[1].mode;
554 if (nops >= 2)
556 oprnd1 = ops->op1;
557 tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
558 xmode1 = insn_data[icode].operand[2].mode;
561 /* The last operand is of a wider mode than the rest of the operands. */
562 if (nops == 2)
564 wmode = tmode1;
565 wxmode = xmode1;
567 else if (nops == 3)
569 gcc_assert (tmode1 == tmode0);
570 gcc_assert (op1);
571 oprnd2 = ops->op2;
572 wmode = TYPE_MODE (TREE_TYPE (oprnd2));
573 wxmode = insn_data[icode].operand[3].mode;
576 if (!wide_op)
577 wmode = wxmode = insn_data[icode].operand[0].mode;
579 if (!target
580 || ! (*insn_data[icode].operand[0].predicate) (target, wmode))
581 temp = gen_reg_rtx (wmode);
582 else
583 temp = target;
585 xop0 = op0;
586 xop1 = op1;
587 wxop = wide_op;
589 /* In case the insn wants input operands in modes different from
590 those of the actual operands, convert the operands. It would
591 seem that we don't need to convert CONST_INTs, but we do, so
592 that they're properly zero-extended, sign-extended or truncated
593 for their mode. */
595 if (GET_MODE (op0) != xmode0 && xmode0 != VOIDmode)
596 xop0 = convert_modes (xmode0,
597 GET_MODE (op0) != VOIDmode
598 ? GET_MODE (op0)
599 : tmode0,
600 xop0, unsignedp);
602 if (op1)
603 if (GET_MODE (op1) != xmode1 && xmode1 != VOIDmode)
604 xop1 = convert_modes (xmode1,
605 GET_MODE (op1) != VOIDmode
606 ? GET_MODE (op1)
607 : tmode1,
608 xop1, unsignedp);
610 if (wide_op)
611 if (GET_MODE (wide_op) != wxmode && wxmode != VOIDmode)
612 wxop = convert_modes (wxmode,
613 GET_MODE (wide_op) != VOIDmode
614 ? GET_MODE (wide_op)
615 : wmode,
616 wxop, unsignedp);
618 /* Now, if insn's predicates don't allow our operands, put them into
619 pseudo regs. */
621 if (! (*insn_data[icode].operand[1].predicate) (xop0, xmode0)
622 && xmode0 != VOIDmode)
623 xop0 = copy_to_mode_reg (xmode0, xop0);
625 if (op1)
627 if (! (*insn_data[icode].operand[2].predicate) (xop1, xmode1)
628 && xmode1 != VOIDmode)
629 xop1 = copy_to_mode_reg (xmode1, xop1);
631 if (wide_op)
633 if (! (*insn_data[icode].operand[3].predicate) (wxop, wxmode)
634 && wxmode != VOIDmode)
635 wxop = copy_to_mode_reg (wxmode, wxop);
637 pat = GEN_FCN (icode) (temp, xop0, xop1, wxop);
639 else
640 pat = GEN_FCN (icode) (temp, xop0, xop1);
642 else
644 if (wide_op)
646 if (! (*insn_data[icode].operand[2].predicate) (wxop, wxmode)
647 && wxmode != VOIDmode)
648 wxop = copy_to_mode_reg (wxmode, wxop);
650 pat = GEN_FCN (icode) (temp, xop0, wxop);
652 else
653 pat = GEN_FCN (icode) (temp, xop0);
656 emit_insn (pat);
657 return temp;
660 /* Generate code to perform an operation specified by TERNARY_OPTAB
661 on operands OP0, OP1 and OP2, with result having machine-mode MODE.
663 UNSIGNEDP is for the case where we have to widen the operands
664 to perform the operation. It says to use zero-extension.
666 If TARGET is nonzero, the value
667 is generated there, if it is convenient to do so.
668 In all cases an rtx is returned for the locus of the value;
669 this may or may not be TARGET. */
672 expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
673 rtx op1, rtx op2, rtx target, int unsignedp)
675 int icode = (int) optab_handler (ternary_optab, mode)->insn_code;
676 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
677 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
678 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
679 rtx temp;
680 rtx pat;
681 rtx xop0 = op0, xop1 = op1, xop2 = op2;
683 gcc_assert (optab_handler (ternary_optab, mode)->insn_code
684 != CODE_FOR_nothing);
686 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
687 temp = gen_reg_rtx (mode);
688 else
689 temp = target;
691 /* In case the insn wants input operands in modes different from
692 those of the actual operands, convert the operands. It would
693 seem that we don't need to convert CONST_INTs, but we do, so
694 that they're properly zero-extended, sign-extended or truncated
695 for their mode. */
697 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
698 xop0 = convert_modes (mode0,
699 GET_MODE (op0) != VOIDmode
700 ? GET_MODE (op0)
701 : mode,
702 xop0, unsignedp);
704 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
705 xop1 = convert_modes (mode1,
706 GET_MODE (op1) != VOIDmode
707 ? GET_MODE (op1)
708 : mode,
709 xop1, unsignedp);
711 if (GET_MODE (op2) != mode2 && mode2 != VOIDmode)
712 xop2 = convert_modes (mode2,
713 GET_MODE (op2) != VOIDmode
714 ? GET_MODE (op2)
715 : mode,
716 xop2, unsignedp);
718 /* Now, if insn's predicates don't allow our operands, put them into
719 pseudo regs. */
721 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
722 && mode0 != VOIDmode)
723 xop0 = copy_to_mode_reg (mode0, xop0);
725 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
726 && mode1 != VOIDmode)
727 xop1 = copy_to_mode_reg (mode1, xop1);
729 if (!insn_data[icode].operand[3].predicate (xop2, mode2)
730 && mode2 != VOIDmode)
731 xop2 = copy_to_mode_reg (mode2, xop2);
733 pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
735 emit_insn (pat);
736 return temp;
740 /* Like expand_binop, but return a constant rtx if the result can be
741 calculated at compile time. The arguments and return value are
742 otherwise the same as for expand_binop. */
744 static rtx
745 simplify_expand_binop (enum machine_mode mode, optab binoptab,
746 rtx op0, rtx op1, rtx target, int unsignedp,
747 enum optab_methods methods)
749 if (CONSTANT_P (op0) && CONSTANT_P (op1))
751 rtx x = simplify_binary_operation (binoptab->code, mode, op0, op1);
753 if (x)
754 return x;
757 return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
760 /* Like simplify_expand_binop, but always put the result in TARGET.
761 Return true if the expansion succeeded. */
763 bool
764 force_expand_binop (enum machine_mode mode, optab binoptab,
765 rtx op0, rtx op1, rtx target, int unsignedp,
766 enum optab_methods methods)
768 rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
769 target, unsignedp, methods);
770 if (x == 0)
771 return false;
772 if (x != target)
773 emit_move_insn (target, x);
774 return true;
777 /* Generate insns for VEC_LSHIFT_EXPR, VEC_RSHIFT_EXPR. */
780 expand_vec_shift_expr (sepops ops, rtx target)
782 enum insn_code icode;
783 rtx rtx_op1, rtx_op2;
784 enum machine_mode mode1;
785 enum machine_mode mode2;
786 enum machine_mode mode = TYPE_MODE (ops->type);
787 tree vec_oprnd = ops->op0;
788 tree shift_oprnd = ops->op1;
789 optab shift_optab;
790 rtx pat;
792 switch (ops->code)
794 case VEC_RSHIFT_EXPR:
795 shift_optab = vec_shr_optab;
796 break;
797 case VEC_LSHIFT_EXPR:
798 shift_optab = vec_shl_optab;
799 break;
800 default:
801 gcc_unreachable ();
804 icode = optab_handler (shift_optab, mode)->insn_code;
805 gcc_assert (icode != CODE_FOR_nothing);
807 mode1 = insn_data[icode].operand[1].mode;
808 mode2 = insn_data[icode].operand[2].mode;
810 rtx_op1 = expand_normal (vec_oprnd);
811 if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode1)
812 && mode1 != VOIDmode)
813 rtx_op1 = force_reg (mode1, rtx_op1);
815 rtx_op2 = expand_normal (shift_oprnd);
816 if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode2)
817 && mode2 != VOIDmode)
818 rtx_op2 = force_reg (mode2, rtx_op2);
820 if (!target
821 || ! (*insn_data[icode].operand[0].predicate) (target, mode))
822 target = gen_reg_rtx (mode);
824 /* Emit instruction */
825 pat = GEN_FCN (icode) (target, rtx_op1, rtx_op2);
826 gcc_assert (pat);
827 emit_insn (pat);
829 return target;
832 /* This subroutine of expand_doubleword_shift handles the cases in which
833 the effective shift value is >= BITS_PER_WORD. The arguments and return
834 value are the same as for the parent routine, except that SUPERWORD_OP1
835 is the shift count to use when shifting OUTOF_INPUT into INTO_TARGET.
836 INTO_TARGET may be null if the caller has decided to calculate it. */
838 static bool
839 expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
840 rtx outof_target, rtx into_target,
841 int unsignedp, enum optab_methods methods)
843 if (into_target != 0)
844 if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
845 into_target, unsignedp, methods))
846 return false;
848 if (outof_target != 0)
850 /* For a signed right shift, we must fill OUTOF_TARGET with copies
851 of the sign bit, otherwise we must fill it with zeros. */
852 if (binoptab != ashr_optab)
853 emit_move_insn (outof_target, CONST0_RTX (word_mode));
854 else
855 if (!force_expand_binop (word_mode, binoptab,
856 outof_input, GEN_INT (BITS_PER_WORD - 1),
857 outof_target, unsignedp, methods))
858 return false;
860 return true;
863 /* This subroutine of expand_doubleword_shift handles the cases in which
864 the effective shift value is < BITS_PER_WORD. The arguments and return
865 value are the same as for the parent routine. */
867 static bool
868 expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
869 rtx outof_input, rtx into_input, rtx op1,
870 rtx outof_target, rtx into_target,
871 int unsignedp, enum optab_methods methods,
872 unsigned HOST_WIDE_INT shift_mask)
874 optab reverse_unsigned_shift, unsigned_shift;
875 rtx tmp, carries;
877 reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
878 unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
880 /* The low OP1 bits of INTO_TARGET come from the high bits of OUTOF_INPUT.
881 We therefore need to shift OUTOF_INPUT by (BITS_PER_WORD - OP1) bits in
882 the opposite direction to BINOPTAB. */
883 if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
885 carries = outof_input;
886 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
887 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
888 0, true, methods);
890 else
892 /* We must avoid shifting by BITS_PER_WORD bits since that is either
893 the same as a zero shift (if shift_mask == BITS_PER_WORD - 1) or
894 has unknown behavior. Do a single shift first, then shift by the
895 remainder. It's OK to use ~OP1 as the remainder if shift counts
896 are truncated to the mode size. */
897 carries = expand_binop (word_mode, reverse_unsigned_shift,
898 outof_input, const1_rtx, 0, unsignedp, methods);
899 if (shift_mask == BITS_PER_WORD - 1)
901 tmp = immed_double_const (-1, -1, op1_mode);
902 tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
903 0, true, methods);
905 else
907 tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode);
908 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
909 0, true, methods);
912 if (tmp == 0 || carries == 0)
913 return false;
914 carries = expand_binop (word_mode, reverse_unsigned_shift,
915 carries, tmp, 0, unsignedp, methods);
916 if (carries == 0)
917 return false;
919 /* Shift INTO_INPUT logically by OP1. This is the last use of INTO_INPUT
920 so the result can go directly into INTO_TARGET if convenient. */
921 tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
922 into_target, unsignedp, methods);
923 if (tmp == 0)
924 return false;
926 /* Now OR in the bits carried over from OUTOF_INPUT. */
927 if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
928 into_target, unsignedp, methods))
929 return false;
931 /* Use a standard word_mode shift for the out-of half. */
932 if (outof_target != 0)
933 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
934 outof_target, unsignedp, methods))
935 return false;
937 return true;
941 #ifdef HAVE_conditional_move
942 /* Try implementing expand_doubleword_shift using conditional moves.
943 The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
944 otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1
945 are the shift counts to use in the former and latter case. All other
946 arguments are the same as the parent routine. */
948 static bool
949 expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
950 enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
951 rtx outof_input, rtx into_input,
952 rtx subword_op1, rtx superword_op1,
953 rtx outof_target, rtx into_target,
954 int unsignedp, enum optab_methods methods,
955 unsigned HOST_WIDE_INT shift_mask)
957 rtx outof_superword, into_superword;
959 /* Put the superword version of the output into OUTOF_SUPERWORD and
960 INTO_SUPERWORD. */
961 outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
962 if (outof_target != 0 && subword_op1 == superword_op1)
964 /* The value INTO_TARGET >> SUBWORD_OP1, which we later store in
965 OUTOF_TARGET, is the same as the value of INTO_SUPERWORD. */
966 into_superword = outof_target;
967 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
968 outof_superword, 0, unsignedp, methods))
969 return false;
971 else
973 into_superword = gen_reg_rtx (word_mode);
974 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
975 outof_superword, into_superword,
976 unsignedp, methods))
977 return false;
980 /* Put the subword version directly in OUTOF_TARGET and INTO_TARGET. */
981 if (!expand_subword_shift (op1_mode, binoptab,
982 outof_input, into_input, subword_op1,
983 outof_target, into_target,
984 unsignedp, methods, shift_mask))
985 return false;
987 /* Select between them. Do the INTO half first because INTO_SUPERWORD
988 might be the current value of OUTOF_TARGET. */
989 if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
990 into_target, into_superword, word_mode, false))
991 return false;
993 if (outof_target != 0)
994 if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
995 outof_target, outof_superword,
996 word_mode, false))
997 return false;
999 return true;
1001 #endif
1003 /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
1004 OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
1005 input operand; the shift moves bits in the direction OUTOF_INPUT->
1006 INTO_TARGET. OUTOF_TARGET and INTO_TARGET are the equivalent words
1007 of the target. OP1 is the shift count and OP1_MODE is its mode.
1008 If OP1 is constant, it will have been truncated as appropriate
1009 and is known to be nonzero.
1011 If SHIFT_MASK is zero, the result of word shifts is undefined when the
1012 shift count is outside the range [0, BITS_PER_WORD). This routine must
1013 avoid generating such shifts for OP1s in the range [0, BITS_PER_WORD * 2).
1015 If SHIFT_MASK is nonzero, all word-mode shift counts are effectively
1016 masked by it and shifts in the range [BITS_PER_WORD, SHIFT_MASK) will
1017 fill with zeros or sign bits as appropriate.
1019 If SHIFT_MASK is BITS_PER_WORD - 1, this routine will synthesize
1020 a doubleword shift whose equivalent mask is BITS_PER_WORD * 2 - 1.
1021 Doing this preserves semantics required by SHIFT_COUNT_TRUNCATED.
1022 In all other cases, shifts by values outside [0, BITS_PER_UNIT * 2)
1023 are undefined.
1025 BINOPTAB, UNSIGNEDP and METHODS are as for expand_binop. This function
1026 may not use INTO_INPUT after modifying INTO_TARGET, and similarly for
1027 OUTOF_INPUT and OUTOF_TARGET. OUTOF_TARGET can be null if the parent
1028 function wants to calculate it itself.
1030 Return true if the shift could be successfully synthesized. */
1032 static bool
1033 expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
1034 rtx outof_input, rtx into_input, rtx op1,
1035 rtx outof_target, rtx into_target,
1036 int unsignedp, enum optab_methods methods,
1037 unsigned HOST_WIDE_INT shift_mask)
1039 rtx superword_op1, tmp, cmp1, cmp2;
1040 rtx subword_label, done_label;
1041 enum rtx_code cmp_code;
1043 /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
1044 fill the result with sign or zero bits as appropriate. If so, the value
1045 of OUTOF_TARGET will always be (SHIFT OUTOF_INPUT OP1). Recursively call
1046 this routine to calculate INTO_TARGET (which depends on both OUTOF_INPUT
1047 and INTO_INPUT), then emit code to set up OUTOF_TARGET.
1049 This isn't worthwhile for constant shifts since the optimizers will
1050 cope better with in-range shift counts. */
1051 if (shift_mask >= BITS_PER_WORD
1052 && outof_target != 0
1053 && !CONSTANT_P (op1))
1055 if (!expand_doubleword_shift (op1_mode, binoptab,
1056 outof_input, into_input, op1,
1057 0, into_target,
1058 unsignedp, methods, shift_mask))
1059 return false;
1060 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
1061 outof_target, unsignedp, methods))
1062 return false;
1063 return true;
1066 /* Set CMP_CODE, CMP1 and CMP2 so that the rtx (CMP_CODE CMP1 CMP2)
1067 is true when the effective shift value is less than BITS_PER_WORD.
1068 Set SUPERWORD_OP1 to the shift count that should be used to shift
1069 OUTOF_INPUT into INTO_TARGET when the condition is false. */
1070 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
1071 if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
1073 /* Set CMP1 to OP1 & BITS_PER_WORD. The result is zero iff OP1
1074 is a subword shift count. */
1075 cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
1076 0, true, methods);
1077 cmp2 = CONST0_RTX (op1_mode);
1078 cmp_code = EQ;
1079 superword_op1 = op1;
1081 else
1083 /* Set CMP1 to OP1 - BITS_PER_WORD. */
1084 cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
1085 0, true, methods);
1086 cmp2 = CONST0_RTX (op1_mode);
1087 cmp_code = LT;
1088 superword_op1 = cmp1;
1090 if (cmp1 == 0)
1091 return false;
1093 /* If we can compute the condition at compile time, pick the
1094 appropriate subroutine. */
1095 tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
1096 if (tmp != 0 && CONST_INT_P (tmp))
1098 if (tmp == const0_rtx)
1099 return expand_superword_shift (binoptab, outof_input, superword_op1,
1100 outof_target, into_target,
1101 unsignedp, methods);
1102 else
1103 return expand_subword_shift (op1_mode, binoptab,
1104 outof_input, into_input, op1,
1105 outof_target, into_target,
1106 unsignedp, methods, shift_mask);
1109 #ifdef HAVE_conditional_move
1110 /* Try using conditional moves to generate straight-line code. */
1112 rtx start = get_last_insn ();
1113 if (expand_doubleword_shift_condmove (op1_mode, binoptab,
1114 cmp_code, cmp1, cmp2,
1115 outof_input, into_input,
1116 op1, superword_op1,
1117 outof_target, into_target,
1118 unsignedp, methods, shift_mask))
1119 return true;
1120 delete_insns_since (start);
1122 #endif
1124 /* As a last resort, use branches to select the correct alternative. */
1125 subword_label = gen_label_rtx ();
1126 done_label = gen_label_rtx ();
1128 NO_DEFER_POP;
1129 do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
1130 0, 0, subword_label, -1);
1131 OK_DEFER_POP;
1133 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
1134 outof_target, into_target,
1135 unsignedp, methods))
1136 return false;
1138 emit_jump_insn (gen_jump (done_label));
1139 emit_barrier ();
1140 emit_label (subword_label);
1142 if (!expand_subword_shift (op1_mode, binoptab,
1143 outof_input, into_input, op1,
1144 outof_target, into_target,
1145 unsignedp, methods, shift_mask))
1146 return false;
1148 emit_label (done_label);
1149 return true;
1152 /* Subroutine of expand_binop. Perform a double word multiplication of
1153 operands OP0 and OP1 both of mode MODE, which is exactly twice as wide
1154 as the target's word_mode. This function return NULL_RTX if anything
1155 goes wrong, in which case it may have already emitted instructions
1156 which need to be deleted.
1158 If we want to multiply two two-word values and have normal and widening
1159 multiplies of single-word values, we can do this with three smaller
1160 multiplications.
1162 The multiplication proceeds as follows:
1163 _______________________
1164 [__op0_high_|__op0_low__]
1165 _______________________
1166 * [__op1_high_|__op1_low__]
1167 _______________________________________________
1168 _______________________
1169 (1) [__op0_low__*__op1_low__]
1170 _______________________
1171 (2a) [__op0_low__*__op1_high_]
1172 _______________________
1173 (2b) [__op0_high_*__op1_low__]
1174 _______________________
1175 (3) [__op0_high_*__op1_high_]
1178 This gives a 4-word result. Since we are only interested in the
1179 lower 2 words, partial result (3) and the upper words of (2a) and
1180 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1181 calculated using non-widening multiplication.
1183 (1), however, needs to be calculated with an unsigned widening
1184 multiplication. If this operation is not directly supported we
1185 try using a signed widening multiplication and adjust the result.
1186 This adjustment works as follows:
1188 If both operands are positive then no adjustment is needed.
1190 If the operands have different signs, for example op0_low < 0 and
1191 op1_low >= 0, the instruction treats the most significant bit of
1192 op0_low as a sign bit instead of a bit with significance
1193 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1194 with 2**BITS_PER_WORD - op0_low, and two's complements the
1195 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1196 the result.
1198 Similarly, if both operands are negative, we need to add
1199 (op0_low + op1_low) * 2**BITS_PER_WORD.
1201 We use a trick to adjust quickly. We logically shift op0_low right
1202 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1203 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1204 logical shift exists, we do an arithmetic right shift and subtract
1205 the 0 or -1. */
1207 static rtx
1208 expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
1209 bool umulp, enum optab_methods methods)
1211 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1212 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1213 rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
1214 rtx product, adjust, product_high, temp;
1216 rtx op0_high = operand_subword_force (op0, high, mode);
1217 rtx op0_low = operand_subword_force (op0, low, mode);
1218 rtx op1_high = operand_subword_force (op1, high, mode);
1219 rtx op1_low = operand_subword_force (op1, low, mode);
1221 /* If we're using an unsigned multiply to directly compute the product
1222 of the low-order words of the operands and perform any required
1223 adjustments of the operands, we begin by trying two more multiplications
1224 and then computing the appropriate sum.
1226 We have checked above that the required addition is provided.
1227 Full-word addition will normally always succeed, especially if
1228 it is provided at all, so we don't worry about its failure. The
1229 multiplication may well fail, however, so we do handle that. */
1231 if (!umulp)
1233 /* ??? This could be done with emit_store_flag where available. */
1234 temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1235 NULL_RTX, 1, methods);
1236 if (temp)
1237 op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
1238 NULL_RTX, 0, OPTAB_DIRECT);
1239 else
1241 temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1242 NULL_RTX, 0, methods);
1243 if (!temp)
1244 return NULL_RTX;
1245 op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
1246 NULL_RTX, 0, OPTAB_DIRECT);
1249 if (!op0_high)
1250 return NULL_RTX;
1253 adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
1254 NULL_RTX, 0, OPTAB_DIRECT);
1255 if (!adjust)
1256 return NULL_RTX;
1258 /* OP0_HIGH should now be dead. */
1260 if (!umulp)
1262 /* ??? This could be done with emit_store_flag where available. */
1263 temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1264 NULL_RTX, 1, methods);
1265 if (temp)
1266 op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
1267 NULL_RTX, 0, OPTAB_DIRECT);
1268 else
1270 temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1271 NULL_RTX, 0, methods);
1272 if (!temp)
1273 return NULL_RTX;
1274 op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
1275 NULL_RTX, 0, OPTAB_DIRECT);
1278 if (!op1_high)
1279 return NULL_RTX;
1282 temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
1283 NULL_RTX, 0, OPTAB_DIRECT);
1284 if (!temp)
1285 return NULL_RTX;
1287 /* OP1_HIGH should now be dead. */
1289 adjust = expand_binop (word_mode, add_optab, adjust, temp,
1290 adjust, 0, OPTAB_DIRECT);
1292 if (target && !REG_P (target))
1293 target = NULL_RTX;
1295 if (umulp)
1296 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1297 target, 1, OPTAB_DIRECT);
1298 else
1299 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1300 target, 1, OPTAB_DIRECT);
1302 if (!product)
1303 return NULL_RTX;
1305 product_high = operand_subword (product, high, 1, mode);
1306 adjust = expand_binop (word_mode, add_optab, product_high, adjust,
1307 REG_P (product_high) ? product_high : adjust,
1308 0, OPTAB_DIRECT);
1309 emit_move_insn (product_high, adjust);
1310 return product;
1313 /* Wrapper around expand_binop which takes an rtx code to specify
1314 the operation to perform, not an optab pointer. All other
1315 arguments are the same. */
1317 expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
1318 rtx op1, rtx target, int unsignedp,
1319 enum optab_methods methods)
1321 optab binop = code_to_optab[(int) code];
1322 gcc_assert (binop);
1324 return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
1327 /* Return whether OP0 and OP1 should be swapped when expanding a commutative
1328 binop. Order them according to commutative_operand_precedence and, if
1329 possible, try to put TARGET or a pseudo first. */
1330 static bool
1331 swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
1333 int op0_prec = commutative_operand_precedence (op0);
1334 int op1_prec = commutative_operand_precedence (op1);
1336 if (op0_prec < op1_prec)
1337 return true;
1339 if (op0_prec > op1_prec)
1340 return false;
1342 /* With equal precedence, both orders are ok, but it is better if the
1343 first operand is TARGET, or if both TARGET and OP0 are pseudos. */
1344 if (target == 0 || REG_P (target))
1345 return (REG_P (op1) && !REG_P (op0)) || target == op1;
1346 else
1347 return rtx_equal_p (op1, target);
1350 /* Return true if BINOPTAB implements a shift operation. */
1352 static bool
1353 shift_optab_p (optab binoptab)
1355 switch (binoptab->code)
1357 case ASHIFT:
1358 case SS_ASHIFT:
1359 case US_ASHIFT:
1360 case ASHIFTRT:
1361 case LSHIFTRT:
1362 case ROTATE:
1363 case ROTATERT:
1364 return true;
1366 default:
1367 return false;
1371 /* Return true if BINOPTAB implements a commutative binary operation. */
1373 static bool
1374 commutative_optab_p (optab binoptab)
1376 return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
1377 || binoptab == smul_widen_optab
1378 || binoptab == umul_widen_optab
1379 || binoptab == smul_highpart_optab
1380 || binoptab == umul_highpart_optab);
1383 /* X is to be used in mode MODE as an operand to BINOPTAB. If we're
1384 optimizing, and if the operand is a constant that costs more than
1385 1 instruction, force the constant into a register and return that
1386 register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */
1388 static rtx
1389 avoid_expensive_constant (enum machine_mode mode, optab binoptab,
1390 rtx x, bool unsignedp)
1392 if (mode != VOIDmode
1393 && optimize
1394 && CONSTANT_P (x)
1395 && rtx_cost (x, binoptab->code, optimize_insn_for_speed_p ())
1396 > COSTS_N_INSNS (1))
1398 if (CONST_INT_P (x))
1400 HOST_WIDE_INT intval = trunc_int_for_mode (INTVAL (x), mode);
1401 if (intval != INTVAL (x))
1402 x = GEN_INT (intval);
1404 else
1405 x = convert_modes (mode, VOIDmode, x, unsignedp);
1406 x = force_reg (mode, x);
1408 return x;
1411 /* Helper function for expand_binop: handle the case where there
1412 is an insn that directly implements the indicated operation.
1413 Returns null if this is not possible. */
1414 static rtx
1415 expand_binop_directly (enum machine_mode mode, optab binoptab,
1416 rtx op0, rtx op1,
1417 rtx target, int unsignedp, enum optab_methods methods,
1418 rtx last)
1420 int icode = (int) optab_handler (binoptab, mode)->insn_code;
1421 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
1422 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
1423 enum machine_mode tmp_mode;
1424 bool commutative_p;
1425 rtx pat;
1426 rtx xop0 = op0, xop1 = op1;
1427 rtx temp;
1428 rtx swap;
1430 if (target)
1431 temp = target;
1432 else
1433 temp = gen_reg_rtx (mode);
1435 /* If it is a commutative operator and the modes would match
1436 if we would swap the operands, we can save the conversions. */
1437 commutative_p = commutative_optab_p (binoptab);
1438 if (commutative_p
1439 && GET_MODE (xop0) != mode0 && GET_MODE (xop1) != mode1
1440 && GET_MODE (xop0) == mode1 && GET_MODE (xop1) == mode1)
1442 swap = xop0;
1443 xop0 = xop1;
1444 xop1 = swap;
1447 /* If we are optimizing, force expensive constants into a register. */
1448 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
1449 if (!shift_optab_p (binoptab))
1450 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
1452 /* In case the insn wants input operands in modes different from
1453 those of the actual operands, convert the operands. It would
1454 seem that we don't need to convert CONST_INTs, but we do, so
1455 that they're properly zero-extended, sign-extended or truncated
1456 for their mode. */
1458 if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode)
1459 xop0 = convert_modes (mode0,
1460 GET_MODE (xop0) != VOIDmode
1461 ? GET_MODE (xop0)
1462 : mode,
1463 xop0, unsignedp);
1465 if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode)
1466 xop1 = convert_modes (mode1,
1467 GET_MODE (xop1) != VOIDmode
1468 ? GET_MODE (xop1)
1469 : mode,
1470 xop1, unsignedp);
1472 /* If operation is commutative,
1473 try to make the first operand a register.
1474 Even better, try to make it the same as the target.
1475 Also try to make the last operand a constant. */
1476 if (commutative_p
1477 && swap_commutative_operands_with_target (target, xop0, xop1))
1479 swap = xop1;
1480 xop1 = xop0;
1481 xop0 = swap;
1484 /* Now, if insn's predicates don't allow our operands, put them into
1485 pseudo regs. */
1487 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
1488 && mode0 != VOIDmode)
1489 xop0 = copy_to_mode_reg (mode0, xop0);
1491 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
1492 && mode1 != VOIDmode)
1493 xop1 = copy_to_mode_reg (mode1, xop1);
1495 if (binoptab == vec_pack_trunc_optab
1496 || binoptab == vec_pack_usat_optab
1497 || binoptab == vec_pack_ssat_optab
1498 || binoptab == vec_pack_ufix_trunc_optab
1499 || binoptab == vec_pack_sfix_trunc_optab)
1501 /* The mode of the result is different then the mode of the
1502 arguments. */
1503 tmp_mode = insn_data[icode].operand[0].mode;
1504 if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
1505 return 0;
1507 else
1508 tmp_mode = mode;
1510 if (!insn_data[icode].operand[0].predicate (temp, tmp_mode))
1511 temp = gen_reg_rtx (tmp_mode);
1513 pat = GEN_FCN (icode) (temp, xop0, xop1);
1514 if (pat)
1516 /* If PAT is composed of more than one insn, try to add an appropriate
1517 REG_EQUAL note to it. If we can't because TEMP conflicts with an
1518 operand, call expand_binop again, this time without a target. */
1519 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
1520 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
1522 delete_insns_since (last);
1523 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
1524 unsignedp, methods);
1527 emit_insn (pat);
1528 return temp;
1531 delete_insns_since (last);
1532 return NULL_RTX;
1535 /* Generate code to perform an operation specified by BINOPTAB
1536 on operands OP0 and OP1, with result having machine-mode MODE.
1538 UNSIGNEDP is for the case where we have to widen the operands
1539 to perform the operation. It says to use zero-extension.
1541 If TARGET is nonzero, the value
1542 is generated there, if it is convenient to do so.
1543 In all cases an rtx is returned for the locus of the value;
1544 this may or may not be TARGET. */
1547 expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
1548 rtx target, int unsignedp, enum optab_methods methods)
1550 enum optab_methods next_methods
1551 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
1552 ? OPTAB_WIDEN : methods);
1553 enum mode_class mclass;
1554 enum machine_mode wider_mode;
1555 rtx libfunc;
1556 rtx temp;
1557 rtx entry_last = get_last_insn ();
1558 rtx last;
1560 mclass = GET_MODE_CLASS (mode);
1562 /* If subtracting an integer constant, convert this into an addition of
1563 the negated constant. */
1565 if (binoptab == sub_optab && CONST_INT_P (op1))
1567 op1 = negate_rtx (mode, op1);
1568 binoptab = add_optab;
1571 /* Record where to delete back to if we backtrack. */
1572 last = get_last_insn ();
1574 /* If we can do it with a three-operand insn, do so. */
1576 if (methods != OPTAB_MUST_WIDEN
1577 && optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing)
1579 temp = expand_binop_directly (mode, binoptab, op0, op1, target,
1580 unsignedp, methods, last);
1581 if (temp)
1582 return temp;
1585 /* If we were trying to rotate, and that didn't work, try rotating
1586 the other direction before falling back to shifts and bitwise-or. */
1587 if (((binoptab == rotl_optab
1588 && optab_handler (rotr_optab, mode)->insn_code != CODE_FOR_nothing)
1589 || (binoptab == rotr_optab
1590 && optab_handler (rotl_optab, mode)->insn_code != CODE_FOR_nothing))
1591 && mclass == MODE_INT)
1593 optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
1594 rtx newop1;
1595 unsigned int bits = GET_MODE_BITSIZE (mode);
1597 if (CONST_INT_P (op1))
1598 newop1 = GEN_INT (bits - INTVAL (op1));
1599 else if (targetm.shift_truncation_mask (mode) == bits - 1)
1600 newop1 = negate_rtx (GET_MODE (op1), op1);
1601 else
1602 newop1 = expand_binop (GET_MODE (op1), sub_optab,
1603 GEN_INT (bits), op1,
1604 NULL_RTX, unsignedp, OPTAB_DIRECT);
1606 temp = expand_binop_directly (mode, otheroptab, op0, newop1,
1607 target, unsignedp, methods, last);
1608 if (temp)
1609 return temp;
1612 /* If this is a multiply, see if we can do a widening operation that
1613 takes operands of this mode and makes a wider mode. */
1615 if (binoptab == smul_optab
1616 && GET_MODE_WIDER_MODE (mode) != VOIDmode
1617 && ((optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab),
1618 GET_MODE_WIDER_MODE (mode))->insn_code)
1619 != CODE_FOR_nothing))
1621 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
1622 unsignedp ? umul_widen_optab : smul_widen_optab,
1623 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
1625 if (temp != 0)
1627 if (GET_MODE_CLASS (mode) == MODE_INT
1628 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1629 GET_MODE_BITSIZE (GET_MODE (temp))))
1630 return gen_lowpart (mode, temp);
1631 else
1632 return convert_to_mode (mode, temp, unsignedp);
1636 /* Look for a wider mode of the same class for which we think we
1637 can open-code the operation. Check for a widening multiply at the
1638 wider mode as well. */
1640 if (CLASS_HAS_WIDER_MODES_P (mclass)
1641 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
1642 for (wider_mode = GET_MODE_WIDER_MODE (mode);
1643 wider_mode != VOIDmode;
1644 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1646 if (optab_handler (binoptab, wider_mode)->insn_code != CODE_FOR_nothing
1647 || (binoptab == smul_optab
1648 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
1649 && ((optab_handler ((unsignedp ? umul_widen_optab
1650 : smul_widen_optab),
1651 GET_MODE_WIDER_MODE (wider_mode))->insn_code)
1652 != CODE_FOR_nothing)))
1654 rtx xop0 = op0, xop1 = op1;
1655 int no_extend = 0;
1657 /* For certain integer operations, we need not actually extend
1658 the narrow operands, as long as we will truncate
1659 the results to the same narrowness. */
1661 if ((binoptab == ior_optab || binoptab == and_optab
1662 || binoptab == xor_optab
1663 || binoptab == add_optab || binoptab == sub_optab
1664 || binoptab == smul_optab || binoptab == ashl_optab)
1665 && mclass == MODE_INT)
1667 no_extend = 1;
1668 xop0 = avoid_expensive_constant (mode, binoptab,
1669 xop0, unsignedp);
1670 if (binoptab != ashl_optab)
1671 xop1 = avoid_expensive_constant (mode, binoptab,
1672 xop1, unsignedp);
1675 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
1677 /* The second operand of a shift must always be extended. */
1678 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1679 no_extend && binoptab != ashl_optab);
1681 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1682 unsignedp, OPTAB_DIRECT);
1683 if (temp)
1685 if (mclass != MODE_INT
1686 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
1687 GET_MODE_BITSIZE (wider_mode)))
1689 if (target == 0)
1690 target = gen_reg_rtx (mode);
1691 convert_move (target, temp, 0);
1692 return target;
1694 else
1695 return gen_lowpart (mode, temp);
1697 else
1698 delete_insns_since (last);
1702 /* If operation is commutative,
1703 try to make the first operand a register.
1704 Even better, try to make it the same as the target.
1705 Also try to make the last operand a constant. */
1706 if (commutative_optab_p (binoptab)
1707 && swap_commutative_operands_with_target (target, op0, op1))
1709 temp = op1;
1710 op1 = op0;
1711 op0 = temp;
1714 /* These can be done a word at a time. */
1715 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
1716 && mclass == MODE_INT
1717 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
1718 && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
1720 int i;
1721 rtx insns;
1723 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1724 won't be accurate, so use a new target. */
1725 if (target == 0 || target == op0 || target == op1)
1726 target = gen_reg_rtx (mode);
1728 start_sequence ();
1730 /* Do the actual arithmetic. */
1731 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1733 rtx target_piece = operand_subword (target, i, 1, mode);
1734 rtx x = expand_binop (word_mode, binoptab,
1735 operand_subword_force (op0, i, mode),
1736 operand_subword_force (op1, i, mode),
1737 target_piece, unsignedp, next_methods);
1739 if (x == 0)
1740 break;
1742 if (target_piece != x)
1743 emit_move_insn (target_piece, x);
1746 insns = get_insns ();
1747 end_sequence ();
1749 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1751 emit_insn (insns);
1752 return target;
1756 /* Synthesize double word shifts from single word shifts. */
1757 if ((binoptab == lshr_optab || binoptab == ashl_optab
1758 || binoptab == ashr_optab)
1759 && mclass == MODE_INT
1760 && (CONST_INT_P (op1) || optimize_insn_for_speed_p ())
1761 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1762 && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing
1763 && optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
1764 && optab_handler (lshr_optab, word_mode)->insn_code != CODE_FOR_nothing)
1766 unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
1767 enum machine_mode op1_mode;
1769 double_shift_mask = targetm.shift_truncation_mask (mode);
1770 shift_mask = targetm.shift_truncation_mask (word_mode);
1771 op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
1773 /* Apply the truncation to constant shifts. */
1774 if (double_shift_mask > 0 && CONST_INT_P (op1))
1775 op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
1777 if (op1 == CONST0_RTX (op1_mode))
1778 return op0;
1780 /* Make sure that this is a combination that expand_doubleword_shift
1781 can handle. See the comments there for details. */
1782 if (double_shift_mask == 0
1783 || (shift_mask == BITS_PER_WORD - 1
1784 && double_shift_mask == BITS_PER_WORD * 2 - 1))
1786 rtx insns;
1787 rtx into_target, outof_target;
1788 rtx into_input, outof_input;
1789 int left_shift, outof_word;
1791 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1792 won't be accurate, so use a new target. */
1793 if (target == 0 || target == op0 || target == op1)
1794 target = gen_reg_rtx (mode);
1796 start_sequence ();
1798 /* OUTOF_* is the word we are shifting bits away from, and
1799 INTO_* is the word that we are shifting bits towards, thus
1800 they differ depending on the direction of the shift and
1801 WORDS_BIG_ENDIAN. */
1803 left_shift = binoptab == ashl_optab;
1804 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1806 outof_target = operand_subword (target, outof_word, 1, mode);
1807 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1809 outof_input = operand_subword_force (op0, outof_word, mode);
1810 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1812 if (expand_doubleword_shift (op1_mode, binoptab,
1813 outof_input, into_input, op1,
1814 outof_target, into_target,
1815 unsignedp, next_methods, shift_mask))
1817 insns = get_insns ();
1818 end_sequence ();
1820 emit_insn (insns);
1821 return target;
1823 end_sequence ();
1827 /* Synthesize double word rotates from single word shifts. */
1828 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1829 && mclass == MODE_INT
1830 && CONST_INT_P (op1)
1831 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1832 && optab_handler (ashl_optab, word_mode)->insn_code != CODE_FOR_nothing
1833 && optab_handler (lshr_optab, word_mode)->insn_code != CODE_FOR_nothing)
1835 rtx insns;
1836 rtx into_target, outof_target;
1837 rtx into_input, outof_input;
1838 rtx inter;
1839 int shift_count, left_shift, outof_word;
1841 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1842 won't be accurate, so use a new target. Do this also if target is not
1843 a REG, first because having a register instead may open optimization
1844 opportunities, and second because if target and op0 happen to be MEMs
1845 designating the same location, we would risk clobbering it too early
1846 in the code sequence we generate below. */
1847 if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
1848 target = gen_reg_rtx (mode);
1850 start_sequence ();
1852 shift_count = INTVAL (op1);
1854 /* OUTOF_* is the word we are shifting bits away from, and
1855 INTO_* is the word that we are shifting bits towards, thus
1856 they differ depending on the direction of the shift and
1857 WORDS_BIG_ENDIAN. */
1859 left_shift = (binoptab == rotl_optab);
1860 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1862 outof_target = operand_subword (target, outof_word, 1, mode);
1863 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1865 outof_input = operand_subword_force (op0, outof_word, mode);
1866 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1868 if (shift_count == BITS_PER_WORD)
1870 /* This is just a word swap. */
1871 emit_move_insn (outof_target, into_input);
1872 emit_move_insn (into_target, outof_input);
1873 inter = const0_rtx;
1875 else
1877 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1878 rtx first_shift_count, second_shift_count;
1879 optab reverse_unsigned_shift, unsigned_shift;
1881 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1882 ? lshr_optab : ashl_optab);
1884 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1885 ? ashl_optab : lshr_optab);
1887 if (shift_count > BITS_PER_WORD)
1889 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1890 second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
1892 else
1894 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1895 second_shift_count = GEN_INT (shift_count);
1898 into_temp1 = expand_binop (word_mode, unsigned_shift,
1899 outof_input, first_shift_count,
1900 NULL_RTX, unsignedp, next_methods);
1901 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1902 into_input, second_shift_count,
1903 NULL_RTX, unsignedp, next_methods);
1905 if (into_temp1 != 0 && into_temp2 != 0)
1906 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1907 into_target, unsignedp, next_methods);
1908 else
1909 inter = 0;
1911 if (inter != 0 && inter != into_target)
1912 emit_move_insn (into_target, inter);
1914 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1915 into_input, first_shift_count,
1916 NULL_RTX, unsignedp, next_methods);
1917 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1918 outof_input, second_shift_count,
1919 NULL_RTX, unsignedp, next_methods);
1921 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1922 inter = expand_binop (word_mode, ior_optab,
1923 outof_temp1, outof_temp2,
1924 outof_target, unsignedp, next_methods);
1926 if (inter != 0 && inter != outof_target)
1927 emit_move_insn (outof_target, inter);
1930 insns = get_insns ();
1931 end_sequence ();
1933 if (inter != 0)
1935 emit_insn (insns);
1936 return target;
1940 /* These can be done a word at a time by propagating carries. */
1941 if ((binoptab == add_optab || binoptab == sub_optab)
1942 && mclass == MODE_INT
1943 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1944 && optab_handler (binoptab, word_mode)->insn_code != CODE_FOR_nothing)
1946 unsigned int i;
1947 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1948 const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1949 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1950 rtx xop0, xop1, xtarget;
1952 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1953 value is one of those, use it. Otherwise, use 1 since it is the
1954 one easiest to get. */
1955 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1956 int normalizep = STORE_FLAG_VALUE;
1957 #else
1958 int normalizep = 1;
1959 #endif
1961 /* Prepare the operands. */
1962 xop0 = force_reg (mode, op0);
1963 xop1 = force_reg (mode, op1);
1965 xtarget = gen_reg_rtx (mode);
1967 if (target == 0 || !REG_P (target))
1968 target = xtarget;
1970 /* Indicate for flow that the entire target reg is being set. */
1971 if (REG_P (target))
1972 emit_clobber (xtarget);
1974 /* Do the actual arithmetic. */
1975 for (i = 0; i < nwords; i++)
1977 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1978 rtx target_piece = operand_subword (xtarget, index, 1, mode);
1979 rtx op0_piece = operand_subword_force (xop0, index, mode);
1980 rtx op1_piece = operand_subword_force (xop1, index, mode);
1981 rtx x;
1983 /* Main add/subtract of the input operands. */
1984 x = expand_binop (word_mode, binoptab,
1985 op0_piece, op1_piece,
1986 target_piece, unsignedp, next_methods);
1987 if (x == 0)
1988 break;
1990 if (i + 1 < nwords)
1992 /* Store carry from main add/subtract. */
1993 carry_out = gen_reg_rtx (word_mode);
1994 carry_out = emit_store_flag_force (carry_out,
1995 (binoptab == add_optab
1996 ? LT : GT),
1997 x, op0_piece,
1998 word_mode, 1, normalizep);
2001 if (i > 0)
2003 rtx newx;
2005 /* Add/subtract previous carry to main result. */
2006 newx = expand_binop (word_mode,
2007 normalizep == 1 ? binoptab : otheroptab,
2008 x, carry_in,
2009 NULL_RTX, 1, next_methods);
2011 if (i + 1 < nwords)
2013 /* Get out carry from adding/subtracting carry in. */
2014 rtx carry_tmp = gen_reg_rtx (word_mode);
2015 carry_tmp = emit_store_flag_force (carry_tmp,
2016 (binoptab == add_optab
2017 ? LT : GT),
2018 newx, x,
2019 word_mode, 1, normalizep);
2021 /* Logical-ior the two poss. carry together. */
2022 carry_out = expand_binop (word_mode, ior_optab,
2023 carry_out, carry_tmp,
2024 carry_out, 0, next_methods);
2025 if (carry_out == 0)
2026 break;
2028 emit_move_insn (target_piece, newx);
2030 else
2032 if (x != target_piece)
2033 emit_move_insn (target_piece, x);
2036 carry_in = carry_out;
2039 if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
2041 if (optab_handler (mov_optab, mode)->insn_code != CODE_FOR_nothing
2042 || ! rtx_equal_p (target, xtarget))
2044 rtx temp = emit_move_insn (target, xtarget);
2046 set_unique_reg_note (temp,
2047 REG_EQUAL,
2048 gen_rtx_fmt_ee (binoptab->code, mode,
2049 copy_rtx (xop0),
2050 copy_rtx (xop1)));
2052 else
2053 target = xtarget;
2055 return target;
2058 else
2059 delete_insns_since (last);
2062 /* Attempt to synthesize double word multiplies using a sequence of word
2063 mode multiplications. We first attempt to generate a sequence using a
2064 more efficient unsigned widening multiply, and if that fails we then
2065 try using a signed widening multiply. */
2067 if (binoptab == smul_optab
2068 && mclass == MODE_INT
2069 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
2070 && optab_handler (smul_optab, word_mode)->insn_code != CODE_FOR_nothing
2071 && optab_handler (add_optab, word_mode)->insn_code != CODE_FOR_nothing)
2073 rtx product = NULL_RTX;
2075 if (optab_handler (umul_widen_optab, mode)->insn_code
2076 != CODE_FOR_nothing)
2078 product = expand_doubleword_mult (mode, op0, op1, target,
2079 true, methods);
2080 if (!product)
2081 delete_insns_since (last);
2084 if (product == NULL_RTX
2085 && optab_handler (smul_widen_optab, mode)->insn_code
2086 != CODE_FOR_nothing)
2088 product = expand_doubleword_mult (mode, op0, op1, target,
2089 false, methods);
2090 if (!product)
2091 delete_insns_since (last);
2094 if (product != NULL_RTX)
2096 if (optab_handler (mov_optab, mode)->insn_code != CODE_FOR_nothing)
2098 temp = emit_move_insn (target ? target : product, product);
2099 set_unique_reg_note (temp,
2100 REG_EQUAL,
2101 gen_rtx_fmt_ee (MULT, mode,
2102 copy_rtx (op0),
2103 copy_rtx (op1)));
2105 return product;
2109 /* It can't be open-coded in this mode.
2110 Use a library call if one is available and caller says that's ok. */
2112 libfunc = optab_libfunc (binoptab, mode);
2113 if (libfunc
2114 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
2116 rtx insns;
2117 rtx op1x = op1;
2118 enum machine_mode op1_mode = mode;
2119 rtx value;
2121 start_sequence ();
2123 if (shift_optab_p (binoptab))
2125 op1_mode = targetm.libgcc_shift_count_mode ();
2126 /* Specify unsigned here,
2127 since negative shift counts are meaningless. */
2128 op1x = convert_to_mode (op1_mode, op1, 1);
2131 if (GET_MODE (op0) != VOIDmode
2132 && GET_MODE (op0) != mode)
2133 op0 = convert_to_mode (mode, op0, unsignedp);
2135 /* Pass 1 for NO_QUEUE so we don't lose any increments
2136 if the libcall is cse'd or moved. */
2137 value = emit_library_call_value (libfunc,
2138 NULL_RTX, LCT_CONST, mode, 2,
2139 op0, mode, op1x, op1_mode);
2141 insns = get_insns ();
2142 end_sequence ();
2144 target = gen_reg_rtx (mode);
2145 emit_libcall_block (insns, target, value,
2146 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
2148 return target;
2151 delete_insns_since (last);
2153 /* It can't be done in this mode. Can we do it in a wider mode? */
2155 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
2156 || methods == OPTAB_MUST_WIDEN))
2158 /* Caller says, don't even try. */
2159 delete_insns_since (entry_last);
2160 return 0;
2163 /* Compute the value of METHODS to pass to recursive calls.
2164 Don't allow widening to be tried recursively. */
2166 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
2168 /* Look for a wider mode of the same class for which it appears we can do
2169 the operation. */
2171 if (CLASS_HAS_WIDER_MODES_P (mclass))
2173 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2174 wider_mode != VOIDmode;
2175 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2177 if ((optab_handler (binoptab, wider_mode)->insn_code
2178 != CODE_FOR_nothing)
2179 || (methods == OPTAB_LIB
2180 && optab_libfunc (binoptab, wider_mode)))
2182 rtx xop0 = op0, xop1 = op1;
2183 int no_extend = 0;
2185 /* For certain integer operations, we need not actually extend
2186 the narrow operands, as long as we will truncate
2187 the results to the same narrowness. */
2189 if ((binoptab == ior_optab || binoptab == and_optab
2190 || binoptab == xor_optab
2191 || binoptab == add_optab || binoptab == sub_optab
2192 || binoptab == smul_optab || binoptab == ashl_optab)
2193 && mclass == MODE_INT)
2194 no_extend = 1;
2196 xop0 = widen_operand (xop0, wider_mode, mode,
2197 unsignedp, no_extend);
2199 /* The second operand of a shift must always be extended. */
2200 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
2201 no_extend && binoptab != ashl_optab);
2203 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
2204 unsignedp, methods);
2205 if (temp)
2207 if (mclass != MODE_INT
2208 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
2209 GET_MODE_BITSIZE (wider_mode)))
2211 if (target == 0)
2212 target = gen_reg_rtx (mode);
2213 convert_move (target, temp, 0);
2214 return target;
2216 else
2217 return gen_lowpart (mode, temp);
2219 else
2220 delete_insns_since (last);
2225 delete_insns_since (entry_last);
2226 return 0;
2229 /* Expand a binary operator which has both signed and unsigned forms.
2230 UOPTAB is the optab for unsigned operations, and SOPTAB is for
2231 signed operations.
2233 If we widen unsigned operands, we may use a signed wider operation instead
2234 of an unsigned wider operation, since the result would be the same. */
2237 sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
2238 rtx op0, rtx op1, rtx target, int unsignedp,
2239 enum optab_methods methods)
2241 rtx temp;
2242 optab direct_optab = unsignedp ? uoptab : soptab;
2243 struct optab_d wide_soptab;
2245 /* Do it without widening, if possible. */
2246 temp = expand_binop (mode, direct_optab, op0, op1, target,
2247 unsignedp, OPTAB_DIRECT);
2248 if (temp || methods == OPTAB_DIRECT)
2249 return temp;
2251 /* Try widening to a signed int. Make a fake signed optab that
2252 hides any signed insn for direct use. */
2253 wide_soptab = *soptab;
2254 optab_handler (&wide_soptab, mode)->insn_code = CODE_FOR_nothing;
2255 /* We don't want to generate new hash table entries from this fake
2256 optab. */
2257 wide_soptab.libcall_gen = NULL;
2259 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2260 unsignedp, OPTAB_WIDEN);
2262 /* For unsigned operands, try widening to an unsigned int. */
2263 if (temp == 0 && unsignedp)
2264 temp = expand_binop (mode, uoptab, op0, op1, target,
2265 unsignedp, OPTAB_WIDEN);
2266 if (temp || methods == OPTAB_WIDEN)
2267 return temp;
2269 /* Use the right width libcall if that exists. */
2270 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
2271 if (temp || methods == OPTAB_LIB)
2272 return temp;
2274 /* Must widen and use a libcall, use either signed or unsigned. */
2275 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
2276 unsignedp, methods);
2277 if (temp != 0)
2278 return temp;
2279 if (unsignedp)
2280 return expand_binop (mode, uoptab, op0, op1, target,
2281 unsignedp, methods);
2282 return 0;
2285 /* Generate code to perform an operation specified by UNOPPTAB
2286 on operand OP0, with two results to TARG0 and TARG1.
2287 We assume that the order of the operands for the instruction
2288 is TARG0, TARG1, OP0.
2290 Either TARG0 or TARG1 may be zero, but what that means is that
2291 the result is not actually wanted. We will generate it into
2292 a dummy pseudo-reg and discard it. They may not both be zero.
2294 Returns 1 if this operation can be performed; 0 if not. */
2297 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
2298 int unsignedp)
2300 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2301 enum mode_class mclass;
2302 enum machine_mode wider_mode;
2303 rtx entry_last = get_last_insn ();
2304 rtx last;
2306 mclass = GET_MODE_CLASS (mode);
2308 if (!targ0)
2309 targ0 = gen_reg_rtx (mode);
2310 if (!targ1)
2311 targ1 = gen_reg_rtx (mode);
2313 /* Record where to go back to if we fail. */
2314 last = get_last_insn ();
2316 if (optab_handler (unoptab, mode)->insn_code != CODE_FOR_nothing)
2318 int icode = (int) optab_handler (unoptab, mode)->insn_code;
2319 enum machine_mode mode0 = insn_data[icode].operand[2].mode;
2320 rtx pat;
2321 rtx xop0 = op0;
2323 if (GET_MODE (xop0) != VOIDmode
2324 && GET_MODE (xop0) != mode0)
2325 xop0 = convert_to_mode (mode0, xop0, unsignedp);
2327 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2328 if (!insn_data[icode].operand[2].predicate (xop0, mode0))
2329 xop0 = copy_to_mode_reg (mode0, xop0);
2331 /* We could handle this, but we should always be called with a pseudo
2332 for our targets and all insns should take them as outputs. */
2333 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2334 gcc_assert (insn_data[icode].operand[1].predicate (targ1, mode));
2336 pat = GEN_FCN (icode) (targ0, targ1, xop0);
2337 if (pat)
2339 emit_insn (pat);
2340 return 1;
2342 else
2343 delete_insns_since (last);
2346 /* It can't be done in this mode. Can we do it in a wider mode? */
2348 if (CLASS_HAS_WIDER_MODES_P (mclass))
2350 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2351 wider_mode != VOIDmode;
2352 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2354 if (optab_handler (unoptab, wider_mode)->insn_code
2355 != CODE_FOR_nothing)
2357 rtx t0 = gen_reg_rtx (wider_mode);
2358 rtx t1 = gen_reg_rtx (wider_mode);
2359 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2361 if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
2363 convert_move (targ0, t0, unsignedp);
2364 convert_move (targ1, t1, unsignedp);
2365 return 1;
2367 else
2368 delete_insns_since (last);
2373 delete_insns_since (entry_last);
2374 return 0;
2377 /* Generate code to perform an operation specified by BINOPTAB
2378 on operands OP0 and OP1, with two results to TARG1 and TARG2.
2379 We assume that the order of the operands for the instruction
2380 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2381 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2383 Either TARG0 or TARG1 may be zero, but what that means is that
2384 the result is not actually wanted. We will generate it into
2385 a dummy pseudo-reg and discard it. They may not both be zero.
2387 Returns 1 if this operation can be performed; 0 if not. */
2390 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
2391 int unsignedp)
2393 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2394 enum mode_class mclass;
2395 enum machine_mode wider_mode;
2396 rtx entry_last = get_last_insn ();
2397 rtx last;
2399 mclass = GET_MODE_CLASS (mode);
2401 if (!targ0)
2402 targ0 = gen_reg_rtx (mode);
2403 if (!targ1)
2404 targ1 = gen_reg_rtx (mode);
2406 /* Record where to go back to if we fail. */
2407 last = get_last_insn ();
2409 if (optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing)
2411 int icode = (int) optab_handler (binoptab, mode)->insn_code;
2412 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
2413 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
2414 rtx pat;
2415 rtx xop0 = op0, xop1 = op1;
2417 /* If we are optimizing, force expensive constants into a register. */
2418 xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp);
2419 xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp);
2421 /* In case the insn wants input operands in modes different from
2422 those of the actual operands, convert the operands. It would
2423 seem that we don't need to convert CONST_INTs, but we do, so
2424 that they're properly zero-extended, sign-extended or truncated
2425 for their mode. */
2427 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
2428 xop0 = convert_modes (mode0,
2429 GET_MODE (op0) != VOIDmode
2430 ? GET_MODE (op0)
2431 : mode,
2432 xop0, unsignedp);
2434 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
2435 xop1 = convert_modes (mode1,
2436 GET_MODE (op1) != VOIDmode
2437 ? GET_MODE (op1)
2438 : mode,
2439 xop1, unsignedp);
2441 /* Now, if insn doesn't accept these operands, put them into pseudos. */
2442 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
2443 xop0 = copy_to_mode_reg (mode0, xop0);
2445 if (!insn_data[icode].operand[2].predicate (xop1, mode1))
2446 xop1 = copy_to_mode_reg (mode1, xop1);
2448 /* We could handle this, but we should always be called with a pseudo
2449 for our targets and all insns should take them as outputs. */
2450 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
2451 gcc_assert (insn_data[icode].operand[3].predicate (targ1, mode));
2453 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
2454 if (pat)
2456 emit_insn (pat);
2457 return 1;
2459 else
2460 delete_insns_since (last);
2463 /* It can't be done in this mode. Can we do it in a wider mode? */
2465 if (CLASS_HAS_WIDER_MODES_P (mclass))
2467 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2468 wider_mode != VOIDmode;
2469 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2471 if (optab_handler (binoptab, wider_mode)->insn_code
2472 != CODE_FOR_nothing)
2474 rtx t0 = gen_reg_rtx (wider_mode);
2475 rtx t1 = gen_reg_rtx (wider_mode);
2476 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2477 rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
2479 if (expand_twoval_binop (binoptab, cop0, cop1,
2480 t0, t1, unsignedp))
2482 convert_move (targ0, t0, unsignedp);
2483 convert_move (targ1, t1, unsignedp);
2484 return 1;
2486 else
2487 delete_insns_since (last);
2492 delete_insns_since (entry_last);
2493 return 0;
2496 /* Expand the two-valued library call indicated by BINOPTAB, but
2497 preserve only one of the values. If TARG0 is non-NULL, the first
2498 value is placed into TARG0; otherwise the second value is placed
2499 into TARG1. Exactly one of TARG0 and TARG1 must be non-NULL. The
2500 value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
2501 This routine assumes that the value returned by the library call is
2502 as if the return value was of an integral mode twice as wide as the
2503 mode of OP0. Returns 1 if the call was successful. */
2505 bool
2506 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
2507 rtx targ0, rtx targ1, enum rtx_code code)
2509 enum machine_mode mode;
2510 enum machine_mode libval_mode;
2511 rtx libval;
2512 rtx insns;
2513 rtx libfunc;
2515 /* Exactly one of TARG0 or TARG1 should be non-NULL. */
2516 gcc_assert (!targ0 != !targ1);
2518 mode = GET_MODE (op0);
2519 libfunc = optab_libfunc (binoptab, mode);
2520 if (!libfunc)
2521 return false;
2523 /* The value returned by the library function will have twice as
2524 many bits as the nominal MODE. */
2525 libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
2526 MODE_INT);
2527 start_sequence ();
2528 libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
2529 libval_mode, 2,
2530 op0, mode,
2531 op1, mode);
2532 /* Get the part of VAL containing the value that we want. */
2533 libval = simplify_gen_subreg (mode, libval, libval_mode,
2534 targ0 ? 0 : GET_MODE_SIZE (mode));
2535 insns = get_insns ();
2536 end_sequence ();
2537 /* Move the into the desired location. */
2538 emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
2539 gen_rtx_fmt_ee (code, mode, op0, op1));
2541 return true;
2545 /* Wrapper around expand_unop which takes an rtx code to specify
2546 the operation to perform, not an optab pointer. All other
2547 arguments are the same. */
2549 expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
2550 rtx target, int unsignedp)
2552 optab unop = code_to_optab[(int) code];
2553 gcc_assert (unop);
2555 return expand_unop (mode, unop, op0, target, unsignedp);
2558 /* Try calculating
2559 (clz:narrow x)
2561 (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)). */
2562 static rtx
2563 widen_clz (enum machine_mode mode, rtx op0, rtx target)
2565 enum mode_class mclass = GET_MODE_CLASS (mode);
2566 if (CLASS_HAS_WIDER_MODES_P (mclass))
2568 enum machine_mode wider_mode;
2569 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2570 wider_mode != VOIDmode;
2571 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2573 if (optab_handler (clz_optab, wider_mode)->insn_code
2574 != CODE_FOR_nothing)
2576 rtx xop0, temp, last;
2578 last = get_last_insn ();
2580 if (target == 0)
2581 target = gen_reg_rtx (mode);
2582 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2583 temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
2584 if (temp != 0)
2585 temp = expand_binop (wider_mode, sub_optab, temp,
2586 GEN_INT (GET_MODE_BITSIZE (wider_mode)
2587 - GET_MODE_BITSIZE (mode)),
2588 target, true, OPTAB_DIRECT);
2589 if (temp == 0)
2590 delete_insns_since (last);
2592 return temp;
2596 return 0;
2599 /* Try calculating clz of a double-word quantity as two clz's of word-sized
2600 quantities, choosing which based on whether the high word is nonzero. */
2601 static rtx
2602 expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target)
2604 rtx xop0 = force_reg (mode, op0);
2605 rtx subhi = gen_highpart (word_mode, xop0);
2606 rtx sublo = gen_lowpart (word_mode, xop0);
2607 rtx hi0_label = gen_label_rtx ();
2608 rtx after_label = gen_label_rtx ();
2609 rtx seq, temp, result;
2611 /* If we were not given a target, use a word_mode register, not a
2612 'mode' register. The result will fit, and nobody is expecting
2613 anything bigger (the return type of __builtin_clz* is int). */
2614 if (!target)
2615 target = gen_reg_rtx (word_mode);
2617 /* In any case, write to a word_mode scratch in both branches of the
2618 conditional, so we can ensure there is a single move insn setting
2619 'target' to tag a REG_EQUAL note on. */
2620 result = gen_reg_rtx (word_mode);
2622 start_sequence ();
2624 /* If the high word is not equal to zero,
2625 then clz of the full value is clz of the high word. */
2626 emit_cmp_and_jump_insns (subhi, CONST0_RTX (word_mode), EQ, 0,
2627 word_mode, true, hi0_label);
2629 temp = expand_unop_direct (word_mode, clz_optab, subhi, result, true);
2630 if (!temp)
2631 goto fail;
2633 if (temp != result)
2634 convert_move (result, temp, true);
2636 emit_jump_insn (gen_jump (after_label));
2637 emit_barrier ();
2639 /* Else clz of the full value is clz of the low word plus the number
2640 of bits in the high word. */
2641 emit_label (hi0_label);
2643 temp = expand_unop_direct (word_mode, clz_optab, sublo, 0, true);
2644 if (!temp)
2645 goto fail;
2646 temp = expand_binop (word_mode, add_optab, temp,
2647 GEN_INT (GET_MODE_BITSIZE (word_mode)),
2648 result, true, OPTAB_DIRECT);
2649 if (!temp)
2650 goto fail;
2651 if (temp != result)
2652 convert_move (result, temp, true);
2654 emit_label (after_label);
2655 convert_move (target, result, true);
2657 seq = get_insns ();
2658 end_sequence ();
2660 add_equal_note (seq, target, CLZ, xop0, 0);
2661 emit_insn (seq);
2662 return target;
2664 fail:
2665 end_sequence ();
2666 return 0;
2669 /* Try calculating
2670 (bswap:narrow x)
2672 (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */
2673 static rtx
2674 widen_bswap (enum machine_mode mode, rtx op0, rtx target)
2676 enum mode_class mclass = GET_MODE_CLASS (mode);
2677 enum machine_mode wider_mode;
2678 rtx x, last;
2680 if (!CLASS_HAS_WIDER_MODES_P (mclass))
2681 return NULL_RTX;
2683 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2684 wider_mode != VOIDmode;
2685 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2686 if (optab_handler (bswap_optab, wider_mode)->insn_code != CODE_FOR_nothing)
2687 goto found;
2688 return NULL_RTX;
2690 found:
2691 last = get_last_insn ();
2693 x = widen_operand (op0, wider_mode, mode, true, true);
2694 x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
2696 if (x != 0)
2697 x = expand_shift (RSHIFT_EXPR, wider_mode, x,
2698 size_int (GET_MODE_BITSIZE (wider_mode)
2699 - GET_MODE_BITSIZE (mode)),
2700 NULL_RTX, true);
2702 if (x != 0)
2704 if (target == 0)
2705 target = gen_reg_rtx (mode);
2706 emit_move_insn (target, gen_lowpart (mode, x));
2708 else
2709 delete_insns_since (last);
2711 return target;
2714 /* Try calculating bswap as two bswaps of two word-sized operands. */
2716 static rtx
2717 expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
2719 rtx t0, t1;
2721 t1 = expand_unop (word_mode, bswap_optab,
2722 operand_subword_force (op, 0, mode), NULL_RTX, true);
2723 t0 = expand_unop (word_mode, bswap_optab,
2724 operand_subword_force (op, 1, mode), NULL_RTX, true);
2726 if (target == 0)
2727 target = gen_reg_rtx (mode);
2728 if (REG_P (target))
2729 emit_clobber (target);
2730 emit_move_insn (operand_subword (target, 0, 1, mode), t0);
2731 emit_move_insn (operand_subword (target, 1, 1, mode), t1);
2733 return target;
2736 /* Try calculating (parity x) as (and (popcount x) 1), where
2737 popcount can also be done in a wider mode. */
2738 static rtx
2739 expand_parity (enum machine_mode mode, rtx op0, rtx target)
2741 enum mode_class mclass = GET_MODE_CLASS (mode);
2742 if (CLASS_HAS_WIDER_MODES_P (mclass))
2744 enum machine_mode wider_mode;
2745 for (wider_mode = mode; wider_mode != VOIDmode;
2746 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2748 if (optab_handler (popcount_optab, wider_mode)->insn_code
2749 != CODE_FOR_nothing)
2751 rtx xop0, temp, last;
2753 last = get_last_insn ();
2755 if (target == 0)
2756 target = gen_reg_rtx (mode);
2757 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2758 temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
2759 true);
2760 if (temp != 0)
2761 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
2762 target, true, OPTAB_DIRECT);
2763 if (temp == 0)
2764 delete_insns_since (last);
2766 return temp;
2770 return 0;
2773 /* Try calculating ctz(x) as K - clz(x & -x) ,
2774 where K is GET_MODE_BITSIZE(mode) - 1.
2776 Both __builtin_ctz and __builtin_clz are undefined at zero, so we
2777 don't have to worry about what the hardware does in that case. (If
2778 the clz instruction produces the usual value at 0, which is K, the
2779 result of this code sequence will be -1; expand_ffs, below, relies
2780 on this. It might be nice to have it be K instead, for consistency
2781 with the (very few) processors that provide a ctz with a defined
2782 value, but that would take one more instruction, and it would be
2783 less convenient for expand_ffs anyway. */
2785 static rtx
2786 expand_ctz (enum machine_mode mode, rtx op0, rtx target)
2788 rtx seq, temp;
2790 if (optab_handler (clz_optab, mode)->insn_code == CODE_FOR_nothing)
2791 return 0;
2793 start_sequence ();
2795 temp = expand_unop_direct (mode, neg_optab, op0, NULL_RTX, true);
2796 if (temp)
2797 temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
2798 true, OPTAB_DIRECT);
2799 if (temp)
2800 temp = expand_unop_direct (mode, clz_optab, temp, NULL_RTX, true);
2801 if (temp)
2802 temp = expand_binop (mode, sub_optab, GEN_INT (GET_MODE_BITSIZE (mode) - 1),
2803 temp, target,
2804 true, OPTAB_DIRECT);
2805 if (temp == 0)
2807 end_sequence ();
2808 return 0;
2811 seq = get_insns ();
2812 end_sequence ();
2814 add_equal_note (seq, temp, CTZ, op0, 0);
2815 emit_insn (seq);
2816 return temp;
2820 /* Try calculating ffs(x) using ctz(x) if we have that instruction, or
2821 else with the sequence used by expand_clz.
2823 The ffs builtin promises to return zero for a zero value and ctz/clz
2824 may have an undefined value in that case. If they do not give us a
2825 convenient value, we have to generate a test and branch. */
2826 static rtx
2827 expand_ffs (enum machine_mode mode, rtx op0, rtx target)
2829 HOST_WIDE_INT val = 0;
2830 bool defined_at_zero = false;
2831 rtx temp, seq;
2833 if (optab_handler (ctz_optab, mode)->insn_code != CODE_FOR_nothing)
2835 start_sequence ();
2837 temp = expand_unop_direct (mode, ctz_optab, op0, 0, true);
2838 if (!temp)
2839 goto fail;
2841 defined_at_zero = (CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2);
2843 else if (optab_handler (clz_optab, mode)->insn_code != CODE_FOR_nothing)
2845 start_sequence ();
2846 temp = expand_ctz (mode, op0, 0);
2847 if (!temp)
2848 goto fail;
2850 if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
2852 defined_at_zero = true;
2853 val = (GET_MODE_BITSIZE (mode) - 1) - val;
2856 else
2857 return 0;
2859 if (defined_at_zero && val == -1)
2860 /* No correction needed at zero. */;
2861 else
2863 /* We don't try to do anything clever with the situation found
2864 on some processors (eg Alpha) where ctz(0:mode) ==
2865 bitsize(mode). If someone can think of a way to send N to -1
2866 and leave alone all values in the range 0..N-1 (where N is a
2867 power of two), cheaper than this test-and-branch, please add it.
2869 The test-and-branch is done after the operation itself, in case
2870 the operation sets condition codes that can be recycled for this.
2871 (This is true on i386, for instance.) */
2873 rtx nonzero_label = gen_label_rtx ();
2874 emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
2875 mode, true, nonzero_label);
2877 convert_move (temp, GEN_INT (-1), false);
2878 emit_label (nonzero_label);
2881 /* temp now has a value in the range -1..bitsize-1. ffs is supposed
2882 to produce a value in the range 0..bitsize. */
2883 temp = expand_binop (mode, add_optab, temp, GEN_INT (1),
2884 target, false, OPTAB_DIRECT);
2885 if (!temp)
2886 goto fail;
2888 seq = get_insns ();
2889 end_sequence ();
2891 add_equal_note (seq, temp, FFS, op0, 0);
2892 emit_insn (seq);
2893 return temp;
2895 fail:
2896 end_sequence ();
2897 return 0;
2900 /* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
2901 conditions, VAL may already be a SUBREG against which we cannot generate
2902 a further SUBREG. In this case, we expect forcing the value into a
2903 register will work around the situation. */
2905 static rtx
2906 lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
2907 enum machine_mode imode)
2909 rtx ret;
2910 ret = lowpart_subreg (omode, val, imode);
2911 if (ret == NULL)
2913 val = force_reg (imode, val);
2914 ret = lowpart_subreg (omode, val, imode);
2915 gcc_assert (ret != NULL);
2917 return ret;
2920 /* Expand a floating point absolute value or negation operation via a
2921 logical operation on the sign bit. */
2923 static rtx
2924 expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
2925 rtx op0, rtx target)
2927 const struct real_format *fmt;
2928 int bitpos, word, nwords, i;
2929 enum machine_mode imode;
2930 HOST_WIDE_INT hi, lo;
2931 rtx temp, insns;
2933 /* The format has to have a simple sign bit. */
2934 fmt = REAL_MODE_FORMAT (mode);
2935 if (fmt == NULL)
2936 return NULL_RTX;
2938 bitpos = fmt->signbit_rw;
2939 if (bitpos < 0)
2940 return NULL_RTX;
2942 /* Don't create negative zeros if the format doesn't support them. */
2943 if (code == NEG && !fmt->has_signed_zero)
2944 return NULL_RTX;
2946 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
2948 imode = int_mode_for_mode (mode);
2949 if (imode == BLKmode)
2950 return NULL_RTX;
2951 word = 0;
2952 nwords = 1;
2954 else
2956 imode = word_mode;
2958 if (FLOAT_WORDS_BIG_ENDIAN)
2959 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
2960 else
2961 word = bitpos / BITS_PER_WORD;
2962 bitpos = bitpos % BITS_PER_WORD;
2963 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
2966 if (bitpos < HOST_BITS_PER_WIDE_INT)
2968 hi = 0;
2969 lo = (HOST_WIDE_INT) 1 << bitpos;
2971 else
2973 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
2974 lo = 0;
2976 if (code == ABS)
2977 lo = ~lo, hi = ~hi;
2979 if (target == 0 || target == op0)
2980 target = gen_reg_rtx (mode);
2982 if (nwords > 1)
2984 start_sequence ();
2986 for (i = 0; i < nwords; ++i)
2988 rtx targ_piece = operand_subword (target, i, 1, mode);
2989 rtx op0_piece = operand_subword_force (op0, i, mode);
2991 if (i == word)
2993 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2994 op0_piece,
2995 immed_double_const (lo, hi, imode),
2996 targ_piece, 1, OPTAB_LIB_WIDEN);
2997 if (temp != targ_piece)
2998 emit_move_insn (targ_piece, temp);
3000 else
3001 emit_move_insn (targ_piece, op0_piece);
3004 insns = get_insns ();
3005 end_sequence ();
3007 emit_insn (insns);
3009 else
3011 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
3012 gen_lowpart (imode, op0),
3013 immed_double_const (lo, hi, imode),
3014 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3015 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3017 set_unique_reg_note (get_last_insn (), REG_EQUAL,
3018 gen_rtx_fmt_e (code, mode, copy_rtx (op0)));
3021 return target;
3024 /* As expand_unop, but will fail rather than attempt the operation in a
3025 different mode or with a libcall. */
3026 static rtx
3027 expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3028 int unsignedp)
3030 if (optab_handler (unoptab, mode)->insn_code != CODE_FOR_nothing)
3032 int icode = (int) optab_handler (unoptab, mode)->insn_code;
3033 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3034 rtx xop0 = op0;
3035 rtx last = get_last_insn ();
3036 rtx pat, temp;
3038 if (target)
3039 temp = target;
3040 else
3041 temp = gen_reg_rtx (mode);
3043 if (GET_MODE (xop0) != VOIDmode
3044 && GET_MODE (xop0) != mode0)
3045 xop0 = convert_to_mode (mode0, xop0, unsignedp);
3047 /* Now, if insn doesn't accept our operand, put it into a pseudo. */
3049 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
3050 xop0 = copy_to_mode_reg (mode0, xop0);
3052 if (!insn_data[icode].operand[0].predicate (temp, mode))
3053 temp = gen_reg_rtx (mode);
3055 pat = GEN_FCN (icode) (temp, xop0);
3056 if (pat)
3058 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
3059 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
3061 delete_insns_since (last);
3062 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
3065 emit_insn (pat);
3067 return temp;
3069 else
3070 delete_insns_since (last);
3072 return 0;
3075 /* Generate code to perform an operation specified by UNOPTAB
3076 on operand OP0, with result having machine-mode MODE.
3078 UNSIGNEDP is for the case where we have to widen the operands
3079 to perform the operation. It says to use zero-extension.
3081 If TARGET is nonzero, the value
3082 is generated there, if it is convenient to do so.
3083 In all cases an rtx is returned for the locus of the value;
3084 this may or may not be TARGET. */
3087 expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
3088 int unsignedp)
3090 enum mode_class mclass = GET_MODE_CLASS (mode);
3091 enum machine_mode wider_mode;
3092 rtx temp;
3093 rtx libfunc;
3095 temp = expand_unop_direct (mode, unoptab, op0, target, unsignedp);
3096 if (temp)
3097 return temp;
3099 /* It can't be done in this mode. Can we open-code it in a wider mode? */
3101 /* Widening (or narrowing) clz needs special treatment. */
3102 if (unoptab == clz_optab)
3104 temp = widen_clz (mode, op0, target);
3105 if (temp)
3106 return temp;
3108 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3109 && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3111 temp = expand_doubleword_clz (mode, op0, target);
3112 if (temp)
3113 return temp;
3116 goto try_libcall;
3119 /* Widening (or narrowing) bswap needs special treatment. */
3120 if (unoptab == bswap_optab)
3122 temp = widen_bswap (mode, op0, target);
3123 if (temp)
3124 return temp;
3126 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
3127 && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3129 temp = expand_doubleword_bswap (mode, op0, target);
3130 if (temp)
3131 return temp;
3134 goto try_libcall;
3137 if (CLASS_HAS_WIDER_MODES_P (mclass))
3138 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3139 wider_mode != VOIDmode;
3140 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3142 if (optab_handler (unoptab, wider_mode)->insn_code != CODE_FOR_nothing)
3144 rtx xop0 = op0;
3145 rtx last = get_last_insn ();
3147 /* For certain operations, we need not actually extend
3148 the narrow operand, as long as we will truncate the
3149 results to the same narrowness. */
3151 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3152 (unoptab == neg_optab
3153 || unoptab == one_cmpl_optab)
3154 && mclass == MODE_INT);
3156 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3157 unsignedp);
3159 if (temp)
3161 if (mclass != MODE_INT
3162 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
3163 GET_MODE_BITSIZE (wider_mode)))
3165 if (target == 0)
3166 target = gen_reg_rtx (mode);
3167 convert_move (target, temp, 0);
3168 return target;
3170 else
3171 return gen_lowpart (mode, temp);
3173 else
3174 delete_insns_since (last);
3178 /* These can be done a word at a time. */
3179 if (unoptab == one_cmpl_optab
3180 && mclass == MODE_INT
3181 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
3182 && optab_handler (unoptab, word_mode)->insn_code != CODE_FOR_nothing)
3184 int i;
3185 rtx insns;
3187 if (target == 0 || target == op0)
3188 target = gen_reg_rtx (mode);
3190 start_sequence ();
3192 /* Do the actual arithmetic. */
3193 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
3195 rtx target_piece = operand_subword (target, i, 1, mode);
3196 rtx x = expand_unop (word_mode, unoptab,
3197 operand_subword_force (op0, i, mode),
3198 target_piece, unsignedp);
3200 if (target_piece != x)
3201 emit_move_insn (target_piece, x);
3204 insns = get_insns ();
3205 end_sequence ();
3207 emit_insn (insns);
3208 return target;
3211 if (unoptab->code == NEG)
3213 /* Try negating floating point values by flipping the sign bit. */
3214 if (SCALAR_FLOAT_MODE_P (mode))
3216 temp = expand_absneg_bit (NEG, mode, op0, target);
3217 if (temp)
3218 return temp;
3221 /* If there is no negation pattern, and we have no negative zero,
3222 try subtracting from zero. */
3223 if (!HONOR_SIGNED_ZEROS (mode))
3225 temp = expand_binop (mode, (unoptab == negv_optab
3226 ? subv_optab : sub_optab),
3227 CONST0_RTX (mode), op0, target,
3228 unsignedp, OPTAB_DIRECT);
3229 if (temp)
3230 return temp;
3234 /* Try calculating parity (x) as popcount (x) % 2. */
3235 if (unoptab == parity_optab)
3237 temp = expand_parity (mode, op0, target);
3238 if (temp)
3239 return temp;
3242 /* Try implementing ffs (x) in terms of clz (x). */
3243 if (unoptab == ffs_optab)
3245 temp = expand_ffs (mode, op0, target);
3246 if (temp)
3247 return temp;
3250 /* Try implementing ctz (x) in terms of clz (x). */
3251 if (unoptab == ctz_optab)
3253 temp = expand_ctz (mode, op0, target);
3254 if (temp)
3255 return temp;
3258 try_libcall:
3259 /* Now try a library call in this mode. */
3260 libfunc = optab_libfunc (unoptab, mode);
3261 if (libfunc)
3263 rtx insns;
3264 rtx value;
3265 rtx eq_value;
3266 enum machine_mode outmode = mode;
3268 /* All of these functions return small values. Thus we choose to
3269 have them return something that isn't a double-word. */
3270 if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
3271 || unoptab == popcount_optab || unoptab == parity_optab)
3272 outmode
3273 = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
3274 optab_libfunc (unoptab, mode)));
3276 start_sequence ();
3278 /* Pass 1 for NO_QUEUE so we don't lose any increments
3279 if the libcall is cse'd or moved. */
3280 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, outmode,
3281 1, op0, mode);
3282 insns = get_insns ();
3283 end_sequence ();
3285 target = gen_reg_rtx (outmode);
3286 eq_value = gen_rtx_fmt_e (unoptab->code, mode, op0);
3287 if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
3288 eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
3289 else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
3290 eq_value = simplify_gen_unary (ZERO_EXTEND, outmode, eq_value, mode);
3291 emit_libcall_block (insns, target, value, eq_value);
3293 return target;
3296 /* It can't be done in this mode. Can we do it in a wider mode? */
3298 if (CLASS_HAS_WIDER_MODES_P (mclass))
3300 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3301 wider_mode != VOIDmode;
3302 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3304 if ((optab_handler (unoptab, wider_mode)->insn_code
3305 != CODE_FOR_nothing)
3306 || optab_libfunc (unoptab, wider_mode))
3308 rtx xop0 = op0;
3309 rtx last = get_last_insn ();
3311 /* For certain operations, we need not actually extend
3312 the narrow operand, as long as we will truncate the
3313 results to the same narrowness. */
3315 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3316 (unoptab == neg_optab
3317 || unoptab == one_cmpl_optab)
3318 && mclass == MODE_INT);
3320 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3321 unsignedp);
3323 /* If we are generating clz using wider mode, adjust the
3324 result. */
3325 if (unoptab == clz_optab && temp != 0)
3326 temp = expand_binop (wider_mode, sub_optab, temp,
3327 GEN_INT (GET_MODE_BITSIZE (wider_mode)
3328 - GET_MODE_BITSIZE (mode)),
3329 target, true, OPTAB_DIRECT);
3331 if (temp)
3333 if (mclass != MODE_INT)
3335 if (target == 0)
3336 target = gen_reg_rtx (mode);
3337 convert_move (target, temp, 0);
3338 return target;
3340 else
3341 return gen_lowpart (mode, temp);
3343 else
3344 delete_insns_since (last);
3349 /* One final attempt at implementing negation via subtraction,
3350 this time allowing widening of the operand. */
3351 if (unoptab->code == NEG && !HONOR_SIGNED_ZEROS (mode))
3353 rtx temp;
3354 temp = expand_binop (mode,
3355 unoptab == negv_optab ? subv_optab : sub_optab,
3356 CONST0_RTX (mode), op0,
3357 target, unsignedp, OPTAB_LIB_WIDEN);
3358 if (temp)
3359 return temp;
3362 return 0;
3365 /* Emit code to compute the absolute value of OP0, with result to
3366 TARGET if convenient. (TARGET may be 0.) The return value says
3367 where the result actually is to be found.
3369 MODE is the mode of the operand; the mode of the result is
3370 different but can be deduced from MODE.
3375 expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
3376 int result_unsignedp)
3378 rtx temp;
3380 if (! flag_trapv)
3381 result_unsignedp = 1;
3383 /* First try to do it with a special abs instruction. */
3384 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
3385 op0, target, 0);
3386 if (temp != 0)
3387 return temp;
3389 /* For floating point modes, try clearing the sign bit. */
3390 if (SCALAR_FLOAT_MODE_P (mode))
3392 temp = expand_absneg_bit (ABS, mode, op0, target);
3393 if (temp)
3394 return temp;
3397 /* If we have a MAX insn, we can do this as MAX (x, -x). */
3398 if (optab_handler (smax_optab, mode)->insn_code != CODE_FOR_nothing
3399 && !HONOR_SIGNED_ZEROS (mode))
3401 rtx last = get_last_insn ();
3403 temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
3404 if (temp != 0)
3405 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3406 OPTAB_WIDEN);
3408 if (temp != 0)
3409 return temp;
3411 delete_insns_since (last);
3414 /* If this machine has expensive jumps, we can do integer absolute
3415 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
3416 where W is the width of MODE. */
3418 if (GET_MODE_CLASS (mode) == MODE_INT
3419 && BRANCH_COST (optimize_insn_for_speed_p (),
3420 false) >= 2)
3422 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3423 size_int (GET_MODE_BITSIZE (mode) - 1),
3424 NULL_RTX, 0);
3426 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3427 OPTAB_LIB_WIDEN);
3428 if (temp != 0)
3429 temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
3430 temp, extended, target, 0, OPTAB_LIB_WIDEN);
3432 if (temp != 0)
3433 return temp;
3436 return NULL_RTX;
3440 expand_abs (enum machine_mode mode, rtx op0, rtx target,
3441 int result_unsignedp, int safe)
3443 rtx temp, op1;
3445 if (! flag_trapv)
3446 result_unsignedp = 1;
3448 temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
3449 if (temp != 0)
3450 return temp;
3452 /* If that does not win, use conditional jump and negate. */
3454 /* It is safe to use the target if it is the same
3455 as the source if this is also a pseudo register */
3456 if (op0 == target && REG_P (op0)
3457 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
3458 safe = 1;
3460 op1 = gen_label_rtx ();
3461 if (target == 0 || ! safe
3462 || GET_MODE (target) != mode
3463 || (MEM_P (target) && MEM_VOLATILE_P (target))
3464 || (REG_P (target)
3465 && REGNO (target) < FIRST_PSEUDO_REGISTER))
3466 target = gen_reg_rtx (mode);
3468 emit_move_insn (target, op0);
3469 NO_DEFER_POP;
3471 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
3472 NULL_RTX, NULL_RTX, op1, -1);
3474 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3475 target, target, 0);
3476 if (op0 != target)
3477 emit_move_insn (target, op0);
3478 emit_label (op1);
3479 OK_DEFER_POP;
3480 return target;
3483 /* Emit code to compute the one's complement absolute value of OP0
3484 (if (OP0 < 0) OP0 = ~OP0), with result to TARGET if convenient.
3485 (TARGET may be NULL_RTX.) The return value says where the result
3486 actually is to be found.
3488 MODE is the mode of the operand; the mode of the result is
3489 different but can be deduced from MODE. */
3492 expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
3494 rtx temp;
3496 /* Not applicable for floating point modes. */
3497 if (FLOAT_MODE_P (mode))
3498 return NULL_RTX;
3500 /* If we have a MAX insn, we can do this as MAX (x, ~x). */
3501 if (optab_handler (smax_optab, mode)->insn_code != CODE_FOR_nothing)
3503 rtx last = get_last_insn ();
3505 temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
3506 if (temp != 0)
3507 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3508 OPTAB_WIDEN);
3510 if (temp != 0)
3511 return temp;
3513 delete_insns_since (last);
3516 /* If this machine has expensive jumps, we can do one's complement
3517 absolute value of X as (((signed) x >> (W-1)) ^ x). */
3519 if (GET_MODE_CLASS (mode) == MODE_INT
3520 && BRANCH_COST (optimize_insn_for_speed_p (),
3521 false) >= 2)
3523 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
3524 size_int (GET_MODE_BITSIZE (mode) - 1),
3525 NULL_RTX, 0);
3527 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3528 OPTAB_LIB_WIDEN);
3530 if (temp != 0)
3531 return temp;
3534 return NULL_RTX;
3537 /* A subroutine of expand_copysign, perform the copysign operation using the
3538 abs and neg primitives advertised to exist on the target. The assumption
3539 is that we have a split register file, and leaving op0 in fp registers,
3540 and not playing with subregs so much, will help the register allocator. */
3542 static rtx
3543 expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3544 int bitpos, bool op0_is_abs)
3546 enum machine_mode imode;
3547 int icode;
3548 rtx sign, label;
3550 if (target == op1)
3551 target = NULL_RTX;
3553 /* Check if the back end provides an insn that handles signbit for the
3554 argument's mode. */
3555 icode = (int) signbit_optab->handlers [(int) mode].insn_code;
3556 if (icode != CODE_FOR_nothing)
3558 imode = insn_data[icode].operand[0].mode;
3559 sign = gen_reg_rtx (imode);
3560 emit_unop_insn (icode, sign, op1, UNKNOWN);
3562 else
3564 HOST_WIDE_INT hi, lo;
3566 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3568 imode = int_mode_for_mode (mode);
3569 if (imode == BLKmode)
3570 return NULL_RTX;
3571 op1 = gen_lowpart (imode, op1);
3573 else
3575 int word;
3577 imode = word_mode;
3578 if (FLOAT_WORDS_BIG_ENDIAN)
3579 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3580 else
3581 word = bitpos / BITS_PER_WORD;
3582 bitpos = bitpos % BITS_PER_WORD;
3583 op1 = operand_subword_force (op1, word, mode);
3586 if (bitpos < HOST_BITS_PER_WIDE_INT)
3588 hi = 0;
3589 lo = (HOST_WIDE_INT) 1 << bitpos;
3591 else
3593 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
3594 lo = 0;
3597 sign = gen_reg_rtx (imode);
3598 sign = expand_binop (imode, and_optab, op1,
3599 immed_double_const (lo, hi, imode),
3600 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3603 if (!op0_is_abs)
3605 op0 = expand_unop (mode, abs_optab, op0, target, 0);
3606 if (op0 == NULL)
3607 return NULL_RTX;
3608 target = op0;
3610 else
3612 if (target == NULL_RTX)
3613 target = copy_to_reg (op0);
3614 else
3615 emit_move_insn (target, op0);
3618 label = gen_label_rtx ();
3619 emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
3621 if (GET_CODE (op0) == CONST_DOUBLE)
3622 op0 = simplify_unary_operation (NEG, mode, op0, mode);
3623 else
3624 op0 = expand_unop (mode, neg_optab, op0, target, 0);
3625 if (op0 != target)
3626 emit_move_insn (target, op0);
3628 emit_label (label);
3630 return target;
3634 /* A subroutine of expand_copysign, perform the entire copysign operation
3635 with integer bitmasks. BITPOS is the position of the sign bit; OP0_IS_ABS
3636 is true if op0 is known to have its sign bit clear. */
3638 static rtx
3639 expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
3640 int bitpos, bool op0_is_abs)
3642 enum machine_mode imode;
3643 HOST_WIDE_INT hi, lo;
3644 int word, nwords, i;
3645 rtx temp, insns;
3647 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3649 imode = int_mode_for_mode (mode);
3650 if (imode == BLKmode)
3651 return NULL_RTX;
3652 word = 0;
3653 nwords = 1;
3655 else
3657 imode = word_mode;
3659 if (FLOAT_WORDS_BIG_ENDIAN)
3660 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3661 else
3662 word = bitpos / BITS_PER_WORD;
3663 bitpos = bitpos % BITS_PER_WORD;
3664 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
3667 if (bitpos < HOST_BITS_PER_WIDE_INT)
3669 hi = 0;
3670 lo = (HOST_WIDE_INT) 1 << bitpos;
3672 else
3674 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
3675 lo = 0;
3678 if (target == 0 || target == op0 || target == op1)
3679 target = gen_reg_rtx (mode);
3681 if (nwords > 1)
3683 start_sequence ();
3685 for (i = 0; i < nwords; ++i)
3687 rtx targ_piece = operand_subword (target, i, 1, mode);
3688 rtx op0_piece = operand_subword_force (op0, i, mode);
3690 if (i == word)
3692 if (!op0_is_abs)
3693 op0_piece = expand_binop (imode, and_optab, op0_piece,
3694 immed_double_const (~lo, ~hi, imode),
3695 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3697 op1 = expand_binop (imode, and_optab,
3698 operand_subword_force (op1, i, mode),
3699 immed_double_const (lo, hi, imode),
3700 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3702 temp = expand_binop (imode, ior_optab, op0_piece, op1,
3703 targ_piece, 1, OPTAB_LIB_WIDEN);
3704 if (temp != targ_piece)
3705 emit_move_insn (targ_piece, temp);
3707 else
3708 emit_move_insn (targ_piece, op0_piece);
3711 insns = get_insns ();
3712 end_sequence ();
3714 emit_insn (insns);
3716 else
3718 op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
3719 immed_double_const (lo, hi, imode),
3720 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3722 op0 = gen_lowpart (imode, op0);
3723 if (!op0_is_abs)
3724 op0 = expand_binop (imode, and_optab, op0,
3725 immed_double_const (~lo, ~hi, imode),
3726 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3728 temp = expand_binop (imode, ior_optab, op0, op1,
3729 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3730 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3733 return target;
3736 /* Expand the C99 copysign operation. OP0 and OP1 must be the same
3737 scalar floating point mode. Return NULL if we do not know how to
3738 expand the operation inline. */
3741 expand_copysign (rtx op0, rtx op1, rtx target)
3743 enum machine_mode mode = GET_MODE (op0);
3744 const struct real_format *fmt;
3745 bool op0_is_abs;
3746 rtx temp;
3748 gcc_assert (SCALAR_FLOAT_MODE_P (mode));
3749 gcc_assert (GET_MODE (op1) == mode);
3751 /* First try to do it with a special instruction. */
3752 temp = expand_binop (mode, copysign_optab, op0, op1,
3753 target, 0, OPTAB_DIRECT);
3754 if (temp)
3755 return temp;
3757 fmt = REAL_MODE_FORMAT (mode);
3758 if (fmt == NULL || !fmt->has_signed_zero)
3759 return NULL_RTX;
3761 op0_is_abs = false;
3762 if (GET_CODE (op0) == CONST_DOUBLE)
3764 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
3765 op0 = simplify_unary_operation (ABS, mode, op0, mode);
3766 op0_is_abs = true;
3769 if (fmt->signbit_ro >= 0
3770 && (GET_CODE (op0) == CONST_DOUBLE
3771 || (optab_handler (neg_optab, mode)->insn_code != CODE_FOR_nothing
3772 && optab_handler (abs_optab, mode)->insn_code != CODE_FOR_nothing)))
3774 temp = expand_copysign_absneg (mode, op0, op1, target,
3775 fmt->signbit_ro, op0_is_abs);
3776 if (temp)
3777 return temp;
3780 if (fmt->signbit_rw < 0)
3781 return NULL_RTX;
3782 return expand_copysign_bit (mode, op0, op1, target,
3783 fmt->signbit_rw, op0_is_abs);
3786 /* Generate an instruction whose insn-code is INSN_CODE,
3787 with two operands: an output TARGET and an input OP0.
3788 TARGET *must* be nonzero, and the output is always stored there.
3789 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3790 the value that is stored into TARGET.
3792 Return false if expansion failed. */
3794 bool
3795 maybe_emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3797 rtx temp;
3798 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3799 rtx pat;
3800 rtx last = get_last_insn ();
3802 temp = target;
3804 /* Now, if insn does not accept our operands, put them into pseudos. */
3806 if (!insn_data[icode].operand[1].predicate (op0, mode0))
3807 op0 = copy_to_mode_reg (mode0, op0);
3809 if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
3810 temp = gen_reg_rtx (GET_MODE (temp));
3812 pat = GEN_FCN (icode) (temp, op0);
3813 if (!pat)
3815 delete_insns_since (last);
3816 return false;
3819 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
3820 add_equal_note (pat, temp, code, op0, NULL_RTX);
3822 emit_insn (pat);
3824 if (temp != target)
3825 emit_move_insn (target, temp);
3826 return true;
3828 /* Generate an instruction whose insn-code is INSN_CODE,
3829 with two operands: an output TARGET and an input OP0.
3830 TARGET *must* be nonzero, and the output is always stored there.
3831 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3832 the value that is stored into TARGET. */
3834 void
3835 emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
3837 bool ok = maybe_emit_unop_insn (icode, target, op0, code);
3838 gcc_assert (ok);
3841 struct no_conflict_data
3843 rtx target, first, insn;
3844 bool must_stay;
3847 /* Called via note_stores by emit_libcall_block. Set P->must_stay if
3848 the currently examined clobber / store has to stay in the list of
3849 insns that constitute the actual libcall block. */
3850 static void
3851 no_conflict_move_test (rtx dest, const_rtx set, void *p0)
3853 struct no_conflict_data *p= (struct no_conflict_data *) p0;
3855 /* If this inns directly contributes to setting the target, it must stay. */
3856 if (reg_overlap_mentioned_p (p->target, dest))
3857 p->must_stay = true;
3858 /* If we haven't committed to keeping any other insns in the list yet,
3859 there is nothing more to check. */
3860 else if (p->insn == p->first)
3861 return;
3862 /* If this insn sets / clobbers a register that feeds one of the insns
3863 already in the list, this insn has to stay too. */
3864 else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
3865 || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
3866 || reg_used_between_p (dest, p->first, p->insn)
3867 /* Likewise if this insn depends on a register set by a previous
3868 insn in the list, or if it sets a result (presumably a hard
3869 register) that is set or clobbered by a previous insn.
3870 N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
3871 SET_DEST perform the former check on the address, and the latter
3872 check on the MEM. */
3873 || (GET_CODE (set) == SET
3874 && (modified_in_p (SET_SRC (set), p->first)
3875 || modified_in_p (SET_DEST (set), p->first)
3876 || modified_between_p (SET_SRC (set), p->first, p->insn)
3877 || modified_between_p (SET_DEST (set), p->first, p->insn))))
3878 p->must_stay = true;
3882 /* Emit code to make a call to a constant function or a library call.
3884 INSNS is a list containing all insns emitted in the call.
3885 These insns leave the result in RESULT. Our block is to copy RESULT
3886 to TARGET, which is logically equivalent to EQUIV.
3888 We first emit any insns that set a pseudo on the assumption that these are
3889 loading constants into registers; doing so allows them to be safely cse'ed
3890 between blocks. Then we emit all the other insns in the block, followed by
3891 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
3892 note with an operand of EQUIV. */
3894 void
3895 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
3897 rtx final_dest = target;
3898 rtx next, last, insn;
3900 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
3901 into a MEM later. Protect the libcall block from this change. */
3902 if (! REG_P (target) || REG_USERVAR_P (target))
3903 target = gen_reg_rtx (GET_MODE (target));
3905 /* If we're using non-call exceptions, a libcall corresponding to an
3906 operation that may trap may also trap. */
3907 /* ??? See the comment in front of make_reg_eh_region_note. */
3908 if (flag_non_call_exceptions && may_trap_p (equiv))
3910 for (insn = insns; insn; insn = NEXT_INSN (insn))
3911 if (CALL_P (insn))
3913 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3914 if (note)
3916 int lp_nr = INTVAL (XEXP (note, 0));
3917 if (lp_nr == 0 || lp_nr == INT_MIN)
3918 remove_note (insn, note);
3922 else
3924 /* Look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
3925 reg note to indicate that this call cannot throw or execute a nonlocal
3926 goto (unless there is already a REG_EH_REGION note, in which case
3927 we update it). */
3928 for (insn = insns; insn; insn = NEXT_INSN (insn))
3929 if (CALL_P (insn))
3930 make_reg_eh_region_note_nothrow_nononlocal (insn);
3933 /* First emit all insns that set pseudos. Remove them from the list as
3934 we go. Avoid insns that set pseudos which were referenced in previous
3935 insns. These can be generated by move_by_pieces, for example,
3936 to update an address. Similarly, avoid insns that reference things
3937 set in previous insns. */
3939 for (insn = insns; insn; insn = next)
3941 rtx set = single_set (insn);
3943 next = NEXT_INSN (insn);
3945 if (set != 0 && REG_P (SET_DEST (set))
3946 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
3948 struct no_conflict_data data;
3950 data.target = const0_rtx;
3951 data.first = insns;
3952 data.insn = insn;
3953 data.must_stay = 0;
3954 note_stores (PATTERN (insn), no_conflict_move_test, &data);
3955 if (! data.must_stay)
3957 if (PREV_INSN (insn))
3958 NEXT_INSN (PREV_INSN (insn)) = next;
3959 else
3960 insns = next;
3962 if (next)
3963 PREV_INSN (next) = PREV_INSN (insn);
3965 add_insn (insn);
3969 /* Some ports use a loop to copy large arguments onto the stack.
3970 Don't move anything outside such a loop. */
3971 if (LABEL_P (insn))
3972 break;
3975 /* Write the remaining insns followed by the final copy. */
3976 for (insn = insns; insn; insn = next)
3978 next = NEXT_INSN (insn);
3980 add_insn (insn);
3983 last = emit_move_insn (target, result);
3984 if (optab_handler (mov_optab, GET_MODE (target))->insn_code
3985 != CODE_FOR_nothing)
3986 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
3988 if (final_dest != target)
3989 emit_move_insn (final_dest, target);
3992 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
3993 PURPOSE describes how this comparison will be used. CODE is the rtx
3994 comparison code we will be using.
3996 ??? Actually, CODE is slightly weaker than that. A target is still
3997 required to implement all of the normal bcc operations, but not
3998 required to implement all (or any) of the unordered bcc operations. */
4001 can_compare_p (enum rtx_code code, enum machine_mode mode,
4002 enum can_compare_purpose purpose)
4004 rtx test;
4005 test = gen_rtx_fmt_ee (code, mode, const0_rtx, const0_rtx);
4008 int icode;
4010 if (purpose == ccp_jump
4011 && (icode = optab_handler (cbranch_optab, mode)->insn_code) != CODE_FOR_nothing
4012 && insn_data[icode].operand[0].predicate (test, mode))
4013 return 1;
4014 if (purpose == ccp_store_flag
4015 && (icode = optab_handler (cstore_optab, mode)->insn_code) != CODE_FOR_nothing
4016 && insn_data[icode].operand[1].predicate (test, mode))
4017 return 1;
4018 if (purpose == ccp_cmov
4019 && optab_handler (cmov_optab, mode)->insn_code != CODE_FOR_nothing)
4020 return 1;
4022 mode = GET_MODE_WIDER_MODE (mode);
4023 PUT_MODE (test, mode);
4025 while (mode != VOIDmode);
4027 return 0;
4030 /* This function is called when we are going to emit a compare instruction that
4031 compares the values found in *PX and *PY, using the rtl operator COMPARISON.
4033 *PMODE is the mode of the inputs (in case they are const_int).
4034 *PUNSIGNEDP nonzero says that the operands are unsigned;
4035 this matters if they need to be widened (as given by METHODS).
4037 If they have mode BLKmode, then SIZE specifies the size of both operands.
4039 This function performs all the setup necessary so that the caller only has
4040 to emit a single comparison insn. This setup can involve doing a BLKmode
4041 comparison or emitting a library call to perform the comparison if no insn
4042 is available to handle it.
4043 The values which are passed in through pointers can be modified; the caller
4044 should perform the comparison on the modified values. Constant
4045 comparisons must have already been folded. */
4047 static void
4048 prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
4049 int unsignedp, enum optab_methods methods,
4050 rtx *ptest, enum machine_mode *pmode)
4052 enum machine_mode mode = *pmode;
4053 rtx libfunc, test;
4054 enum machine_mode cmp_mode;
4055 enum mode_class mclass;
4057 /* The other methods are not needed. */
4058 gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
4059 || methods == OPTAB_LIB_WIDEN);
4061 /* If we are optimizing, force expensive constants into a register. */
4062 if (CONSTANT_P (x) && optimize
4063 && (rtx_cost (x, COMPARE, optimize_insn_for_speed_p ())
4064 > COSTS_N_INSNS (1)))
4065 x = force_reg (mode, x);
4067 if (CONSTANT_P (y) && optimize
4068 && (rtx_cost (y, COMPARE, optimize_insn_for_speed_p ())
4069 > COSTS_N_INSNS (1)))
4070 y = force_reg (mode, y);
4072 #ifdef HAVE_cc0
4073 /* Make sure if we have a canonical comparison. The RTL
4074 documentation states that canonical comparisons are required only
4075 for targets which have cc0. */
4076 gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
4077 #endif
4079 /* Don't let both operands fail to indicate the mode. */
4080 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
4081 x = force_reg (mode, x);
4082 if (mode == VOIDmode)
4083 mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : GET_MODE (y);
4085 /* Handle all BLKmode compares. */
4087 if (mode == BLKmode)
4089 enum machine_mode result_mode;
4090 enum insn_code cmp_code;
4091 tree length_type;
4092 rtx libfunc;
4093 rtx result;
4094 rtx opalign
4095 = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
4097 gcc_assert (size);
4099 /* Try to use a memory block compare insn - either cmpstr
4100 or cmpmem will do. */
4101 for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
4102 cmp_mode != VOIDmode;
4103 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
4105 cmp_code = cmpmem_optab[cmp_mode];
4106 if (cmp_code == CODE_FOR_nothing)
4107 cmp_code = cmpstr_optab[cmp_mode];
4108 if (cmp_code == CODE_FOR_nothing)
4109 cmp_code = cmpstrn_optab[cmp_mode];
4110 if (cmp_code == CODE_FOR_nothing)
4111 continue;
4113 /* Must make sure the size fits the insn's mode. */
4114 if ((CONST_INT_P (size)
4115 && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
4116 || (GET_MODE_BITSIZE (GET_MODE (size))
4117 > GET_MODE_BITSIZE (cmp_mode)))
4118 continue;
4120 result_mode = insn_data[cmp_code].operand[0].mode;
4121 result = gen_reg_rtx (result_mode);
4122 size = convert_to_mode (cmp_mode, size, 1);
4123 emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
4125 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4126 *pmode = result_mode;
4127 return;
4130 if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
4131 goto fail;
4133 /* Otherwise call a library function, memcmp. */
4134 libfunc = memcmp_libfunc;
4135 length_type = sizetype;
4136 result_mode = TYPE_MODE (integer_type_node);
4137 cmp_mode = TYPE_MODE (length_type);
4138 size = convert_to_mode (TYPE_MODE (length_type), size,
4139 TYPE_UNSIGNED (length_type));
4141 result = emit_library_call_value (libfunc, 0, LCT_PURE,
4142 result_mode, 3,
4143 XEXP (x, 0), Pmode,
4144 XEXP (y, 0), Pmode,
4145 size, cmp_mode);
4147 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4148 *pmode = result_mode;
4149 return;
4152 /* Don't allow operands to the compare to trap, as that can put the
4153 compare and branch in different basic blocks. */
4154 if (flag_non_call_exceptions)
4156 if (may_trap_p (x))
4157 x = force_reg (mode, x);
4158 if (may_trap_p (y))
4159 y = force_reg (mode, y);
4162 if (GET_MODE_CLASS (mode) == MODE_CC)
4164 gcc_assert (can_compare_p (comparison, CCmode, ccp_jump));
4165 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4166 return;
4169 mclass = GET_MODE_CLASS (mode);
4170 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4171 cmp_mode = mode;
4174 enum insn_code icode;
4175 icode = optab_handler (cbranch_optab, cmp_mode)->insn_code;
4176 if (icode != CODE_FOR_nothing
4177 && insn_data[icode].operand[0].predicate (test, VOIDmode))
4179 rtx last = get_last_insn ();
4180 rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp);
4181 rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp);
4182 if (op0 && op1
4183 && insn_data[icode].operand[1].predicate
4184 (op0, insn_data[icode].operand[1].mode)
4185 && insn_data[icode].operand[2].predicate
4186 (op1, insn_data[icode].operand[2].mode))
4188 XEXP (test, 0) = op0;
4189 XEXP (test, 1) = op1;
4190 *ptest = test;
4191 *pmode = cmp_mode;
4192 return;
4194 delete_insns_since (last);
4197 if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
4198 break;
4199 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode);
4201 while (cmp_mode != VOIDmode);
4203 if (methods != OPTAB_LIB_WIDEN)
4204 goto fail;
4206 if (!SCALAR_FLOAT_MODE_P (mode))
4208 rtx result;
4210 /* Handle a libcall just for the mode we are using. */
4211 libfunc = optab_libfunc (cmp_optab, mode);
4212 gcc_assert (libfunc);
4214 /* If we want unsigned, and this mode has a distinct unsigned
4215 comparison routine, use that. */
4216 if (unsignedp)
4218 rtx ulibfunc = optab_libfunc (ucmp_optab, mode);
4219 if (ulibfunc)
4220 libfunc = ulibfunc;
4223 result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4224 targetm.libgcc_cmp_return_mode (),
4225 2, x, mode, y, mode);
4227 /* There are two kinds of comparison routines. Biased routines
4228 return 0/1/2, and unbiased routines return -1/0/1. Other parts
4229 of gcc expect that the comparison operation is equivalent
4230 to the modified comparison. For signed comparisons compare the
4231 result against 1 in the biased case, and zero in the unbiased
4232 case. For unsigned comparisons always compare against 1 after
4233 biasing the unbiased result by adding 1. This gives us a way to
4234 represent LTU. */
4235 x = result;
4236 y = const1_rtx;
4238 if (!TARGET_LIB_INT_CMP_BIASED)
4240 if (unsignedp)
4241 x = plus_constant (result, 1);
4242 else
4243 y = const0_rtx;
4246 *pmode = word_mode;
4247 prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods,
4248 ptest, pmode);
4250 else
4251 prepare_float_lib_cmp (x, y, comparison, ptest, pmode);
4253 return;
4255 fail:
4256 *ptest = NULL_RTX;
4259 /* Before emitting an insn with code ICODE, make sure that X, which is going
4260 to be used for operand OPNUM of the insn, is converted from mode MODE to
4261 WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
4262 that it is accepted by the operand predicate. Return the new value. */
4265 prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
4266 enum machine_mode wider_mode, int unsignedp)
4268 if (mode != wider_mode)
4269 x = convert_modes (wider_mode, mode, x, unsignedp);
4271 if (!insn_data[icode].operand[opnum].predicate
4272 (x, insn_data[icode].operand[opnum].mode))
4274 if (reload_completed)
4275 return NULL_RTX;
4276 x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
4279 return x;
4282 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
4283 we can do the branch. */
4285 static void
4286 emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label)
4288 enum machine_mode optab_mode;
4289 enum mode_class mclass;
4290 enum insn_code icode;
4292 mclass = GET_MODE_CLASS (mode);
4293 optab_mode = (mclass == MODE_CC) ? CCmode : mode;
4294 icode = optab_handler (cbranch_optab, optab_mode)->insn_code;
4296 gcc_assert (icode != CODE_FOR_nothing);
4297 gcc_assert (insn_data[icode].operand[0].predicate (test, VOIDmode));
4298 emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0), XEXP (test, 1), label));
4301 /* Generate code to compare X with Y so that the condition codes are
4302 set and to jump to LABEL if the condition is true. If X is a
4303 constant and Y is not a constant, then the comparison is swapped to
4304 ensure that the comparison RTL has the canonical form.
4306 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
4307 need to be widened. UNSIGNEDP is also used to select the proper
4308 branch condition code.
4310 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
4312 MODE is the mode of the inputs (in case they are const_int).
4314 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
4315 It will be potentially converted into an unsigned variant based on
4316 UNSIGNEDP to select a proper jump instruction. */
4318 void
4319 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
4320 enum machine_mode mode, int unsignedp, rtx label)
4322 rtx op0 = x, op1 = y;
4323 rtx test;
4325 /* Swap operands and condition to ensure canonical RTL. */
4326 if (swap_commutative_operands_p (x, y)
4327 && can_compare_p (swap_condition (comparison), mode, ccp_jump))
4329 op0 = y, op1 = x;
4330 comparison = swap_condition (comparison);
4333 /* If OP0 is still a constant, then both X and Y must be constants
4334 or the opposite comparison is not supported. Force X into a register
4335 to create canonical RTL. */
4336 if (CONSTANT_P (op0))
4337 op0 = force_reg (mode, op0);
4339 if (unsignedp)
4340 comparison = unsigned_condition (comparison);
4342 prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
4343 &test, &mode);
4344 emit_cmp_and_jump_insn_1 (test, mode, label);
4348 /* Emit a library call comparison between floating point X and Y.
4349 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
4351 static void
4352 prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
4353 rtx *ptest, enum machine_mode *pmode)
4355 enum rtx_code swapped = swap_condition (comparison);
4356 enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
4357 enum machine_mode orig_mode = GET_MODE (x);
4358 enum machine_mode mode, cmp_mode;
4359 rtx value, target, insns, equiv;
4360 rtx libfunc = 0;
4361 bool reversed_p = false;
4362 cmp_mode = targetm.libgcc_cmp_return_mode ();
4364 for (mode = orig_mode;
4365 mode != VOIDmode;
4366 mode = GET_MODE_WIDER_MODE (mode))
4368 if (code_to_optab[comparison]
4369 && (libfunc = optab_libfunc (code_to_optab[comparison], mode)))
4370 break;
4372 if (code_to_optab[swapped]
4373 && (libfunc = optab_libfunc (code_to_optab[swapped], mode)))
4375 rtx tmp;
4376 tmp = x; x = y; y = tmp;
4377 comparison = swapped;
4378 break;
4381 if (code_to_optab[reversed]
4382 && (libfunc = optab_libfunc (code_to_optab[reversed], mode))
4383 && FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, reversed))
4385 comparison = reversed;
4386 reversed_p = true;
4387 break;
4391 gcc_assert (mode != VOIDmode);
4393 if (mode != orig_mode)
4395 x = convert_to_mode (mode, x, 0);
4396 y = convert_to_mode (mode, y, 0);
4399 /* Attach a REG_EQUAL note describing the semantics of the libcall to
4400 the RTL. The allows the RTL optimizers to delete the libcall if the
4401 condition can be determined at compile-time. */
4402 if (comparison == UNORDERED)
4404 rtx temp = simplify_gen_relational (NE, cmp_mode, mode, x, x);
4405 equiv = simplify_gen_relational (NE, cmp_mode, mode, y, y);
4406 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4407 temp, const_true_rtx, equiv);
4409 else
4411 equiv = simplify_gen_relational (comparison, cmp_mode, mode, x, y);
4412 if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4414 rtx true_rtx, false_rtx;
4416 switch (comparison)
4418 case EQ:
4419 true_rtx = const0_rtx;
4420 false_rtx = const_true_rtx;
4421 break;
4423 case NE:
4424 true_rtx = const_true_rtx;
4425 false_rtx = const0_rtx;
4426 break;
4428 case GT:
4429 true_rtx = const1_rtx;
4430 false_rtx = const0_rtx;
4431 break;
4433 case GE:
4434 true_rtx = const0_rtx;
4435 false_rtx = constm1_rtx;
4436 break;
4438 case LT:
4439 true_rtx = constm1_rtx;
4440 false_rtx = const0_rtx;
4441 break;
4443 case LE:
4444 true_rtx = const0_rtx;
4445 false_rtx = const1_rtx;
4446 break;
4448 default:
4449 gcc_unreachable ();
4451 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4452 equiv, true_rtx, false_rtx);
4456 start_sequence ();
4457 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4458 cmp_mode, 2, x, mode, y, mode);
4459 insns = get_insns ();
4460 end_sequence ();
4462 target = gen_reg_rtx (cmp_mode);
4463 emit_libcall_block (insns, target, value, equiv);
4465 if (comparison == UNORDERED
4466 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4467 comparison = reversed_p ? EQ : NE;
4469 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, target, const0_rtx);
4470 *pmode = cmp_mode;
4473 /* Generate code to indirectly jump to a location given in the rtx LOC. */
4475 void
4476 emit_indirect_jump (rtx loc)
4478 if (!insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate
4479 (loc, Pmode))
4480 loc = copy_to_mode_reg (Pmode, loc);
4482 emit_jump_insn (gen_indirect_jump (loc));
4483 emit_barrier ();
4486 #ifdef HAVE_conditional_move
4488 /* Emit a conditional move instruction if the machine supports one for that
4489 condition and machine mode.
4491 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4492 the mode to use should they be constants. If it is VOIDmode, they cannot
4493 both be constants.
4495 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
4496 should be stored there. MODE is the mode to use should they be constants.
4497 If it is VOIDmode, they cannot both be constants.
4499 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4500 is not supported. */
4503 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
4504 enum machine_mode cmode, rtx op2, rtx op3,
4505 enum machine_mode mode, int unsignedp)
4507 rtx tem, subtarget, comparison, insn;
4508 enum insn_code icode;
4509 enum rtx_code reversed;
4511 /* If one operand is constant, make it the second one. Only do this
4512 if the other operand is not constant as well. */
4514 if (swap_commutative_operands_p (op0, op1))
4516 tem = op0;
4517 op0 = op1;
4518 op1 = tem;
4519 code = swap_condition (code);
4522 /* get_condition will prefer to generate LT and GT even if the old
4523 comparison was against zero, so undo that canonicalization here since
4524 comparisons against zero are cheaper. */
4525 if (code == LT && op1 == const1_rtx)
4526 code = LE, op1 = const0_rtx;
4527 else if (code == GT && op1 == constm1_rtx)
4528 code = GE, op1 = const0_rtx;
4530 if (cmode == VOIDmode)
4531 cmode = GET_MODE (op0);
4533 if (swap_commutative_operands_p (op2, op3)
4534 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4535 != UNKNOWN))
4537 tem = op2;
4538 op2 = op3;
4539 op3 = tem;
4540 code = reversed;
4543 if (mode == VOIDmode)
4544 mode = GET_MODE (op2);
4546 icode = movcc_gen_code[mode];
4548 if (icode == CODE_FOR_nothing)
4549 return 0;
4551 if (!target)
4552 target = gen_reg_rtx (mode);
4554 subtarget = target;
4556 /* If the insn doesn't accept these operands, put them in pseudos. */
4558 if (!insn_data[icode].operand[0].predicate
4559 (subtarget, insn_data[icode].operand[0].mode))
4560 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4562 if (!insn_data[icode].operand[2].predicate
4563 (op2, insn_data[icode].operand[2].mode))
4564 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4566 if (!insn_data[icode].operand[3].predicate
4567 (op3, insn_data[icode].operand[3].mode))
4568 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4570 /* Everything should now be in the suitable form. */
4572 code = unsignedp ? unsigned_condition (code) : code;
4573 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4575 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4576 return NULL and let the caller figure out how best to deal with this
4577 situation. */
4578 if (!COMPARISON_P (comparison))
4579 return NULL_RTX;
4581 do_pending_stack_adjust ();
4582 start_sequence ();
4583 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4584 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4585 &comparison, &cmode);
4586 if (!comparison)
4587 insn = NULL_RTX;
4588 else
4589 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4591 /* If that failed, then give up. */
4592 if (insn == 0)
4594 end_sequence ();
4595 return 0;
4598 emit_insn (insn);
4599 insn = get_insns ();
4600 end_sequence ();
4601 emit_insn (insn);
4602 if (subtarget != target)
4603 convert_move (target, subtarget, 0);
4605 return target;
4608 /* Return nonzero if a conditional move of mode MODE is supported.
4610 This function is for combine so it can tell whether an insn that looks
4611 like a conditional move is actually supported by the hardware. If we
4612 guess wrong we lose a bit on optimization, but that's it. */
4613 /* ??? sparc64 supports conditionally moving integers values based on fp
4614 comparisons, and vice versa. How do we handle them? */
4617 can_conditionally_move_p (enum machine_mode mode)
4619 if (movcc_gen_code[mode] != CODE_FOR_nothing)
4620 return 1;
4622 return 0;
4625 #endif /* HAVE_conditional_move */
4627 /* Emit a conditional addition instruction if the machine supports one for that
4628 condition and machine mode.
4630 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4631 the mode to use should they be constants. If it is VOIDmode, they cannot
4632 both be constants.
4634 OP2 should be stored in TARGET if the comparison is true, otherwise OP2+OP3
4635 should be stored there. MODE is the mode to use should they be constants.
4636 If it is VOIDmode, they cannot both be constants.
4638 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4639 is not supported. */
4642 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
4643 enum machine_mode cmode, rtx op2, rtx op3,
4644 enum machine_mode mode, int unsignedp)
4646 rtx tem, subtarget, comparison, insn;
4647 enum insn_code icode;
4648 enum rtx_code reversed;
4650 /* If one operand is constant, make it the second one. Only do this
4651 if the other operand is not constant as well. */
4653 if (swap_commutative_operands_p (op0, op1))
4655 tem = op0;
4656 op0 = op1;
4657 op1 = tem;
4658 code = swap_condition (code);
4661 /* get_condition will prefer to generate LT and GT even if the old
4662 comparison was against zero, so undo that canonicalization here since
4663 comparisons against zero are cheaper. */
4664 if (code == LT && op1 == const1_rtx)
4665 code = LE, op1 = const0_rtx;
4666 else if (code == GT && op1 == constm1_rtx)
4667 code = GE, op1 = const0_rtx;
4669 if (cmode == VOIDmode)
4670 cmode = GET_MODE (op0);
4672 if (swap_commutative_operands_p (op2, op3)
4673 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4674 != UNKNOWN))
4676 tem = op2;
4677 op2 = op3;
4678 op3 = tem;
4679 code = reversed;
4682 if (mode == VOIDmode)
4683 mode = GET_MODE (op2);
4685 icode = optab_handler (addcc_optab, mode)->insn_code;
4687 if (icode == CODE_FOR_nothing)
4688 return 0;
4690 if (!target)
4691 target = gen_reg_rtx (mode);
4693 /* If the insn doesn't accept these operands, put them in pseudos. */
4695 if (!insn_data[icode].operand[0].predicate
4696 (target, insn_data[icode].operand[0].mode))
4697 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4698 else
4699 subtarget = target;
4701 if (!insn_data[icode].operand[2].predicate
4702 (op2, insn_data[icode].operand[2].mode))
4703 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4705 if (!insn_data[icode].operand[3].predicate
4706 (op3, insn_data[icode].operand[3].mode))
4707 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4709 /* Everything should now be in the suitable form. */
4711 code = unsignedp ? unsigned_condition (code) : code;
4712 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4714 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4715 return NULL and let the caller figure out how best to deal with this
4716 situation. */
4717 if (!COMPARISON_P (comparison))
4718 return NULL_RTX;
4720 do_pending_stack_adjust ();
4721 start_sequence ();
4722 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4723 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4724 &comparison, &cmode);
4725 if (!comparison)
4726 insn = NULL_RTX;
4727 else
4728 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
4730 /* If that failed, then give up. */
4731 if (insn == 0)
4733 end_sequence ();
4734 return 0;
4737 emit_insn (insn);
4738 insn = get_insns ();
4739 end_sequence ();
4740 emit_insn (insn);
4741 if (subtarget != target)
4742 convert_move (target, subtarget, 0);
4744 return target;
4747 /* These functions attempt to generate an insn body, rather than
4748 emitting the insn, but if the gen function already emits them, we
4749 make no attempt to turn them back into naked patterns. */
4751 /* Generate and return an insn body to add Y to X. */
4754 gen_add2_insn (rtx x, rtx y)
4756 int icode = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
4758 gcc_assert (insn_data[icode].operand[0].predicate
4759 (x, insn_data[icode].operand[0].mode));
4760 gcc_assert (insn_data[icode].operand[1].predicate
4761 (x, insn_data[icode].operand[1].mode));
4762 gcc_assert (insn_data[icode].operand[2].predicate
4763 (y, insn_data[icode].operand[2].mode));
4765 return GEN_FCN (icode) (x, x, y);
4768 /* Generate and return an insn body to add r1 and c,
4769 storing the result in r0. */
4772 gen_add3_insn (rtx r0, rtx r1, rtx c)
4774 int icode = (int) optab_handler (add_optab, GET_MODE (r0))->insn_code;
4776 if (icode == CODE_FOR_nothing
4777 || !(insn_data[icode].operand[0].predicate
4778 (r0, insn_data[icode].operand[0].mode))
4779 || !(insn_data[icode].operand[1].predicate
4780 (r1, insn_data[icode].operand[1].mode))
4781 || !(insn_data[icode].operand[2].predicate
4782 (c, insn_data[icode].operand[2].mode)))
4783 return NULL_RTX;
4785 return GEN_FCN (icode) (r0, r1, c);
4789 have_add2_insn (rtx x, rtx y)
4791 int icode;
4793 gcc_assert (GET_MODE (x) != VOIDmode);
4795 icode = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
4797 if (icode == CODE_FOR_nothing)
4798 return 0;
4800 if (!(insn_data[icode].operand[0].predicate
4801 (x, insn_data[icode].operand[0].mode))
4802 || !(insn_data[icode].operand[1].predicate
4803 (x, insn_data[icode].operand[1].mode))
4804 || !(insn_data[icode].operand[2].predicate
4805 (y, insn_data[icode].operand[2].mode)))
4806 return 0;
4808 return 1;
4811 /* Generate and return an insn body to subtract Y from X. */
4814 gen_sub2_insn (rtx x, rtx y)
4816 int icode = (int) optab_handler (sub_optab, GET_MODE (x))->insn_code;
4818 gcc_assert (insn_data[icode].operand[0].predicate
4819 (x, insn_data[icode].operand[0].mode));
4820 gcc_assert (insn_data[icode].operand[1].predicate
4821 (x, insn_data[icode].operand[1].mode));
4822 gcc_assert (insn_data[icode].operand[2].predicate
4823 (y, insn_data[icode].operand[2].mode));
4825 return GEN_FCN (icode) (x, x, y);
4828 /* Generate and return an insn body to subtract r1 and c,
4829 storing the result in r0. */
4832 gen_sub3_insn (rtx r0, rtx r1, rtx c)
4834 int icode = (int) optab_handler (sub_optab, GET_MODE (r0))->insn_code;
4836 if (icode == CODE_FOR_nothing
4837 || !(insn_data[icode].operand[0].predicate
4838 (r0, insn_data[icode].operand[0].mode))
4839 || !(insn_data[icode].operand[1].predicate
4840 (r1, insn_data[icode].operand[1].mode))
4841 || !(insn_data[icode].operand[2].predicate
4842 (c, insn_data[icode].operand[2].mode)))
4843 return NULL_RTX;
4845 return GEN_FCN (icode) (r0, r1, c);
4849 have_sub2_insn (rtx x, rtx y)
4851 int icode;
4853 gcc_assert (GET_MODE (x) != VOIDmode);
4855 icode = (int) optab_handler (sub_optab, GET_MODE (x))->insn_code;
4857 if (icode == CODE_FOR_nothing)
4858 return 0;
4860 if (!(insn_data[icode].operand[0].predicate
4861 (x, insn_data[icode].operand[0].mode))
4862 || !(insn_data[icode].operand[1].predicate
4863 (x, insn_data[icode].operand[1].mode))
4864 || !(insn_data[icode].operand[2].predicate
4865 (y, insn_data[icode].operand[2].mode)))
4866 return 0;
4868 return 1;
4871 /* Generate the body of an instruction to copy Y into X.
4872 It may be a list of insns, if one insn isn't enough. */
4875 gen_move_insn (rtx x, rtx y)
4877 rtx seq;
4879 start_sequence ();
4880 emit_move_insn_1 (x, y);
4881 seq = get_insns ();
4882 end_sequence ();
4883 return seq;
4886 /* Return the insn code used to extend FROM_MODE to TO_MODE.
4887 UNSIGNEDP specifies zero-extension instead of sign-extension. If
4888 no such operation exists, CODE_FOR_nothing will be returned. */
4890 enum insn_code
4891 can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
4892 int unsignedp)
4894 convert_optab tab;
4895 #ifdef HAVE_ptr_extend
4896 if (unsignedp < 0)
4897 return CODE_FOR_ptr_extend;
4898 #endif
4900 tab = unsignedp ? zext_optab : sext_optab;
4901 return convert_optab_handler (tab, to_mode, from_mode)->insn_code;
4904 /* Generate the body of an insn to extend Y (with mode MFROM)
4905 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
4908 gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
4909 enum machine_mode mfrom, int unsignedp)
4911 enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
4912 return GEN_FCN (icode) (x, y);
4915 /* can_fix_p and can_float_p say whether the target machine
4916 can directly convert a given fixed point type to
4917 a given floating point type, or vice versa.
4918 The returned value is the CODE_FOR_... value to use,
4919 or CODE_FOR_nothing if these modes cannot be directly converted.
4921 *TRUNCP_PTR is set to 1 if it is necessary to output
4922 an explicit FTRUNC insn before the fix insn; otherwise 0. */
4924 static enum insn_code
4925 can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
4926 int unsignedp, int *truncp_ptr)
4928 convert_optab tab;
4929 enum insn_code icode;
4931 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
4932 icode = convert_optab_handler (tab, fixmode, fltmode)->insn_code;
4933 if (icode != CODE_FOR_nothing)
4935 *truncp_ptr = 0;
4936 return icode;
4939 /* FIXME: This requires a port to define both FIX and FTRUNC pattern
4940 for this to work. We need to rework the fix* and ftrunc* patterns
4941 and documentation. */
4942 tab = unsignedp ? ufix_optab : sfix_optab;
4943 icode = convert_optab_handler (tab, fixmode, fltmode)->insn_code;
4944 if (icode != CODE_FOR_nothing
4945 && optab_handler (ftrunc_optab, fltmode)->insn_code != CODE_FOR_nothing)
4947 *truncp_ptr = 1;
4948 return icode;
4951 *truncp_ptr = 0;
4952 return CODE_FOR_nothing;
4955 static enum insn_code
4956 can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
4957 int unsignedp)
4959 convert_optab tab;
4961 tab = unsignedp ? ufloat_optab : sfloat_optab;
4962 return convert_optab_handler (tab, fltmode, fixmode)->insn_code;
4965 /* Generate code to convert FROM to floating point
4966 and store in TO. FROM must be fixed point and not VOIDmode.
4967 UNSIGNEDP nonzero means regard FROM as unsigned.
4968 Normally this is done by correcting the final value
4969 if it is negative. */
4971 void
4972 expand_float (rtx to, rtx from, int unsignedp)
4974 enum insn_code icode;
4975 rtx target = to;
4976 enum machine_mode fmode, imode;
4977 bool can_do_signed = false;
4979 /* Crash now, because we won't be able to decide which mode to use. */
4980 gcc_assert (GET_MODE (from) != VOIDmode);
4982 /* Look for an insn to do the conversion. Do it in the specified
4983 modes if possible; otherwise convert either input, output or both to
4984 wider mode. If the integer mode is wider than the mode of FROM,
4985 we can do the conversion signed even if the input is unsigned. */
4987 for (fmode = GET_MODE (to); fmode != VOIDmode;
4988 fmode = GET_MODE_WIDER_MODE (fmode))
4989 for (imode = GET_MODE (from); imode != VOIDmode;
4990 imode = GET_MODE_WIDER_MODE (imode))
4992 int doing_unsigned = unsignedp;
4994 if (fmode != GET_MODE (to)
4995 && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
4996 continue;
4998 icode = can_float_p (fmode, imode, unsignedp);
4999 if (icode == CODE_FOR_nothing && unsignedp)
5001 enum insn_code scode = can_float_p (fmode, imode, 0);
5002 if (scode != CODE_FOR_nothing)
5003 can_do_signed = true;
5004 if (imode != GET_MODE (from))
5005 icode = scode, doing_unsigned = 0;
5008 if (icode != CODE_FOR_nothing)
5010 if (imode != GET_MODE (from))
5011 from = convert_to_mode (imode, from, unsignedp);
5013 if (fmode != GET_MODE (to))
5014 target = gen_reg_rtx (fmode);
5016 emit_unop_insn (icode, target, from,
5017 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
5019 if (target != to)
5020 convert_move (to, target, 0);
5021 return;
5025 /* Unsigned integer, and no way to convert directly. Convert as signed,
5026 then unconditionally adjust the result. */
5027 if (unsignedp && can_do_signed)
5029 rtx label = gen_label_rtx ();
5030 rtx temp;
5031 REAL_VALUE_TYPE offset;
5033 /* Look for a usable floating mode FMODE wider than the source and at
5034 least as wide as the target. Using FMODE will avoid rounding woes
5035 with unsigned values greater than the signed maximum value. */
5037 for (fmode = GET_MODE (to); fmode != VOIDmode;
5038 fmode = GET_MODE_WIDER_MODE (fmode))
5039 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
5040 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
5041 break;
5043 if (fmode == VOIDmode)
5045 /* There is no such mode. Pretend the target is wide enough. */
5046 fmode = GET_MODE (to);
5048 /* Avoid double-rounding when TO is narrower than FROM. */
5049 if ((significand_size (fmode) + 1)
5050 < GET_MODE_BITSIZE (GET_MODE (from)))
5052 rtx temp1;
5053 rtx neglabel = gen_label_rtx ();
5055 /* Don't use TARGET if it isn't a register, is a hard register,
5056 or is the wrong mode. */
5057 if (!REG_P (target)
5058 || REGNO (target) < FIRST_PSEUDO_REGISTER
5059 || GET_MODE (target) != fmode)
5060 target = gen_reg_rtx (fmode);
5062 imode = GET_MODE (from);
5063 do_pending_stack_adjust ();
5065 /* Test whether the sign bit is set. */
5066 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
5067 0, neglabel);
5069 /* The sign bit is not set. Convert as signed. */
5070 expand_float (target, from, 0);
5071 emit_jump_insn (gen_jump (label));
5072 emit_barrier ();
5074 /* The sign bit is set.
5075 Convert to a usable (positive signed) value by shifting right
5076 one bit, while remembering if a nonzero bit was shifted
5077 out; i.e., compute (from & 1) | (from >> 1). */
5079 emit_label (neglabel);
5080 temp = expand_binop (imode, and_optab, from, const1_rtx,
5081 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5082 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
5083 NULL_RTX, 1);
5084 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
5085 OPTAB_LIB_WIDEN);
5086 expand_float (target, temp, 0);
5088 /* Multiply by 2 to undo the shift above. */
5089 temp = expand_binop (fmode, add_optab, target, target,
5090 target, 0, OPTAB_LIB_WIDEN);
5091 if (temp != target)
5092 emit_move_insn (target, temp);
5094 do_pending_stack_adjust ();
5095 emit_label (label);
5096 goto done;
5100 /* If we are about to do some arithmetic to correct for an
5101 unsigned operand, do it in a pseudo-register. */
5103 if (GET_MODE (to) != fmode
5104 || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
5105 target = gen_reg_rtx (fmode);
5107 /* Convert as signed integer to floating. */
5108 expand_float (target, from, 0);
5110 /* If FROM is negative (and therefore TO is negative),
5111 correct its value by 2**bitwidth. */
5113 do_pending_stack_adjust ();
5114 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
5115 0, label);
5118 real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)), fmode);
5119 temp = expand_binop (fmode, add_optab, target,
5120 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
5121 target, 0, OPTAB_LIB_WIDEN);
5122 if (temp != target)
5123 emit_move_insn (target, temp);
5125 do_pending_stack_adjust ();
5126 emit_label (label);
5127 goto done;
5130 /* No hardware instruction available; call a library routine. */
5132 rtx libfunc;
5133 rtx insns;
5134 rtx value;
5135 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
5137 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
5138 from = convert_to_mode (SImode, from, unsignedp);
5140 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5141 gcc_assert (libfunc);
5143 start_sequence ();
5145 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5146 GET_MODE (to), 1, from,
5147 GET_MODE (from));
5148 insns = get_insns ();
5149 end_sequence ();
5151 emit_libcall_block (insns, target, value,
5152 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FLOAT : FLOAT,
5153 GET_MODE (to), from));
5156 done:
5158 /* Copy result to requested destination
5159 if we have been computing in a temp location. */
5161 if (target != to)
5163 if (GET_MODE (target) == GET_MODE (to))
5164 emit_move_insn (to, target);
5165 else
5166 convert_move (to, target, 0);
5170 /* Generate code to convert FROM to fixed point and store in TO. FROM
5171 must be floating point. */
5173 void
5174 expand_fix (rtx to, rtx from, int unsignedp)
5176 enum insn_code icode;
5177 rtx target = to;
5178 enum machine_mode fmode, imode;
5179 int must_trunc = 0;
5181 /* We first try to find a pair of modes, one real and one integer, at
5182 least as wide as FROM and TO, respectively, in which we can open-code
5183 this conversion. If the integer mode is wider than the mode of TO,
5184 we can do the conversion either signed or unsigned. */
5186 for (fmode = GET_MODE (from); fmode != VOIDmode;
5187 fmode = GET_MODE_WIDER_MODE (fmode))
5188 for (imode = GET_MODE (to); imode != VOIDmode;
5189 imode = GET_MODE_WIDER_MODE (imode))
5191 int doing_unsigned = unsignedp;
5193 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
5194 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
5195 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
5197 if (icode != CODE_FOR_nothing)
5199 rtx last = get_last_insn ();
5200 if (fmode != GET_MODE (from))
5201 from = convert_to_mode (fmode, from, 0);
5203 if (must_trunc)
5205 rtx temp = gen_reg_rtx (GET_MODE (from));
5206 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
5207 temp, 0);
5210 if (imode != GET_MODE (to))
5211 target = gen_reg_rtx (imode);
5213 if (maybe_emit_unop_insn (icode, target, from,
5214 doing_unsigned ? UNSIGNED_FIX : FIX))
5216 if (target != to)
5217 convert_move (to, target, unsignedp);
5218 return;
5220 delete_insns_since (last);
5224 /* For an unsigned conversion, there is one more way to do it.
5225 If we have a signed conversion, we generate code that compares
5226 the real value to the largest representable positive number. If if
5227 is smaller, the conversion is done normally. Otherwise, subtract
5228 one plus the highest signed number, convert, and add it back.
5230 We only need to check all real modes, since we know we didn't find
5231 anything with a wider integer mode.
5233 This code used to extend FP value into mode wider than the destination.
5234 This is needed for decimal float modes which cannot accurately
5235 represent one plus the highest signed number of the same size, but
5236 not for binary modes. Consider, for instance conversion from SFmode
5237 into DImode.
5239 The hot path through the code is dealing with inputs smaller than 2^63
5240 and doing just the conversion, so there is no bits to lose.
5242 In the other path we know the value is positive in the range 2^63..2^64-1
5243 inclusive. (as for other input overflow happens and result is undefined)
5244 So we know that the most important bit set in mantissa corresponds to
5245 2^63. The subtraction of 2^63 should not generate any rounding as it
5246 simply clears out that bit. The rest is trivial. */
5248 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
5249 for (fmode = GET_MODE (from); fmode != VOIDmode;
5250 fmode = GET_MODE_WIDER_MODE (fmode))
5251 if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc)
5252 && (!DECIMAL_FLOAT_MODE_P (fmode)
5253 || GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))))
5255 int bitsize;
5256 REAL_VALUE_TYPE offset;
5257 rtx limit, lab1, lab2, insn;
5259 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
5260 real_2expN (&offset, bitsize - 1, fmode);
5261 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
5262 lab1 = gen_label_rtx ();
5263 lab2 = gen_label_rtx ();
5265 if (fmode != GET_MODE (from))
5266 from = convert_to_mode (fmode, from, 0);
5268 /* See if we need to do the subtraction. */
5269 do_pending_stack_adjust ();
5270 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
5271 0, lab1);
5273 /* If not, do the signed "fix" and branch around fixup code. */
5274 expand_fix (to, from, 0);
5275 emit_jump_insn (gen_jump (lab2));
5276 emit_barrier ();
5278 /* Otherwise, subtract 2**(N-1), convert to signed number,
5279 then add 2**(N-1). Do the addition using XOR since this
5280 will often generate better code. */
5281 emit_label (lab1);
5282 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
5283 NULL_RTX, 0, OPTAB_LIB_WIDEN);
5284 expand_fix (to, target, 0);
5285 target = expand_binop (GET_MODE (to), xor_optab, to,
5286 gen_int_mode
5287 ((HOST_WIDE_INT) 1 << (bitsize - 1),
5288 GET_MODE (to)),
5289 to, 1, OPTAB_LIB_WIDEN);
5291 if (target != to)
5292 emit_move_insn (to, target);
5294 emit_label (lab2);
5296 if (optab_handler (mov_optab, GET_MODE (to))->insn_code
5297 != CODE_FOR_nothing)
5299 /* Make a place for a REG_NOTE and add it. */
5300 insn = emit_move_insn (to, to);
5301 set_unique_reg_note (insn,
5302 REG_EQUAL,
5303 gen_rtx_fmt_e (UNSIGNED_FIX,
5304 GET_MODE (to),
5305 copy_rtx (from)));
5308 return;
5311 /* We can't do it with an insn, so use a library call. But first ensure
5312 that the mode of TO is at least as wide as SImode, since those are the
5313 only library calls we know about. */
5315 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
5317 target = gen_reg_rtx (SImode);
5319 expand_fix (target, from, unsignedp);
5321 else
5323 rtx insns;
5324 rtx value;
5325 rtx libfunc;
5327 convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
5328 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5329 gcc_assert (libfunc);
5331 start_sequence ();
5333 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5334 GET_MODE (to), 1, from,
5335 GET_MODE (from));
5336 insns = get_insns ();
5337 end_sequence ();
5339 emit_libcall_block (insns, target, value,
5340 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
5341 GET_MODE (to), from));
5344 if (target != to)
5346 if (GET_MODE (to) == GET_MODE (target))
5347 emit_move_insn (to, target);
5348 else
5349 convert_move (to, target, 0);
5353 /* Generate code to convert FROM or TO a fixed-point.
5354 If UINTP is true, either TO or FROM is an unsigned integer.
5355 If SATP is true, we need to saturate the result. */
5357 void
5358 expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
5360 enum machine_mode to_mode = GET_MODE (to);
5361 enum machine_mode from_mode = GET_MODE (from);
5362 convert_optab tab;
5363 enum rtx_code this_code;
5364 enum insn_code code;
5365 rtx insns, value;
5366 rtx libfunc;
5368 if (to_mode == from_mode)
5370 emit_move_insn (to, from);
5371 return;
5374 if (uintp)
5376 tab = satp ? satfractuns_optab : fractuns_optab;
5377 this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
5379 else
5381 tab = satp ? satfract_optab : fract_optab;
5382 this_code = satp ? SAT_FRACT : FRACT_CONVERT;
5384 code = tab->handlers[to_mode][from_mode].insn_code;
5385 if (code != CODE_FOR_nothing)
5387 emit_unop_insn (code, to, from, this_code);
5388 return;
5391 libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
5392 gcc_assert (libfunc);
5394 start_sequence ();
5395 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
5396 1, from, from_mode);
5397 insns = get_insns ();
5398 end_sequence ();
5400 emit_libcall_block (insns, to, value,
5401 gen_rtx_fmt_e (tab->code, to_mode, from));
5404 /* Generate code to convert FROM to fixed point and store in TO. FROM
5405 must be floating point, TO must be signed. Use the conversion optab
5406 TAB to do the conversion. */
5408 bool
5409 expand_sfix_optab (rtx to, rtx from, convert_optab tab)
5411 enum insn_code icode;
5412 rtx target = to;
5413 enum machine_mode fmode, imode;
5415 /* We first try to find a pair of modes, one real and one integer, at
5416 least as wide as FROM and TO, respectively, in which we can open-code
5417 this conversion. If the integer mode is wider than the mode of TO,
5418 we can do the conversion either signed or unsigned. */
5420 for (fmode = GET_MODE (from); fmode != VOIDmode;
5421 fmode = GET_MODE_WIDER_MODE (fmode))
5422 for (imode = GET_MODE (to); imode != VOIDmode;
5423 imode = GET_MODE_WIDER_MODE (imode))
5425 icode = convert_optab_handler (tab, imode, fmode)->insn_code;
5426 if (icode != CODE_FOR_nothing)
5428 rtx last = get_last_insn ();
5429 if (fmode != GET_MODE (from))
5430 from = convert_to_mode (fmode, from, 0);
5432 if (imode != GET_MODE (to))
5433 target = gen_reg_rtx (imode);
5435 if (!maybe_emit_unop_insn (icode, target, from, UNKNOWN))
5437 delete_insns_since (last);
5438 continue;
5440 if (target != to)
5441 convert_move (to, target, 0);
5442 return true;
5446 return false;
5449 /* Report whether we have an instruction to perform the operation
5450 specified by CODE on operands of mode MODE. */
5452 have_insn_for (enum rtx_code code, enum machine_mode mode)
5454 return (code_to_optab[(int) code] != 0
5455 && (optab_handler (code_to_optab[(int) code], mode)->insn_code
5456 != CODE_FOR_nothing));
5459 /* Set all insn_code fields to CODE_FOR_nothing. */
5461 static void
5462 init_insn_codes (void)
5464 unsigned int i;
5466 for (i = 0; i < (unsigned int) OTI_MAX; i++)
5468 unsigned int j;
5469 optab op;
5471 op = &optab_table[i];
5472 for (j = 0; j < NUM_MACHINE_MODES; j++)
5473 optab_handler (op, j)->insn_code = CODE_FOR_nothing;
5475 for (i = 0; i < (unsigned int) COI_MAX; i++)
5477 unsigned int j, k;
5478 convert_optab op;
5480 op = &convert_optab_table[i];
5481 for (j = 0; j < NUM_MACHINE_MODES; j++)
5482 for (k = 0; k < NUM_MACHINE_MODES; k++)
5483 convert_optab_handler (op, j, k)->insn_code = CODE_FOR_nothing;
5487 /* Initialize OP's code to CODE, and write it into the code_to_optab table. */
5488 static inline void
5489 init_optab (optab op, enum rtx_code code)
5491 op->code = code;
5492 code_to_optab[(int) code] = op;
5495 /* Same, but fill in its code as CODE, and do _not_ write it into
5496 the code_to_optab table. */
5497 static inline void
5498 init_optabv (optab op, enum rtx_code code)
5500 op->code = code;
5503 /* Conversion optabs never go in the code_to_optab table. */
5504 static void
5505 init_convert_optab (convert_optab op, enum rtx_code code)
5507 op->code = code;
5510 /* Initialize the libfunc fields of an entire group of entries in some
5511 optab. Each entry is set equal to a string consisting of a leading
5512 pair of underscores followed by a generic operation name followed by
5513 a mode name (downshifted to lowercase) followed by a single character
5514 representing the number of operands for the given operation (which is
5515 usually one of the characters '2', '3', or '4').
5517 OPTABLE is the table in which libfunc fields are to be initialized.
5518 OPNAME is the generic (string) name of the operation.
5519 SUFFIX is the character which specifies the number of operands for
5520 the given generic operation.
5521 MODE is the mode to generate for.
5524 static void
5525 gen_libfunc (optab optable, const char *opname, int suffix, enum machine_mode mode)
5527 unsigned opname_len = strlen (opname);
5528 const char *mname = GET_MODE_NAME (mode);
5529 unsigned mname_len = strlen (mname);
5530 char *libfunc_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5531 char *p;
5532 const char *q;
5534 p = libfunc_name;
5535 *p++ = '_';
5536 *p++ = '_';
5537 for (q = opname; *q; )
5538 *p++ = *q++;
5539 for (q = mname; *q; q++)
5540 *p++ = TOLOWER (*q);
5541 *p++ = suffix;
5542 *p = '\0';
5544 set_optab_libfunc (optable, mode,
5545 ggc_alloc_string (libfunc_name, p - libfunc_name));
5548 /* Like gen_libfunc, but verify that integer operation is involved. */
5550 static void
5551 gen_int_libfunc (optab optable, const char *opname, char suffix,
5552 enum machine_mode mode)
5554 int maxsize = 2 * BITS_PER_WORD;
5556 if (GET_MODE_CLASS (mode) != MODE_INT)
5557 return;
5558 if (maxsize < LONG_LONG_TYPE_SIZE)
5559 maxsize = LONG_LONG_TYPE_SIZE;
5560 if (GET_MODE_CLASS (mode) != MODE_INT
5561 || mode < word_mode || GET_MODE_BITSIZE (mode) > maxsize)
5562 return;
5563 gen_libfunc (optable, opname, suffix, mode);
5566 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed. */
5568 static void
5569 gen_fp_libfunc (optab optable, const char *opname, char suffix,
5570 enum machine_mode mode)
5572 char *dec_opname;
5574 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
5575 gen_libfunc (optable, opname, suffix, mode);
5576 if (DECIMAL_FLOAT_MODE_P (mode))
5578 dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
5579 /* For BID support, change the name to have either a bid_ or dpd_ prefix
5580 depending on the low level floating format used. */
5581 memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
5582 strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
5583 gen_libfunc (optable, dec_opname, suffix, mode);
5587 /* Like gen_libfunc, but verify that fixed-point operation is involved. */
5589 static void
5590 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
5591 enum machine_mode mode)
5593 if (!ALL_FIXED_POINT_MODE_P (mode))
5594 return;
5595 gen_libfunc (optable, opname, suffix, mode);
5598 /* Like gen_libfunc, but verify that signed fixed-point operation is
5599 involved. */
5601 static void
5602 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
5603 enum machine_mode mode)
5605 if (!SIGNED_FIXED_POINT_MODE_P (mode))
5606 return;
5607 gen_libfunc (optable, opname, suffix, mode);
5610 /* Like gen_libfunc, but verify that unsigned fixed-point operation is
5611 involved. */
5613 static void
5614 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
5615 enum machine_mode mode)
5617 if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
5618 return;
5619 gen_libfunc (optable, opname, suffix, mode);
5622 /* Like gen_libfunc, but verify that FP or INT operation is involved. */
5624 static void
5625 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
5626 enum machine_mode mode)
5628 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5629 gen_fp_libfunc (optable, name, suffix, mode);
5630 if (INTEGRAL_MODE_P (mode))
5631 gen_int_libfunc (optable, name, suffix, mode);
5634 /* Like gen_libfunc, but verify that FP or INT operation is involved
5635 and add 'v' suffix for integer operation. */
5637 static void
5638 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
5639 enum machine_mode mode)
5641 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5642 gen_fp_libfunc (optable, name, suffix, mode);
5643 if (GET_MODE_CLASS (mode) == MODE_INT)
5645 int len = strlen (name);
5646 char *v_name = XALLOCAVEC (char, len + 2);
5647 strcpy (v_name, name);
5648 v_name[len] = 'v';
5649 v_name[len + 1] = 0;
5650 gen_int_libfunc (optable, v_name, suffix, mode);
5654 /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
5655 involved. */
5657 static void
5658 gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
5659 enum machine_mode mode)
5661 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5662 gen_fp_libfunc (optable, name, suffix, mode);
5663 if (INTEGRAL_MODE_P (mode))
5664 gen_int_libfunc (optable, name, suffix, mode);
5665 if (ALL_FIXED_POINT_MODE_P (mode))
5666 gen_fixed_libfunc (optable, name, suffix, mode);
5669 /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
5670 involved. */
5672 static void
5673 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5674 enum machine_mode mode)
5676 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5677 gen_fp_libfunc (optable, name, suffix, mode);
5678 if (INTEGRAL_MODE_P (mode))
5679 gen_int_libfunc (optable, name, suffix, mode);
5680 if (SIGNED_FIXED_POINT_MODE_P (mode))
5681 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5684 /* Like gen_libfunc, but verify that INT or FIXED operation is
5685 involved. */
5687 static void
5688 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
5689 enum machine_mode mode)
5691 if (INTEGRAL_MODE_P (mode))
5692 gen_int_libfunc (optable, name, suffix, mode);
5693 if (ALL_FIXED_POINT_MODE_P (mode))
5694 gen_fixed_libfunc (optable, name, suffix, mode);
5697 /* Like gen_libfunc, but verify that INT or signed FIXED operation is
5698 involved. */
5700 static void
5701 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
5702 enum machine_mode mode)
5704 if (INTEGRAL_MODE_P (mode))
5705 gen_int_libfunc (optable, name, suffix, mode);
5706 if (SIGNED_FIXED_POINT_MODE_P (mode))
5707 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5710 /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
5711 involved. */
5713 static void
5714 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
5715 enum machine_mode mode)
5717 if (INTEGRAL_MODE_P (mode))
5718 gen_int_libfunc (optable, name, suffix, mode);
5719 if (UNSIGNED_FIXED_POINT_MODE_P (mode))
5720 gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
5723 /* Initialize the libfunc fields of an entire group of entries of an
5724 inter-mode-class conversion optab. The string formation rules are
5725 similar to the ones for init_libfuncs, above, but instead of having
5726 a mode name and an operand count these functions have two mode names
5727 and no operand count. */
5729 static void
5730 gen_interclass_conv_libfunc (convert_optab tab,
5731 const char *opname,
5732 enum machine_mode tmode,
5733 enum machine_mode fmode)
5735 size_t opname_len = strlen (opname);
5736 size_t mname_len = 0;
5738 const char *fname, *tname;
5739 const char *q;
5740 char *libfunc_name, *suffix;
5741 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5742 char *p;
5744 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5745 depends on which underlying decimal floating point format is used. */
5746 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5748 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5750 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5751 nondec_name[0] = '_';
5752 nondec_name[1] = '_';
5753 memcpy (&nondec_name[2], opname, opname_len);
5754 nondec_suffix = nondec_name + opname_len + 2;
5756 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5757 dec_name[0] = '_';
5758 dec_name[1] = '_';
5759 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5760 memcpy (&dec_name[2+dec_len], opname, opname_len);
5761 dec_suffix = dec_name + dec_len + opname_len + 2;
5763 fname = GET_MODE_NAME (fmode);
5764 tname = GET_MODE_NAME (tmode);
5766 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5768 libfunc_name = dec_name;
5769 suffix = dec_suffix;
5771 else
5773 libfunc_name = nondec_name;
5774 suffix = nondec_suffix;
5777 p = suffix;
5778 for (q = fname; *q; p++, q++)
5779 *p = TOLOWER (*q);
5780 for (q = tname; *q; p++, q++)
5781 *p = TOLOWER (*q);
5783 *p = '\0';
5785 set_conv_libfunc (tab, tmode, fmode,
5786 ggc_alloc_string (libfunc_name, p - libfunc_name));
5789 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5790 int->fp conversion. */
5792 static void
5793 gen_int_to_fp_conv_libfunc (convert_optab tab,
5794 const char *opname,
5795 enum machine_mode tmode,
5796 enum machine_mode fmode)
5798 if (GET_MODE_CLASS (fmode) != MODE_INT)
5799 return;
5800 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5801 return;
5802 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5805 /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
5806 naming scheme. */
5808 static void
5809 gen_ufloat_conv_libfunc (convert_optab tab,
5810 const char *opname ATTRIBUTE_UNUSED,
5811 enum machine_mode tmode,
5812 enum machine_mode fmode)
5814 if (DECIMAL_FLOAT_MODE_P (tmode))
5815 gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
5816 else
5817 gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
5820 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5821 fp->int conversion. */
5823 static void
5824 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
5825 const char *opname,
5826 enum machine_mode tmode,
5827 enum machine_mode fmode)
5829 if (GET_MODE_CLASS (fmode) != MODE_INT)
5830 return;
5831 if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
5832 return;
5833 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5836 /* Same as gen_interclass_conv_libfunc but verify that we are producing
5837 fp->int conversion with no decimal floating point involved. */
5839 static void
5840 gen_fp_to_int_conv_libfunc (convert_optab tab,
5841 const char *opname,
5842 enum machine_mode tmode,
5843 enum machine_mode fmode)
5845 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5846 return;
5847 if (GET_MODE_CLASS (tmode) != MODE_INT)
5848 return;
5849 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5852 /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
5853 The string formation rules are
5854 similar to the ones for init_libfunc, above. */
5856 static void
5857 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
5858 enum machine_mode tmode, enum machine_mode fmode)
5860 size_t opname_len = strlen (opname);
5861 size_t mname_len = 0;
5863 const char *fname, *tname;
5864 const char *q;
5865 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
5866 char *libfunc_name, *suffix;
5867 char *p;
5869 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5870 depends on which underlying decimal floating point format is used. */
5871 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5873 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
5875 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
5876 nondec_name[0] = '_';
5877 nondec_name[1] = '_';
5878 memcpy (&nondec_name[2], opname, opname_len);
5879 nondec_suffix = nondec_name + opname_len + 2;
5881 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
5882 dec_name[0] = '_';
5883 dec_name[1] = '_';
5884 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5885 memcpy (&dec_name[2 + dec_len], opname, opname_len);
5886 dec_suffix = dec_name + dec_len + opname_len + 2;
5888 fname = GET_MODE_NAME (fmode);
5889 tname = GET_MODE_NAME (tmode);
5891 if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
5893 libfunc_name = dec_name;
5894 suffix = dec_suffix;
5896 else
5898 libfunc_name = nondec_name;
5899 suffix = nondec_suffix;
5902 p = suffix;
5903 for (q = fname; *q; p++, q++)
5904 *p = TOLOWER (*q);
5905 for (q = tname; *q; p++, q++)
5906 *p = TOLOWER (*q);
5908 *p++ = '2';
5909 *p = '\0';
5911 set_conv_libfunc (tab, tmode, fmode,
5912 ggc_alloc_string (libfunc_name, p - libfunc_name));
5915 /* Pick proper libcall for trunc_optab. We need to chose if we do
5916 truncation or extension and interclass or intraclass. */
5918 static void
5919 gen_trunc_conv_libfunc (convert_optab tab,
5920 const char *opname,
5921 enum machine_mode tmode,
5922 enum machine_mode fmode)
5924 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5925 return;
5926 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5927 return;
5928 if (tmode == fmode)
5929 return;
5931 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5932 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5933 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5935 if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
5936 return;
5938 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5939 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5940 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5941 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5944 /* Pick proper libcall for extend_optab. We need to chose if we do
5945 truncation or extension and interclass or intraclass. */
5947 static void
5948 gen_extend_conv_libfunc (convert_optab tab,
5949 const char *opname ATTRIBUTE_UNUSED,
5950 enum machine_mode tmode,
5951 enum machine_mode fmode)
5953 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5954 return;
5955 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5956 return;
5957 if (tmode == fmode)
5958 return;
5960 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5961 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5962 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5964 if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
5965 return;
5967 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5968 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5969 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5970 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5973 /* Pick proper libcall for fract_optab. We need to chose if we do
5974 interclass or intraclass. */
5976 static void
5977 gen_fract_conv_libfunc (convert_optab tab,
5978 const char *opname,
5979 enum machine_mode tmode,
5980 enum machine_mode fmode)
5982 if (tmode == fmode)
5983 return;
5984 if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
5985 return;
5987 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
5988 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5989 else
5990 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5993 /* Pick proper libcall for fractuns_optab. */
5995 static void
5996 gen_fractuns_conv_libfunc (convert_optab tab,
5997 const char *opname,
5998 enum machine_mode tmode,
5999 enum machine_mode fmode)
6001 if (tmode == fmode)
6002 return;
6003 /* One mode must be a fixed-point mode, and the other must be an integer
6004 mode. */
6005 if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
6006 || (ALL_FIXED_POINT_MODE_P (fmode)
6007 && GET_MODE_CLASS (tmode) == MODE_INT)))
6008 return;
6010 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6013 /* Pick proper libcall for satfract_optab. We need to chose if we do
6014 interclass or intraclass. */
6016 static void
6017 gen_satfract_conv_libfunc (convert_optab tab,
6018 const char *opname,
6019 enum machine_mode tmode,
6020 enum machine_mode fmode)
6022 if (tmode == fmode)
6023 return;
6024 /* TMODE must be a fixed-point mode. */
6025 if (!ALL_FIXED_POINT_MODE_P (tmode))
6026 return;
6028 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
6029 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6030 else
6031 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6034 /* Pick proper libcall for satfractuns_optab. */
6036 static void
6037 gen_satfractuns_conv_libfunc (convert_optab tab,
6038 const char *opname,
6039 enum machine_mode tmode,
6040 enum machine_mode fmode)
6042 if (tmode == fmode)
6043 return;
6044 /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
6045 if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
6046 return;
6048 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6051 /* A table of previously-created libfuncs, hashed by name. */
6052 static GTY ((param_is (union tree_node))) htab_t libfunc_decls;
6054 /* Hashtable callbacks for libfunc_decls. */
6056 static hashval_t
6057 libfunc_decl_hash (const void *entry)
6059 return htab_hash_string (IDENTIFIER_POINTER (DECL_NAME ((const_tree) entry)));
6062 static int
6063 libfunc_decl_eq (const void *entry1, const void *entry2)
6065 return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
6068 /* Build a decl for a libfunc named NAME. */
6070 tree
6071 build_libfunc_function (const char *name)
6073 tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
6074 get_identifier (name),
6075 build_function_type (integer_type_node, NULL_TREE));
6076 /* ??? We don't have any type information except for this is
6077 a function. Pretend this is "int foo()". */
6078 DECL_ARTIFICIAL (decl) = 1;
6079 DECL_EXTERNAL (decl) = 1;
6080 TREE_PUBLIC (decl) = 1;
6081 gcc_assert (DECL_ASSEMBLER_NAME (decl));
6083 /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
6084 are the flags assigned by targetm.encode_section_info. */
6085 SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
6087 return decl;
6091 init_one_libfunc (const char *name)
6093 tree id, decl;
6094 void **slot;
6095 hashval_t hash;
6097 if (libfunc_decls == NULL)
6098 libfunc_decls = htab_create_ggc (37, libfunc_decl_hash,
6099 libfunc_decl_eq, NULL);
6101 /* See if we have already created a libfunc decl for this function. */
6102 id = get_identifier (name);
6103 hash = htab_hash_string (name);
6104 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, INSERT);
6105 decl = (tree) *slot;
6106 if (decl == NULL)
6108 /* Create a new decl, so that it can be passed to
6109 targetm.encode_section_info. */
6110 decl = build_libfunc_function (name);
6111 *slot = decl;
6113 return XEXP (DECL_RTL (decl), 0);
6116 /* Adjust the assembler name of libfunc NAME to ASMSPEC. */
6119 set_user_assembler_libfunc (const char *name, const char *asmspec)
6121 tree id, decl;
6122 void **slot;
6123 hashval_t hash;
6125 id = get_identifier (name);
6126 hash = htab_hash_string (name);
6127 slot = htab_find_slot_with_hash (libfunc_decls, id, hash, NO_INSERT);
6128 gcc_assert (slot);
6129 decl = (tree) *slot;
6130 set_user_assembler_name (decl, asmspec);
6131 return XEXP (DECL_RTL (decl), 0);
6134 /* Call this to reset the function entry for one optab (OPTABLE) in mode
6135 MODE to NAME, which should be either 0 or a string constant. */
6136 void
6137 set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
6139 rtx val;
6140 struct libfunc_entry e;
6141 struct libfunc_entry **slot;
6142 e.optab = (size_t) (optable - &optab_table[0]);
6143 e.mode1 = mode;
6144 e.mode2 = VOIDmode;
6146 if (name)
6147 val = init_one_libfunc (name);
6148 else
6149 val = 0;
6150 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6151 if (*slot == NULL)
6152 *slot = GGC_NEW (struct libfunc_entry);
6153 (*slot)->optab = (size_t) (optable - &optab_table[0]);
6154 (*slot)->mode1 = mode;
6155 (*slot)->mode2 = VOIDmode;
6156 (*slot)->libfunc = val;
6159 /* Call this to reset the function entry for one conversion optab
6160 (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
6161 either 0 or a string constant. */
6162 void
6163 set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
6164 enum machine_mode fmode, const char *name)
6166 rtx val;
6167 struct libfunc_entry e;
6168 struct libfunc_entry **slot;
6169 e.optab = (size_t) (optable - &convert_optab_table[0]);
6170 e.mode1 = tmode;
6171 e.mode2 = fmode;
6173 if (name)
6174 val = init_one_libfunc (name);
6175 else
6176 val = 0;
6177 slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
6178 if (*slot == NULL)
6179 *slot = GGC_NEW (struct libfunc_entry);
6180 (*slot)->optab = (size_t) (optable - &convert_optab_table[0]);
6181 (*slot)->mode1 = tmode;
6182 (*slot)->mode2 = fmode;
6183 (*slot)->libfunc = val;
6186 /* Call this to initialize the contents of the optabs
6187 appropriately for the current target machine. */
6189 void
6190 init_optabs (void)
6192 unsigned int i;
6193 static bool reinit;
6195 libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
6196 /* Start by initializing all tables to contain CODE_FOR_nothing. */
6198 #ifdef HAVE_conditional_move
6199 for (i = 0; i < NUM_MACHINE_MODES; i++)
6200 movcc_gen_code[i] = CODE_FOR_nothing;
6201 #endif
6203 for (i = 0; i < NUM_MACHINE_MODES; i++)
6205 vcond_gen_code[i] = CODE_FOR_nothing;
6206 vcondu_gen_code[i] = CODE_FOR_nothing;
6209 #if GCC_VERSION >= 4000 && HAVE_DESIGNATED_INITIALIZERS
6210 /* We statically initialize the insn_codes with CODE_FOR_nothing. */
6211 if (reinit)
6212 init_insn_codes ();
6213 #else
6214 init_insn_codes ();
6215 #endif
6217 init_optab (add_optab, PLUS);
6218 init_optabv (addv_optab, PLUS);
6219 init_optab (sub_optab, MINUS);
6220 init_optabv (subv_optab, MINUS);
6221 init_optab (ssadd_optab, SS_PLUS);
6222 init_optab (usadd_optab, US_PLUS);
6223 init_optab (sssub_optab, SS_MINUS);
6224 init_optab (ussub_optab, US_MINUS);
6225 init_optab (smul_optab, MULT);
6226 init_optab (ssmul_optab, SS_MULT);
6227 init_optab (usmul_optab, US_MULT);
6228 init_optabv (smulv_optab, MULT);
6229 init_optab (smul_highpart_optab, UNKNOWN);
6230 init_optab (umul_highpart_optab, UNKNOWN);
6231 init_optab (smul_widen_optab, UNKNOWN);
6232 init_optab (umul_widen_optab, UNKNOWN);
6233 init_optab (usmul_widen_optab, UNKNOWN);
6234 init_optab (smadd_widen_optab, UNKNOWN);
6235 init_optab (umadd_widen_optab, UNKNOWN);
6236 init_optab (ssmadd_widen_optab, UNKNOWN);
6237 init_optab (usmadd_widen_optab, UNKNOWN);
6238 init_optab (smsub_widen_optab, UNKNOWN);
6239 init_optab (umsub_widen_optab, UNKNOWN);
6240 init_optab (ssmsub_widen_optab, UNKNOWN);
6241 init_optab (usmsub_widen_optab, UNKNOWN);
6242 init_optab (sdiv_optab, DIV);
6243 init_optab (ssdiv_optab, SS_DIV);
6244 init_optab (usdiv_optab, US_DIV);
6245 init_optabv (sdivv_optab, DIV);
6246 init_optab (sdivmod_optab, UNKNOWN);
6247 init_optab (udiv_optab, UDIV);
6248 init_optab (udivmod_optab, UNKNOWN);
6249 init_optab (smod_optab, MOD);
6250 init_optab (umod_optab, UMOD);
6251 init_optab (fmod_optab, UNKNOWN);
6252 init_optab (remainder_optab, UNKNOWN);
6253 init_optab (ftrunc_optab, UNKNOWN);
6254 init_optab (and_optab, AND);
6255 init_optab (ior_optab, IOR);
6256 init_optab (xor_optab, XOR);
6257 init_optab (ashl_optab, ASHIFT);
6258 init_optab (ssashl_optab, SS_ASHIFT);
6259 init_optab (usashl_optab, US_ASHIFT);
6260 init_optab (ashr_optab, ASHIFTRT);
6261 init_optab (lshr_optab, LSHIFTRT);
6262 init_optab (rotl_optab, ROTATE);
6263 init_optab (rotr_optab, ROTATERT);
6264 init_optab (smin_optab, SMIN);
6265 init_optab (smax_optab, SMAX);
6266 init_optab (umin_optab, UMIN);
6267 init_optab (umax_optab, UMAX);
6268 init_optab (pow_optab, UNKNOWN);
6269 init_optab (atan2_optab, UNKNOWN);
6271 /* These three have codes assigned exclusively for the sake of
6272 have_insn_for. */
6273 init_optab (mov_optab, SET);
6274 init_optab (movstrict_optab, STRICT_LOW_PART);
6275 init_optab (cbranch_optab, COMPARE);
6277 init_optab (cmov_optab, UNKNOWN);
6278 init_optab (cstore_optab, UNKNOWN);
6279 init_optab (ctrap_optab, UNKNOWN);
6281 init_optab (storent_optab, UNKNOWN);
6283 init_optab (cmp_optab, UNKNOWN);
6284 init_optab (ucmp_optab, UNKNOWN);
6286 init_optab (eq_optab, EQ);
6287 init_optab (ne_optab, NE);
6288 init_optab (gt_optab, GT);
6289 init_optab (ge_optab, GE);
6290 init_optab (lt_optab, LT);
6291 init_optab (le_optab, LE);
6292 init_optab (unord_optab, UNORDERED);
6294 init_optab (neg_optab, NEG);
6295 init_optab (ssneg_optab, SS_NEG);
6296 init_optab (usneg_optab, US_NEG);
6297 init_optabv (negv_optab, NEG);
6298 init_optab (abs_optab, ABS);
6299 init_optabv (absv_optab, ABS);
6300 init_optab (addcc_optab, UNKNOWN);
6301 init_optab (one_cmpl_optab, NOT);
6302 init_optab (bswap_optab, BSWAP);
6303 init_optab (ffs_optab, FFS);
6304 init_optab (clz_optab, CLZ);
6305 init_optab (ctz_optab, CTZ);
6306 init_optab (popcount_optab, POPCOUNT);
6307 init_optab (parity_optab, PARITY);
6308 init_optab (sqrt_optab, SQRT);
6309 init_optab (floor_optab, UNKNOWN);
6310 init_optab (ceil_optab, UNKNOWN);
6311 init_optab (round_optab, UNKNOWN);
6312 init_optab (btrunc_optab, UNKNOWN);
6313 init_optab (nearbyint_optab, UNKNOWN);
6314 init_optab (rint_optab, UNKNOWN);
6315 init_optab (sincos_optab, UNKNOWN);
6316 init_optab (sin_optab, UNKNOWN);
6317 init_optab (asin_optab, UNKNOWN);
6318 init_optab (cos_optab, UNKNOWN);
6319 init_optab (acos_optab, UNKNOWN);
6320 init_optab (exp_optab, UNKNOWN);
6321 init_optab (exp10_optab, UNKNOWN);
6322 init_optab (exp2_optab, UNKNOWN);
6323 init_optab (expm1_optab, UNKNOWN);
6324 init_optab (ldexp_optab, UNKNOWN);
6325 init_optab (scalb_optab, UNKNOWN);
6326 init_optab (significand_optab, UNKNOWN);
6327 init_optab (logb_optab, UNKNOWN);
6328 init_optab (ilogb_optab, UNKNOWN);
6329 init_optab (log_optab, UNKNOWN);
6330 init_optab (log10_optab, UNKNOWN);
6331 init_optab (log2_optab, UNKNOWN);
6332 init_optab (log1p_optab, UNKNOWN);
6333 init_optab (tan_optab, UNKNOWN);
6334 init_optab (atan_optab, UNKNOWN);
6335 init_optab (copysign_optab, UNKNOWN);
6336 init_optab (signbit_optab, UNKNOWN);
6338 init_optab (isinf_optab, UNKNOWN);
6340 init_optab (strlen_optab, UNKNOWN);
6341 init_optab (push_optab, UNKNOWN);
6343 init_optab (reduc_smax_optab, UNKNOWN);
6344 init_optab (reduc_umax_optab, UNKNOWN);
6345 init_optab (reduc_smin_optab, UNKNOWN);
6346 init_optab (reduc_umin_optab, UNKNOWN);
6347 init_optab (reduc_splus_optab, UNKNOWN);
6348 init_optab (reduc_uplus_optab, UNKNOWN);
6350 init_optab (ssum_widen_optab, UNKNOWN);
6351 init_optab (usum_widen_optab, UNKNOWN);
6352 init_optab (sdot_prod_optab, UNKNOWN);
6353 init_optab (udot_prod_optab, UNKNOWN);
6355 init_optab (vec_extract_optab, UNKNOWN);
6356 init_optab (vec_extract_even_optab, UNKNOWN);
6357 init_optab (vec_extract_odd_optab, UNKNOWN);
6358 init_optab (vec_interleave_high_optab, UNKNOWN);
6359 init_optab (vec_interleave_low_optab, UNKNOWN);
6360 init_optab (vec_set_optab, UNKNOWN);
6361 init_optab (vec_init_optab, UNKNOWN);
6362 init_optab (vec_shl_optab, UNKNOWN);
6363 init_optab (vec_shr_optab, UNKNOWN);
6364 init_optab (vec_realign_load_optab, UNKNOWN);
6365 init_optab (movmisalign_optab, UNKNOWN);
6366 init_optab (vec_widen_umult_hi_optab, UNKNOWN);
6367 init_optab (vec_widen_umult_lo_optab, UNKNOWN);
6368 init_optab (vec_widen_smult_hi_optab, UNKNOWN);
6369 init_optab (vec_widen_smult_lo_optab, UNKNOWN);
6370 init_optab (vec_unpacks_hi_optab, UNKNOWN);
6371 init_optab (vec_unpacks_lo_optab, UNKNOWN);
6372 init_optab (vec_unpacku_hi_optab, UNKNOWN);
6373 init_optab (vec_unpacku_lo_optab, UNKNOWN);
6374 init_optab (vec_unpacks_float_hi_optab, UNKNOWN);
6375 init_optab (vec_unpacks_float_lo_optab, UNKNOWN);
6376 init_optab (vec_unpacku_float_hi_optab, UNKNOWN);
6377 init_optab (vec_unpacku_float_lo_optab, UNKNOWN);
6378 init_optab (vec_pack_trunc_optab, UNKNOWN);
6379 init_optab (vec_pack_usat_optab, UNKNOWN);
6380 init_optab (vec_pack_ssat_optab, UNKNOWN);
6381 init_optab (vec_pack_ufix_trunc_optab, UNKNOWN);
6382 init_optab (vec_pack_sfix_trunc_optab, UNKNOWN);
6384 init_optab (powi_optab, UNKNOWN);
6386 /* Conversions. */
6387 init_convert_optab (sext_optab, SIGN_EXTEND);
6388 init_convert_optab (zext_optab, ZERO_EXTEND);
6389 init_convert_optab (trunc_optab, TRUNCATE);
6390 init_convert_optab (sfix_optab, FIX);
6391 init_convert_optab (ufix_optab, UNSIGNED_FIX);
6392 init_convert_optab (sfixtrunc_optab, UNKNOWN);
6393 init_convert_optab (ufixtrunc_optab, UNKNOWN);
6394 init_convert_optab (sfloat_optab, FLOAT);
6395 init_convert_optab (ufloat_optab, UNSIGNED_FLOAT);
6396 init_convert_optab (lrint_optab, UNKNOWN);
6397 init_convert_optab (lround_optab, UNKNOWN);
6398 init_convert_optab (lfloor_optab, UNKNOWN);
6399 init_convert_optab (lceil_optab, UNKNOWN);
6401 init_convert_optab (fract_optab, FRACT_CONVERT);
6402 init_convert_optab (fractuns_optab, UNSIGNED_FRACT_CONVERT);
6403 init_convert_optab (satfract_optab, SAT_FRACT);
6404 init_convert_optab (satfractuns_optab, UNSIGNED_SAT_FRACT);
6406 for (i = 0; i < NUM_MACHINE_MODES; i++)
6408 movmem_optab[i] = CODE_FOR_nothing;
6409 cmpstr_optab[i] = CODE_FOR_nothing;
6410 cmpstrn_optab[i] = CODE_FOR_nothing;
6411 cmpmem_optab[i] = CODE_FOR_nothing;
6412 setmem_optab[i] = CODE_FOR_nothing;
6414 sync_add_optab[i] = CODE_FOR_nothing;
6415 sync_sub_optab[i] = CODE_FOR_nothing;
6416 sync_ior_optab[i] = CODE_FOR_nothing;
6417 sync_and_optab[i] = CODE_FOR_nothing;
6418 sync_xor_optab[i] = CODE_FOR_nothing;
6419 sync_nand_optab[i] = CODE_FOR_nothing;
6420 sync_old_add_optab[i] = CODE_FOR_nothing;
6421 sync_old_sub_optab[i] = CODE_FOR_nothing;
6422 sync_old_ior_optab[i] = CODE_FOR_nothing;
6423 sync_old_and_optab[i] = CODE_FOR_nothing;
6424 sync_old_xor_optab[i] = CODE_FOR_nothing;
6425 sync_old_nand_optab[i] = CODE_FOR_nothing;
6426 sync_new_add_optab[i] = CODE_FOR_nothing;
6427 sync_new_sub_optab[i] = CODE_FOR_nothing;
6428 sync_new_ior_optab[i] = CODE_FOR_nothing;
6429 sync_new_and_optab[i] = CODE_FOR_nothing;
6430 sync_new_xor_optab[i] = CODE_FOR_nothing;
6431 sync_new_nand_optab[i] = CODE_FOR_nothing;
6432 sync_compare_and_swap[i] = CODE_FOR_nothing;
6433 sync_lock_test_and_set[i] = CODE_FOR_nothing;
6434 sync_lock_release[i] = CODE_FOR_nothing;
6436 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
6439 /* Fill in the optabs with the insns we support. */
6440 init_all_optabs ();
6442 /* Initialize the optabs with the names of the library functions. */
6443 add_optab->libcall_basename = "add";
6444 add_optab->libcall_suffix = '3';
6445 add_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6446 addv_optab->libcall_basename = "add";
6447 addv_optab->libcall_suffix = '3';
6448 addv_optab->libcall_gen = gen_intv_fp_libfunc;
6449 ssadd_optab->libcall_basename = "ssadd";
6450 ssadd_optab->libcall_suffix = '3';
6451 ssadd_optab->libcall_gen = gen_signed_fixed_libfunc;
6452 usadd_optab->libcall_basename = "usadd";
6453 usadd_optab->libcall_suffix = '3';
6454 usadd_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6455 sub_optab->libcall_basename = "sub";
6456 sub_optab->libcall_suffix = '3';
6457 sub_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6458 subv_optab->libcall_basename = "sub";
6459 subv_optab->libcall_suffix = '3';
6460 subv_optab->libcall_gen = gen_intv_fp_libfunc;
6461 sssub_optab->libcall_basename = "sssub";
6462 sssub_optab->libcall_suffix = '3';
6463 sssub_optab->libcall_gen = gen_signed_fixed_libfunc;
6464 ussub_optab->libcall_basename = "ussub";
6465 ussub_optab->libcall_suffix = '3';
6466 ussub_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6467 smul_optab->libcall_basename = "mul";
6468 smul_optab->libcall_suffix = '3';
6469 smul_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6470 smulv_optab->libcall_basename = "mul";
6471 smulv_optab->libcall_suffix = '3';
6472 smulv_optab->libcall_gen = gen_intv_fp_libfunc;
6473 ssmul_optab->libcall_basename = "ssmul";
6474 ssmul_optab->libcall_suffix = '3';
6475 ssmul_optab->libcall_gen = gen_signed_fixed_libfunc;
6476 usmul_optab->libcall_basename = "usmul";
6477 usmul_optab->libcall_suffix = '3';
6478 usmul_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6479 sdiv_optab->libcall_basename = "div";
6480 sdiv_optab->libcall_suffix = '3';
6481 sdiv_optab->libcall_gen = gen_int_fp_signed_fixed_libfunc;
6482 sdivv_optab->libcall_basename = "divv";
6483 sdivv_optab->libcall_suffix = '3';
6484 sdivv_optab->libcall_gen = gen_int_libfunc;
6485 ssdiv_optab->libcall_basename = "ssdiv";
6486 ssdiv_optab->libcall_suffix = '3';
6487 ssdiv_optab->libcall_gen = gen_signed_fixed_libfunc;
6488 udiv_optab->libcall_basename = "udiv";
6489 udiv_optab->libcall_suffix = '3';
6490 udiv_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6491 usdiv_optab->libcall_basename = "usdiv";
6492 usdiv_optab->libcall_suffix = '3';
6493 usdiv_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6494 sdivmod_optab->libcall_basename = "divmod";
6495 sdivmod_optab->libcall_suffix = '4';
6496 sdivmod_optab->libcall_gen = gen_int_libfunc;
6497 udivmod_optab->libcall_basename = "udivmod";
6498 udivmod_optab->libcall_suffix = '4';
6499 udivmod_optab->libcall_gen = gen_int_libfunc;
6500 smod_optab->libcall_basename = "mod";
6501 smod_optab->libcall_suffix = '3';
6502 smod_optab->libcall_gen = gen_int_libfunc;
6503 umod_optab->libcall_basename = "umod";
6504 umod_optab->libcall_suffix = '3';
6505 umod_optab->libcall_gen = gen_int_libfunc;
6506 ftrunc_optab->libcall_basename = "ftrunc";
6507 ftrunc_optab->libcall_suffix = '2';
6508 ftrunc_optab->libcall_gen = gen_fp_libfunc;
6509 and_optab->libcall_basename = "and";
6510 and_optab->libcall_suffix = '3';
6511 and_optab->libcall_gen = gen_int_libfunc;
6512 ior_optab->libcall_basename = "ior";
6513 ior_optab->libcall_suffix = '3';
6514 ior_optab->libcall_gen = gen_int_libfunc;
6515 xor_optab->libcall_basename = "xor";
6516 xor_optab->libcall_suffix = '3';
6517 xor_optab->libcall_gen = gen_int_libfunc;
6518 ashl_optab->libcall_basename = "ashl";
6519 ashl_optab->libcall_suffix = '3';
6520 ashl_optab->libcall_gen = gen_int_fixed_libfunc;
6521 ssashl_optab->libcall_basename = "ssashl";
6522 ssashl_optab->libcall_suffix = '3';
6523 ssashl_optab->libcall_gen = gen_signed_fixed_libfunc;
6524 usashl_optab->libcall_basename = "usashl";
6525 usashl_optab->libcall_suffix = '3';
6526 usashl_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6527 ashr_optab->libcall_basename = "ashr";
6528 ashr_optab->libcall_suffix = '3';
6529 ashr_optab->libcall_gen = gen_int_signed_fixed_libfunc;
6530 lshr_optab->libcall_basename = "lshr";
6531 lshr_optab->libcall_suffix = '3';
6532 lshr_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
6533 smin_optab->libcall_basename = "min";
6534 smin_optab->libcall_suffix = '3';
6535 smin_optab->libcall_gen = gen_int_fp_libfunc;
6536 smax_optab->libcall_basename = "max";
6537 smax_optab->libcall_suffix = '3';
6538 smax_optab->libcall_gen = gen_int_fp_libfunc;
6539 umin_optab->libcall_basename = "umin";
6540 umin_optab->libcall_suffix = '3';
6541 umin_optab->libcall_gen = gen_int_libfunc;
6542 umax_optab->libcall_basename = "umax";
6543 umax_optab->libcall_suffix = '3';
6544 umax_optab->libcall_gen = gen_int_libfunc;
6545 neg_optab->libcall_basename = "neg";
6546 neg_optab->libcall_suffix = '2';
6547 neg_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6548 ssneg_optab->libcall_basename = "ssneg";
6549 ssneg_optab->libcall_suffix = '2';
6550 ssneg_optab->libcall_gen = gen_signed_fixed_libfunc;
6551 usneg_optab->libcall_basename = "usneg";
6552 usneg_optab->libcall_suffix = '2';
6553 usneg_optab->libcall_gen = gen_unsigned_fixed_libfunc;
6554 negv_optab->libcall_basename = "neg";
6555 negv_optab->libcall_suffix = '2';
6556 negv_optab->libcall_gen = gen_intv_fp_libfunc;
6557 one_cmpl_optab->libcall_basename = "one_cmpl";
6558 one_cmpl_optab->libcall_suffix = '2';
6559 one_cmpl_optab->libcall_gen = gen_int_libfunc;
6560 ffs_optab->libcall_basename = "ffs";
6561 ffs_optab->libcall_suffix = '2';
6562 ffs_optab->libcall_gen = gen_int_libfunc;
6563 clz_optab->libcall_basename = "clz";
6564 clz_optab->libcall_suffix = '2';
6565 clz_optab->libcall_gen = gen_int_libfunc;
6566 ctz_optab->libcall_basename = "ctz";
6567 ctz_optab->libcall_suffix = '2';
6568 ctz_optab->libcall_gen = gen_int_libfunc;
6569 popcount_optab->libcall_basename = "popcount";
6570 popcount_optab->libcall_suffix = '2';
6571 popcount_optab->libcall_gen = gen_int_libfunc;
6572 parity_optab->libcall_basename = "parity";
6573 parity_optab->libcall_suffix = '2';
6574 parity_optab->libcall_gen = gen_int_libfunc;
6576 /* Comparison libcalls for integers MUST come in pairs,
6577 signed/unsigned. */
6578 cmp_optab->libcall_basename = "cmp";
6579 cmp_optab->libcall_suffix = '2';
6580 cmp_optab->libcall_gen = gen_int_fp_fixed_libfunc;
6581 ucmp_optab->libcall_basename = "ucmp";
6582 ucmp_optab->libcall_suffix = '2';
6583 ucmp_optab->libcall_gen = gen_int_libfunc;
6585 /* EQ etc are floating point only. */
6586 eq_optab->libcall_basename = "eq";
6587 eq_optab->libcall_suffix = '2';
6588 eq_optab->libcall_gen = gen_fp_libfunc;
6589 ne_optab->libcall_basename = "ne";
6590 ne_optab->libcall_suffix = '2';
6591 ne_optab->libcall_gen = gen_fp_libfunc;
6592 gt_optab->libcall_basename = "gt";
6593 gt_optab->libcall_suffix = '2';
6594 gt_optab->libcall_gen = gen_fp_libfunc;
6595 ge_optab->libcall_basename = "ge";
6596 ge_optab->libcall_suffix = '2';
6597 ge_optab->libcall_gen = gen_fp_libfunc;
6598 lt_optab->libcall_basename = "lt";
6599 lt_optab->libcall_suffix = '2';
6600 lt_optab->libcall_gen = gen_fp_libfunc;
6601 le_optab->libcall_basename = "le";
6602 le_optab->libcall_suffix = '2';
6603 le_optab->libcall_gen = gen_fp_libfunc;
6604 unord_optab->libcall_basename = "unord";
6605 unord_optab->libcall_suffix = '2';
6606 unord_optab->libcall_gen = gen_fp_libfunc;
6608 powi_optab->libcall_basename = "powi";
6609 powi_optab->libcall_suffix = '2';
6610 powi_optab->libcall_gen = gen_fp_libfunc;
6612 /* Conversions. */
6613 sfloat_optab->libcall_basename = "float";
6614 sfloat_optab->libcall_gen = gen_int_to_fp_conv_libfunc;
6615 ufloat_optab->libcall_gen = gen_ufloat_conv_libfunc;
6616 sfix_optab->libcall_basename = "fix";
6617 sfix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6618 ufix_optab->libcall_basename = "fixuns";
6619 ufix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
6620 lrint_optab->libcall_basename = "lrint";
6621 lrint_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6622 lround_optab->libcall_basename = "lround";
6623 lround_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6624 lfloor_optab->libcall_basename = "lfloor";
6625 lfloor_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6626 lceil_optab->libcall_basename = "lceil";
6627 lceil_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
6629 /* trunc_optab is also used for FLOAT_EXTEND. */
6630 sext_optab->libcall_basename = "extend";
6631 sext_optab->libcall_gen = gen_extend_conv_libfunc;
6632 trunc_optab->libcall_basename = "trunc";
6633 trunc_optab->libcall_gen = gen_trunc_conv_libfunc;
6635 /* Conversions for fixed-point modes and other modes. */
6636 fract_optab->libcall_basename = "fract";
6637 fract_optab->libcall_gen = gen_fract_conv_libfunc;
6638 satfract_optab->libcall_basename = "satfract";
6639 satfract_optab->libcall_gen = gen_satfract_conv_libfunc;
6640 fractuns_optab->libcall_basename = "fractuns";
6641 fractuns_optab->libcall_gen = gen_fractuns_conv_libfunc;
6642 satfractuns_optab->libcall_basename = "satfractuns";
6643 satfractuns_optab->libcall_gen = gen_satfractuns_conv_libfunc;
6645 /* The ffs function operates on `int'. Fall back on it if we do not
6646 have a libgcc2 function for that width. */
6647 if (INT_TYPE_SIZE < BITS_PER_WORD)
6648 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
6649 "ffs");
6651 /* Explicitly initialize the bswap libfuncs since we need them to be
6652 valid for things other than word_mode. */
6653 set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
6654 set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
6656 /* Use cabs for double complex abs, since systems generally have cabs.
6657 Don't define any libcall for float complex, so that cabs will be used. */
6658 if (complex_double_type_node)
6659 set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node), "cabs");
6661 abort_libfunc = init_one_libfunc ("abort");
6662 memcpy_libfunc = init_one_libfunc ("memcpy");
6663 memmove_libfunc = init_one_libfunc ("memmove");
6664 memcmp_libfunc = init_one_libfunc ("memcmp");
6665 memset_libfunc = init_one_libfunc ("memset");
6666 setbits_libfunc = init_one_libfunc ("__setbits");
6668 #ifndef DONT_USE_BUILTIN_SETJMP
6669 setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
6670 longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
6671 #else
6672 setjmp_libfunc = init_one_libfunc ("setjmp");
6673 longjmp_libfunc = init_one_libfunc ("longjmp");
6674 #endif
6675 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
6676 unwind_sjlj_unregister_libfunc
6677 = init_one_libfunc ("_Unwind_SjLj_Unregister");
6679 /* For function entry/exit instrumentation. */
6680 profile_function_entry_libfunc
6681 = init_one_libfunc ("__cyg_profile_func_enter");
6682 profile_function_exit_libfunc
6683 = init_one_libfunc ("__cyg_profile_func_exit");
6685 gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
6687 /* Allow the target to add more libcalls or rename some, etc. */
6688 targetm.init_libfuncs ();
6690 reinit = true;
6693 /* Print information about the current contents of the optabs on
6694 STDERR. */
6696 void
6697 debug_optab_libfuncs (void)
6699 int i;
6700 int j;
6701 int k;
6703 /* Dump the arithmetic optabs. */
6704 for (i = 0; i != (int) OTI_MAX; i++)
6705 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6707 optab o;
6708 rtx l;
6710 o = &optab_table[i];
6711 l = optab_libfunc (o, (enum machine_mode) j);
6712 if (l)
6714 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6715 fprintf (stderr, "%s\t%s:\t%s\n",
6716 GET_RTX_NAME (o->code),
6717 GET_MODE_NAME (j),
6718 XSTR (l, 0));
6722 /* Dump the conversion optabs. */
6723 for (i = 0; i < (int) COI_MAX; ++i)
6724 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6725 for (k = 0; k < NUM_MACHINE_MODES; ++k)
6727 convert_optab o;
6728 rtx l;
6730 o = &convert_optab_table[i];
6731 l = convert_optab_libfunc (o, (enum machine_mode) j,
6732 (enum machine_mode) k);
6733 if (l)
6735 gcc_assert (GET_CODE (l) == SYMBOL_REF);
6736 fprintf (stderr, "%s\t%s\t%s:\t%s\n",
6737 GET_RTX_NAME (o->code),
6738 GET_MODE_NAME (j),
6739 GET_MODE_NAME (k),
6740 XSTR (l, 0));
6746 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
6747 CODE. Return 0 on failure. */
6750 gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
6752 enum machine_mode mode = GET_MODE (op1);
6753 enum insn_code icode;
6754 rtx insn;
6755 rtx trap_rtx;
6757 if (mode == VOIDmode)
6758 return 0;
6760 icode = optab_handler (ctrap_optab, mode)->insn_code;
6761 if (icode == CODE_FOR_nothing)
6762 return 0;
6764 /* Some targets only accept a zero trap code. */
6765 if (insn_data[icode].operand[3].predicate
6766 && !insn_data[icode].operand[3].predicate (tcode, VOIDmode))
6767 return 0;
6769 do_pending_stack_adjust ();
6770 start_sequence ();
6771 prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
6772 &trap_rtx, &mode);
6773 if (!trap_rtx)
6774 insn = NULL_RTX;
6775 else
6776 insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
6777 tcode);
6779 /* If that failed, then give up. */
6780 if (insn == 0)
6782 end_sequence ();
6783 return 0;
6786 emit_insn (insn);
6787 insn = get_insns ();
6788 end_sequence ();
6789 return insn;
6792 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
6793 or unsigned operation code. */
6795 static enum rtx_code
6796 get_rtx_code (enum tree_code tcode, bool unsignedp)
6798 enum rtx_code code;
6799 switch (tcode)
6801 case EQ_EXPR:
6802 code = EQ;
6803 break;
6804 case NE_EXPR:
6805 code = NE;
6806 break;
6807 case LT_EXPR:
6808 code = unsignedp ? LTU : LT;
6809 break;
6810 case LE_EXPR:
6811 code = unsignedp ? LEU : LE;
6812 break;
6813 case GT_EXPR:
6814 code = unsignedp ? GTU : GT;
6815 break;
6816 case GE_EXPR:
6817 code = unsignedp ? GEU : GE;
6818 break;
6820 case UNORDERED_EXPR:
6821 code = UNORDERED;
6822 break;
6823 case ORDERED_EXPR:
6824 code = ORDERED;
6825 break;
6826 case UNLT_EXPR:
6827 code = UNLT;
6828 break;
6829 case UNLE_EXPR:
6830 code = UNLE;
6831 break;
6832 case UNGT_EXPR:
6833 code = UNGT;
6834 break;
6835 case UNGE_EXPR:
6836 code = UNGE;
6837 break;
6838 case UNEQ_EXPR:
6839 code = UNEQ;
6840 break;
6841 case LTGT_EXPR:
6842 code = LTGT;
6843 break;
6845 default:
6846 gcc_unreachable ();
6848 return code;
6851 /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
6852 unsigned operators. Do not generate compare instruction. */
6854 static rtx
6855 vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
6857 enum rtx_code rcode;
6858 tree t_op0, t_op1;
6859 rtx rtx_op0, rtx_op1;
6861 /* This is unlikely. While generating VEC_COND_EXPR, auto vectorizer
6862 ensures that condition is a relational operation. */
6863 gcc_assert (COMPARISON_CLASS_P (cond));
6865 rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
6866 t_op0 = TREE_OPERAND (cond, 0);
6867 t_op1 = TREE_OPERAND (cond, 1);
6869 /* Expand operands. */
6870 rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
6871 EXPAND_STACK_PARM);
6872 rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
6873 EXPAND_STACK_PARM);
6875 if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
6876 && GET_MODE (rtx_op0) != VOIDmode)
6877 rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
6879 if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
6880 && GET_MODE (rtx_op1) != VOIDmode)
6881 rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
6883 return gen_rtx_fmt_ee (rcode, VOIDmode, rtx_op0, rtx_op1);
6886 /* Return insn code for TYPE, the type of a VEC_COND_EXPR. */
6888 static inline enum insn_code
6889 get_vcond_icode (tree type, enum machine_mode mode)
6891 enum insn_code icode = CODE_FOR_nothing;
6893 if (TYPE_UNSIGNED (type))
6894 icode = vcondu_gen_code[mode];
6895 else
6896 icode = vcond_gen_code[mode];
6897 return icode;
6900 /* Return TRUE iff, appropriate vector insns are available
6901 for vector cond expr with type TYPE in VMODE mode. */
6903 bool
6904 expand_vec_cond_expr_p (tree type, enum machine_mode vmode)
6906 if (get_vcond_icode (type, vmode) == CODE_FOR_nothing)
6907 return false;
6908 return true;
6911 /* Generate insns for a VEC_COND_EXPR, given its TYPE and its
6912 three operands. */
6915 expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
6916 rtx target)
6918 enum insn_code icode;
6919 rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
6920 enum machine_mode mode = TYPE_MODE (vec_cond_type);
6921 bool unsignedp = TYPE_UNSIGNED (vec_cond_type);
6923 icode = get_vcond_icode (vec_cond_type, mode);
6924 if (icode == CODE_FOR_nothing)
6925 return 0;
6927 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6928 target = gen_reg_rtx (mode);
6930 /* Get comparison rtx. First expand both cond expr operands. */
6931 comparison = vector_compare_rtx (op0,
6932 unsignedp, icode);
6933 cc_op0 = XEXP (comparison, 0);
6934 cc_op1 = XEXP (comparison, 1);
6935 /* Expand both operands and force them in reg, if required. */
6936 rtx_op1 = expand_normal (op1);
6937 if (!insn_data[icode].operand[1].predicate (rtx_op1, mode)
6938 && mode != VOIDmode)
6939 rtx_op1 = force_reg (mode, rtx_op1);
6941 rtx_op2 = expand_normal (op2);
6942 if (!insn_data[icode].operand[2].predicate (rtx_op2, mode)
6943 && mode != VOIDmode)
6944 rtx_op2 = force_reg (mode, rtx_op2);
6946 /* Emit instruction! */
6947 emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
6948 comparison, cc_op0, cc_op1));
6950 return target;
6954 /* This is an internal subroutine of the other compare_and_swap expanders.
6955 MEM, OLD_VAL and NEW_VAL are as you'd expect for a compare-and-swap
6956 operation. TARGET is an optional place to store the value result of
6957 the operation. ICODE is the particular instruction to expand. Return
6958 the result of the operation. */
6960 static rtx
6961 expand_val_compare_and_swap_1 (rtx mem, rtx old_val, rtx new_val,
6962 rtx target, enum insn_code icode)
6964 enum machine_mode mode = GET_MODE (mem);
6965 rtx insn;
6967 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
6968 target = gen_reg_rtx (mode);
6970 if (GET_MODE (old_val) != VOIDmode && GET_MODE (old_val) != mode)
6971 old_val = convert_modes (mode, GET_MODE (old_val), old_val, 1);
6972 if (!insn_data[icode].operand[2].predicate (old_val, mode))
6973 old_val = force_reg (mode, old_val);
6975 if (GET_MODE (new_val) != VOIDmode && GET_MODE (new_val) != mode)
6976 new_val = convert_modes (mode, GET_MODE (new_val), new_val, 1);
6977 if (!insn_data[icode].operand[3].predicate (new_val, mode))
6978 new_val = force_reg (mode, new_val);
6980 insn = GEN_FCN (icode) (target, mem, old_val, new_val);
6981 if (insn == NULL_RTX)
6982 return NULL_RTX;
6983 emit_insn (insn);
6985 return target;
6988 /* Expand a compare-and-swap operation and return its value. */
6991 expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
6993 enum machine_mode mode = GET_MODE (mem);
6994 enum insn_code icode = sync_compare_and_swap[mode];
6996 if (icode == CODE_FOR_nothing)
6997 return NULL_RTX;
6999 return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode);
7002 /* Helper function to find the MODE_CC set in a sync_compare_and_swap
7003 pattern. */
7005 static void
7006 find_cc_set (rtx x, const_rtx pat, void *data)
7008 if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
7009 && GET_CODE (pat) == SET)
7011 rtx *p_cc_reg = (rtx *) data;
7012 gcc_assert (!*p_cc_reg);
7013 *p_cc_reg = x;
7017 /* Expand a compare-and-swap operation and store true into the result if
7018 the operation was successful and false otherwise. Return the result.
7019 Unlike other routines, TARGET is not optional. */
7022 expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
7024 enum machine_mode mode = GET_MODE (mem);
7025 enum insn_code icode;
7026 rtx subtarget, seq, cc_reg;
7028 /* If the target supports a compare-and-swap pattern that simultaneously
7029 sets some flag for success, then use it. Otherwise use the regular
7030 compare-and-swap and follow that immediately with a compare insn. */
7031 icode = sync_compare_and_swap[mode];
7032 if (icode == CODE_FOR_nothing)
7033 return NULL_RTX;
7037 start_sequence ();
7038 subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
7039 NULL_RTX, icode);
7040 cc_reg = NULL_RTX;
7041 if (subtarget == NULL_RTX)
7043 end_sequence ();
7044 return NULL_RTX;
7047 if (have_insn_for (COMPARE, CCmode))
7048 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
7049 seq = get_insns ();
7050 end_sequence ();
7052 /* We might be comparing against an old value. Try again. :-( */
7053 if (!cc_reg && MEM_P (old_val))
7055 seq = NULL_RTX;
7056 old_val = force_reg (mode, old_val);
7059 while (!seq);
7061 emit_insn (seq);
7062 if (cc_reg)
7063 return emit_store_flag_force (target, EQ, cc_reg, const0_rtx, VOIDmode, 0, 1);
7064 else
7065 return emit_store_flag_force (target, EQ, subtarget, old_val, VOIDmode, 1, 1);
7068 /* This is a helper function for the other atomic operations. This function
7069 emits a loop that contains SEQ that iterates until a compare-and-swap
7070 operation at the end succeeds. MEM is the memory to be modified. SEQ is
7071 a set of instructions that takes a value from OLD_REG as an input and
7072 produces a value in NEW_REG as an output. Before SEQ, OLD_REG will be
7073 set to the current contents of MEM. After SEQ, a compare-and-swap will
7074 attempt to update MEM with NEW_REG. The function returns true when the
7075 loop was generated successfully. */
7077 static bool
7078 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
7080 enum machine_mode mode = GET_MODE (mem);
7081 enum insn_code icode;
7082 rtx label, cmp_reg, subtarget, cc_reg;
7084 /* The loop we want to generate looks like
7086 cmp_reg = mem;
7087 label:
7088 old_reg = cmp_reg;
7089 seq;
7090 cmp_reg = compare-and-swap(mem, old_reg, new_reg)
7091 if (cmp_reg != old_reg)
7092 goto label;
7094 Note that we only do the plain load from memory once. Subsequent
7095 iterations use the value loaded by the compare-and-swap pattern. */
7097 label = gen_label_rtx ();
7098 cmp_reg = gen_reg_rtx (mode);
7100 emit_move_insn (cmp_reg, mem);
7101 emit_label (label);
7102 emit_move_insn (old_reg, cmp_reg);
7103 if (seq)
7104 emit_insn (seq);
7106 /* If the target supports a compare-and-swap pattern that simultaneously
7107 sets some flag for success, then use it. Otherwise use the regular
7108 compare-and-swap and follow that immediately with a compare insn. */
7109 icode = sync_compare_and_swap[mode];
7110 if (icode == CODE_FOR_nothing)
7111 return false;
7113 subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
7114 cmp_reg, icode);
7115 if (subtarget == NULL_RTX)
7116 return false;
7118 cc_reg = NULL_RTX;
7119 if (have_insn_for (COMPARE, CCmode))
7120 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
7121 if (cc_reg)
7123 cmp_reg = cc_reg;
7124 old_reg = const0_rtx;
7126 else
7128 if (subtarget != cmp_reg)
7129 emit_move_insn (cmp_reg, subtarget);
7132 /* ??? Mark this jump predicted not taken? */
7133 emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, const0_rtx, GET_MODE (cmp_reg), 1,
7134 label);
7135 return true;
7138 /* This function generates the atomic operation MEM CODE= VAL. In this
7139 case, we do not care about any resulting value. Returns NULL if we
7140 cannot generate the operation. */
7143 expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
7145 enum machine_mode mode = GET_MODE (mem);
7146 enum insn_code icode;
7147 rtx insn;
7149 /* Look to see if the target supports the operation directly. */
7150 switch (code)
7152 case PLUS:
7153 icode = sync_add_optab[mode];
7154 break;
7155 case IOR:
7156 icode = sync_ior_optab[mode];
7157 break;
7158 case XOR:
7159 icode = sync_xor_optab[mode];
7160 break;
7161 case AND:
7162 icode = sync_and_optab[mode];
7163 break;
7164 case NOT:
7165 icode = sync_nand_optab[mode];
7166 break;
7168 case MINUS:
7169 icode = sync_sub_optab[mode];
7170 if (icode == CODE_FOR_nothing || CONST_INT_P (val))
7172 icode = sync_add_optab[mode];
7173 if (icode != CODE_FOR_nothing)
7175 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7176 code = PLUS;
7179 break;
7181 default:
7182 gcc_unreachable ();
7185 /* Generate the direct operation, if present. */
7186 if (icode != CODE_FOR_nothing)
7188 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7189 val = convert_modes (mode, GET_MODE (val), val, 1);
7190 if (!insn_data[icode].operand[1].predicate (val, mode))
7191 val = force_reg (mode, val);
7193 insn = GEN_FCN (icode) (mem, val);
7194 if (insn)
7196 emit_insn (insn);
7197 return const0_rtx;
7201 /* Failing that, generate a compare-and-swap loop in which we perform the
7202 operation with normal arithmetic instructions. */
7203 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7205 rtx t0 = gen_reg_rtx (mode), t1;
7207 start_sequence ();
7209 t1 = t0;
7210 if (code == NOT)
7212 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7213 true, OPTAB_LIB_WIDEN);
7214 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7216 else
7217 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7218 true, OPTAB_LIB_WIDEN);
7219 insn = get_insns ();
7220 end_sequence ();
7222 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7223 return const0_rtx;
7226 return NULL_RTX;
7229 /* This function generates the atomic operation MEM CODE= VAL. In this
7230 case, we do care about the resulting value: if AFTER is true then
7231 return the value MEM holds after the operation, if AFTER is false
7232 then return the value MEM holds before the operation. TARGET is an
7233 optional place for the result value to be stored. */
7236 expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
7237 bool after, rtx target)
7239 enum machine_mode mode = GET_MODE (mem);
7240 enum insn_code old_code, new_code, icode;
7241 bool compensate;
7242 rtx insn;
7244 /* Look to see if the target supports the operation directly. */
7245 switch (code)
7247 case PLUS:
7248 old_code = sync_old_add_optab[mode];
7249 new_code = sync_new_add_optab[mode];
7250 break;
7251 case IOR:
7252 old_code = sync_old_ior_optab[mode];
7253 new_code = sync_new_ior_optab[mode];
7254 break;
7255 case XOR:
7256 old_code = sync_old_xor_optab[mode];
7257 new_code = sync_new_xor_optab[mode];
7258 break;
7259 case AND:
7260 old_code = sync_old_and_optab[mode];
7261 new_code = sync_new_and_optab[mode];
7262 break;
7263 case NOT:
7264 old_code = sync_old_nand_optab[mode];
7265 new_code = sync_new_nand_optab[mode];
7266 break;
7268 case MINUS:
7269 old_code = sync_old_sub_optab[mode];
7270 new_code = sync_new_sub_optab[mode];
7271 if ((old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
7272 || CONST_INT_P (val))
7274 old_code = sync_old_add_optab[mode];
7275 new_code = sync_new_add_optab[mode];
7276 if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
7278 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
7279 code = PLUS;
7282 break;
7284 default:
7285 gcc_unreachable ();
7288 /* If the target does supports the proper new/old operation, great. But
7289 if we only support the opposite old/new operation, check to see if we
7290 can compensate. In the case in which the old value is supported, then
7291 we can always perform the operation again with normal arithmetic. In
7292 the case in which the new value is supported, then we can only handle
7293 this in the case the operation is reversible. */
7294 compensate = false;
7295 if (after)
7297 icode = new_code;
7298 if (icode == CODE_FOR_nothing)
7300 icode = old_code;
7301 if (icode != CODE_FOR_nothing)
7302 compensate = true;
7305 else
7307 icode = old_code;
7308 if (icode == CODE_FOR_nothing
7309 && (code == PLUS || code == MINUS || code == XOR))
7311 icode = new_code;
7312 if (icode != CODE_FOR_nothing)
7313 compensate = true;
7317 /* If we found something supported, great. */
7318 if (icode != CODE_FOR_nothing)
7320 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7321 target = gen_reg_rtx (mode);
7323 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7324 val = convert_modes (mode, GET_MODE (val), val, 1);
7325 if (!insn_data[icode].operand[2].predicate (val, mode))
7326 val = force_reg (mode, val);
7328 insn = GEN_FCN (icode) (target, mem, val);
7329 if (insn)
7331 emit_insn (insn);
7333 /* If we need to compensate for using an operation with the
7334 wrong return value, do so now. */
7335 if (compensate)
7337 if (!after)
7339 if (code == PLUS)
7340 code = MINUS;
7341 else if (code == MINUS)
7342 code = PLUS;
7345 if (code == NOT)
7347 target = expand_simple_binop (mode, AND, target, val,
7348 NULL_RTX, true,
7349 OPTAB_LIB_WIDEN);
7350 target = expand_simple_unop (mode, code, target,
7351 NULL_RTX, true);
7353 else
7354 target = expand_simple_binop (mode, code, target, val,
7355 NULL_RTX, true,
7356 OPTAB_LIB_WIDEN);
7359 return target;
7363 /* Failing that, generate a compare-and-swap loop in which we perform the
7364 operation with normal arithmetic instructions. */
7365 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7367 rtx t0 = gen_reg_rtx (mode), t1;
7369 if (!target || !register_operand (target, mode))
7370 target = gen_reg_rtx (mode);
7372 start_sequence ();
7374 if (!after)
7375 emit_move_insn (target, t0);
7376 t1 = t0;
7377 if (code == NOT)
7379 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7380 true, OPTAB_LIB_WIDEN);
7381 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7383 else
7384 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
7385 true, OPTAB_LIB_WIDEN);
7386 if (after)
7387 emit_move_insn (target, t1);
7389 insn = get_insns ();
7390 end_sequence ();
7392 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7393 return target;
7396 return NULL_RTX;
7399 /* This function expands a test-and-set operation. Ideally we atomically
7400 store VAL in MEM and return the previous value in MEM. Some targets
7401 may not support this operation and only support VAL with the constant 1;
7402 in this case while the return value will be 0/1, but the exact value
7403 stored in MEM is target defined. TARGET is an option place to stick
7404 the return value. */
7407 expand_sync_lock_test_and_set (rtx mem, rtx val, rtx target)
7409 enum machine_mode mode = GET_MODE (mem);
7410 enum insn_code icode;
7411 rtx insn;
7413 /* If the target supports the test-and-set directly, great. */
7414 icode = sync_lock_test_and_set[mode];
7415 if (icode != CODE_FOR_nothing)
7417 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
7418 target = gen_reg_rtx (mode);
7420 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7421 val = convert_modes (mode, GET_MODE (val), val, 1);
7422 if (!insn_data[icode].operand[2].predicate (val, mode))
7423 val = force_reg (mode, val);
7425 insn = GEN_FCN (icode) (target, mem, val);
7426 if (insn)
7428 emit_insn (insn);
7429 return target;
7433 /* Otherwise, use a compare-and-swap loop for the exchange. */
7434 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
7436 if (!target || !register_operand (target, mode))
7437 target = gen_reg_rtx (mode);
7438 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
7439 val = convert_modes (mode, GET_MODE (val), val, 1);
7440 if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
7441 return target;
7444 return NULL_RTX;
7447 #include "gt-optabs.h"