]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/optabs.c
genattrtab.c (write_header): Include hash-set.h...
[thirdparty/gcc.git] / gcc / optabs.c
CommitLineData
77c9c6c2 1/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
5624e564 2 Copyright (C) 1987-2015 Free Software Foundation, Inc.
77c9c6c2 3
1322177d 4This file is part of GCC.
77c9c6c2 5
1322177d
LB
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
1322177d 9version.
77c9c6c2 10
1322177d
LB
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
77c9c6c2
RK
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
77c9c6c2
RK
19
20
21#include "config.h"
670ee920 22#include "system.h"
4977bab6
ZW
23#include "coretypes.h"
24#include "tm.h"
718f9c0f 25#include "diagnostic-core.h"
dff01034
KG
26
27/* Include insn-config.h before expr.h so that HAVE_conditional_move
dc297297 28 is properly defined. */
dff01034 29#include "insn-config.h"
77c9c6c2 30#include "rtl.h"
40e23961
MC
31#include "hash-set.h"
32#include "machmode.h"
33#include "vec.h"
34#include "double-int.h"
35#include "input.h"
36#include "alias.h"
37#include "symtab.h"
38#include "wide-int.h"
39#include "inchash.h"
77c9c6c2 40#include "tree.h"
2a22f99c 41#include "tree-hasher.h"
d8a2d370
DN
42#include "stor-layout.h"
43#include "stringpool.h"
44#include "varasm.h"
6baf1cc8 45#include "tm_p.h"
77c9c6c2 46#include "flags.h"
83685514
AM
47#include "hard-reg-set.h"
48#include "input.h"
49ad7cfa 49#include "function.h"
52a11cbf 50#include "except.h"
77c9c6c2 51#include "expr.h"
b0710fe1 52#include "insn-codes.h"
e78d8e51
ZW
53#include "optabs.h"
54#include "libfuncs.h"
77c9c6c2 55#include "recog.h"
2829c155 56#include "reload.h"
87ff9c8e 57#include "ggc.h"
60393bbc
AM
58#include "predict.h"
59#include "dominance.h"
60#include "cfg.h"
4a69cf79 61#include "basic-block.h"
c15c90bb 62#include "target.h"
77c9c6c2 63
4bcbfa03 64struct target_optabs default_target_optabs;
3e9c326a 65struct target_libfuncs default_target_libfuncs;
135204dd 66struct target_optabs *this_fn_optabs = &default_target_optabs;
4bcbfa03
RS
67#if SWITCHABLE_TARGET
68struct target_optabs *this_target_optabs = &default_target_optabs;
3e9c326a 69struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
4bcbfa03 70#endif
34220a12 71
3e9c326a
RS
72#define libfunc_hash \
73 (this_target_libfuncs->x_libfunc_hash)
19c3fc24 74
f90b7a5a 75static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
ef4bddc2
RS
76 machine_mode *);
77static rtx expand_unop_direct (machine_mode, optab, rtx, rtx, int);
38295e01 78static void emit_libcall_block_1 (rtx_insn *, rtx, rtx, rtx, bool);
842a431a 79
8a33f100
JH
80/* Debug facility for use in GDB. */
81void debug_optab_libfuncs (void);
82
79b87c74
MM
83/* Prefixes for the current version of decimal floating point (BID vs. DPD) */
84#if ENABLE_DECIMAL_BID_FORMAT
85#define DECIMAL_PREFIX "bid_"
86#else
87#define DECIMAL_PREFIX "dpd_"
88#endif
8a33f100 89\f
3e9c326a 90/* Used for libfunc_hash. */
8a33f100 91
2a22f99c
TS
92hashval_t
93libfunc_hasher::hash (libfunc_entry *e)
8a33f100 94{
5714c34f 95 return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
8a33f100
JH
96}
97
3e9c326a 98/* Used for libfunc_hash. */
8a33f100 99
2a22f99c
TS
100bool
101libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
8a33f100 102{
cd1440b1 103 return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
8a33f100
JH
104}
105
106/* Return libfunc corresponding operation defined by OPTAB converting
107 from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL
108 if no libfunc is available. */
109rtx
ef4bddc2
RS
110convert_optab_libfunc (convert_optab optab, machine_mode mode1,
111 machine_mode mode2)
8a33f100
JH
112{
113 struct libfunc_entry e;
114 struct libfunc_entry **slot;
115
cd1440b1
RH
116 /* ??? This ought to be an assert, but not all of the places
117 that we expand optabs know about the optabs that got moved
118 to being direct. */
119 if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
120 return NULL_RTX;
121
122 e.op = optab;
8a33f100
JH
123 e.mode1 = mode1;
124 e.mode2 = mode2;
2a22f99c 125 slot = libfunc_hash->find_slot (&e, NO_INSERT);
8a33f100
JH
126 if (!slot)
127 {
cd1440b1
RH
128 const struct convert_optab_libcall_d *d
129 = &convlib_def[optab - FIRST_CONV_OPTAB];
130
131 if (d->libcall_gen == NULL)
132 return NULL;
133
134 d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
2a22f99c 135 slot = libfunc_hash->find_slot (&e, NO_INSERT);
cd1440b1
RH
136 if (!slot)
137 return NULL;
8a33f100
JH
138 }
139 return (*slot)->libfunc;
140}
141
142/* Return libfunc corresponding operation defined by OPTAB in MODE.
143 Trigger lazy initialization if needed, return NULL if no libfunc is
144 available. */
145rtx
ef4bddc2 146optab_libfunc (optab optab, machine_mode mode)
8a33f100
JH
147{
148 struct libfunc_entry e;
149 struct libfunc_entry **slot;
150
cd1440b1
RH
151 /* ??? This ought to be an assert, but not all of the places
152 that we expand optabs know about the optabs that got moved
153 to being direct. */
154 if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
155 return NULL_RTX;
156
157 e.op = optab;
8a33f100
JH
158 e.mode1 = mode;
159 e.mode2 = VOIDmode;
2a22f99c 160 slot = libfunc_hash->find_slot (&e, NO_INSERT);
8a33f100
JH
161 if (!slot)
162 {
cd1440b1
RH
163 const struct optab_libcall_d *d
164 = &normlib_def[optab - FIRST_NORM_OPTAB];
165
166 if (d->libcall_gen == NULL)
167 return NULL;
168
169 d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
2a22f99c 170 slot = libfunc_hash->find_slot (&e, NO_INSERT);
cd1440b1
RH
171 if (!slot)
172 return NULL;
8a33f100
JH
173 }
174 return (*slot)->libfunc;
175}
79b87c74 176
77c9c6c2 177\f
2f937369 178/* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
77c9c6c2
RK
179 the result of operation CODE applied to OP0 (and OP1 if it is a binary
180 operation).
181
182 If the last insn does not set TARGET, don't do anything, but return 1.
183
853f8f1c
SB
184 If the last insn or a previous insn sets TARGET and TARGET is one of OP0
185 or OP1, don't add the REG_EQUAL note but return 0. Our caller can then
186 try again, ensuring that TARGET is not one of the operands. */
77c9c6c2
RK
187
188static int
dc01c3d1 189add_equal_note (rtx_insn *insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
77c9c6c2 190{
dc01c3d1
DM
191 rtx_insn *last_insn;
192 rtx set;
77c9c6c2
RK
193 rtx note;
194
e3feb571 195 gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
2f937369 196
ec8e098d
PB
197 if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
198 && GET_RTX_CLASS (code) != RTX_BIN_ARITH
199 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
200 && GET_RTX_CLASS (code) != RTX_COMPARE
201 && GET_RTX_CLASS (code) != RTX_UNARY)
2f937369
DM
202 return 1;
203
204 if (GET_CODE (target) == ZERO_EXTRACT)
205 return 1;
206
207 for (last_insn = insns;
208 NEXT_INSN (last_insn) != NULL_RTX;
209 last_insn = NEXT_INSN (last_insn))
210 ;
211
6da26889
JJ
212 /* If TARGET is in OP0 or OP1, punt. We'd end up with a note referencing
213 a value changing in the insn, so the note would be invalid for CSE. */
214 if (reg_overlap_mentioned_p (target, op0)
215 || (op1 && reg_overlap_mentioned_p (target, op1)))
216 {
217 if (MEM_P (target)
218 && (rtx_equal_p (target, op0)
219 || (op1 && rtx_equal_p (target, op1))))
220 {
221 /* For MEM target, with MEM = MEM op X, prefer no REG_EQUAL note
222 over expanding it as temp = MEM op X, MEM = temp. If the target
223 supports MEM = MEM op X instructions, it is sometimes too hard
224 to reconstruct that form later, especially if X is also a memory,
225 and due to multiple occurrences of addresses the address might
226 be forced into register unnecessarily.
227 Note that not emitting the REG_EQUIV note might inhibit
228 CSE in some cases. */
229 set = single_set (last_insn);
230 if (set
231 && GET_CODE (SET_SRC (set)) == code
232 && MEM_P (SET_DEST (set))
233 && (rtx_equal_p (SET_DEST (set), XEXP (SET_SRC (set), 0))
234 || (op1 && rtx_equal_p (SET_DEST (set),
235 XEXP (SET_SRC (set), 1)))))
236 return 1;
237 }
238 return 0;
239 }
240
c8912e53 241 set = set_for_reg_notes (last_insn);
2f937369
DM
242 if (set == NULL_RTX)
243 return 1;
244
245 if (! rtx_equal_p (SET_DEST (set), target)
f9d36a92 246 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it. */
2f937369 247 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
f9d36a92 248 || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
77c9c6c2
RK
249 return 1;
250
ec8e098d 251 if (GET_RTX_CLASS (code) == RTX_UNARY)
e2f00837
JJ
252 switch (code)
253 {
254 case FFS:
255 case CLZ:
256 case CTZ:
257 case CLRSB:
258 case POPCOUNT:
259 case PARITY:
260 case BSWAP:
261 if (GET_MODE (op0) != VOIDmode && GET_MODE (target) != GET_MODE (op0))
262 {
263 note = gen_rtx_fmt_e (code, GET_MODE (op0), copy_rtx (op0));
264 if (GET_MODE_SIZE (GET_MODE (op0))
265 > GET_MODE_SIZE (GET_MODE (target)))
266 note = simplify_gen_unary (TRUNCATE, GET_MODE (target),
267 note, GET_MODE (op0));
268 else
269 note = simplify_gen_unary (ZERO_EXTEND, GET_MODE (target),
270 note, GET_MODE (op0));
271 break;
272 }
273 /* FALLTHRU */
274 default:
275 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
276 break;
277 }
77c9c6c2 278 else
9e6a5703 279 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
77c9c6c2 280
2f937369 281 set_unique_reg_note (last_insn, REG_EQUAL, note);
77c9c6c2
RK
282
283 return 1;
284}
285\f
a484f6ba
AS
286/* Given two input operands, OP0 and OP1, determine what the correct from_mode
287 for a widening operation would be. In most cases this would be OP0, but if
288 that's a constant it'll be VOIDmode, which isn't useful. */
289
ef4bddc2
RS
290static machine_mode
291widened_mode (machine_mode to_mode, rtx op0, rtx op1)
a484f6ba 292{
ef4bddc2
RS
293 machine_mode m0 = GET_MODE (op0);
294 machine_mode m1 = GET_MODE (op1);
295 machine_mode result;
a484f6ba
AS
296
297 if (m0 == VOIDmode && m1 == VOIDmode)
298 return to_mode;
299 else if (m0 == VOIDmode || GET_MODE_SIZE (m0) < GET_MODE_SIZE (m1))
300 result = m1;
301 else
302 result = m0;
303
304 if (GET_MODE_SIZE (result) > GET_MODE_SIZE (to_mode))
305 return to_mode;
306
307 return result;
308}
309\f
4df199d1
JH
310/* Like optab_handler, but for widening_operations that have a
311 TO_MODE and a FROM_MODE. */
312
313enum insn_code
ef4bddc2
RS
314widening_optab_handler (optab op, machine_mode to_mode,
315 machine_mode from_mode)
4df199d1
JH
316{
317 unsigned scode = (op << 16) | to_mode;
318 if (to_mode != from_mode && from_mode != VOIDmode)
319 {
320 /* ??? Why does find_widening_optab_handler_and_mode attempt to
321 widen things that can't be widened? E.g. add_optab... */
322 if (op > LAST_CONV_OPTAB)
323 return CODE_FOR_nothing;
324 scode |= from_mode << 8;
325 }
326 return raw_optab_handler (scode);
327}
328
5dfe80ba
AS
329/* Find a widening optab even if it doesn't widen as much as we want.
330 E.g. if from_mode is HImode, and to_mode is DImode, and there is no
331 direct HI->SI insn, then return SI->DI, if that exists.
332 If PERMIT_NON_WIDENING is non-zero then this can be used with
333 non-widening optabs also. */
334
335enum insn_code
ef4bddc2
RS
336find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
337 machine_mode from_mode,
5dfe80ba 338 int permit_non_widening,
ef4bddc2 339 machine_mode *found_mode)
5dfe80ba
AS
340{
341 for (; (permit_non_widening || from_mode != to_mode)
342 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
343 && from_mode != VOIDmode;
344 from_mode = GET_MODE_WIDER_MODE (from_mode))
345 {
346 enum insn_code handler = widening_optab_handler (op, to_mode,
347 from_mode);
348
349 if (handler != CODE_FOR_nothing)
350 {
351 if (found_mode)
352 *found_mode = from_mode;
353 return handler;
354 }
355 }
356
357 return CODE_FOR_nothing;
358}
359\f
835532b8
RK
360/* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
361 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
0c20a65f 362 not actually do a sign-extend or zero-extend, but can leave the
835532b8
RK
363 higher-order bits of the result rtx undefined, for example, in the case
364 of logical operations, but not right shifts. */
365
366static rtx
ef4bddc2 367widen_operand (rtx op, machine_mode mode, machine_mode oldmode,
0c20a65f 368 int unsignedp, int no_extend)
835532b8
RK
369{
370 rtx result;
371
8041889f
RK
372 /* If we don't have to extend and this is a constant, return it. */
373 if (no_extend && GET_MODE (op) == VOIDmode)
374 return op;
375
376 /* If we must extend do so. If OP is a SUBREG for a promoted object, also
377 extend since it will be more efficient to do so unless the signedness of
378 a promoted object differs from our extension. */
835532b8 379 if (! no_extend
cb8f73be 380 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
362d42dc 381 && SUBREG_CHECK_PROMOTED_SIGN (op, unsignedp)))
0661a3de 382 return convert_modes (mode, oldmode, op, unsignedp);
835532b8 383
a78a8cc4 384 /* If MODE is no wider than a single word, we return a lowpart or paradoxical
835532b8
RK
385 SUBREG. */
386 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
a78a8cc4 387 return gen_lowpart (mode, force_reg (GET_MODE (op), op));
835532b8
RK
388
389 /* Otherwise, get an object of MODE, clobber it, and set the low-order
390 part to OP. */
391
392 result = gen_reg_rtx (mode);
c41c1387 393 emit_clobber (result);
835532b8
RK
394 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
395 return result;
396}
397\f
71d46ca5
MM
398/* Return the optab used for computing the operation given by the tree code,
399 CODE and the tree EXP. This function is not always usable (for example, it
400 cannot give complete results for multiplication or division) but probably
401 ought to be relied on more widely throughout the expander. */
26277d41 402optab
71d46ca5
MM
403optab_for_tree_code (enum tree_code code, const_tree type,
404 enum optab_subtype subtype)
26277d41
PB
405{
406 bool trapv;
407 switch (code)
408 {
409 case BIT_AND_EXPR:
410 return and_optab;
411
412 case BIT_IOR_EXPR:
413 return ior_optab;
414
415 case BIT_NOT_EXPR:
416 return one_cmpl_optab;
417
418 case BIT_XOR_EXPR:
419 return xor_optab;
420
98449720
RH
421 case MULT_HIGHPART_EXPR:
422 return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab;
423
26277d41
PB
424 case TRUNC_MOD_EXPR:
425 case CEIL_MOD_EXPR:
426 case FLOOR_MOD_EXPR:
427 case ROUND_MOD_EXPR:
428 return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
429
430 case RDIV_EXPR:
431 case TRUNC_DIV_EXPR:
432 case CEIL_DIV_EXPR:
433 case FLOOR_DIV_EXPR:
434 case ROUND_DIV_EXPR:
435 case EXACT_DIV_EXPR:
c3284718
RS
436 if (TYPE_SATURATING (type))
437 return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
26277d41
PB
438 return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
439
440 case LSHIFT_EXPR:
8750672f 441 if (TREE_CODE (type) == VECTOR_TYPE)
71d46ca5
MM
442 {
443 if (subtype == optab_vector)
2225b9f2 444 return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
71d46ca5
MM
445
446 gcc_assert (subtype == optab_scalar);
447 }
c3284718
RS
448 if (TYPE_SATURATING (type))
449 return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
26277d41
PB
450 return ashl_optab;
451
452 case RSHIFT_EXPR:
8750672f 453 if (TREE_CODE (type) == VECTOR_TYPE)
71d46ca5
MM
454 {
455 if (subtype == optab_vector)
456 return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
457
458 gcc_assert (subtype == optab_scalar);
459 }
26277d41
PB
460 return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
461
462 case LROTATE_EXPR:
8750672f 463 if (TREE_CODE (type) == VECTOR_TYPE)
71d46ca5
MM
464 {
465 if (subtype == optab_vector)
466 return vrotl_optab;
467
468 gcc_assert (subtype == optab_scalar);
469 }
26277d41
PB
470 return rotl_optab;
471
472 case RROTATE_EXPR:
8750672f 473 if (TREE_CODE (type) == VECTOR_TYPE)
71d46ca5
MM
474 {
475 if (subtype == optab_vector)
476 return vrotr_optab;
477
478 gcc_assert (subtype == optab_scalar);
479 }
26277d41
PB
480 return rotr_optab;
481
482 case MAX_EXPR:
483 return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
484
485 case MIN_EXPR:
486 return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
487
7ccf35ed
DN
488 case REALIGN_LOAD_EXPR:
489 return vec_realign_load_optab;
490
20f06221
DN
491 case WIDEN_SUM_EXPR:
492 return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
493
494 case DOT_PROD_EXPR:
495 return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
496
79d652a5
CH
497 case SAD_EXPR:
498 return TYPE_UNSIGNED (type) ? usad_optab : ssad_optab;
499
0354c0c7
BS
500 case WIDEN_MULT_PLUS_EXPR:
501 return (TYPE_UNSIGNED (type)
502 ? (TYPE_SATURATING (type)
503 ? usmadd_widen_optab : umadd_widen_optab)
504 : (TYPE_SATURATING (type)
505 ? ssmadd_widen_optab : smadd_widen_optab));
506
507 case WIDEN_MULT_MINUS_EXPR:
508 return (TYPE_UNSIGNED (type)
509 ? (TYPE_SATURATING (type)
510 ? usmsub_widen_optab : umsub_widen_optab)
511 : (TYPE_SATURATING (type)
512 ? ssmsub_widen_optab : smsub_widen_optab));
513
16949072
RG
514 case FMA_EXPR:
515 return fma_optab;
516
61d3cdbb 517 case REDUC_MAX_EXPR:
d43a252e
AL
518 return TYPE_UNSIGNED (type)
519 ? reduc_umax_scal_optab : reduc_smax_scal_optab;
61d3cdbb
DN
520
521 case REDUC_MIN_EXPR:
d43a252e
AL
522 return TYPE_UNSIGNED (type)
523 ? reduc_umin_scal_optab : reduc_smin_scal_optab;
61d3cdbb
DN
524
525 case REDUC_PLUS_EXPR:
d43a252e 526 return reduc_plus_scal_optab;
a6b46ba2 527
89d67cca 528 case VEC_WIDEN_MULT_HI_EXPR:
b8698a0f 529 return TYPE_UNSIGNED (type) ?
89d67cca
DN
530 vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
531
532 case VEC_WIDEN_MULT_LO_EXPR:
b8698a0f 533 return TYPE_UNSIGNED (type) ?
89d67cca
DN
534 vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
535
3f30a9a6
RH
536 case VEC_WIDEN_MULT_EVEN_EXPR:
537 return TYPE_UNSIGNED (type) ?
538 vec_widen_umult_even_optab : vec_widen_smult_even_optab;
539
540 case VEC_WIDEN_MULT_ODD_EXPR:
541 return TYPE_UNSIGNED (type) ?
542 vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
543
36ba4aae
IR
544 case VEC_WIDEN_LSHIFT_HI_EXPR:
545 return TYPE_UNSIGNED (type) ?
546 vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;
547
548 case VEC_WIDEN_LSHIFT_LO_EXPR:
549 return TYPE_UNSIGNED (type) ?
550 vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab;
551
89d67cca 552 case VEC_UNPACK_HI_EXPR:
8115817b 553 return TYPE_UNSIGNED (type) ?
89d67cca
DN
554 vec_unpacku_hi_optab : vec_unpacks_hi_optab;
555
556 case VEC_UNPACK_LO_EXPR:
b8698a0f 557 return TYPE_UNSIGNED (type) ?
89d67cca
DN
558 vec_unpacku_lo_optab : vec_unpacks_lo_optab;
559
d9987fb4
UB
560 case VEC_UNPACK_FLOAT_HI_EXPR:
561 /* The signedness is determined from input operand. */
562 return TYPE_UNSIGNED (type) ?
563 vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
564
565 case VEC_UNPACK_FLOAT_LO_EXPR:
566 /* The signedness is determined from input operand. */
b8698a0f 567 return TYPE_UNSIGNED (type) ?
d9987fb4
UB
568 vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
569
8115817b
UB
570 case VEC_PACK_TRUNC_EXPR:
571 return vec_pack_trunc_optab;
572
89d67cca
DN
573 case VEC_PACK_SAT_EXPR:
574 return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
8115817b 575
d9987fb4 576 case VEC_PACK_FIX_TRUNC_EXPR:
9f106823 577 /* The signedness is determined from output operand. */
d9987fb4
UB
578 return TYPE_UNSIGNED (type) ?
579 vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
580
26277d41
PB
581 default:
582 break;
583 }
584
eeef0e45 585 trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
26277d41
PB
586 switch (code)
587 {
5be014d5 588 case POINTER_PLUS_EXPR:
26277d41 589 case PLUS_EXPR:
c3284718
RS
590 if (TYPE_SATURATING (type))
591 return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
26277d41
PB
592 return trapv ? addv_optab : add_optab;
593
594 case MINUS_EXPR:
c3284718
RS
595 if (TYPE_SATURATING (type))
596 return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
26277d41
PB
597 return trapv ? subv_optab : sub_optab;
598
599 case MULT_EXPR:
c3284718
RS
600 if (TYPE_SATURATING (type))
601 return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
26277d41
PB
602 return trapv ? smulv_optab : smul_optab;
603
604 case NEGATE_EXPR:
c3284718
RS
605 if (TYPE_SATURATING (type))
606 return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
26277d41
PB
607 return trapv ? negv_optab : neg_optab;
608
609 case ABS_EXPR:
610 return trapv ? absv_optab : abs_optab;
611
612 default:
2225b9f2 613 return unknown_optab;
26277d41
PB
614 }
615}
d43a252e
AL
616
617/* Given optab UNOPTAB that reduces a vector to a scalar, find instead the old
618 optab that produces a vector with the reduction result in one element,
619 for a tree with type TYPE. */
620
621optab
622scalar_reduc_to_vector (optab unoptab, const_tree type)
623{
624 switch (unoptab)
625 {
626 case reduc_plus_scal_optab:
627 return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
628
629 case reduc_smin_scal_optab: return reduc_smin_optab;
630 case reduc_umin_scal_optab: return reduc_umin_optab;
631 case reduc_smax_scal_optab: return reduc_smax_optab;
632 case reduc_umax_scal_optab: return reduc_umax_optab;
633 default: return unknown_optab;
634 }
635}
7ccf35ed 636
20f06221
DN
637/* Expand vector widening operations.
638
639 There are two different classes of operations handled here:
640 1) Operations whose result is wider than all the arguments to the operation.
641 Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR
642 In this case OP0 and optionally OP1 would be initialized,
643 but WIDE_OP wouldn't (not relevant for this case).
644 2) Operations whose result is of the same size as the last argument to the
645 operation, but wider than all the other arguments to the operation.
646 Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR.
647 In the case WIDE_OP, OP0 and optionally OP1 would be initialized.
648
649 E.g, when called to expand the following operations, this is how
650 the arguments will be initialized:
651 nops OP0 OP1 WIDE_OP
b8698a0f 652 widening-sum 2 oprnd0 - oprnd1
20f06221
DN
653 widening-dot-product 3 oprnd0 oprnd1 oprnd2
654 widening-mult 2 oprnd0 oprnd1 -
655 type-promotion (vec-unpack) 1 oprnd0 - - */
656
657rtx
8e7aa1f9
MM
658expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
659 rtx target, int unsignedp)
b8698a0f 660{
a5c7d693 661 struct expand_operand eops[4];
20f06221 662 tree oprnd0, oprnd1, oprnd2;
ef4bddc2 663 machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
20f06221 664 optab widen_pattern_optab;
a5c7d693 665 enum insn_code icode;
8e7aa1f9 666 int nops = TREE_CODE_LENGTH (ops->code);
a5c7d693 667 int op;
20f06221 668
8e7aa1f9 669 oprnd0 = ops->op0;
20f06221
DN
670 tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
671 widen_pattern_optab =
8e7aa1f9 672 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
0354c0c7
BS
673 if (ops->code == WIDEN_MULT_PLUS_EXPR
674 || ops->code == WIDEN_MULT_MINUS_EXPR)
5dfe80ba
AS
675 icode = find_widening_optab_handler (widen_pattern_optab,
676 TYPE_MODE (TREE_TYPE (ops->op2)),
677 tmode0, 0);
0354c0c7 678 else
a5c7d693 679 icode = optab_handler (widen_pattern_optab, tmode0);
20f06221 680 gcc_assert (icode != CODE_FOR_nothing);
20f06221
DN
681
682 if (nops >= 2)
683 {
8e7aa1f9 684 oprnd1 = ops->op1;
20f06221 685 tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
20f06221
DN
686 }
687
688 /* The last operand is of a wider mode than the rest of the operands. */
689 if (nops == 2)
a5c7d693 690 wmode = tmode1;
20f06221
DN
691 else if (nops == 3)
692 {
693 gcc_assert (tmode1 == tmode0);
694 gcc_assert (op1);
8e7aa1f9 695 oprnd2 = ops->op2;
20f06221 696 wmode = TYPE_MODE (TREE_TYPE (oprnd2));
20f06221
DN
697 }
698
a5c7d693
RS
699 op = 0;
700 create_output_operand (&eops[op++], target, TYPE_MODE (ops->type));
701 create_convert_operand_from (&eops[op++], op0, tmode0, unsignedp);
20f06221 702 if (op1)
a5c7d693 703 create_convert_operand_from (&eops[op++], op1, tmode1, unsignedp);
20f06221 704 if (wide_op)
a5c7d693
RS
705 create_convert_operand_from (&eops[op++], wide_op, wmode, unsignedp);
706 expand_insn (icode, op, eops);
707 return eops[0].value;
20f06221
DN
708}
709
7ccf35ed
DN
710/* Generate code to perform an operation specified by TERNARY_OPTAB
711 on operands OP0, OP1 and OP2, with result having machine-mode MODE.
712
713 UNSIGNEDP is for the case where we have to widen the operands
714 to perform the operation. It says to use zero-extension.
715
716 If TARGET is nonzero, the value
717 is generated there, if it is convenient to do so.
718 In all cases an rtx is returned for the locus of the value;
719 this may or may not be TARGET. */
720
721rtx
ef4bddc2 722expand_ternary_op (machine_mode mode, optab ternary_optab, rtx op0,
c414ac1d 723 rtx op1, rtx op2, rtx target, int unsignedp)
7ccf35ed 724{
a5c7d693
RS
725 struct expand_operand ops[4];
726 enum insn_code icode = optab_handler (ternary_optab, mode);
7ccf35ed 727
947131ba 728 gcc_assert (optab_handler (ternary_optab, mode) != CODE_FOR_nothing);
7ccf35ed 729
a5c7d693
RS
730 create_output_operand (&ops[0], target, mode);
731 create_convert_operand_from (&ops[1], op0, mode, unsignedp);
732 create_convert_operand_from (&ops[2], op1, mode, unsignedp);
733 create_convert_operand_from (&ops[3], op2, mode, unsignedp);
734 expand_insn (icode, 4, ops);
735 return ops[0].value;
7ccf35ed
DN
736}
737
738
273a2526
RS
739/* Like expand_binop, but return a constant rtx if the result can be
740 calculated at compile time. The arguments and return value are
741 otherwise the same as for expand_binop. */
742
3bdb97b8 743rtx
ef4bddc2 744simplify_expand_binop (machine_mode mode, optab binoptab,
273a2526
RS
745 rtx op0, rtx op1, rtx target, int unsignedp,
746 enum optab_methods methods)
747{
748 if (CONSTANT_P (op0) && CONSTANT_P (op1))
68162a97 749 {
19b5fafb
RH
750 rtx x = simplify_binary_operation (optab_to_code (binoptab),
751 mode, op0, op1);
68162a97
ILT
752 if (x)
753 return x;
754 }
755
756 return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
273a2526
RS
757}
758
759/* Like simplify_expand_binop, but always put the result in TARGET.
760 Return true if the expansion succeeded. */
761
bef5d8b6 762bool
ef4bddc2 763force_expand_binop (machine_mode mode, optab binoptab,
273a2526
RS
764 rtx op0, rtx op1, rtx target, int unsignedp,
765 enum optab_methods methods)
766{
767 rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
768 target, unsignedp, methods);
769 if (x == 0)
770 return false;
771 if (x != target)
772 emit_move_insn (target, x);
773 return true;
774}
775
bdc3ee5d
RH
776/* Create a new vector value in VMODE with all elements set to OP. The
777 mode of OP must be the element mode of VMODE. If OP is a constant,
778 then the return value will be a constant. */
779
780static rtx
ef4bddc2 781expand_vector_broadcast (machine_mode vmode, rtx op)
bdc3ee5d
RH
782{
783 enum insn_code icode;
784 rtvec vec;
785 rtx ret;
786 int i, n;
787
788 gcc_checking_assert (VECTOR_MODE_P (vmode));
789
790 n = GET_MODE_NUNITS (vmode);
791 vec = rtvec_alloc (n);
792 for (i = 0; i < n; ++i)
793 RTVEC_ELT (vec, i) = op;
794
795 if (CONSTANT_P (op))
796 return gen_rtx_CONST_VECTOR (vmode, vec);
797
798 /* ??? If the target doesn't have a vec_init, then we have no easy way
799 of performing this operation. Most of this sort of generic support
800 is hidden away in the vector lowering support in gimple. */
801 icode = optab_handler (vec_init_optab, vmode);
802 if (icode == CODE_FOR_nothing)
803 return NULL;
804
805 ret = gen_reg_rtx (vmode);
806 emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
807
808 return ret;
809}
810
273a2526
RS
811/* This subroutine of expand_doubleword_shift handles the cases in which
812 the effective shift value is >= BITS_PER_WORD. The arguments and return
813 value are the same as for the parent routine, except that SUPERWORD_OP1
814 is the shift count to use when shifting OUTOF_INPUT into INTO_TARGET.
815 INTO_TARGET may be null if the caller has decided to calculate it. */
816
817static bool
818expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
819 rtx outof_target, rtx into_target,
820 int unsignedp, enum optab_methods methods)
821{
822 if (into_target != 0)
823 if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
824 into_target, unsignedp, methods))
825 return false;
826
827 if (outof_target != 0)
828 {
829 /* For a signed right shift, we must fill OUTOF_TARGET with copies
830 of the sign bit, otherwise we must fill it with zeros. */
831 if (binoptab != ashr_optab)
832 emit_move_insn (outof_target, CONST0_RTX (word_mode));
833 else
834 if (!force_expand_binop (word_mode, binoptab,
835 outof_input, GEN_INT (BITS_PER_WORD - 1),
836 outof_target, unsignedp, methods))
837 return false;
838 }
839 return true;
840}
841
842/* This subroutine of expand_doubleword_shift handles the cases in which
843 the effective shift value is < BITS_PER_WORD. The arguments and return
844 value are the same as for the parent routine. */
845
846static bool
ef4bddc2 847expand_subword_shift (machine_mode op1_mode, optab binoptab,
273a2526
RS
848 rtx outof_input, rtx into_input, rtx op1,
849 rtx outof_target, rtx into_target,
850 int unsignedp, enum optab_methods methods,
851 unsigned HOST_WIDE_INT shift_mask)
852{
853 optab reverse_unsigned_shift, unsigned_shift;
854 rtx tmp, carries;
855
856 reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
857 unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
858
859 /* The low OP1 bits of INTO_TARGET come from the high bits of OUTOF_INPUT.
860 We therefore need to shift OUTOF_INPUT by (BITS_PER_WORD - OP1) bits in
861 the opposite direction to BINOPTAB. */
862 if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
863 {
864 carries = outof_input;
807e902e
KZ
865 tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD,
866 op1_mode), op1_mode);
273a2526
RS
867 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
868 0, true, methods);
869 }
870 else
871 {
872 /* We must avoid shifting by BITS_PER_WORD bits since that is either
873 the same as a zero shift (if shift_mask == BITS_PER_WORD - 1) or
b01d837f 874 has unknown behavior. Do a single shift first, then shift by the
273a2526
RS
875 remainder. It's OK to use ~OP1 as the remainder if shift counts
876 are truncated to the mode size. */
877 carries = expand_binop (word_mode, reverse_unsigned_shift,
878 outof_input, const1_rtx, 0, unsignedp, methods);
879 if (shift_mask == BITS_PER_WORD - 1)
880 {
807e902e
KZ
881 tmp = immed_wide_int_const
882 (wi::minus_one (GET_MODE_PRECISION (op1_mode)), op1_mode);
273a2526
RS
883 tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
884 0, true, methods);
885 }
886 else
887 {
807e902e
KZ
888 tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD - 1,
889 op1_mode), op1_mode);
273a2526
RS
890 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
891 0, true, methods);
892 }
893 }
894 if (tmp == 0 || carries == 0)
895 return false;
896 carries = expand_binop (word_mode, reverse_unsigned_shift,
897 carries, tmp, 0, unsignedp, methods);
898 if (carries == 0)
899 return false;
900
901 /* Shift INTO_INPUT logically by OP1. This is the last use of INTO_INPUT
902 so the result can go directly into INTO_TARGET if convenient. */
903 tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
904 into_target, unsignedp, methods);
905 if (tmp == 0)
906 return false;
907
908 /* Now OR in the bits carried over from OUTOF_INPUT. */
909 if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
910 into_target, unsignedp, methods))
911 return false;
912
913 /* Use a standard word_mode shift for the out-of half. */
914 if (outof_target != 0)
915 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
916 outof_target, unsignedp, methods))
917 return false;
918
919 return true;
920}
921
922
923#ifdef HAVE_conditional_move
924/* Try implementing expand_doubleword_shift using conditional moves.
925 The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
926 otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1
927 are the shift counts to use in the former and latter case. All other
928 arguments are the same as the parent routine. */
929
930static bool
ef4bddc2 931expand_doubleword_shift_condmove (machine_mode op1_mode, optab binoptab,
273a2526
RS
932 enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
933 rtx outof_input, rtx into_input,
934 rtx subword_op1, rtx superword_op1,
935 rtx outof_target, rtx into_target,
936 int unsignedp, enum optab_methods methods,
937 unsigned HOST_WIDE_INT shift_mask)
938{
939 rtx outof_superword, into_superword;
940
941 /* Put the superword version of the output into OUTOF_SUPERWORD and
942 INTO_SUPERWORD. */
943 outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
944 if (outof_target != 0 && subword_op1 == superword_op1)
945 {
946 /* The value INTO_TARGET >> SUBWORD_OP1, which we later store in
947 OUTOF_TARGET, is the same as the value of INTO_SUPERWORD. */
948 into_superword = outof_target;
949 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
950 outof_superword, 0, unsignedp, methods))
951 return false;
952 }
953 else
954 {
955 into_superword = gen_reg_rtx (word_mode);
956 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
957 outof_superword, into_superword,
958 unsignedp, methods))
959 return false;
960 }
26277d41 961
273a2526
RS
962 /* Put the subword version directly in OUTOF_TARGET and INTO_TARGET. */
963 if (!expand_subword_shift (op1_mode, binoptab,
964 outof_input, into_input, subword_op1,
965 outof_target, into_target,
966 unsignedp, methods, shift_mask))
967 return false;
968
969 /* Select between them. Do the INTO half first because INTO_SUPERWORD
970 might be the current value of OUTOF_TARGET. */
971 if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
972 into_target, into_superword, word_mode, false))
973 return false;
974
975 if (outof_target != 0)
976 if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
977 outof_target, outof_superword,
978 word_mode, false))
979 return false;
980
981 return true;
982}
983#endif
984
985/* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
986 OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
987 input operand; the shift moves bits in the direction OUTOF_INPUT->
988 INTO_TARGET. OUTOF_TARGET and INTO_TARGET are the equivalent words
989 of the target. OP1 is the shift count and OP1_MODE is its mode.
990 If OP1 is constant, it will have been truncated as appropriate
991 and is known to be nonzero.
992
993 If SHIFT_MASK is zero, the result of word shifts is undefined when the
994 shift count is outside the range [0, BITS_PER_WORD). This routine must
995 avoid generating such shifts for OP1s in the range [0, BITS_PER_WORD * 2).
996
997 If SHIFT_MASK is nonzero, all word-mode shift counts are effectively
998 masked by it and shifts in the range [BITS_PER_WORD, SHIFT_MASK) will
999 fill with zeros or sign bits as appropriate.
1000
2a7e31df 1001 If SHIFT_MASK is BITS_PER_WORD - 1, this routine will synthesize
273a2526
RS
1002 a doubleword shift whose equivalent mask is BITS_PER_WORD * 2 - 1.
1003 Doing this preserves semantics required by SHIFT_COUNT_TRUNCATED.
1004 In all other cases, shifts by values outside [0, BITS_PER_UNIT * 2)
1005 are undefined.
1006
1007 BINOPTAB, UNSIGNEDP and METHODS are as for expand_binop. This function
1008 may not use INTO_INPUT after modifying INTO_TARGET, and similarly for
1009 OUTOF_INPUT and OUTOF_TARGET. OUTOF_TARGET can be null if the parent
1010 function wants to calculate it itself.
1011
1012 Return true if the shift could be successfully synthesized. */
1013
1014static bool
ef4bddc2 1015expand_doubleword_shift (machine_mode op1_mode, optab binoptab,
273a2526
RS
1016 rtx outof_input, rtx into_input, rtx op1,
1017 rtx outof_target, rtx into_target,
1018 int unsignedp, enum optab_methods methods,
1019 unsigned HOST_WIDE_INT shift_mask)
1020{
1021 rtx superword_op1, tmp, cmp1, cmp2;
273a2526
RS
1022 enum rtx_code cmp_code;
1023
1024 /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
1025 fill the result with sign or zero bits as appropriate. If so, the value
1026 of OUTOF_TARGET will always be (SHIFT OUTOF_INPUT OP1). Recursively call
1027 this routine to calculate INTO_TARGET (which depends on both OUTOF_INPUT
1028 and INTO_INPUT), then emit code to set up OUTOF_TARGET.
1029
1030 This isn't worthwhile for constant shifts since the optimizers will
1031 cope better with in-range shift counts. */
1032 if (shift_mask >= BITS_PER_WORD
1033 && outof_target != 0
1034 && !CONSTANT_P (op1))
1035 {
1036 if (!expand_doubleword_shift (op1_mode, binoptab,
1037 outof_input, into_input, op1,
1038 0, into_target,
1039 unsignedp, methods, shift_mask))
1040 return false;
1041 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
1042 outof_target, unsignedp, methods))
1043 return false;
1044 return true;
1045 }
1046
1047 /* Set CMP_CODE, CMP1 and CMP2 so that the rtx (CMP_CODE CMP1 CMP2)
1048 is true when the effective shift value is less than BITS_PER_WORD.
1049 Set SUPERWORD_OP1 to the shift count that should be used to shift
1050 OUTOF_INPUT into INTO_TARGET when the condition is false. */
807e902e 1051 tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD, op1_mode), op1_mode);
273a2526
RS
1052 if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
1053 {
1054 /* Set CMP1 to OP1 & BITS_PER_WORD. The result is zero iff OP1
1055 is a subword shift count. */
1056 cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
1057 0, true, methods);
1058 cmp2 = CONST0_RTX (op1_mode);
1059 cmp_code = EQ;
1060 superword_op1 = op1;
1061 }
1062 else
1063 {
1064 /* Set CMP1 to OP1 - BITS_PER_WORD. */
1065 cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
1066 0, true, methods);
1067 cmp2 = CONST0_RTX (op1_mode);
1068 cmp_code = LT;
1069 superword_op1 = cmp1;
1070 }
1071 if (cmp1 == 0)
1072 return false;
1073
1074 /* If we can compute the condition at compile time, pick the
1075 appropriate subroutine. */
1076 tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
481683e1 1077 if (tmp != 0 && CONST_INT_P (tmp))
273a2526
RS
1078 {
1079 if (tmp == const0_rtx)
1080 return expand_superword_shift (binoptab, outof_input, superword_op1,
1081 outof_target, into_target,
1082 unsignedp, methods);
1083 else
1084 return expand_subword_shift (op1_mode, binoptab,
1085 outof_input, into_input, op1,
1086 outof_target, into_target,
1087 unsignedp, methods, shift_mask);
1088 }
1089
1090#ifdef HAVE_conditional_move
1091 /* Try using conditional moves to generate straight-line code. */
1092 {
38295e01 1093 rtx_insn *start = get_last_insn ();
273a2526
RS
1094 if (expand_doubleword_shift_condmove (op1_mode, binoptab,
1095 cmp_code, cmp1, cmp2,
1096 outof_input, into_input,
1097 op1, superword_op1,
1098 outof_target, into_target,
1099 unsignedp, methods, shift_mask))
1100 return true;
1101 delete_insns_since (start);
1102 }
1103#endif
1104
1105 /* As a last resort, use branches to select the correct alternative. */
19f8b229
TS
1106 rtx_code_label *subword_label = gen_label_rtx ();
1107 rtx_code_label *done_label = gen_label_rtx ();
273a2526 1108
2763a67e 1109 NO_DEFER_POP;
273a2526 1110 do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
40e90eac 1111 0, 0, subword_label, -1);
2763a67e 1112 OK_DEFER_POP;
273a2526
RS
1113
1114 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
1115 outof_target, into_target,
1116 unsignedp, methods))
1117 return false;
1118
1119 emit_jump_insn (gen_jump (done_label));
1120 emit_barrier ();
1121 emit_label (subword_label);
1122
1123 if (!expand_subword_shift (op1_mode, binoptab,
1124 outof_input, into_input, op1,
1125 outof_target, into_target,
1126 unsignedp, methods, shift_mask))
1127 return false;
1128
1129 emit_label (done_label);
1130 return true;
1131}
c64f913e 1132\f
f927760b
RS
1133/* Subroutine of expand_binop. Perform a double word multiplication of
1134 operands OP0 and OP1 both of mode MODE, which is exactly twice as wide
1135 as the target's word_mode. This function return NULL_RTX if anything
1136 goes wrong, in which case it may have already emitted instructions
1137 which need to be deleted.
1138
1139 If we want to multiply two two-word values and have normal and widening
1140 multiplies of single-word values, we can do this with three smaller
d70dcf29 1141 multiplications.
f927760b
RS
1142
1143 The multiplication proceeds as follows:
1144 _______________________
1145 [__op0_high_|__op0_low__]
1146 _______________________
1147 * [__op1_high_|__op1_low__]
1148 _______________________________________________
1149 _______________________
1150 (1) [__op0_low__*__op1_low__]
1151 _______________________
1152 (2a) [__op0_low__*__op1_high_]
1153 _______________________
1154 (2b) [__op0_high_*__op1_low__]
1155 _______________________
1156 (3) [__op0_high_*__op1_high_]
1157
1158
1159 This gives a 4-word result. Since we are only interested in the
1160 lower 2 words, partial result (3) and the upper words of (2a) and
1161 (2b) don't need to be calculated. Hence (2a) and (2b) can be
1162 calculated using non-widening multiplication.
1163
1164 (1), however, needs to be calculated with an unsigned widening
1165 multiplication. If this operation is not directly supported we
1166 try using a signed widening multiplication and adjust the result.
1167 This adjustment works as follows:
1168
1169 If both operands are positive then no adjustment is needed.
1170
1171 If the operands have different signs, for example op0_low < 0 and
1172 op1_low >= 0, the instruction treats the most significant bit of
1173 op0_low as a sign bit instead of a bit with significance
1174 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
1175 with 2**BITS_PER_WORD - op0_low, and two's complements the
1176 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
1177 the result.
1178
1179 Similarly, if both operands are negative, we need to add
1180 (op0_low + op1_low) * 2**BITS_PER_WORD.
1181
1182 We use a trick to adjust quickly. We logically shift op0_low right
1183 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
1184 op0_high (op1_high) before it is used to calculate 2b (2a). If no
1185 logical shift exists, we do an arithmetic right shift and subtract
1186 the 0 or -1. */
1187
1188static rtx
ef4bddc2 1189expand_doubleword_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
f927760b
RS
1190 bool umulp, enum optab_methods methods)
1191{
1192 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
1193 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
1194 rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
1195 rtx product, adjust, product_high, temp;
1196
1197 rtx op0_high = operand_subword_force (op0, high, mode);
1198 rtx op0_low = operand_subword_force (op0, low, mode);
1199 rtx op1_high = operand_subword_force (op1, high, mode);
1200 rtx op1_low = operand_subword_force (op1, low, mode);
1201
1202 /* If we're using an unsigned multiply to directly compute the product
1203 of the low-order words of the operands and perform any required
1204 adjustments of the operands, we begin by trying two more multiplications
1205 and then computing the appropriate sum.
1206
1207 We have checked above that the required addition is provided.
1208 Full-word addition will normally always succeed, especially if
1209 it is provided at all, so we don't worry about its failure. The
1210 multiplication may well fail, however, so we do handle that. */
1211
1212 if (!umulp)
1213 {
1214 /* ??? This could be done with emit_store_flag where available. */
1215 temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1216 NULL_RTX, 1, methods);
1217 if (temp)
1218 op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
69f39b11 1219 NULL_RTX, 0, OPTAB_DIRECT);
f927760b
RS
1220 else
1221 {
1222 temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1223 NULL_RTX, 0, methods);
1224 if (!temp)
1225 return NULL_RTX;
1226 op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
69f39b11 1227 NULL_RTX, 0, OPTAB_DIRECT);
f927760b
RS
1228 }
1229
1230 if (!op0_high)
1231 return NULL_RTX;
1232 }
1233
1234 adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
1235 NULL_RTX, 0, OPTAB_DIRECT);
1236 if (!adjust)
1237 return NULL_RTX;
1238
1239 /* OP0_HIGH should now be dead. */
1240
1241 if (!umulp)
1242 {
1243 /* ??? This could be done with emit_store_flag where available. */
1244 temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1245 NULL_RTX, 1, methods);
1246 if (temp)
1247 op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
69f39b11 1248 NULL_RTX, 0, OPTAB_DIRECT);
f927760b
RS
1249 else
1250 {
1251 temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1252 NULL_RTX, 0, methods);
1253 if (!temp)
1254 return NULL_RTX;
1255 op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
69f39b11 1256 NULL_RTX, 0, OPTAB_DIRECT);
f927760b
RS
1257 }
1258
1259 if (!op1_high)
1260 return NULL_RTX;
1261 }
1262
1263 temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
1264 NULL_RTX, 0, OPTAB_DIRECT);
1265 if (!temp)
1266 return NULL_RTX;
1267
1268 /* OP1_HIGH should now be dead. */
1269
1270 adjust = expand_binop (word_mode, add_optab, adjust, temp,
c701e857 1271 NULL_RTX, 0, OPTAB_DIRECT);
f927760b
RS
1272
1273 if (target && !REG_P (target))
1274 target = NULL_RTX;
1275
1276 if (umulp)
1277 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
1278 target, 1, OPTAB_DIRECT);
1279 else
1280 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
1281 target, 1, OPTAB_DIRECT);
1282
1283 if (!product)
1284 return NULL_RTX;
1285
1286 product_high = operand_subword (product, high, 1, mode);
1287 adjust = expand_binop (word_mode, add_optab, product_high, adjust,
c701e857 1288 NULL_RTX, 0, OPTAB_DIRECT);
f927760b
RS
1289 emit_move_insn (product_high, adjust);
1290 return product;
1291}
1292\f
ef89d648
ZW
1293/* Wrapper around expand_binop which takes an rtx code to specify
1294 the operation to perform, not an optab pointer. All other
1295 arguments are the same. */
1296rtx
ef4bddc2 1297expand_simple_binop (machine_mode mode, enum rtx_code code, rtx op0,
0c20a65f
AJ
1298 rtx op1, rtx target, int unsignedp,
1299 enum optab_methods methods)
ef89d648 1300{
19b5fafb 1301 optab binop = code_to_optab (code);
e3feb571 1302 gcc_assert (binop);
ef89d648
ZW
1303
1304 return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
1305}
1306
665d18c6
PB
1307/* Return whether OP0 and OP1 should be swapped when expanding a commutative
1308 binop. Order them according to commutative_operand_precedence and, if
1309 possible, try to put TARGET or a pseudo first. */
1310static bool
1311swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
1312{
1313 int op0_prec = commutative_operand_precedence (op0);
1314 int op1_prec = commutative_operand_precedence (op1);
1315
1316 if (op0_prec < op1_prec)
1317 return true;
1318
1319 if (op0_prec > op1_prec)
1320 return false;
1321
1322 /* With equal precedence, both orders are ok, but it is better if the
1323 first operand is TARGET, or if both TARGET and OP0 are pseudos. */
1324 if (target == 0 || REG_P (target))
1325 return (REG_P (op1) && !REG_P (op0)) || target == op1;
1326 else
1327 return rtx_equal_p (op1, target);
1328}
1329
62442ab9
RS
1330/* Return true if BINOPTAB implements a shift operation. */
1331
1332static bool
1333shift_optab_p (optab binoptab)
1334{
19b5fafb 1335 switch (optab_to_code (binoptab))
62442ab9
RS
1336 {
1337 case ASHIFT:
0f996086
CF
1338 case SS_ASHIFT:
1339 case US_ASHIFT:
62442ab9
RS
1340 case ASHIFTRT:
1341 case LSHIFTRT:
1342 case ROTATE:
1343 case ROTATERT:
1344 return true;
1345
1346 default:
1347 return false;
1348 }
1349}
1350
15dc95cb 1351/* Return true if BINOPTAB implements a commutative binary operation. */
62442ab9
RS
1352
1353static bool
1354commutative_optab_p (optab binoptab)
1355{
19b5fafb 1356 return (GET_RTX_CLASS (optab_to_code (binoptab)) == RTX_COMM_ARITH
62442ab9
RS
1357 || binoptab == smul_widen_optab
1358 || binoptab == umul_widen_optab
1359 || binoptab == smul_highpart_optab
1360 || binoptab == umul_highpart_optab);
1361}
1362
68f932c4 1363/* X is to be used in mode MODE as operand OPN to BINOPTAB. If we're
62442ab9
RS
1364 optimizing, and if the operand is a constant that costs more than
1365 1 instruction, force the constant into a register and return that
1366 register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */
1367
1368static rtx
ef4bddc2 1369avoid_expensive_constant (machine_mode mode, optab binoptab,
68f932c4 1370 int opn, rtx x, bool unsignedp)
62442ab9 1371{
c99102b8 1372 bool speed = optimize_insn_for_speed_p ();
fdb2c684 1373
47de45c6
RS
1374 if (mode != VOIDmode
1375 && optimize
62442ab9 1376 && CONSTANT_P (x)
19b5fafb
RH
1377 && (rtx_cost (x, optab_to_code (binoptab), opn, speed)
1378 > set_src_cost (x, speed)))
62442ab9 1379 {
481683e1 1380 if (CONST_INT_P (x))
c722c7da
RS
1381 {
1382 HOST_WIDE_INT intval = trunc_int_for_mode (INTVAL (x), mode);
1383 if (intval != INTVAL (x))
1384 x = GEN_INT (intval);
1385 }
1386 else
62442ab9
RS
1387 x = convert_modes (mode, VOIDmode, x, unsignedp);
1388 x = force_reg (mode, x);
1389 }
1390 return x;
1391}
665d18c6 1392
0aa222d1
SL
1393/* Helper function for expand_binop: handle the case where there
1394 is an insn that directly implements the indicated operation.
1395 Returns null if this is not possible. */
1396static rtx
ef4bddc2 1397expand_binop_directly (machine_mode mode, optab binoptab,
0aa222d1
SL
1398 rtx op0, rtx op1,
1399 rtx target, int unsignedp, enum optab_methods methods,
fee3e72c 1400 rtx_insn *last)
0aa222d1 1401{
ef4bddc2 1402 machine_mode from_mode = widened_mode (mode, op0, op1);
5dfe80ba
AS
1403 enum insn_code icode = find_widening_optab_handler (binoptab, mode,
1404 from_mode, 1);
ef4bddc2
RS
1405 machine_mode xmode0 = insn_data[(int) icode].operand[1].mode;
1406 machine_mode xmode1 = insn_data[(int) icode].operand[2].mode;
1407 machine_mode mode0, mode1, tmp_mode;
a5c7d693 1408 struct expand_operand ops[3];
62442ab9 1409 bool commutative_p;
0aa222d1
SL
1410 rtx pat;
1411 rtx xop0 = op0, xop1 = op1;
62442ab9 1412 rtx swap;
b8698a0f 1413
0aa222d1
SL
1414 /* If it is a commutative operator and the modes would match
1415 if we would swap the operands, we can save the conversions. */
62442ab9
RS
1416 commutative_p = commutative_optab_p (binoptab);
1417 if (commutative_p
4f431835
RS
1418 && GET_MODE (xop0) != xmode0 && GET_MODE (xop1) != xmode1
1419 && GET_MODE (xop0) == xmode1 && GET_MODE (xop1) == xmode1)
0aa222d1 1420 {
62442ab9
RS
1421 swap = xop0;
1422 xop0 = xop1;
1423 xop1 = swap;
0aa222d1 1424 }
b8698a0f 1425
62442ab9 1426 /* If we are optimizing, force expensive constants into a register. */
68f932c4 1427 xop0 = avoid_expensive_constant (xmode0, binoptab, 0, xop0, unsignedp);
62442ab9 1428 if (!shift_optab_p (binoptab))
68f932c4 1429 xop1 = avoid_expensive_constant (xmode1, binoptab, 1, xop1, unsignedp);
62442ab9 1430
2b99b2b8
RS
1431 /* In case the insn wants input operands in modes different from
1432 those of the actual operands, convert the operands. It would
1433 seem that we don't need to convert CONST_INTs, but we do, so
1434 that they're properly zero-extended, sign-extended or truncated
1435 for their mode. */
1436
4f431835
RS
1437 mode0 = GET_MODE (xop0) != VOIDmode ? GET_MODE (xop0) : mode;
1438 if (xmode0 != VOIDmode && xmode0 != mode0)
1439 {
1440 xop0 = convert_modes (xmode0, mode0, xop0, unsignedp);
1441 mode0 = xmode0;
1442 }
1443
1444 mode1 = GET_MODE (xop1) != VOIDmode ? GET_MODE (xop1) : mode;
1445 if (xmode1 != VOIDmode && xmode1 != mode1)
1446 {
1447 xop1 = convert_modes (xmode1, mode1, xop1, unsignedp);
1448 mode1 = xmode1;
1449 }
2b99b2b8
RS
1450
1451 /* If operation is commutative,
1452 try to make the first operand a register.
1453 Even better, try to make it the same as the target.
1454 Also try to make the last operand a constant. */
1455 if (commutative_p
1456 && swap_commutative_operands_with_target (target, xop0, xop1))
1457 {
1458 swap = xop1;
1459 xop1 = xop0;
1460 xop0 = swap;
1461 }
1462
0aa222d1
SL
1463 /* Now, if insn's predicates don't allow our operands, put them into
1464 pseudo regs. */
b8698a0f 1465
b8698a0f 1466 if (binoptab == vec_pack_trunc_optab
0aa222d1
SL
1467 || binoptab == vec_pack_usat_optab
1468 || binoptab == vec_pack_ssat_optab
1469 || binoptab == vec_pack_ufix_trunc_optab
1470 || binoptab == vec_pack_sfix_trunc_optab)
1471 {
1472 /* The mode of the result is different then the mode of the
1473 arguments. */
a5c7d693 1474 tmp_mode = insn_data[(int) icode].operand[0].mode;
0aa222d1 1475 if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
a5c7d693
RS
1476 {
1477 delete_insns_since (last);
1478 return NULL_RTX;
1479 }
0aa222d1
SL
1480 }
1481 else
1482 tmp_mode = mode;
1483
a5c7d693 1484 create_output_operand (&ops[0], target, tmp_mode);
2b99b2b8
RS
1485 create_input_operand (&ops[1], xop0, mode0);
1486 create_input_operand (&ops[2], xop1, mode1);
1487 pat = maybe_gen_insn (icode, 3, ops);
1488 if (pat)
a5c7d693 1489 {
2b99b2b8
RS
1490 /* If PAT is composed of more than one insn, try to add an appropriate
1491 REG_EQUAL note to it. If we can't because TEMP conflicts with an
1492 operand, call expand_binop again, this time without a target. */
dc01c3d1
DM
1493 if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX
1494 && ! add_equal_note (as_a <rtx_insn *> (pat), ops[0].value,
1495 optab_to_code (binoptab),
2b99b2b8 1496 ops[1].value, ops[2].value))
0aa222d1 1497 {
2b99b2b8
RS
1498 delete_insns_since (last);
1499 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
1500 unsignedp, methods);
0aa222d1 1501 }
b8698a0f 1502
2b99b2b8
RS
1503 emit_insn (pat);
1504 return ops[0].value;
a5c7d693 1505 }
0aa222d1
SL
1506 delete_insns_since (last);
1507 return NULL_RTX;
1508}
1509
77c9c6c2
RK
1510/* Generate code to perform an operation specified by BINOPTAB
1511 on operands OP0 and OP1, with result having machine-mode MODE.
1512
1513 UNSIGNEDP is for the case where we have to widen the operands
1514 to perform the operation. It says to use zero-extension.
1515
1516 If TARGET is nonzero, the value
1517 is generated there, if it is convenient to do so.
1518 In all cases an rtx is returned for the locus of the value;
1519 this may or may not be TARGET. */
1520
1521rtx
ef4bddc2 1522expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
0c20a65f 1523 rtx target, int unsignedp, enum optab_methods methods)
77c9c6c2 1524{
70864443
RK
1525 enum optab_methods next_methods
1526 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
1527 ? OPTAB_WIDEN : methods);
d858f359 1528 enum mode_class mclass;
ef4bddc2 1529 machine_mode wider_mode;
8a33f100 1530 rtx libfunc;
b3694847 1531 rtx temp;
38295e01
DM
1532 rtx_insn *entry_last = get_last_insn ();
1533 rtx_insn *last;
77c9c6c2 1534
d858f359 1535 mclass = GET_MODE_CLASS (mode);
77c9c6c2 1536
8aecce0a
RK
1537 /* If subtracting an integer constant, convert this into an addition of
1538 the negated constant. */
1539
481683e1 1540 if (binoptab == sub_optab && CONST_INT_P (op1))
8aecce0a
RK
1541 {
1542 op1 = negate_rtx (mode, op1);
1543 binoptab = add_optab;
1544 }
1545
77c9c6c2
RK
1546 /* Record where to delete back to if we backtrack. */
1547 last = get_last_insn ();
1548
77c9c6c2
RK
1549 /* If we can do it with a three-operand insn, do so. */
1550
1551 if (methods != OPTAB_MUST_WIDEN
5dfe80ba
AS
1552 && find_widening_optab_handler (binoptab, mode,
1553 widened_mode (mode, op0, op1), 1)
a484f6ba 1554 != CODE_FOR_nothing)
77c9c6c2 1555 {
0aa222d1 1556 temp = expand_binop_directly (mode, binoptab, op0, op1, target,
62442ab9 1557 unsignedp, methods, last);
0aa222d1
SL
1558 if (temp)
1559 return temp;
77c9c6c2
RK
1560 }
1561
0aa222d1
SL
1562 /* If we were trying to rotate, and that didn't work, try rotating
1563 the other direction before falling back to shifts and bitwise-or. */
1564 if (((binoptab == rotl_optab
947131ba 1565 && optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
0aa222d1 1566 || (binoptab == rotr_optab
947131ba 1567 && optab_handler (rotl_optab, mode) != CODE_FOR_nothing))
d858f359 1568 && mclass == MODE_INT)
0f8594ee 1569 {
0aa222d1
SL
1570 optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
1571 rtx newop1;
69660a70 1572 unsigned int bits = GET_MODE_PRECISION (mode);
0aa222d1 1573
481683e1 1574 if (CONST_INT_P (op1))
db826dae 1575 newop1 = GEN_INT (bits - INTVAL (op1));
0aa222d1 1576 else if (targetm.shift_truncation_mask (mode) == bits - 1)
db826dae 1577 newop1 = negate_rtx (GET_MODE (op1), op1);
0aa222d1 1578 else
db826dae 1579 newop1 = expand_binop (GET_MODE (op1), sub_optab,
2f1cd2eb 1580 gen_int_mode (bits, GET_MODE (op1)), op1,
0aa222d1 1581 NULL_RTX, unsignedp, OPTAB_DIRECT);
b8698a0f 1582
0aa222d1 1583 temp = expand_binop_directly (mode, otheroptab, op0, newop1,
62442ab9 1584 target, unsignedp, methods, last);
0aa222d1
SL
1585 if (temp)
1586 return temp;
0f8594ee
MM
1587 }
1588
5a5064dc
RK
1589 /* If this is a multiply, see if we can do a widening operation that
1590 takes operands of this mode and makes a wider mode. */
1591
86556d87 1592 if (binoptab == smul_optab
0d44736e 1593 && GET_MODE_2XWIDER_MODE (mode) != VOIDmode
a484f6ba
AS
1594 && (widening_optab_handler ((unsignedp ? umul_widen_optab
1595 : smul_widen_optab),
1596 GET_MODE_2XWIDER_MODE (mode), mode)
5a5064dc
RK
1597 != CODE_FOR_nothing))
1598 {
0d44736e 1599 temp = expand_binop (GET_MODE_2XWIDER_MODE (mode),
5a5064dc 1600 unsignedp ? umul_widen_optab : smul_widen_optab,
73d9a835 1601 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
5a5064dc 1602
70864443
RK
1603 if (temp != 0)
1604 {
28f52a4d 1605 if (GET_MODE_CLASS (mode) == MODE_INT
d0edd768 1606 && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (temp)))
70864443
RK
1607 return gen_lowpart (mode, temp);
1608 else
1609 return convert_to_mode (mode, temp, unsignedp);
1610 }
5a5064dc
RK
1611 }
1612
bdc3ee5d
RH
1613 /* If this is a vector shift by a scalar, see if we can do a vector
1614 shift by a vector. If so, broadcast the scalar into a vector. */
1615 if (mclass == MODE_VECTOR_INT)
1616 {
2225b9f2 1617 optab otheroptab = unknown_optab;
bdc3ee5d
RH
1618
1619 if (binoptab == ashl_optab)
1620 otheroptab = vashl_optab;
1621 else if (binoptab == ashr_optab)
1622 otheroptab = vashr_optab;
1623 else if (binoptab == lshr_optab)
1624 otheroptab = vlshr_optab;
1625 else if (binoptab == rotl_optab)
1626 otheroptab = vrotl_optab;
1627 else if (binoptab == rotr_optab)
1628 otheroptab = vrotr_optab;
1629
1630 if (otheroptab && optab_handler (otheroptab, mode) != CODE_FOR_nothing)
1631 {
1632 rtx vop1 = expand_vector_broadcast (mode, op1);
1633 if (vop1)
1634 {
1635 temp = expand_binop_directly (mode, otheroptab, op0, vop1,
1636 target, unsignedp, methods, last);
1637 if (temp)
1638 return temp;
1639 }
1640 }
1641 }
1642
9a856ec7 1643 /* Look for a wider mode of the same class for which we think we
5a5064dc
RK
1644 can open-code the operation. Check for a widening multiply at the
1645 wider mode as well. */
9a856ec7 1646
d858f359 1647 if (CLASS_HAS_WIDER_MODES_P (mclass)
6f43c157 1648 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
86556d87
BE
1649 for (wider_mode = GET_MODE_WIDER_MODE (mode);
1650 wider_mode != VOIDmode;
9a856ec7
RK
1651 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
1652 {
947131ba 1653 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
5a5064dc
RK
1654 || (binoptab == smul_optab
1655 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
5dfe80ba
AS
1656 && (find_widening_optab_handler ((unsignedp
1657 ? umul_widen_optab
1658 : smul_widen_optab),
1659 GET_MODE_WIDER_MODE (wider_mode),
1660 mode, 0)
5a5064dc 1661 != CODE_FOR_nothing)))
9a856ec7
RK
1662 {
1663 rtx xop0 = op0, xop1 = op1;
1664 int no_extend = 0;
1665
1666 /* For certain integer operations, we need not actually extend
1667 the narrow operands, as long as we will truncate
6d2f8887 1668 the results to the same narrowness. */
9a856ec7
RK
1669
1670 if ((binoptab == ior_optab || binoptab == and_optab
1671 || binoptab == xor_optab
1672 || binoptab == add_optab || binoptab == sub_optab
e5df894b 1673 || binoptab == smul_optab || binoptab == ashl_optab)
d858f359 1674 && mclass == MODE_INT)
62442ab9
RS
1675 {
1676 no_extend = 1;
68f932c4 1677 xop0 = avoid_expensive_constant (mode, binoptab, 0,
62442ab9
RS
1678 xop0, unsignedp);
1679 if (binoptab != ashl_optab)
68f932c4 1680 xop1 = avoid_expensive_constant (mode, binoptab, 1,
62442ab9
RS
1681 xop1, unsignedp);
1682 }
9a856ec7 1683
0661a3de 1684 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
943cc242
RK
1685
1686 /* The second operand of a shift must always be extended. */
0661a3de 1687 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
e5df894b 1688 no_extend && binoptab != ashl_optab);
943cc242 1689
b1ec3c92 1690 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
9a856ec7
RK
1691 unsignedp, OPTAB_DIRECT);
1692 if (temp)
1693 {
d858f359 1694 if (mclass != MODE_INT
d0edd768 1695 || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
9a856ec7
RK
1696 {
1697 if (target == 0)
1698 target = gen_reg_rtx (mode);
1699 convert_move (target, temp, 0);
1700 return target;
1701 }
1702 else
1703 return gen_lowpart (mode, temp);
1704 }
1705 else
1706 delete_insns_since (last);
1707 }
1708 }
1709
62442ab9
RS
1710 /* If operation is commutative,
1711 try to make the first operand a register.
1712 Even better, try to make it the same as the target.
1713 Also try to make the last operand a constant. */
1714 if (commutative_optab_p (binoptab)
1715 && swap_commutative_operands_with_target (target, op0, op1))
1716 {
1717 temp = op1;
1718 op1 = op0;
1719 op0 = temp;
1720 }
1721
77c9c6c2
RK
1722 /* These can be done a word at a time. */
1723 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
d858f359 1724 && mclass == MODE_INT
77c9c6c2 1725 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
947131ba 1726 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
77c9c6c2 1727 {
bb93b973 1728 int i;
38295e01 1729 rtx_insn *insns;
77c9c6c2
RK
1730
1731 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1732 won't be accurate, so use a new target. */
02972eaf
RS
1733 if (target == 0
1734 || target == op0
1735 || target == op1
1736 || !valid_multiword_target_p (target))
77c9c6c2
RK
1737 target = gen_reg_rtx (mode);
1738
1739 start_sequence ();
1740
1741 /* Do the actual arithmetic. */
1742 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
1743 {
1744 rtx target_piece = operand_subword (target, i, 1, mode);
34e56753 1745 rtx x = expand_binop (word_mode, binoptab,
77c9c6c2
RK
1746 operand_subword_force (op0, i, mode),
1747 operand_subword_force (op1, i, mode),
70864443
RK
1748 target_piece, unsignedp, next_methods);
1749
1750 if (x == 0)
1751 break;
1752
77c9c6c2
RK
1753 if (target_piece != x)
1754 emit_move_insn (target_piece, x);
1755 }
1756
1757 insns = get_insns ();
1758 end_sequence ();
1759
70864443
RK
1760 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
1761 {
d70dcf29 1762 emit_insn (insns);
70864443
RK
1763 return target;
1764 }
77c9c6c2
RK
1765 }
1766
8c597270 1767 /* Synthesize double word shifts from single word shifts. */
e5df894b
RK
1768 if ((binoptab == lshr_optab || binoptab == ashl_optab
1769 || binoptab == ashr_optab)
d858f359 1770 && mclass == MODE_INT
481683e1 1771 && (CONST_INT_P (op1) || optimize_insn_for_speed_p ())
8c597270 1772 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
0d44736e 1773 && GET_MODE_PRECISION (mode) == GET_MODE_BITSIZE (mode)
947131ba
RS
1774 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing
1775 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1776 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
8c597270 1777 {
273a2526 1778 unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
ef4bddc2 1779 machine_mode op1_mode;
8c597270 1780
273a2526
RS
1781 double_shift_mask = targetm.shift_truncation_mask (mode);
1782 shift_mask = targetm.shift_truncation_mask (word_mode);
1783 op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
8c597270 1784
273a2526 1785 /* Apply the truncation to constant shifts. */
481683e1 1786 if (double_shift_mask > 0 && CONST_INT_P (op1))
273a2526 1787 op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
8c597270 1788
273a2526
RS
1789 if (op1 == CONST0_RTX (op1_mode))
1790 return op0;
8c597270 1791
273a2526
RS
1792 /* Make sure that this is a combination that expand_doubleword_shift
1793 can handle. See the comments there for details. */
1794 if (double_shift_mask == 0
1795 || (shift_mask == BITS_PER_WORD - 1
1796 && double_shift_mask == BITS_PER_WORD * 2 - 1))
8c597270 1797 {
38295e01 1798 rtx_insn *insns;
273a2526
RS
1799 rtx into_target, outof_target;
1800 rtx into_input, outof_input;
1801 int left_shift, outof_word;
8c597270 1802
273a2526
RS
1803 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1804 won't be accurate, so use a new target. */
02972eaf
RS
1805 if (target == 0
1806 || target == op0
1807 || target == op1
1808 || !valid_multiword_target_p (target))
273a2526 1809 target = gen_reg_rtx (mode);
8c597270 1810
273a2526 1811 start_sequence ();
8c597270 1812
273a2526
RS
1813 /* OUTOF_* is the word we are shifting bits away from, and
1814 INTO_* is the word that we are shifting bits towards, thus
1815 they differ depending on the direction of the shift and
1816 WORDS_BIG_ENDIAN. */
70864443 1817
273a2526
RS
1818 left_shift = binoptab == ashl_optab;
1819 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
70864443 1820
273a2526
RS
1821 outof_target = operand_subword (target, outof_word, 1, mode);
1822 into_target = operand_subword (target, 1 - outof_word, 1, mode);
cf2f7113 1823
273a2526
RS
1824 outof_input = operand_subword_force (op0, outof_word, mode);
1825 into_input = operand_subword_force (op0, 1 - outof_word, mode);
0c20a65f 1826
273a2526
RS
1827 if (expand_doubleword_shift (op1_mode, binoptab,
1828 outof_input, into_input, op1,
1829 outof_target, into_target,
f8bdb931 1830 unsignedp, next_methods, shift_mask))
273a2526
RS
1831 {
1832 insns = get_insns ();
1833 end_sequence ();
8c597270 1834
d70dcf29 1835 emit_insn (insns);
273a2526
RS
1836 return target;
1837 }
1838 end_sequence ();
70864443 1839 }
8c597270
JW
1840 }
1841
1842 /* Synthesize double word rotates from single word shifts. */
1843 if ((binoptab == rotl_optab || binoptab == rotr_optab)
d858f359 1844 && mclass == MODE_INT
481683e1 1845 && CONST_INT_P (op1)
0d44736e 1846 && GET_MODE_PRECISION (mode) == 2 * BITS_PER_WORD
947131ba
RS
1847 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1848 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
8c597270 1849 {
38295e01 1850 rtx_insn *insns;
8c597270
JW
1851 rtx into_target, outof_target;
1852 rtx into_input, outof_input;
70864443 1853 rtx inter;
8c597270
JW
1854 int shift_count, left_shift, outof_word;
1855
1856 /* If TARGET is the same as one of the operands, the REG_EQUAL note
0c0ab0f1
OH
1857 won't be accurate, so use a new target. Do this also if target is not
1858 a REG, first because having a register instead may open optimization
1ae58c30 1859 opportunities, and second because if target and op0 happen to be MEMs
0c0ab0f1
OH
1860 designating the same location, we would risk clobbering it too early
1861 in the code sequence we generate below. */
02972eaf
RS
1862 if (target == 0
1863 || target == op0
1864 || target == op1
1865 || !REG_P (target)
1866 || !valid_multiword_target_p (target))
8c597270
JW
1867 target = gen_reg_rtx (mode);
1868
1869 start_sequence ();
1870
1871 shift_count = INTVAL (op1);
1872
1873 /* OUTOF_* is the word we are shifting bits away from, and
1874 INTO_* is the word that we are shifting bits towards, thus
1875 they differ depending on the direction of the shift and
1876 WORDS_BIG_ENDIAN. */
1877
1878 left_shift = (binoptab == rotl_optab);
1879 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1880
1881 outof_target = operand_subword (target, outof_word, 1, mode);
1882 into_target = operand_subword (target, 1 - outof_word, 1, mode);
1883
1884 outof_input = operand_subword_force (op0, outof_word, mode);
1885 into_input = operand_subword_force (op0, 1 - outof_word, mode);
1886
1887 if (shift_count == BITS_PER_WORD)
1888 {
1889 /* This is just a word swap. */
1890 emit_move_insn (outof_target, into_input);
1891 emit_move_insn (into_target, outof_input);
70864443 1892 inter = const0_rtx;
8c597270
JW
1893 }
1894 else
1895 {
1896 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1897 rtx first_shift_count, second_shift_count;
1898 optab reverse_unsigned_shift, unsigned_shift;
1899
1900 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1901 ? lshr_optab : ashl_optab);
1902
1903 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1904 ? ashl_optab : lshr_optab);
1905
1906 if (shift_count > BITS_PER_WORD)
1907 {
1908 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
7e1a450d 1909 second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
8c597270
JW
1910 }
1911 else
1912 {
1913 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
1914 second_shift_count = GEN_INT (shift_count);
1915 }
1916
1917 into_temp1 = expand_binop (word_mode, unsigned_shift,
1918 outof_input, first_shift_count,
70864443 1919 NULL_RTX, unsignedp, next_methods);
8c597270
JW
1920 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1921 into_input, second_shift_count,
5be5c8d4 1922 NULL_RTX, unsignedp, next_methods);
70864443
RK
1923
1924 if (into_temp1 != 0 && into_temp2 != 0)
1925 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1926 into_target, unsignedp, next_methods);
1927 else
1928 inter = 0;
1929
cb5b00cf 1930 if (inter != 0 && inter != into_target)
70864443 1931 emit_move_insn (into_target, inter);
8c597270
JW
1932
1933 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1934 into_input, first_shift_count,
70864443 1935 NULL_RTX, unsignedp, next_methods);
8c597270
JW
1936 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1937 outof_input, second_shift_count,
5be5c8d4 1938 NULL_RTX, unsignedp, next_methods);
70864443
RK
1939
1940 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1941 inter = expand_binop (word_mode, ior_optab,
1942 outof_temp1, outof_temp2,
1943 outof_target, unsignedp, next_methods);
1944
cb5b00cf 1945 if (inter != 0 && inter != outof_target)
70864443 1946 emit_move_insn (outof_target, inter);
8c597270
JW
1947 }
1948
1949 insns = get_insns ();
1950 end_sequence ();
1951
70864443
RK
1952 if (inter != 0)
1953 {
ebd8b60d 1954 emit_insn (insns);
70864443
RK
1955 return target;
1956 }
8c597270
JW
1957 }
1958
77c9c6c2
RK
1959 /* These can be done a word at a time by propagating carries. */
1960 if ((binoptab == add_optab || binoptab == sub_optab)
d858f359 1961 && mclass == MODE_INT
77c9c6c2 1962 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
947131ba 1963 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
77c9c6c2 1964 {
e2500fed 1965 unsigned int i;
77c9c6c2 1966 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
a4b5414c 1967 const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
07444f1d 1968 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
64de6c0a 1969 rtx xop0, xop1, xtarget;
77c9c6c2
RK
1970
1971 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1972 value is one of those, use it. Otherwise, use 1 since it is the
1973 one easiest to get. */
1974#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1975 int normalizep = STORE_FLAG_VALUE;
1976#else
1977 int normalizep = 1;
1978#endif
1979
1980 /* Prepare the operands. */
cee85023
RS
1981 xop0 = force_reg (mode, op0);
1982 xop1 = force_reg (mode, op1);
77c9c6c2 1983
64de6c0a
DE
1984 xtarget = gen_reg_rtx (mode);
1985
02972eaf 1986 if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
64de6c0a 1987 target = xtarget;
77c9c6c2 1988
af2cc4dd 1989 /* Indicate for flow that the entire target reg is being set. */
f8cfc6aa 1990 if (REG_P (target))
c41c1387 1991 emit_clobber (xtarget);
af2cc4dd 1992
77c9c6c2
RK
1993 /* Do the actual arithmetic. */
1994 for (i = 0; i < nwords; i++)
1995 {
1996 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
64de6c0a 1997 rtx target_piece = operand_subword (xtarget, index, 1, mode);
cee85023
RS
1998 rtx op0_piece = operand_subword_force (xop0, index, mode);
1999 rtx op1_piece = operand_subword_force (xop1, index, mode);
77c9c6c2
RK
2000 rtx x;
2001
2002 /* Main add/subtract of the input operands. */
34e56753 2003 x = expand_binop (word_mode, binoptab,
77c9c6c2 2004 op0_piece, op1_piece,
70864443 2005 target_piece, unsignedp, next_methods);
77c9c6c2
RK
2006 if (x == 0)
2007 break;
2008
2009 if (i + 1 < nwords)
2010 {
2011 /* Store carry from main add/subtract. */
34e56753 2012 carry_out = gen_reg_rtx (word_mode);
23357404
TG
2013 carry_out = emit_store_flag_force (carry_out,
2014 (binoptab == add_optab
b30f05db 2015 ? LT : GT),
23357404
TG
2016 x, op0_piece,
2017 word_mode, 1, normalizep);
77c9c6c2
RK
2018 }
2019
2020 if (i > 0)
2021 {
859cb4d8 2022 rtx newx;
0c20a65f 2023
77c9c6c2 2024 /* Add/subtract previous carry to main result. */
859cb4d8
GK
2025 newx = expand_binop (word_mode,
2026 normalizep == 1 ? binoptab : otheroptab,
2027 x, carry_in,
2028 NULL_RTX, 1, next_methods);
77c9c6c2
RK
2029
2030 if (i + 1 < nwords)
2031 {
77c9c6c2 2032 /* Get out carry from adding/subtracting carry in. */
859cb4d8 2033 rtx carry_tmp = gen_reg_rtx (word_mode);
23357404 2034 carry_tmp = emit_store_flag_force (carry_tmp,
859cb4d8
GK
2035 (binoptab == add_optab
2036 ? LT : GT),
2037 newx, x,
23357404 2038 word_mode, 1, normalizep);
70864443 2039
77c9c6c2 2040 /* Logical-ior the two poss. carry together. */
34e56753 2041 carry_out = expand_binop (word_mode, ior_optab,
77c9c6c2 2042 carry_out, carry_tmp,
70864443
RK
2043 carry_out, 0, next_methods);
2044 if (carry_out == 0)
77c9c6c2
RK
2045 break;
2046 }
859cb4d8 2047 emit_move_insn (target_piece, newx);
77c9c6c2 2048 }
06cd9d72
DD
2049 else
2050 {
2051 if (x != target_piece)
2052 emit_move_insn (target_piece, x);
2053 }
77c9c6c2
RK
2054
2055 carry_in = carry_out;
0c20a65f 2056 }
77c9c6c2 2057
e2500fed 2058 if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
77c9c6c2 2059 {
947131ba 2060 if (optab_handler (mov_optab, mode) != CODE_FOR_nothing
d0ccc658 2061 || ! rtx_equal_p (target, xtarget))
02214a5c 2062 {
64de6c0a 2063 rtx temp = emit_move_insn (target, xtarget);
70864443 2064
7543f918 2065 set_dst_reg_note (temp, REG_EQUAL,
19b5fafb
RH
2066 gen_rtx_fmt_ee (optab_to_code (binoptab),
2067 mode, copy_rtx (xop0),
7543f918
JR
2068 copy_rtx (xop1)),
2069 target);
02214a5c 2070 }
2cd622c3
AO
2071 else
2072 target = xtarget;
c5c76735 2073
77c9c6c2
RK
2074 return target;
2075 }
c5c76735 2076
77c9c6c2
RK
2077 else
2078 delete_insns_since (last);
2079 }
2080
f927760b
RS
2081 /* Attempt to synthesize double word multiplies using a sequence of word
2082 mode multiplications. We first attempt to generate a sequence using a
2083 more efficient unsigned widening multiply, and if that fails we then
2084 try using a signed widening multiply. */
77c9c6c2
RK
2085
2086 if (binoptab == smul_optab
d858f359 2087 && mclass == MODE_INT
77c9c6c2 2088 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
947131ba
RS
2089 && optab_handler (smul_optab, word_mode) != CODE_FOR_nothing
2090 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)
77c9c6c2 2091 {
f927760b 2092 rtx product = NULL_RTX;
a484f6ba
AS
2093 if (widening_optab_handler (umul_widen_optab, mode, word_mode)
2094 != CODE_FOR_nothing)
f927760b
RS
2095 {
2096 product = expand_doubleword_mult (mode, op0, op1, target,
2097 true, methods);
2098 if (!product)
77c9c6c2 2099 delete_insns_since (last);
77c9c6c2
RK
2100 }
2101
f927760b 2102 if (product == NULL_RTX
a484f6ba
AS
2103 && widening_optab_handler (smul_widen_optab, mode, word_mode)
2104 != CODE_FOR_nothing)
77c9c6c2 2105 {
f927760b
RS
2106 product = expand_doubleword_mult (mode, op0, op1, target,
2107 false, methods);
2108 if (!product)
2109 delete_insns_since (last);
77c9c6c2
RK
2110 }
2111
f927760b 2112 if (product != NULL_RTX)
77c9c6c2 2113 {
947131ba 2114 if (optab_handler (mov_optab, mode) != CODE_FOR_nothing)
70864443 2115 {
f927760b 2116 temp = emit_move_insn (target ? target : product, product);
7543f918
JR
2117 set_dst_reg_note (temp,
2118 REG_EQUAL,
2119 gen_rtx_fmt_ee (MULT, mode,
2120 copy_rtx (op0),
2121 copy_rtx (op1)),
2122 target ? target : product);
77c9c6c2 2123 }
f927760b 2124 return product;
77c9c6c2 2125 }
77c9c6c2
RK
2126 }
2127
2128 /* It can't be open-coded in this mode.
2129 Use a library call if one is available and caller says that's ok. */
2130
8a33f100
JH
2131 libfunc = optab_libfunc (binoptab, mode);
2132 if (libfunc
77c9c6c2
RK
2133 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
2134 {
38295e01 2135 rtx_insn *insns;
0bbb7f4d 2136 rtx op1x = op1;
ef4bddc2 2137 machine_mode op1_mode = mode;
9a7f678c 2138 rtx value;
77c9c6c2
RK
2139
2140 start_sequence ();
2141
62442ab9 2142 if (shift_optab_p (binoptab))
0bbb7f4d 2143 {
c7ff6e7a 2144 op1_mode = targetm.libgcc_shift_count_mode ();
0bbb7f4d
RS
2145 /* Specify unsigned here,
2146 since negative shift counts are meaningless. */
c7ff6e7a 2147 op1x = convert_to_mode (op1_mode, op1, 1);
0bbb7f4d
RS
2148 }
2149
82f0e2cc
RK
2150 if (GET_MODE (op0) != VOIDmode
2151 && GET_MODE (op0) != mode)
5035bbfe
TG
2152 op0 = convert_to_mode (mode, op0, unsignedp);
2153
77c9c6c2
RK
2154 /* Pass 1 for NO_QUEUE so we don't lose any increments
2155 if the libcall is cse'd or moved. */
8a33f100 2156 value = emit_library_call_value (libfunc,
ebb1b59a 2157 NULL_RTX, LCT_CONST, mode, 2,
9a7f678c 2158 op0, mode, op1x, op1_mode);
77c9c6c2
RK
2159
2160 insns = get_insns ();
2161 end_sequence ();
2162
2163 target = gen_reg_rtx (mode);
b55f62cc 2164 emit_libcall_block_1 (insns, target, value,
19b5fafb
RH
2165 gen_rtx_fmt_ee (optab_to_code (binoptab),
2166 mode, op0, op1),
b55f62cc 2167 trapv_binoptab_p (binoptab));
77c9c6c2
RK
2168
2169 return target;
2170 }
2171
2172 delete_insns_since (last);
2173
2174 /* It can't be done in this mode. Can we do it in a wider mode? */
2175
2176 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
2177 || methods == OPTAB_MUST_WIDEN))
abd418d3
RS
2178 {
2179 /* Caller says, don't even try. */
2180 delete_insns_since (entry_last);
2181 return 0;
2182 }
77c9c6c2
RK
2183
2184 /* Compute the value of METHODS to pass to recursive calls.
2185 Don't allow widening to be tried recursively. */
2186
2187 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
2188
34e56753
RS
2189 /* Look for a wider mode of the same class for which it appears we can do
2190 the operation. */
77c9c6c2 2191
d858f359 2192 if (CLASS_HAS_WIDER_MODES_P (mclass))
77c9c6c2 2193 {
86556d87
BE
2194 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2195 wider_mode != VOIDmode;
77c9c6c2
RK
2196 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2197 {
5dfe80ba 2198 if (find_widening_optab_handler (binoptab, wider_mode, mode, 1)
a484f6ba 2199 != CODE_FOR_nothing
77c9c6c2 2200 || (methods == OPTAB_LIB
8a33f100 2201 && optab_libfunc (binoptab, wider_mode)))
77c9c6c2
RK
2202 {
2203 rtx xop0 = op0, xop1 = op1;
2204 int no_extend = 0;
2205
34e56753 2206 /* For certain integer operations, we need not actually extend
77c9c6c2 2207 the narrow operands, as long as we will truncate
835532b8 2208 the results to the same narrowness. */
77c9c6c2 2209
34e56753
RS
2210 if ((binoptab == ior_optab || binoptab == and_optab
2211 || binoptab == xor_optab
2212 || binoptab == add_optab || binoptab == sub_optab
e5df894b 2213 || binoptab == smul_optab || binoptab == ashl_optab)
d858f359 2214 && mclass == MODE_INT)
77c9c6c2
RK
2215 no_extend = 1;
2216
0661a3de
RS
2217 xop0 = widen_operand (xop0, wider_mode, mode,
2218 unsignedp, no_extend);
943cc242
RK
2219
2220 /* The second operand of a shift must always be extended. */
0661a3de 2221 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
e5df894b 2222 no_extend && binoptab != ashl_optab);
77c9c6c2 2223
b1ec3c92 2224 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
77c9c6c2
RK
2225 unsignedp, methods);
2226 if (temp)
2227 {
d858f359 2228 if (mclass != MODE_INT
d0edd768 2229 || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
77c9c6c2
RK
2230 {
2231 if (target == 0)
2232 target = gen_reg_rtx (mode);
2233 convert_move (target, temp, 0);
2234 return target;
2235 }
2236 else
2237 return gen_lowpart (mode, temp);
2238 }
2239 else
2240 delete_insns_since (last);
2241 }
2242 }
2243 }
2244
abd418d3 2245 delete_insns_since (entry_last);
77c9c6c2
RK
2246 return 0;
2247}
2248\f
2249/* Expand a binary operator which has both signed and unsigned forms.
2250 UOPTAB is the optab for unsigned operations, and SOPTAB is for
2251 signed operations.
2252
2253 If we widen unsigned operands, we may use a signed wider operation instead
2254 of an unsigned wider operation, since the result would be the same. */
2255
2256rtx
ef4bddc2 2257sign_expand_binop (machine_mode mode, optab uoptab, optab soptab,
0c20a65f
AJ
2258 rtx op0, rtx op1, rtx target, int unsignedp,
2259 enum optab_methods methods)
77c9c6c2 2260{
b3694847 2261 rtx temp;
77c9c6c2 2262 optab direct_optab = unsignedp ? uoptab : soptab;
cd1440b1 2263 bool save_enable;
77c9c6c2
RK
2264
2265 /* Do it without widening, if possible. */
2266 temp = expand_binop (mode, direct_optab, op0, op1, target,
2267 unsignedp, OPTAB_DIRECT);
2268 if (temp || methods == OPTAB_DIRECT)
2269 return temp;
2270
cd1440b1
RH
2271 /* Try widening to a signed int. Disable any direct use of any
2272 signed insn in the current mode. */
2273 save_enable = swap_optab_enable (soptab, mode, false);
77c9c6c2 2274
cd1440b1 2275 temp = expand_binop (mode, soptab, op0, op1, target,
77c9c6c2
RK
2276 unsignedp, OPTAB_WIDEN);
2277
2278 /* For unsigned operands, try widening to an unsigned int. */
cd1440b1 2279 if (!temp && unsignedp)
77c9c6c2
RK
2280 temp = expand_binop (mode, uoptab, op0, op1, target,
2281 unsignedp, OPTAB_WIDEN);
2282 if (temp || methods == OPTAB_WIDEN)
cd1440b1 2283 goto egress;
77c9c6c2 2284
f90b7a5a 2285 /* Use the right width libcall if that exists. */
cd1440b1
RH
2286 temp = expand_binop (mode, direct_optab, op0, op1, target,
2287 unsignedp, OPTAB_LIB);
77c9c6c2 2288 if (temp || methods == OPTAB_LIB)
cd1440b1 2289 goto egress;
77c9c6c2 2290
f90b7a5a 2291 /* Must widen and use a libcall, use either signed or unsigned. */
cd1440b1 2292 temp = expand_binop (mode, soptab, op0, op1, target,
77c9c6c2 2293 unsignedp, methods);
cd1440b1
RH
2294 if (!temp && unsignedp)
2295 temp = expand_binop (mode, uoptab, op0, op1, target,
77c9c6c2 2296 unsignedp, methods);
cd1440b1
RH
2297
2298 egress:
2299 /* Undo the fiddling above. */
2300 if (save_enable)
2301 swap_optab_enable (soptab, mode, true);
2302 return temp;
77c9c6c2
RK
2303}
2304\f
6c7cf1f0
UB
2305/* Generate code to perform an operation specified by UNOPPTAB
2306 on operand OP0, with two results to TARG0 and TARG1.
2307 We assume that the order of the operands for the instruction
2308 is TARG0, TARG1, OP0.
2309
2310 Either TARG0 or TARG1 may be zero, but what that means is that
2311 the result is not actually wanted. We will generate it into
2312 a dummy pseudo-reg and discard it. They may not both be zero.
2313
2314 Returns 1 if this operation can be performed; 0 if not. */
2315
2316int
a072d43b 2317expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
6c7cf1f0
UB
2318 int unsignedp)
2319{
ef4bddc2 2320 machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
d858f359 2321 enum mode_class mclass;
ef4bddc2 2322 machine_mode wider_mode;
38295e01
DM
2323 rtx_insn *entry_last = get_last_insn ();
2324 rtx_insn *last;
6c7cf1f0 2325
d858f359 2326 mclass = GET_MODE_CLASS (mode);
6c7cf1f0 2327
ad76cef8 2328 if (!targ0)
6c7cf1f0 2329 targ0 = gen_reg_rtx (mode);
ad76cef8 2330 if (!targ1)
6c7cf1f0
UB
2331 targ1 = gen_reg_rtx (mode);
2332
2333 /* Record where to go back to if we fail. */
2334 last = get_last_insn ();
2335
947131ba 2336 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
6c7cf1f0 2337 {
a5c7d693
RS
2338 struct expand_operand ops[3];
2339 enum insn_code icode = optab_handler (unoptab, mode);
6c7cf1f0 2340
a5c7d693
RS
2341 create_fixed_operand (&ops[0], targ0);
2342 create_fixed_operand (&ops[1], targ1);
2343 create_convert_operand_from (&ops[2], op0, mode, unsignedp);
2344 if (maybe_expand_insn (icode, 3, ops))
2345 return 1;
6c7cf1f0
UB
2346 }
2347
2348 /* It can't be done in this mode. Can we do it in a wider mode? */
2349
d858f359 2350 if (CLASS_HAS_WIDER_MODES_P (mclass))
6c7cf1f0 2351 {
86556d87
BE
2352 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2353 wider_mode != VOIDmode;
6c7cf1f0
UB
2354 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2355 {
947131ba 2356 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
6c7cf1f0
UB
2357 {
2358 rtx t0 = gen_reg_rtx (wider_mode);
2359 rtx t1 = gen_reg_rtx (wider_mode);
2360 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2361
a072d43b 2362 if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
6c7cf1f0
UB
2363 {
2364 convert_move (targ0, t0, unsignedp);
2365 convert_move (targ1, t1, unsignedp);
2366 return 1;
2367 }
2368 else
2369 delete_insns_since (last);
2370 }
2371 }
2372 }
2373
2374 delete_insns_since (entry_last);
2375 return 0;
2376}
2377\f
77c9c6c2
RK
2378/* Generate code to perform an operation specified by BINOPTAB
2379 on operands OP0 and OP1, with two results to TARG1 and TARG2.
2380 We assume that the order of the operands for the instruction
2381 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2382 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2383
2384 Either TARG0 or TARG1 may be zero, but what that means is that
38e01259 2385 the result is not actually wanted. We will generate it into
77c9c6c2
RK
2386 a dummy pseudo-reg and discard it. They may not both be zero.
2387
2388 Returns 1 if this operation can be performed; 0 if not. */
2389
2390int
0c20a65f
AJ
2391expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
2392 int unsignedp)
77c9c6c2 2393{
ef4bddc2 2394 machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
d858f359 2395 enum mode_class mclass;
ef4bddc2 2396 machine_mode wider_mode;
38295e01
DM
2397 rtx_insn *entry_last = get_last_insn ();
2398 rtx_insn *last;
77c9c6c2 2399
d858f359 2400 mclass = GET_MODE_CLASS (mode);
77c9c6c2 2401
ad76cef8 2402 if (!targ0)
77c9c6c2 2403 targ0 = gen_reg_rtx (mode);
ad76cef8 2404 if (!targ1)
77c9c6c2
RK
2405 targ1 = gen_reg_rtx (mode);
2406
2407 /* Record where to go back to if we fail. */
2408 last = get_last_insn ();
2409
947131ba 2410 if (optab_handler (binoptab, mode) != CODE_FOR_nothing)
77c9c6c2 2411 {
a5c7d693
RS
2412 struct expand_operand ops[4];
2413 enum insn_code icode = optab_handler (binoptab, mode);
ef4bddc2
RS
2414 machine_mode mode0 = insn_data[icode].operand[1].mode;
2415 machine_mode mode1 = insn_data[icode].operand[2].mode;
77c9c6c2
RK
2416 rtx xop0 = op0, xop1 = op1;
2417
62442ab9 2418 /* If we are optimizing, force expensive constants into a register. */
68f932c4
RS
2419 xop0 = avoid_expensive_constant (mode0, binoptab, 0, xop0, unsignedp);
2420 xop1 = avoid_expensive_constant (mode1, binoptab, 1, xop1, unsignedp);
62442ab9 2421
a5c7d693
RS
2422 create_fixed_operand (&ops[0], targ0);
2423 create_convert_operand_from (&ops[1], op0, mode, unsignedp);
2424 create_convert_operand_from (&ops[2], op1, mode, unsignedp);
2425 create_fixed_operand (&ops[3], targ1);
2426 if (maybe_expand_insn (icode, 4, ops))
2427 return 1;
2428 delete_insns_since (last);
77c9c6c2
RK
2429 }
2430
2431 /* It can't be done in this mode. Can we do it in a wider mode? */
2432
d858f359 2433 if (CLASS_HAS_WIDER_MODES_P (mclass))
77c9c6c2 2434 {
86556d87
BE
2435 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2436 wider_mode != VOIDmode;
77c9c6c2
RK
2437 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2438 {
947131ba 2439 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing)
77c9c6c2 2440 {
b3694847
SS
2441 rtx t0 = gen_reg_rtx (wider_mode);
2442 rtx t1 = gen_reg_rtx (wider_mode);
76791f3d
JH
2443 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2444 rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
77c9c6c2 2445
76791f3d 2446 if (expand_twoval_binop (binoptab, cop0, cop1,
77c9c6c2
RK
2447 t0, t1, unsignedp))
2448 {
2449 convert_move (targ0, t0, unsignedp);
2450 convert_move (targ1, t1, unsignedp);
2451 return 1;
2452 }
2453 else
2454 delete_insns_since (last);
2455 }
2456 }
2457 }
2458
abd418d3 2459 delete_insns_since (entry_last);
77c9c6c2
RK
2460 return 0;
2461}
b3f8d95d
MM
2462
2463/* Expand the two-valued library call indicated by BINOPTAB, but
2464 preserve only one of the values. If TARG0 is non-NULL, the first
2465 value is placed into TARG0; otherwise the second value is placed
2466 into TARG1. Exactly one of TARG0 and TARG1 must be non-NULL. The
2467 value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
2468 This routine assumes that the value returned by the library call is
2469 as if the return value was of an integral mode twice as wide as the
2470 mode of OP0. Returns 1 if the call was successful. */
2471
2472bool
5906d013 2473expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
b3f8d95d
MM
2474 rtx targ0, rtx targ1, enum rtx_code code)
2475{
ef4bddc2
RS
2476 machine_mode mode;
2477 machine_mode libval_mode;
b3f8d95d 2478 rtx libval;
38295e01 2479 rtx_insn *insns;
8a33f100 2480 rtx libfunc;
5906d013 2481
b3f8d95d 2482 /* Exactly one of TARG0 or TARG1 should be non-NULL. */
e3feb571 2483 gcc_assert (!targ0 != !targ1);
b3f8d95d
MM
2484
2485 mode = GET_MODE (op0);
8a33f100
JH
2486 libfunc = optab_libfunc (binoptab, mode);
2487 if (!libfunc)
b3f8d95d
MM
2488 return false;
2489
2490 /* The value returned by the library function will have twice as
2491 many bits as the nominal MODE. */
5906d013 2492 libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
b3f8d95d
MM
2493 MODE_INT);
2494 start_sequence ();
8a33f100 2495 libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
b3f8d95d 2496 libval_mode, 2,
5906d013 2497 op0, mode,
b3f8d95d
MM
2498 op1, mode);
2499 /* Get the part of VAL containing the value that we want. */
2500 libval = simplify_gen_subreg (mode, libval, libval_mode,
2501 targ0 ? 0 : GET_MODE_SIZE (mode));
2502 insns = get_insns ();
2503 end_sequence ();
2504 /* Move the into the desired location. */
5906d013 2505 emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
b3f8d95d 2506 gen_rtx_fmt_ee (code, mode, op0, op1));
5906d013 2507
b3f8d95d
MM
2508 return true;
2509}
2510
77c9c6c2 2511\f
ef89d648
ZW
2512/* Wrapper around expand_unop which takes an rtx code to specify
2513 the operation to perform, not an optab pointer. All other
2514 arguments are the same. */
2515rtx
ef4bddc2 2516expand_simple_unop (machine_mode mode, enum rtx_code code, rtx op0,
0c20a65f 2517 rtx target, int unsignedp)
ef89d648 2518{
19b5fafb 2519 optab unop = code_to_optab (code);
e3feb571 2520 gcc_assert (unop);
ef89d648
ZW
2521
2522 return expand_unop (mode, unop, op0, target, unsignedp);
2523}
2524
2928cd7a
RH
2525/* Try calculating
2526 (clz:narrow x)
2527 as
3801c801
BS
2528 (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)).
2529
2530 A similar operation can be used for clrsb. UNOPTAB says which operation
2531 we are trying to expand. */
2928cd7a 2532static rtx
ef4bddc2 2533widen_leading (machine_mode mode, rtx op0, rtx target, optab unoptab)
2928cd7a 2534{
d858f359
KG
2535 enum mode_class mclass = GET_MODE_CLASS (mode);
2536 if (CLASS_HAS_WIDER_MODES_P (mclass))
2928cd7a 2537 {
ef4bddc2 2538 machine_mode wider_mode;
86556d87
BE
2539 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2540 wider_mode != VOIDmode;
2928cd7a
RH
2541 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2542 {
3801c801 2543 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
2928cd7a 2544 {
38295e01
DM
2545 rtx xop0, temp;
2546 rtx_insn *last;
2928cd7a
RH
2547
2548 last = get_last_insn ();
2549
2550 if (target == 0)
2551 target = gen_reg_rtx (mode);
146aef0b
JJ
2552 xop0 = widen_operand (op0, wider_mode, mode,
2553 unoptab != clrsb_optab, false);
2554 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2555 unoptab != clrsb_optab);
2928cd7a 2556 if (temp != 0)
2f1cd2eb
RS
2557 temp = expand_binop
2558 (wider_mode, sub_optab, temp,
2559 gen_int_mode (GET_MODE_PRECISION (wider_mode)
2560 - GET_MODE_PRECISION (mode),
2561 wider_mode),
2562 target, true, OPTAB_DIRECT);
2928cd7a
RH
2563 if (temp == 0)
2564 delete_insns_since (last);
2565
2566 return temp;
2567 }
2568 }
2569 }
2570 return 0;
2571}
2572
9cce5b20
ZW
2573/* Try calculating clz of a double-word quantity as two clz's of word-sized
2574 quantities, choosing which based on whether the high word is nonzero. */
2575static rtx
ef4bddc2 2576expand_doubleword_clz (machine_mode mode, rtx op0, rtx target)
9cce5b20
ZW
2577{
2578 rtx xop0 = force_reg (mode, op0);
2579 rtx subhi = gen_highpart (word_mode, xop0);
2580 rtx sublo = gen_lowpart (word_mode, xop0);
38295e01
DM
2581 rtx_code_label *hi0_label = gen_label_rtx ();
2582 rtx_code_label *after_label = gen_label_rtx ();
2583 rtx_insn *seq;
2584 rtx temp, result;
9cce5b20
ZW
2585
2586 /* If we were not given a target, use a word_mode register, not a
2587 'mode' register. The result will fit, and nobody is expecting
2588 anything bigger (the return type of __builtin_clz* is int). */
2589 if (!target)
2590 target = gen_reg_rtx (word_mode);
2591
2592 /* In any case, write to a word_mode scratch in both branches of the
2593 conditional, so we can ensure there is a single move insn setting
2594 'target' to tag a REG_EQUAL note on. */
2595 result = gen_reg_rtx (word_mode);
2596
2597 start_sequence ();
2598
2599 /* If the high word is not equal to zero,
2600 then clz of the full value is clz of the high word. */
2601 emit_cmp_and_jump_insns (subhi, CONST0_RTX (word_mode), EQ, 0,
2602 word_mode, true, hi0_label);
2603
2604 temp = expand_unop_direct (word_mode, clz_optab, subhi, result, true);
2605 if (!temp)
2606 goto fail;
2607
2608 if (temp != result)
2609 convert_move (result, temp, true);
2610
2611 emit_jump_insn (gen_jump (after_label));
2612 emit_barrier ();
2613
2614 /* Else clz of the full value is clz of the low word plus the number
2615 of bits in the high word. */
2616 emit_label (hi0_label);
2617
2618 temp = expand_unop_direct (word_mode, clz_optab, sublo, 0, true);
2619 if (!temp)
2620 goto fail;
2621 temp = expand_binop (word_mode, add_optab, temp,
2f1cd2eb 2622 gen_int_mode (GET_MODE_BITSIZE (word_mode), word_mode),
9cce5b20
ZW
2623 result, true, OPTAB_DIRECT);
2624 if (!temp)
2625 goto fail;
2626 if (temp != result)
2627 convert_move (result, temp, true);
2628
2629 emit_label (after_label);
2630 convert_move (target, result, true);
2631
2632 seq = get_insns ();
2633 end_sequence ();
2634
2635 add_equal_note (seq, target, CLZ, xop0, 0);
2636 emit_insn (seq);
2637 return target;
2638
2639 fail:
2640 end_sequence ();
2641 return 0;
2642}
2643
2e6834d3
RH
2644/* Try calculating
2645 (bswap:narrow x)
2646 as
2647 (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */
2648static rtx
ef4bddc2 2649widen_bswap (machine_mode mode, rtx op0, rtx target)
2e6834d3 2650{
d858f359 2651 enum mode_class mclass = GET_MODE_CLASS (mode);
ef4bddc2 2652 machine_mode wider_mode;
38295e01
DM
2653 rtx x;
2654 rtx_insn *last;
2e6834d3 2655
d858f359 2656 if (!CLASS_HAS_WIDER_MODES_P (mclass))
2e6834d3
RH
2657 return NULL_RTX;
2658
2659 for (wider_mode = GET_MODE_WIDER_MODE (mode);
2660 wider_mode != VOIDmode;
2661 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
947131ba 2662 if (optab_handler (bswap_optab, wider_mode) != CODE_FOR_nothing)
2e6834d3
RH
2663 goto found;
2664 return NULL_RTX;
2665
2666 found:
2667 last = get_last_insn ();
2668
2669 x = widen_operand (op0, wider_mode, mode, true, true);
2670 x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
2671
0d44736e
BS
2672 gcc_assert (GET_MODE_PRECISION (wider_mode) == GET_MODE_BITSIZE (wider_mode)
2673 && GET_MODE_PRECISION (mode) == GET_MODE_BITSIZE (mode));
2e6834d3
RH
2674 if (x != 0)
2675 x = expand_shift (RSHIFT_EXPR, wider_mode, x,
eb6c3df1
RG
2676 GET_MODE_BITSIZE (wider_mode)
2677 - GET_MODE_BITSIZE (mode),
2e6834d3
RH
2678 NULL_RTX, true);
2679
2680 if (x != 0)
2681 {
2682 if (target == 0)
2683 target = gen_reg_rtx (mode);
2684 emit_move_insn (target, gen_lowpart (mode, x));
2685 }
2686 else
2687 delete_insns_since (last);
2688
2689 return target;
2690}
2691
2692/* Try calculating bswap as two bswaps of two word-sized operands. */
2693
2694static rtx
ef4bddc2 2695expand_doubleword_bswap (machine_mode mode, rtx op, rtx target)
2e6834d3
RH
2696{
2697 rtx t0, t1;
2698
2699 t1 = expand_unop (word_mode, bswap_optab,
2700 operand_subword_force (op, 0, mode), NULL_RTX, true);
2701 t0 = expand_unop (word_mode, bswap_optab,
2702 operand_subword_force (op, 1, mode), NULL_RTX, true);
2703
02972eaf 2704 if (target == 0 || !valid_multiword_target_p (target))
2e6834d3
RH
2705 target = gen_reg_rtx (mode);
2706 if (REG_P (target))
c41c1387 2707 emit_clobber (target);
2e6834d3
RH
2708 emit_move_insn (operand_subword (target, 0, 1, mode), t0);
2709 emit_move_insn (operand_subword (target, 1, 1, mode), t1);
2710
2711 return target;
2712}
2713
2928cd7a
RH
2714/* Try calculating (parity x) as (and (popcount x) 1), where
2715 popcount can also be done in a wider mode. */
2716static rtx
ef4bddc2 2717expand_parity (machine_mode mode, rtx op0, rtx target)
2928cd7a 2718{
d858f359
KG
2719 enum mode_class mclass = GET_MODE_CLASS (mode);
2720 if (CLASS_HAS_WIDER_MODES_P (mclass))
2928cd7a 2721 {
ef4bddc2 2722 machine_mode wider_mode;
2928cd7a
RH
2723 for (wider_mode = mode; wider_mode != VOIDmode;
2724 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
2725 {
947131ba 2726 if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
2928cd7a 2727 {
38295e01
DM
2728 rtx xop0, temp;
2729 rtx_insn *last;
2928cd7a
RH
2730
2731 last = get_last_insn ();
2732
2733 if (target == 0)
2734 target = gen_reg_rtx (mode);
2735 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2736 temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
2737 true);
2738 if (temp != 0)
60c81c89 2739 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
2928cd7a
RH
2740 target, true, OPTAB_DIRECT);
2741 if (temp == 0)
2742 delete_insns_since (last);
2743
2744 return temp;
2745 }
2746 }
2747 }
2748 return 0;
2749}
2750
9cce5b20 2751/* Try calculating ctz(x) as K - clz(x & -x) ,
69660a70 2752 where K is GET_MODE_PRECISION(mode) - 1.
9cce5b20
ZW
2753
2754 Both __builtin_ctz and __builtin_clz are undefined at zero, so we
2755 don't have to worry about what the hardware does in that case. (If
2756 the clz instruction produces the usual value at 0, which is K, the
2757 result of this code sequence will be -1; expand_ffs, below, relies
2758 on this. It might be nice to have it be K instead, for consistency
2759 with the (very few) processors that provide a ctz with a defined
2760 value, but that would take one more instruction, and it would be
2761 less convenient for expand_ffs anyway. */
2762
14670a74 2763static rtx
ef4bddc2 2764expand_ctz (machine_mode mode, rtx op0, rtx target)
14670a74 2765{
38295e01
DM
2766 rtx_insn *seq;
2767 rtx temp;
b8698a0f 2768
947131ba 2769 if (optab_handler (clz_optab, mode) == CODE_FOR_nothing)
9cce5b20 2770 return 0;
b8698a0f 2771
9cce5b20 2772 start_sequence ();
14670a74 2773
9cce5b20
ZW
2774 temp = expand_unop_direct (mode, neg_optab, op0, NULL_RTX, true);
2775 if (temp)
2776 temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
2777 true, OPTAB_DIRECT);
2778 if (temp)
2779 temp = expand_unop_direct (mode, clz_optab, temp, NULL_RTX, true);
2780 if (temp)
2f1cd2eb
RS
2781 temp = expand_binop (mode, sub_optab,
2782 gen_int_mode (GET_MODE_PRECISION (mode) - 1, mode),
9cce5b20
ZW
2783 temp, target,
2784 true, OPTAB_DIRECT);
2785 if (temp == 0)
2786 {
2787 end_sequence ();
2788 return 0;
14670a74 2789 }
9cce5b20
ZW
2790
2791 seq = get_insns ();
2792 end_sequence ();
2793
2794 add_equal_note (seq, temp, CTZ, op0, 0);
2795 emit_insn (seq);
2796 return temp;
14670a74
SL
2797}
2798
9cce5b20
ZW
2799
2800/* Try calculating ffs(x) using ctz(x) if we have that instruction, or
2801 else with the sequence used by expand_clz.
b8698a0f 2802
9cce5b20
ZW
2803 The ffs builtin promises to return zero for a zero value and ctz/clz
2804 may have an undefined value in that case. If they do not give us a
2805 convenient value, we have to generate a test and branch. */
14670a74 2806static rtx
ef4bddc2 2807expand_ffs (machine_mode mode, rtx op0, rtx target)
14670a74 2808{
a3324f26
ZW
2809 HOST_WIDE_INT val = 0;
2810 bool defined_at_zero = false;
38295e01
DM
2811 rtx temp;
2812 rtx_insn *seq;
9cce5b20 2813
947131ba 2814 if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing)
14670a74 2815 {
9cce5b20 2816 start_sequence ();
14670a74 2817
9cce5b20
ZW
2818 temp = expand_unop_direct (mode, ctz_optab, op0, 0, true);
2819 if (!temp)
2820 goto fail;
2821
2822 defined_at_zero = (CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2);
14670a74 2823 }
947131ba 2824 else if (optab_handler (clz_optab, mode) != CODE_FOR_nothing)
9cce5b20
ZW
2825 {
2826 start_sequence ();
2827 temp = expand_ctz (mode, op0, 0);
2828 if (!temp)
2829 goto fail;
2830
2831 if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
2832 {
2833 defined_at_zero = true;
69660a70 2834 val = (GET_MODE_PRECISION (mode) - 1) - val;
9cce5b20
ZW
2835 }
2836 }
2837 else
2838 return 0;
2839
2840 if (defined_at_zero && val == -1)
2841 /* No correction needed at zero. */;
b8698a0f 2842 else
9cce5b20
ZW
2843 {
2844 /* We don't try to do anything clever with the situation found
2845 on some processors (eg Alpha) where ctz(0:mode) ==
2846 bitsize(mode). If someone can think of a way to send N to -1
2847 and leave alone all values in the range 0..N-1 (where N is a
2848 power of two), cheaper than this test-and-branch, please add it.
2849
2850 The test-and-branch is done after the operation itself, in case
2851 the operation sets condition codes that can be recycled for this.
2852 (This is true on i386, for instance.) */
2853
38295e01 2854 rtx_code_label *nonzero_label = gen_label_rtx ();
9cce5b20
ZW
2855 emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
2856 mode, true, nonzero_label);
2857
2858 convert_move (temp, GEN_INT (-1), false);
2859 emit_label (nonzero_label);
2860 }
2861
2862 /* temp now has a value in the range -1..bitsize-1. ffs is supposed
2863 to produce a value in the range 0..bitsize. */
2f1cd2eb 2864 temp = expand_binop (mode, add_optab, temp, gen_int_mode (1, mode),
9cce5b20
ZW
2865 target, false, OPTAB_DIRECT);
2866 if (!temp)
2867 goto fail;
2868
2869 seq = get_insns ();
2870 end_sequence ();
2871
2872 add_equal_note (seq, temp, FFS, op0, 0);
2873 emit_insn (seq);
2874 return temp;
2875
2876 fail:
2877 end_sequence ();
14670a74
SL
2878 return 0;
2879}
2880
c414ac1d 2881/* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
6b132673
RH
2882 conditions, VAL may already be a SUBREG against which we cannot generate
2883 a further SUBREG. In this case, we expect forcing the value into a
2884 register will work around the situation. */
2885
2886static rtx
ef4bddc2
RS
2887lowpart_subreg_maybe_copy (machine_mode omode, rtx val,
2888 machine_mode imode)
6b132673
RH
2889{
2890 rtx ret;
2891 ret = lowpart_subreg (omode, val, imode);
2892 if (ret == NULL)
2893 {
2894 val = force_reg (imode, val);
2895 ret = lowpart_subreg (omode, val, imode);
2896 gcc_assert (ret != NULL);
2897 }
2898 return ret;
2899}
2900
8c55a142
RH
2901/* Expand a floating point absolute value or negation operation via a
2902 logical operation on the sign bit. */
2903
2904static rtx
ef4bddc2 2905expand_absneg_bit (enum rtx_code code, machine_mode mode,
8c55a142
RH
2906 rtx op0, rtx target)
2907{
2908 const struct real_format *fmt;
2909 int bitpos, word, nwords, i;
ef4bddc2 2910 machine_mode imode;
38295e01
DM
2911 rtx temp;
2912 rtx_insn *insns;
8c55a142
RH
2913
2914 /* The format has to have a simple sign bit. */
2915 fmt = REAL_MODE_FORMAT (mode);
2916 if (fmt == NULL)
2917 return NULL_RTX;
2918
b87a0206 2919 bitpos = fmt->signbit_rw;
8c55a142
RH
2920 if (bitpos < 0)
2921 return NULL_RTX;
2922
2923 /* Don't create negative zeros if the format doesn't support them. */
2924 if (code == NEG && !fmt->has_signed_zero)
2925 return NULL_RTX;
2926
2927 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
2928 {
2929 imode = int_mode_for_mode (mode);
2930 if (imode == BLKmode)
2931 return NULL_RTX;
2932 word = 0;
2933 nwords = 1;
2934 }
2935 else
2936 {
2937 imode = word_mode;
2938
2939 if (FLOAT_WORDS_BIG_ENDIAN)
2940 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
2941 else
2942 word = bitpos / BITS_PER_WORD;
2943 bitpos = bitpos % BITS_PER_WORD;
2944 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
2945 }
2946
807e902e 2947 wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
8c55a142 2948 if (code == ABS)
27bcd47c 2949 mask = ~mask;
8c55a142 2950
02972eaf
RS
2951 if (target == 0
2952 || target == op0
2953 || (nwords > 1 && !valid_multiword_target_p (target)))
8c55a142
RH
2954 target = gen_reg_rtx (mode);
2955
2956 if (nwords > 1)
2957 {
2958 start_sequence ();
2959
2960 for (i = 0; i < nwords; ++i)
2961 {
2962 rtx targ_piece = operand_subword (target, i, 1, mode);
2963 rtx op0_piece = operand_subword_force (op0, i, mode);
c414ac1d 2964
8c55a142
RH
2965 if (i == word)
2966 {
2967 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2968 op0_piece,
807e902e 2969 immed_wide_int_const (mask, imode),
8c55a142
RH
2970 targ_piece, 1, OPTAB_LIB_WIDEN);
2971 if (temp != targ_piece)
2972 emit_move_insn (targ_piece, temp);
2973 }
2974 else
2975 emit_move_insn (targ_piece, op0_piece);
2976 }
2977
2978 insns = get_insns ();
2979 end_sequence ();
2980
d70dcf29 2981 emit_insn (insns);
8c55a142
RH
2982 }
2983 else
2984 {
2985 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2986 gen_lowpart (imode, op0),
807e902e 2987 immed_wide_int_const (mask, imode),
8c55a142
RH
2988 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
2989 target = lowpart_subreg_maybe_copy (mode, temp, imode);
2990
7543f918
JR
2991 set_dst_reg_note (get_last_insn (), REG_EQUAL,
2992 gen_rtx_fmt_e (code, mode, copy_rtx (op0)),
2993 target);
8c55a142
RH
2994 }
2995
2996 return target;
2997}
2998
9cce5b20
ZW
2999/* As expand_unop, but will fail rather than attempt the operation in a
3000 different mode or with a libcall. */
3001static rtx
ef4bddc2 3002expand_unop_direct (machine_mode mode, optab unoptab, rtx op0, rtx target,
0c20a65f 3003 int unsignedp)
77c9c6c2 3004{
947131ba 3005 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
77c9c6c2 3006 {
a5c7d693
RS
3007 struct expand_operand ops[2];
3008 enum insn_code icode = optab_handler (unoptab, mode);
38295e01 3009 rtx_insn *last = get_last_insn ();
a5c7d693 3010 rtx pat;
77c9c6c2 3011
a5c7d693
RS
3012 create_output_operand (&ops[0], target, mode);
3013 create_convert_operand_from (&ops[1], op0, mode, unsignedp);
3014 pat = maybe_gen_insn (icode, 2, ops);
77c9c6c2
RK
3015 if (pat)
3016 {
dc01c3d1
DM
3017 if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX
3018 && ! add_equal_note (as_a <rtx_insn *> (pat), ops[0].value,
3019 optab_to_code (unoptab),
a5c7d693 3020 ops[1].value, NULL_RTX))
77c9c6c2
RK
3021 {
3022 delete_insns_since (last);
b1ec3c92 3023 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
77c9c6c2
RK
3024 }
3025
3026 emit_insn (pat);
0c20a65f 3027
a5c7d693 3028 return ops[0].value;
77c9c6c2 3029 }
77c9c6c2 3030 }
9cce5b20
ZW
3031 return 0;
3032}
3033
3034/* Generate code to perform an operation specified by UNOPTAB
3035 on operand OP0, with result having machine-mode MODE.
3036
3037 UNSIGNEDP is for the case where we have to widen the operands
3038 to perform the operation. It says to use zero-extension.
3039
3040 If TARGET is nonzero, the value
3041 is generated there, if it is convenient to do so.
3042 In all cases an rtx is returned for the locus of the value;
3043 this may or may not be TARGET. */
3044
3045rtx
ef4bddc2 3046expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
9cce5b20
ZW
3047 int unsignedp)
3048{
d858f359 3049 enum mode_class mclass = GET_MODE_CLASS (mode);
ef4bddc2 3050 machine_mode wider_mode;
9cce5b20 3051 rtx temp;
8a33f100 3052 rtx libfunc;
9cce5b20
ZW
3053
3054 temp = expand_unop_direct (mode, unoptab, op0, target, unsignedp);
3055 if (temp)
3056 return temp;
77c9c6c2 3057
9a856ec7
RK
3058 /* It can't be done in this mode. Can we open-code it in a wider mode? */
3059
9cce5b20 3060 /* Widening (or narrowing) clz needs special treatment. */
2928cd7a
RH
3061 if (unoptab == clz_optab)
3062 {
3801c801 3063 temp = widen_leading (mode, op0, target, unoptab);
2928cd7a
RH
3064 if (temp)
3065 return temp;
9cce5b20
ZW
3066
3067 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
947131ba 3068 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
9cce5b20
ZW
3069 {
3070 temp = expand_doubleword_clz (mode, op0, target);
3071 if (temp)
3072 return temp;
3073 }
3074
3801c801
BS
3075 goto try_libcall;
3076 }
3077
3078 if (unoptab == clrsb_optab)
3079 {
3080 temp = widen_leading (mode, op0, target, unoptab);
3081 if (temp)
3082 return temp;
3083 goto try_libcall;
2928cd7a
RH
3084 }
3085
2e6834d3 3086 /* Widening (or narrowing) bswap needs special treatment. */
167fa32c 3087 if (unoptab == bswap_optab)
2e6834d3 3088 {
ac868f29
EB
3089 /* HImode is special because in this mode BSWAP is equivalent to ROTATE
3090 or ROTATERT. First try these directly; if this fails, then try the
3091 obvious pair of shifts with allowed widening, as this will probably
3092 be always more efficient than the other fallback methods. */
3093 if (mode == HImode)
3094 {
38295e01
DM
3095 rtx_insn *last;
3096 rtx temp1, temp2;
ac868f29
EB
3097
3098 if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing)
3099 {
3100 temp = expand_binop (mode, rotl_optab, op0, GEN_INT (8), target,
3101 unsignedp, OPTAB_DIRECT);
3102 if (temp)
3103 return temp;
3104 }
3105
3106 if (optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
3107 {
3108 temp = expand_binop (mode, rotr_optab, op0, GEN_INT (8), target,
3109 unsignedp, OPTAB_DIRECT);
3110 if (temp)
3111 return temp;
3112 }
3113
3114 last = get_last_insn ();
3115
3116 temp1 = expand_binop (mode, ashl_optab, op0, GEN_INT (8), NULL_RTX,
3117 unsignedp, OPTAB_WIDEN);
3118 temp2 = expand_binop (mode, lshr_optab, op0, GEN_INT (8), NULL_RTX,
3119 unsignedp, OPTAB_WIDEN);
3120 if (temp1 && temp2)
3121 {
3122 temp = expand_binop (mode, ior_optab, temp1, temp2, target,
3123 unsignedp, OPTAB_WIDEN);
3124 if (temp)
3125 return temp;
3126 }
3127
3128 delete_insns_since (last);
3129 }
3130
2e6834d3
RH
3131 temp = widen_bswap (mode, op0, target);
3132 if (temp)
3133 return temp;
3134
3135 if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
947131ba 3136 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
2e6834d3
RH
3137 {
3138 temp = expand_doubleword_bswap (mode, op0, target);
3139 if (temp)
3140 return temp;
3141 }
3142
3143 goto try_libcall;
3144 }
167fa32c 3145
d858f359 3146 if (CLASS_HAS_WIDER_MODES_P (mclass))
86556d87
BE
3147 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3148 wider_mode != VOIDmode;
9a856ec7
RK
3149 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3150 {
947131ba 3151 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
9a856ec7
RK
3152 {
3153 rtx xop0 = op0;
38295e01 3154 rtx_insn *last = get_last_insn ();
9a856ec7
RK
3155
3156 /* For certain operations, we need not actually extend
3157 the narrow operand, as long as we will truncate the
835532b8
RK
3158 results to the same narrowness. */
3159
0661a3de 3160 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
835532b8
RK
3161 (unoptab == neg_optab
3162 || unoptab == one_cmpl_optab)
d858f359 3163 && mclass == MODE_INT);
0c20a65f 3164
b1ec3c92
CH
3165 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3166 unsignedp);
9a856ec7
RK
3167
3168 if (temp)
3169 {
d858f359 3170 if (mclass != MODE_INT
d0edd768 3171 || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
9a856ec7
RK
3172 {
3173 if (target == 0)
3174 target = gen_reg_rtx (mode);
3175 convert_move (target, temp, 0);
3176 return target;
3177 }
3178 else
3179 return gen_lowpart (mode, temp);
3180 }
3181 else
3182 delete_insns_since (last);
3183 }
3184 }
3185
77c9c6c2
RK
3186 /* These can be done a word at a time. */
3187 if (unoptab == one_cmpl_optab
d858f359 3188 && mclass == MODE_INT
77c9c6c2 3189 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
947131ba 3190 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
77c9c6c2 3191 {
bb93b973 3192 int i;
38295e01 3193 rtx_insn *insns;
77c9c6c2 3194
02972eaf 3195 if (target == 0 || target == op0 || !valid_multiword_target_p (target))
77c9c6c2
RK
3196 target = gen_reg_rtx (mode);
3197
3198 start_sequence ();
3199
3200 /* Do the actual arithmetic. */
3201 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
3202 {
3203 rtx target_piece = operand_subword (target, i, 1, mode);
34e56753 3204 rtx x = expand_unop (word_mode, unoptab,
77c9c6c2
RK
3205 operand_subword_force (op0, i, mode),
3206 target_piece, unsignedp);
bb93b973 3207
77c9c6c2
RK
3208 if (target_piece != x)
3209 emit_move_insn (target_piece, x);
3210 }
3211
3212 insns = get_insns ();
3213 end_sequence ();
3214
d70dcf29 3215 emit_insn (insns);
77c9c6c2
RK
3216 return target;
3217 }
3218
19b5fafb 3219 if (optab_to_code (unoptab) == NEG)
4977bab6 3220 {
8c55a142 3221 /* Try negating floating point values by flipping the sign bit. */
74b14698 3222 if (SCALAR_FLOAT_MODE_P (mode))
4977bab6 3223 {
8c55a142
RH
3224 temp = expand_absneg_bit (NEG, mode, op0, target);
3225 if (temp)
3226 return temp;
3227 }
9ee0a442 3228
8c55a142
RH
3229 /* If there is no negation pattern, and we have no negative zero,
3230 try subtracting from zero. */
3231 if (!HONOR_SIGNED_ZEROS (mode))
3232 {
3233 temp = expand_binop (mode, (unoptab == negv_optab
3234 ? subv_optab : sub_optab),
3235 CONST0_RTX (mode), op0, target,
3236 unsignedp, OPTAB_DIRECT);
3237 if (temp)
3238 return temp;
3239 }
4977bab6
ZW
3240 }
3241
2928cd7a
RH
3242 /* Try calculating parity (x) as popcount (x) % 2. */
3243 if (unoptab == parity_optab)
3244 {
3245 temp = expand_parity (mode, op0, target);
3246 if (temp)
3247 return temp;
3248 }
3249
14670a74
SL
3250 /* Try implementing ffs (x) in terms of clz (x). */
3251 if (unoptab == ffs_optab)
3252 {
3253 temp = expand_ffs (mode, op0, target);
3254 if (temp)
3255 return temp;
3256 }
3257
3258 /* Try implementing ctz (x) in terms of clz (x). */
3259 if (unoptab == ctz_optab)
3260 {
3261 temp = expand_ctz (mode, op0, target);
3262 if (temp)
3263 return temp;
3264 }
3265
2928cd7a 3266 try_libcall:
139e5e08 3267 /* Now try a library call in this mode. */
8a33f100
JH
3268 libfunc = optab_libfunc (unoptab, mode);
3269 if (libfunc)
77c9c6c2 3270 {
38295e01 3271 rtx_insn *insns;
9a7f678c 3272 rtx value;
1230d7f8 3273 rtx eq_value;
ef4bddc2 3274 machine_mode outmode = mode;
2928cd7a
RH
3275
3276 /* All of these functions return small values. Thus we choose to
3277 have them return something that isn't a double-word. */
3278 if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
3801c801
BS
3279 || unoptab == clrsb_optab || unoptab == popcount_optab
3280 || unoptab == parity_optab)
cd2ac05b 3281 outmode
390b17c2
RE
3282 = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
3283 optab_libfunc (unoptab, mode)));
77c9c6c2
RK
3284
3285 start_sequence ();
3286
3287 /* Pass 1 for NO_QUEUE so we don't lose any increments
3288 if the libcall is cse'd or moved. */
8a33f100 3289 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, outmode,
2928cd7a 3290 1, op0, mode);
77c9c6c2
RK
3291 insns = get_insns ();
3292 end_sequence ();
3293
2928cd7a 3294 target = gen_reg_rtx (outmode);
19b5fafb 3295 eq_value = gen_rtx_fmt_e (optab_to_code (unoptab), mode, op0);
1230d7f8
RS
3296 if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
3297 eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
3298 else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
3299 eq_value = simplify_gen_unary (ZERO_EXTEND, outmode, eq_value, mode);
b55f62cc
RG
3300 emit_libcall_block_1 (insns, target, value, eq_value,
3301 trapv_unoptab_p (unoptab));
77c9c6c2
RK
3302
3303 return target;
3304 }
3305
3306 /* It can't be done in this mode. Can we do it in a wider mode? */
3307
d858f359 3308 if (CLASS_HAS_WIDER_MODES_P (mclass))
77c9c6c2 3309 {
86556d87
BE
3310 for (wider_mode = GET_MODE_WIDER_MODE (mode);
3311 wider_mode != VOIDmode;
77c9c6c2
RK
3312 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
3313 {
947131ba 3314 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing
8a33f100 3315 || optab_libfunc (unoptab, wider_mode))
77c9c6c2 3316 {
34e56753 3317 rtx xop0 = op0;
38295e01 3318 rtx_insn *last = get_last_insn ();
34e56753
RS
3319
3320 /* For certain operations, we need not actually extend
3321 the narrow operand, as long as we will truncate the
3322 results to the same narrowness. */
0661a3de 3323 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
835532b8 3324 (unoptab == neg_optab
ac868f29
EB
3325 || unoptab == one_cmpl_optab
3326 || unoptab == bswap_optab)
d858f359 3327 && mclass == MODE_INT);
0c20a65f 3328
b1ec3c92
CH
3329 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3330 unsignedp);
34e56753 3331
c117dddc 3332 /* If we are generating clz using wider mode, adjust the
146aef0b
JJ
3333 result. Similarly for clrsb. */
3334 if ((unoptab == clz_optab || unoptab == clrsb_optab)
3335 && temp != 0)
2f1cd2eb
RS
3336 temp = expand_binop
3337 (wider_mode, sub_optab, temp,
3338 gen_int_mode (GET_MODE_PRECISION (wider_mode)
3339 - GET_MODE_PRECISION (mode),
3340 wider_mode),
3341 target, true, OPTAB_DIRECT);
c117dddc 3342
ac868f29
EB
3343 /* Likewise for bswap. */
3344 if (unoptab == bswap_optab && temp != 0)
3345 {
3346 gcc_assert (GET_MODE_PRECISION (wider_mode)
3347 == GET_MODE_BITSIZE (wider_mode)
3348 && GET_MODE_PRECISION (mode)
3349 == GET_MODE_BITSIZE (mode));
3350
3351 temp = expand_shift (RSHIFT_EXPR, wider_mode, temp,
3352 GET_MODE_BITSIZE (wider_mode)
3353 - GET_MODE_BITSIZE (mode),
3354 NULL_RTX, true);
3355 }
3356
34e56753 3357 if (temp)
77c9c6c2 3358 {
d858f359 3359 if (mclass != MODE_INT)
34e56753
RS
3360 {
3361 if (target == 0)
3362 target = gen_reg_rtx (mode);
3363 convert_move (target, temp, 0);
3364 return target;
3365 }
3366 else
3367 return gen_lowpart (mode, temp);
77c9c6c2
RK
3368 }
3369 else
34e56753 3370 delete_insns_since (last);
77c9c6c2
RK
3371 }
3372 }
3373 }
3374
8c55a142
RH
3375 /* One final attempt at implementing negation via subtraction,
3376 this time allowing widening of the operand. */
19b5fafb 3377 if (optab_to_code (unoptab) == NEG && !HONOR_SIGNED_ZEROS (mode))
0c20a65f 3378 {
b82b6eea 3379 rtx temp;
91ce572a
CC
3380 temp = expand_binop (mode,
3381 unoptab == negv_optab ? subv_optab : sub_optab,
3382 CONST0_RTX (mode), op0,
3383 target, unsignedp, OPTAB_LIB_WIDEN);
b82b6eea 3384 if (temp)
8c55a142 3385 return temp;
b82b6eea 3386 }
0c20a65f 3387
77c9c6c2
RK
3388 return 0;
3389}
3390\f
decdfa82
RS
3391/* Emit code to compute the absolute value of OP0, with result to
3392 TARGET if convenient. (TARGET may be 0.) The return value says
3393 where the result actually is to be found.
3394
3395 MODE is the mode of the operand; the mode of the result is
3396 different but can be deduced from MODE.
3397
91813b28 3398 */
7fd01431
RK
3399
3400rtx
ef4bddc2 3401expand_abs_nojump (machine_mode mode, rtx op0, rtx target,
0c20a65f 3402 int result_unsignedp)
7fd01431 3403{
2ef0a555 3404 rtx temp;
7fd01431 3405
dad16761
RB
3406 if (GET_MODE_CLASS (mode) != MODE_INT
3407 || ! flag_trapv)
91ce572a
CC
3408 result_unsignedp = 1;
3409
7fd01431 3410 /* First try to do it with a special abs instruction. */
91ce572a
CC
3411 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
3412 op0, target, 0);
7fd01431
RK
3413 if (temp != 0)
3414 return temp;
3415
4977bab6 3416 /* For floating point modes, try clearing the sign bit. */
3d8bf70f 3417 if (SCALAR_FLOAT_MODE_P (mode))
4977bab6 3418 {
8c55a142
RH
3419 temp = expand_absneg_bit (ABS, mode, op0, target);
3420 if (temp)
3421 return temp;
4977bab6
ZW
3422 }
3423
14a774a9 3424 /* If we have a MAX insn, we can do this as MAX (x, -x). */
947131ba 3425 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing
8c55a142 3426 && !HONOR_SIGNED_ZEROS (mode))
14a774a9 3427 {
38295e01 3428 rtx_insn *last = get_last_insn ();
14a774a9 3429
dad16761
RB
3430 temp = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3431 op0, NULL_RTX, 0);
14a774a9
RK
3432 if (temp != 0)
3433 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3434 OPTAB_WIDEN);
3435
3436 if (temp != 0)
3437 return temp;
3438
3439 delete_insns_since (last);
3440 }
3441
7fd01431
RK
3442 /* If this machine has expensive jumps, we can do integer absolute
3443 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
e1078cfc 3444 where W is the width of MODE. */
7fd01431 3445
3a4fd356
JH
3446 if (GET_MODE_CLASS (mode) == MODE_INT
3447 && BRANCH_COST (optimize_insn_for_speed_p (),
3448 false) >= 2)
7fd01431
RK
3449 {
3450 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
69660a70 3451 GET_MODE_PRECISION (mode) - 1,
7fd01431
RK
3452 NULL_RTX, 0);
3453
3454 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3455 OPTAB_LIB_WIDEN);
3456 if (temp != 0)
91ce572a
CC
3457 temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
3458 temp, extended, target, 0, OPTAB_LIB_WIDEN);
7fd01431
RK
3459
3460 if (temp != 0)
3461 return temp;
3462 }
3463
2ef0a555
RH
3464 return NULL_RTX;
3465}
3466
3467rtx
ef4bddc2 3468expand_abs (machine_mode mode, rtx op0, rtx target,
0c20a65f 3469 int result_unsignedp, int safe)
2ef0a555 3470{
38295e01
DM
3471 rtx temp;
3472 rtx_code_label *op1;
2ef0a555 3473
dad16761
RB
3474 if (GET_MODE_CLASS (mode) != MODE_INT
3475 || ! flag_trapv)
77173bbe
KH
3476 result_unsignedp = 1;
3477
2ef0a555
RH
3478 temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
3479 if (temp != 0)
3480 return temp;
3481
7fd01431 3482 /* If that does not win, use conditional jump and negate. */
5c0bf747
RK
3483
3484 /* It is safe to use the target if it is the same
3485 as the source if this is also a pseudo register */
f8cfc6aa 3486 if (op0 == target && REG_P (op0)
5c0bf747
RK
3487 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
3488 safe = 1;
3489
7fd01431
RK
3490 op1 = gen_label_rtx ();
3491 if (target == 0 || ! safe
3492 || GET_MODE (target) != mode
3c0cb5de 3493 || (MEM_P (target) && MEM_VOLATILE_P (target))
f8cfc6aa 3494 || (REG_P (target)
7fd01431
RK
3495 && REGNO (target) < FIRST_PSEUDO_REGISTER))
3496 target = gen_reg_rtx (mode);
3497
3498 emit_move_insn (target, op0);
3499 NO_DEFER_POP;
3500
3bf78d3b 3501 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
40e90eac 3502 NULL_RTX, NULL_RTX, op1, -1);
7fd01431 3503
91ce572a
CC
3504 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3505 target, target, 0);
7fd01431
RK
3506 if (op0 != target)
3507 emit_move_insn (target, op0);
3508 emit_label (op1);
3509 OK_DEFER_POP;
3510 return target;
3511}
046625fa 3512
65026047
ER
3513/* Emit code to compute the one's complement absolute value of OP0
3514 (if (OP0 < 0) OP0 = ~OP0), with result to TARGET if convenient.
3515 (TARGET may be NULL_RTX.) The return value says where the result
3516 actually is to be found.
3517
3518 MODE is the mode of the operand; the mode of the result is
3519 different but can be deduced from MODE. */
3520
3521rtx
ef4bddc2 3522expand_one_cmpl_abs_nojump (machine_mode mode, rtx op0, rtx target)
65026047
ER
3523{
3524 rtx temp;
3525
3526 /* Not applicable for floating point modes. */
3527 if (FLOAT_MODE_P (mode))
3528 return NULL_RTX;
3529
3530 /* If we have a MAX insn, we can do this as MAX (x, ~x). */
947131ba 3531 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing)
65026047 3532 {
38295e01 3533 rtx_insn *last = get_last_insn ();
65026047
ER
3534
3535 temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
3536 if (temp != 0)
3537 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3538 OPTAB_WIDEN);
3539
3540 if (temp != 0)
3541 return temp;
3542
3543 delete_insns_since (last);
3544 }
3545
3546 /* If this machine has expensive jumps, we can do one's complement
3547 absolute value of X as (((signed) x >> (W-1)) ^ x). */
3548
3549 if (GET_MODE_CLASS (mode) == MODE_INT
3550 && BRANCH_COST (optimize_insn_for_speed_p (),
3551 false) >= 2)
3552 {
3553 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
69660a70 3554 GET_MODE_PRECISION (mode) - 1,
65026047
ER
3555 NULL_RTX, 0);
3556
3557 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
3558 OPTAB_LIB_WIDEN);
3559
3560 if (temp != 0)
3561 return temp;
3562 }
3563
3564 return NULL_RTX;
3565}
3566
ae394659
RH
3567/* A subroutine of expand_copysign, perform the copysign operation using the
3568 abs and neg primitives advertised to exist on the target. The assumption
3569 is that we have a split register file, and leaving op0 in fp registers,
3570 and not playing with subregs so much, will help the register allocator. */
046625fa 3571
9abd1955 3572static rtx
ef4bddc2 3573expand_copysign_absneg (machine_mode mode, rtx op0, rtx op1, rtx target,
ae394659 3574 int bitpos, bool op0_is_abs)
046625fa 3575{
ef4bddc2 3576 machine_mode imode;
a5c7d693 3577 enum insn_code icode;
38295e01
DM
3578 rtx sign;
3579 rtx_code_label *label;
046625fa 3580
ae394659
RH
3581 if (target == op1)
3582 target = NULL_RTX;
046625fa 3583
d0c9d431
UB
3584 /* Check if the back end provides an insn that handles signbit for the
3585 argument's mode. */
a5c7d693 3586 icode = optab_handler (signbit_optab, mode);
d0c9d431 3587 if (icode != CODE_FOR_nothing)
ae394659 3588 {
a5c7d693 3589 imode = insn_data[(int) icode].operand[0].mode;
d0c9d431
UB
3590 sign = gen_reg_rtx (imode);
3591 emit_unop_insn (icode, sign, op1, UNKNOWN);
ae394659
RH
3592 }
3593 else
3594 {
d0c9d431
UB
3595 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3596 {
3597 imode = int_mode_for_mode (mode);
3598 if (imode == BLKmode)
3599 return NULL_RTX;
3600 op1 = gen_lowpart (imode, op1);
3601 }
ae394659 3602 else
d0c9d431
UB
3603 {
3604 int word;
046625fa 3605
d0c9d431
UB
3606 imode = word_mode;
3607 if (FLOAT_WORDS_BIG_ENDIAN)
3608 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3609 else
3610 word = bitpos / BITS_PER_WORD;
3611 bitpos = bitpos % BITS_PER_WORD;
3612 op1 = operand_subword_force (op1, word, mode);
3613 }
3614
807e902e 3615 wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
d0c9d431 3616 sign = expand_binop (imode, and_optab, op1,
807e902e 3617 immed_wide_int_const (mask, imode),
d0c9d431 3618 NULL_RTX, 1, OPTAB_LIB_WIDEN);
ae394659 3619 }
046625fa 3620
d0c9d431 3621 if (!op0_is_abs)
8c55a142 3622 {
d0c9d431
UB
3623 op0 = expand_unop (mode, abs_optab, op0, target, 0);
3624 if (op0 == NULL)
3625 return NULL_RTX;
3626 target = op0;
8c55a142 3627 }
ae394659
RH
3628 else
3629 {
d0c9d431
UB
3630 if (target == NULL_RTX)
3631 target = copy_to_reg (op0);
3632 else
3633 emit_move_insn (target, op0);
ae394659
RH
3634 }
3635
ae394659 3636 label = gen_label_rtx ();
d0c9d431 3637 emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
ae394659 3638
48175537 3639 if (CONST_DOUBLE_AS_FLOAT_P (op0))
ae394659
RH
3640 op0 = simplify_unary_operation (NEG, mode, op0, mode);
3641 else
3642 op0 = expand_unop (mode, neg_optab, op0, target, 0);
3643 if (op0 != target)
3644 emit_move_insn (target, op0);
3645
3646 emit_label (label);
3647
3648 return target;
3649}
3650
3651
3652/* A subroutine of expand_copysign, perform the entire copysign operation
3653 with integer bitmasks. BITPOS is the position of the sign bit; OP0_IS_ABS
3654 is true if op0 is known to have its sign bit clear. */
3655
3656static rtx
ef4bddc2 3657expand_copysign_bit (machine_mode mode, rtx op0, rtx op1, rtx target,
ae394659
RH
3658 int bitpos, bool op0_is_abs)
3659{
ef4bddc2 3660 machine_mode imode;
ae394659 3661 int word, nwords, i;
38295e01
DM
3662 rtx temp;
3663 rtx_insn *insns;
046625fa 3664
8c55a142 3665 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
046625fa 3666 {
8c55a142
RH
3667 imode = int_mode_for_mode (mode);
3668 if (imode == BLKmode)
3669 return NULL_RTX;
3670 word = 0;
3671 nwords = 1;
3672 }
3673 else
3674 {
3675 imode = word_mode;
3676
3677 if (FLOAT_WORDS_BIG_ENDIAN)
3678 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3679 else
3680 word = bitpos / BITS_PER_WORD;
3681 bitpos = bitpos % BITS_PER_WORD;
3682 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
046625fa
RH
3683 }
3684
807e902e 3685 wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
046625fa 3686
02972eaf
RS
3687 if (target == 0
3688 || target == op0
3689 || target == op1
3690 || (nwords > 1 && !valid_multiword_target_p (target)))
8c55a142
RH
3691 target = gen_reg_rtx (mode);
3692
3693 if (nwords > 1)
046625fa 3694 {
8c55a142
RH
3695 start_sequence ();
3696
3697 for (i = 0; i < nwords; ++i)
046625fa 3698 {
8c55a142
RH
3699 rtx targ_piece = operand_subword (target, i, 1, mode);
3700 rtx op0_piece = operand_subword_force (op0, i, mode);
c414ac1d 3701
8c55a142
RH
3702 if (i == word)
3703 {
ae394659 3704 if (!op0_is_abs)
54fb1ae0
AS
3705 op0_piece
3706 = expand_binop (imode, and_optab, op0_piece,
807e902e 3707 immed_wide_int_const (~mask, imode),
54fb1ae0 3708 NULL_RTX, 1, OPTAB_LIB_WIDEN);
8c55a142
RH
3709 op1 = expand_binop (imode, and_optab,
3710 operand_subword_force (op1, i, mode),
807e902e 3711 immed_wide_int_const (mask, imode),
8c55a142
RH
3712 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3713
3714 temp = expand_binop (imode, ior_optab, op0_piece, op1,
3715 targ_piece, 1, OPTAB_LIB_WIDEN);
3716 if (temp != targ_piece)
3717 emit_move_insn (targ_piece, temp);
3718 }
3719 else
3720 emit_move_insn (targ_piece, op0_piece);
046625fa 3721 }
8c55a142
RH
3722
3723 insns = get_insns ();
3724 end_sequence ();
3725
d70dcf29 3726 emit_insn (insns);
046625fa
RH
3727 }
3728 else
8c55a142
RH
3729 {
3730 op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
807e902e 3731 immed_wide_int_const (mask, imode),
8c55a142
RH
3732 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3733
3734 op0 = gen_lowpart (imode, op0);
ae394659 3735 if (!op0_is_abs)
8c55a142 3736 op0 = expand_binop (imode, and_optab, op0,
807e902e 3737 immed_wide_int_const (~mask, imode),
8c55a142
RH
3738 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3739
3740 temp = expand_binop (imode, ior_optab, op0, op1,
3741 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3742 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3743 }
046625fa
RH
3744
3745 return target;
3746}
ae394659 3747
c414ac1d 3748/* Expand the C99 copysign operation. OP0 and OP1 must be the same
ae394659
RH
3749 scalar floating point mode. Return NULL if we do not know how to
3750 expand the operation inline. */
3751
3752rtx
3753expand_copysign (rtx op0, rtx op1, rtx target)
3754{
ef4bddc2 3755 machine_mode mode = GET_MODE (op0);
ae394659 3756 const struct real_format *fmt;
ae394659
RH
3757 bool op0_is_abs;
3758 rtx temp;
3759
3760 gcc_assert (SCALAR_FLOAT_MODE_P (mode));
3761 gcc_assert (GET_MODE (op1) == mode);
3762
3763 /* First try to do it with a special instruction. */
3764 temp = expand_binop (mode, copysign_optab, op0, op1,
3765 target, 0, OPTAB_DIRECT);
3766 if (temp)
3767 return temp;
3768
3769 fmt = REAL_MODE_FORMAT (mode);
3770 if (fmt == NULL || !fmt->has_signed_zero)
3771 return NULL_RTX;
3772
ae394659 3773 op0_is_abs = false;
48175537 3774 if (CONST_DOUBLE_AS_FLOAT_P (op0))
ae394659
RH
3775 {
3776 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
3777 op0 = simplify_unary_operation (ABS, mode, op0, mode);
3778 op0_is_abs = true;
3779 }
3780
c064fde5 3781 if (fmt->signbit_ro >= 0
48175537 3782 && (CONST_DOUBLE_AS_FLOAT_P (op0)
947131ba
RS
3783 || (optab_handler (neg_optab, mode) != CODE_FOR_nothing
3784 && optab_handler (abs_optab, mode) != CODE_FOR_nothing)))
ae394659
RH
3785 {
3786 temp = expand_copysign_absneg (mode, op0, op1, target,
c064fde5 3787 fmt->signbit_ro, op0_is_abs);
ae394659
RH
3788 if (temp)
3789 return temp;
3790 }
3791
c064fde5
RS
3792 if (fmt->signbit_rw < 0)
3793 return NULL_RTX;
3794 return expand_copysign_bit (mode, op0, op1, target,
3795 fmt->signbit_rw, op0_is_abs);
ae394659 3796}
7fd01431 3797\f
77c9c6c2
RK
3798/* Generate an instruction whose insn-code is INSN_CODE,
3799 with two operands: an output TARGET and an input OP0.
3800 TARGET *must* be nonzero, and the output is always stored there.
3801 CODE is an rtx code such that (CODE OP0) is an rtx that describes
b8698a0f 3802 the value that is stored into TARGET.
77c9c6c2 3803
18bd082d
JH
3804 Return false if expansion failed. */
3805
3806bool
a5c7d693
RS
3807maybe_emit_unop_insn (enum insn_code icode, rtx target, rtx op0,
3808 enum rtx_code code)
77c9c6c2 3809{
a5c7d693 3810 struct expand_operand ops[2];
77c9c6c2 3811 rtx pat;
77c9c6c2 3812
a5c7d693
RS
3813 create_output_operand (&ops[0], target, GET_MODE (target));
3814 create_input_operand (&ops[1], op0, GET_MODE (op0));
3815 pat = maybe_gen_insn (icode, 2, ops);
18bd082d 3816 if (!pat)
a5c7d693 3817 return false;
77c9c6c2 3818
dc01c3d1
DM
3819 if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX
3820 && code != UNKNOWN)
3821 add_equal_note (as_a <rtx_insn *> (pat), ops[0].value, code, ops[1].value,
3822 NULL_RTX);
0c20a65f 3823
77c9c6c2
RK
3824 emit_insn (pat);
3825
a5c7d693
RS
3826 if (ops[0].value != target)
3827 emit_move_insn (target, ops[0].value);
18bd082d
JH
3828 return true;
3829}
3830/* Generate an instruction whose insn-code is INSN_CODE,
3831 with two operands: an output TARGET and an input OP0.
3832 TARGET *must* be nonzero, and the output is always stored there.
3833 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3834 the value that is stored into TARGET. */
3835
3836void
a5c7d693 3837emit_unop_insn (enum insn_code icode, rtx target, rtx op0, enum rtx_code code)
18bd082d
JH
3838{
3839 bool ok = maybe_emit_unop_insn (icode, target, op0, code);
3840 gcc_assert (ok);
77c9c6c2
RK
3841}
3842\f
326a31e9
R
3843struct no_conflict_data
3844{
38295e01
DM
3845 rtx target;
3846 rtx_insn *first, *insn;
326a31e9
R
3847 bool must_stay;
3848};
3849
d70dcf29
KZ
3850/* Called via note_stores by emit_libcall_block. Set P->must_stay if
3851 the currently examined clobber / store has to stay in the list of
3852 insns that constitute the actual libcall block. */
326a31e9 3853static void
7bc980e1 3854no_conflict_move_test (rtx dest, const_rtx set, void *p0)
326a31e9 3855{
d3bfe4de 3856 struct no_conflict_data *p= (struct no_conflict_data *) p0;
326a31e9
R
3857
3858 /* If this inns directly contributes to setting the target, it must stay. */
3859 if (reg_overlap_mentioned_p (p->target, dest))
3860 p->must_stay = true;
3861 /* If we haven't committed to keeping any other insns in the list yet,
3862 there is nothing more to check. */
3863 else if (p->insn == p->first)
3864 return;
3865 /* If this insn sets / clobbers a register that feeds one of the insns
3866 already in the list, this insn has to stay too. */
9617ccfd
R
3867 else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
3868 || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
326a31e9
R
3869 || reg_used_between_p (dest, p->first, p->insn)
3870 /* Likewise if this insn depends on a register set by a previous
ca7a5aec
R
3871 insn in the list, or if it sets a result (presumably a hard
3872 register) that is set or clobbered by a previous insn.
3873 N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
3874 SET_DEST perform the former check on the address, and the latter
3875 check on the MEM. */
326a31e9
R
3876 || (GET_CODE (set) == SET
3877 && (modified_in_p (SET_SRC (set), p->first)
ca7a5aec
R
3878 || modified_in_p (SET_DEST (set), p->first)
3879 || modified_between_p (SET_SRC (set), p->first, p->insn)
3880 || modified_between_p (SET_DEST (set), p->first, p->insn))))
326a31e9
R
3881 p->must_stay = true;
3882}
3883
77c9c6c2
RK
3884\f
3885/* Emit code to make a call to a constant function or a library call.
3886
3887 INSNS is a list containing all insns emitted in the call.
3888 These insns leave the result in RESULT. Our block is to copy RESULT
3889 to TARGET, which is logically equivalent to EQUIV.
3890
3891 We first emit any insns that set a pseudo on the assumption that these are
3892 loading constants into registers; doing so allows them to be safely cse'ed
3893 between blocks. Then we emit all the other insns in the block, followed by
3894 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
856905c2
SB
3895 note with an operand of EQUIV. */
3896
b55f62cc 3897static void
38295e01 3898emit_libcall_block_1 (rtx_insn *insns, rtx target, rtx result, rtx equiv,
b55f62cc 3899 bool equiv_may_trap)
77c9c6c2 3900{
aff2c2d3 3901 rtx final_dest = target;
38295e01 3902 rtx_insn *next, *last, *insn;
77c9c6c2 3903
aff2c2d3
BS
3904 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
3905 into a MEM later. Protect the libcall block from this change. */
3906 if (! REG_P (target) || REG_USERVAR_P (target))
3907 target = gen_reg_rtx (GET_MODE (target));
0c20a65f 3908
5154e79a
AH
3909 /* If we're using non-call exceptions, a libcall corresponding to an
3910 operation that may trap may also trap. */
1d65f45c 3911 /* ??? See the comment in front of make_reg_eh_region_note. */
b55f62cc
RG
3912 if (cfun->can_throw_non_call_exceptions
3913 && (equiv_may_trap || may_trap_p (equiv)))
5154e79a
AH
3914 {
3915 for (insn = insns; insn; insn = NEXT_INSN (insn))
4b4bf941 3916 if (CALL_P (insn))
5154e79a
AH
3917 {
3918 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1d65f45c
RH
3919 if (note)
3920 {
3921 int lp_nr = INTVAL (XEXP (note, 0));
3922 if (lp_nr == 0 || lp_nr == INT_MIN)
3923 remove_note (insn, note);
3924 }
5154e79a
AH
3925 }
3926 }
3927 else
1d65f45c
RH
3928 {
3929 /* Look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
3930 reg note to indicate that this call cannot throw or execute a nonlocal
3931 goto (unless there is already a REG_EH_REGION note, in which case
3932 we update it). */
3933 for (insn = insns; insn; insn = NEXT_INSN (insn))
3934 if (CALL_P (insn))
3935 make_reg_eh_region_note_nothrow_nononlocal (insn);
3936 }
b472794d 3937
77c9c6c2 3938 /* First emit all insns that set pseudos. Remove them from the list as
ccf5f342 3939 we go. Avoid insns that set pseudos which were referenced in previous
29ebe69a 3940 insns. These can be generated by move_by_pieces, for example,
ccf5f342
RK
3941 to update an address. Similarly, avoid insns that reference things
3942 set in previous insns. */
77c9c6c2
RK
3943
3944 for (insn = insns; insn; insn = next)
3945 {
3946 rtx set = single_set (insn);
3947
3948 next = NEXT_INSN (insn);
3949
f8cfc6aa 3950 if (set != 0 && REG_P (SET_DEST (set))
748ebfc7 3951 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
77c9c6c2 3952 {
748ebfc7
R
3953 struct no_conflict_data data;
3954
3955 data.target = const0_rtx;
3956 data.first = insns;
3957 data.insn = insn;
3958 data.must_stay = 0;
3959 note_stores (PATTERN (insn), no_conflict_move_test, &data);
3960 if (! data.must_stay)
3961 {
3962 if (PREV_INSN (insn))
0f82e5c9 3963 SET_NEXT_INSN (PREV_INSN (insn)) = next;
748ebfc7
R
3964 else
3965 insns = next;
77c9c6c2 3966
748ebfc7 3967 if (next)
0f82e5c9 3968 SET_PREV_INSN (next) = PREV_INSN (insn);
77c9c6c2 3969
748ebfc7
R
3970 add_insn (insn);
3971 }
77c9c6c2 3972 }
695a94b3
RS
3973
3974 /* Some ports use a loop to copy large arguments onto the stack.
3975 Don't move anything outside such a loop. */
4b4bf941 3976 if (LABEL_P (insn))
695a94b3 3977 break;
77c9c6c2
RK
3978 }
3979
77c9c6c2 3980 /* Write the remaining insns followed by the final copy. */
77c9c6c2
RK
3981 for (insn = insns; insn; insn = next)
3982 {
3983 next = NEXT_INSN (insn);
3984
3985 add_insn (insn);
3986 }
3987
3988 last = emit_move_insn (target, result);
7543f918 3989 set_dst_reg_note (last, REG_EQUAL, copy_rtx (equiv), target);
77c9c6c2 3990
e85427f9
BS
3991 if (final_dest != target)
3992 emit_move_insn (final_dest, target);
77c9c6c2 3993}
b55f62cc
RG
3994
3995void
3996emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
3997{
38295e01
DM
3998 emit_libcall_block_1 (safe_as_a <rtx_insn *> (insns),
3999 target, result, equiv, false);
b55f62cc 4000}
77c9c6c2 4001\f
1c0290ea 4002/* Nonzero if we can perform a comparison of mode MODE straightforwardly.
1eb8759b
RH
4003 PURPOSE describes how this comparison will be used. CODE is the rtx
4004 comparison code we will be using.
4005
4006 ??? Actually, CODE is slightly weaker than that. A target is still
0c20a65f 4007 required to implement all of the normal bcc operations, but not
1eb8759b 4008 required to implement all (or any) of the unordered bcc operations. */
0c20a65f 4009
1c0290ea 4010int
ef4bddc2 4011can_compare_p (enum rtx_code code, machine_mode mode,
0c20a65f 4012 enum can_compare_purpose purpose)
b30f05db 4013{
c3c64f50
PB
4014 rtx test;
4015 test = gen_rtx_fmt_ee (code, mode, const0_rtx, const0_rtx);
b30f05db
BS
4016 do
4017 {
2ef6ce06 4018 enum insn_code icode;
c3c64f50 4019
1c0290ea 4020 if (purpose == ccp_jump
947131ba 4021 && (icode = optab_handler (cbranch_optab, mode)) != CODE_FOR_nothing
2ef6ce06 4022 && insn_operand_matches (icode, 0, test))
c3c64f50
PB
4023 return 1;
4024 if (purpose == ccp_store_flag
947131ba 4025 && (icode = optab_handler (cstore_optab, mode)) != CODE_FOR_nothing
2ef6ce06 4026 && insn_operand_matches (icode, 1, test))
c3c64f50 4027 return 1;
1c0290ea 4028 if (purpose == ccp_cmov
947131ba 4029 && optab_handler (cmov_optab, mode) != CODE_FOR_nothing)
1c0290ea 4030 return 1;
c3c64f50 4031
b30f05db 4032 mode = GET_MODE_WIDER_MODE (mode);
c3c64f50 4033 PUT_MODE (test, mode);
1c0290ea
BS
4034 }
4035 while (mode != VOIDmode);
b30f05db
BS
4036
4037 return 0;
4038}
4039
4040/* This function is called when we are going to emit a compare instruction that
4041 compares the values found in *PX and *PY, using the rtl operator COMPARISON.
4042
4043 *PMODE is the mode of the inputs (in case they are const_int).
4044 *PUNSIGNEDP nonzero says that the operands are unsigned;
f90b7a5a 4045 this matters if they need to be widened (as given by METHODS).
77c9c6c2 4046
a06ef755 4047 If they have mode BLKmode, then SIZE specifies the size of both operands.
77c9c6c2 4048
b30f05db
BS
4049 This function performs all the setup necessary so that the caller only has
4050 to emit a single comparison insn. This setup can involve doing a BLKmode
4051 comparison or emitting a library call to perform the comparison if no insn
4052 is available to handle it.
4053 The values which are passed in through pointers can be modified; the caller
0e61db61
NS
4054 should perform the comparison on the modified values. Constant
4055 comparisons must have already been folded. */
77c9c6c2 4056
a06ef755 4057static void
f90b7a5a
PB
4058prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
4059 int unsignedp, enum optab_methods methods,
ef4bddc2 4060 rtx *ptest, machine_mode *pmode)
77c9c6c2 4061{
ef4bddc2 4062 machine_mode mode = *pmode;
f90b7a5a 4063 rtx libfunc, test;
ef4bddc2 4064 machine_mode cmp_mode;
f90b7a5a
PB
4065 enum mode_class mclass;
4066
4067 /* The other methods are not needed. */
4068 gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
4069 || methods == OPTAB_LIB_WIDEN);
77c9c6c2 4070
5e8d1826
PB
4071 /* If we are optimizing, force expensive constants into a register. */
4072 if (CONSTANT_P (x) && optimize
68f932c4 4073 && (rtx_cost (x, COMPARE, 0, optimize_insn_for_speed_p ())
5e8d1826
PB
4074 > COSTS_N_INSNS (1)))
4075 x = force_reg (mode, x);
4076
4077 if (CONSTANT_P (y) && optimize
68f932c4 4078 && (rtx_cost (y, COMPARE, 1, optimize_insn_for_speed_p ())
5e8d1826
PB
4079 > COSTS_N_INSNS (1)))
4080 y = force_reg (mode, y);
4081
362cc3d4 4082#ifdef HAVE_cc0
0e61db61
NS
4083 /* Make sure if we have a canonical comparison. The RTL
4084 documentation states that canonical comparisons are required only
4085 for targets which have cc0. */
e3feb571 4086 gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
362cc3d4
MH
4087#endif
4088
77c9c6c2
RK
4089 /* Don't let both operands fail to indicate the mode. */
4090 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
4091 x = force_reg (mode, x);
f90b7a5a
PB
4092 if (mode == VOIDmode)
4093 mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : GET_MODE (y);
77c9c6c2
RK
4094
4095 /* Handle all BLKmode compares. */
4096
4097 if (mode == BLKmode)
4098 {
ef4bddc2 4099 machine_mode result_mode;
118355a0
ZW
4100 enum insn_code cmp_code;
4101 tree length_type;
4102 rtx libfunc;
b30f05db 4103 rtx result;
118355a0 4104 rtx opalign
f4dc10d1 4105 = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
b30f05db 4106
e3feb571 4107 gcc_assert (size);
118355a0 4108
118355a0
ZW
4109 /* Try to use a memory block compare insn - either cmpstr
4110 or cmpmem will do. */
4111 for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
4112 cmp_mode != VOIDmode;
4113 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
358b8f01 4114 {
f9621cc4 4115 cmp_code = direct_optab_handler (cmpmem_optab, cmp_mode);
118355a0 4116 if (cmp_code == CODE_FOR_nothing)
f9621cc4 4117 cmp_code = direct_optab_handler (cmpstr_optab, cmp_mode);
40c1d5f8 4118 if (cmp_code == CODE_FOR_nothing)
f9621cc4 4119 cmp_code = direct_optab_handler (cmpstrn_optab, cmp_mode);
118355a0
ZW
4120 if (cmp_code == CODE_FOR_nothing)
4121 continue;
4122
4123 /* Must make sure the size fits the insn's mode. */
481683e1 4124 if ((CONST_INT_P (size)
118355a0
ZW
4125 && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
4126 || (GET_MODE_BITSIZE (GET_MODE (size))
4127 > GET_MODE_BITSIZE (cmp_mode)))
4128 continue;
4129
4130 result_mode = insn_data[cmp_code].operand[0].mode;
358b8f01 4131 result = gen_reg_rtx (result_mode);
118355a0
ZW
4132 size = convert_to_mode (cmp_mode, size, 1);
4133 emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
4134
f90b7a5a
PB
4135 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
4136 *pmode = result_mode;
118355a0 4137 return;
77c9c6c2 4138 }
118355a0 4139
f90b7a5a
PB
4140 if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
4141 goto fail;
4142
8f99553f 4143 /* Otherwise call a library function, memcmp. */
118355a0
ZW
4144 libfunc = memcmp_libfunc;
4145 length_type = sizetype;
118355a0
ZW
4146 result_mode = TYPE_MODE (integer_type_node);
4147 cmp_mode = TYPE_MODE (length_type);
4148 size = convert_to_mode (TYPE_MODE (length_type), size,
8df83eae 4149 TYPE_UNSIGNED (length_type));
118355a0 4150
84b8030f 4151 result = emit_library_call_value (libfunc, 0, LCT_PURE,
118355a0
ZW
4152 result_mode, 3,
4153 XEXP (x, 0), Pmode,
4154 XEXP (y, 0), Pmode,
4155 size, cmp_mode);
ae5f0678
UB
4156 x = result;
4157 y = const0_rtx;
4158 mode = result_mode;
4159 methods = OPTAB_LIB_WIDEN;
4160 unsignedp = false;
77c9c6c2
RK
4161 }
4162
27ab3e91
RH
4163 /* Don't allow operands to the compare to trap, as that can put the
4164 compare and branch in different basic blocks. */
8f4f502f 4165 if (cfun->can_throw_non_call_exceptions)
27ab3e91
RH
4166 {
4167 if (may_trap_p (x))
4168 x = force_reg (mode, x);
4169 if (may_trap_p (y))
4170 y = force_reg (mode, y);
4171 }
4172
4a77c72b
PB
4173 if (GET_MODE_CLASS (mode) == MODE_CC)
4174 {
de6fba39
UW
4175 enum insn_code icode = optab_handler (cbranch_optab, CCmode);
4176 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4177 gcc_assert (icode != CODE_FOR_nothing
4178 && insn_operand_matches (icode, 0, test));
4179 *ptest = test;
4a77c72b
PB
4180 return;
4181 }
77c9c6c2 4182
f90b7a5a
PB
4183 mclass = GET_MODE_CLASS (mode);
4184 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
4185 cmp_mode = mode;
4186 do
4187 {
4188 enum insn_code icode;
947131ba 4189 icode = optab_handler (cbranch_optab, cmp_mode);
f90b7a5a 4190 if (icode != CODE_FOR_nothing
2ef6ce06 4191 && insn_operand_matches (icode, 0, test))
f90b7a5a 4192 {
38295e01 4193 rtx_insn *last = get_last_insn ();
f90b7a5a
PB
4194 rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp);
4195 rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp);
4196 if (op0 && op1
2ef6ce06
RS
4197 && insn_operand_matches (icode, 1, op0)
4198 && insn_operand_matches (icode, 2, op1))
f90b7a5a
PB
4199 {
4200 XEXP (test, 0) = op0;
4201 XEXP (test, 1) = op1;
4202 *ptest = test;
4203 *pmode = cmp_mode;
4204 return;
4205 }
4206 delete_insns_since (last);
4207 }
4208
4209 if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
4210 break;
4211 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode);
4212 }
4213 while (cmp_mode != VOIDmode);
4214
4215 if (methods != OPTAB_LIB_WIDEN)
4216 goto fail;
4217
4218 if (!SCALAR_FLOAT_MODE_P (mode))
77c9c6c2 4219 {
9725066d 4220 rtx result;
ef4bddc2 4221 machine_mode ret_mode;
9725066d 4222
f90b7a5a
PB
4223 /* Handle a libcall just for the mode we are using. */
4224 libfunc = optab_libfunc (cmp_optab, mode);
4225 gcc_assert (libfunc);
4226
77c9c6c2
RK
4227 /* If we want unsigned, and this mode has a distinct unsigned
4228 comparison routine, use that. */
8a33f100
JH
4229 if (unsignedp)
4230 {
ba8a73e9
EB
4231 rtx ulibfunc = optab_libfunc (ucmp_optab, mode);
4232 if (ulibfunc)
4233 libfunc = ulibfunc;
8a33f100 4234 }
77c9c6c2 4235
0a81f074 4236 ret_mode = targetm.libgcc_cmp_return_mode ();
84b8030f 4237 result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
0a81f074 4238 ret_mode, 2, x, mode, y, mode);
9725066d 4239
f34312c2
CD
4240 /* There are two kinds of comparison routines. Biased routines
4241 return 0/1/2, and unbiased routines return -1/0/1. Other parts
4242 of gcc expect that the comparison operation is equivalent
b8698a0f 4243 to the modified comparison. For signed comparisons compare the
f34312c2
CD
4244 result against 1 in the biased case, and zero in the unbiased
4245 case. For unsigned comparisons always compare against 1 after
917f1b7e 4246 biasing the unbiased result by adding 1. This gives us a way to
f64398b5
JB
4247 represent LTU.
4248 The comparisons in the fixed-point helper library are always
4249 biased. */
f90b7a5a
PB
4250 x = result;
4251 y = const1_rtx;
f34312c2 4252
f64398b5 4253 if (!TARGET_LIB_INT_CMP_BIASED && !ALL_FIXED_POINT_MODE_P (mode))
b3f8d95d 4254 {
f90b7a5a 4255 if (unsignedp)
0a81f074 4256 x = plus_constant (ret_mode, result, 1);
f34312c2 4257 else
f90b7a5a 4258 y = const0_rtx;
b3f8d95d 4259 }
f90b7a5a 4260
a0169320 4261 *pmode = ret_mode;
f90b7a5a
PB
4262 prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods,
4263 ptest, pmode);
77c9c6c2 4264 }
b8698a0f 4265 else
f90b7a5a 4266 prepare_float_lib_cmp (x, y, comparison, ptest, pmode);
77c9c6c2 4267
f90b7a5a
PB
4268 return;
4269
4270 fail:
4271 *ptest = NULL_RTX;
77c9c6c2
RK
4272}
4273
b30f05db
BS
4274/* Before emitting an insn with code ICODE, make sure that X, which is going
4275 to be used for operand OPNUM of the insn, is converted from mode MODE to
4fe9b91c 4276 WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
b30f05db 4277 that it is accepted by the operand predicate. Return the new value. */
749a2da1 4278
f90b7a5a 4279rtx
ef4bddc2
RS
4280prepare_operand (enum insn_code icode, rtx x, int opnum, machine_mode mode,
4281 machine_mode wider_mode, int unsignedp)
b30f05db 4282{
b30f05db
BS
4283 if (mode != wider_mode)
4284 x = convert_modes (wider_mode, mode, x, unsignedp);
4285
2ef6ce06 4286 if (!insn_operand_matches (icode, opnum, x))
d893ccde 4287 {
6fad471b 4288 machine_mode op_mode = insn_data[(int) icode].operand[opnum].mode;
ef4375b2 4289 if (reload_completed)
d893ccde 4290 return NULL_RTX;
6fad471b
UW
4291 if (GET_MODE (x) != op_mode && GET_MODE (x) != VOIDmode)
4292 return NULL_RTX;
4293 x = copy_to_mode_reg (op_mode, x);
d893ccde
RH
4294 }
4295
b30f05db
BS
4296 return x;
4297}
4298
4299/* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
f90b7a5a 4300 we can do the branch. */
b30f05db
BS
4301
4302static void
ef4bddc2 4303emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob)
b30f05db 4304{
ef4bddc2 4305 machine_mode optab_mode;
f90b7a5a
PB
4306 enum mode_class mclass;
4307 enum insn_code icode;
38295e01 4308 rtx_insn *insn;
b30f05db 4309
f90b7a5a
PB
4310 mclass = GET_MODE_CLASS (mode);
4311 optab_mode = (mclass == MODE_CC) ? CCmode : mode;
947131ba 4312 icode = optab_handler (cbranch_optab, optab_mode);
8127d0e0 4313
f90b7a5a 4314 gcc_assert (icode != CODE_FOR_nothing);
2ef6ce06 4315 gcc_assert (insn_operand_matches (icode, 0, test));
a4da41e1
ER
4316 insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
4317 XEXP (test, 1), label));
4318 if (prob != -1
0a6a6ac9 4319 && profile_status_for_fn (cfun) != PROFILE_ABSENT
a4da41e1
ER
4320 && insn
4321 && JUMP_P (insn)
0f379f76
ER
4322 && any_condjump_p (insn)
4323 && !find_reg_note (insn, REG_BR_PROB, 0))
e5af9ddd 4324 add_int_reg_note (insn, REG_BR_PROB, prob);
b30f05db
BS
4325}
4326
362cc3d4
MH
4327/* Generate code to compare X with Y so that the condition codes are
4328 set and to jump to LABEL if the condition is true. If X is a
4329 constant and Y is not a constant, then the comparison is swapped to
4330 ensure that the comparison RTL has the canonical form.
4331
c5d5d461 4332 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
f90b7a5a
PB
4333 need to be widened. UNSIGNEDP is also used to select the proper
4334 branch condition code.
362cc3d4 4335
a06ef755 4336 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
362cc3d4 4337
c5d5d461
JL
4338 MODE is the mode of the inputs (in case they are const_int).
4339
f90b7a5a
PB
4340 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
4341 It will be potentially converted into an unsigned variant based on
a4da41e1
ER
4342 UNSIGNEDP to select a proper jump instruction.
4343
4344 PROB is the probability of jumping to LABEL. */
362cc3d4
MH
4345
4346void
0c20a65f 4347emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
ef4bddc2 4348 machine_mode mode, int unsignedp, rtx label,
a4da41e1 4349 int prob)
362cc3d4 4350{
8c9864f3 4351 rtx op0 = x, op1 = y;
f90b7a5a 4352 rtx test;
8c9864f3
JH
4353
4354 /* Swap operands and condition to ensure canonical RTL. */
45475a3f
PB
4355 if (swap_commutative_operands_p (x, y)
4356 && can_compare_p (swap_condition (comparison), mode, ccp_jump))
362cc3d4 4357 {
8c9864f3
JH
4358 op0 = y, op1 = x;
4359 comparison = swap_condition (comparison);
362cc3d4 4360 }
0ca40216 4361
45475a3f
PB
4362 /* If OP0 is still a constant, then both X and Y must be constants
4363 or the opposite comparison is not supported. Force X into a register
4364 to create canonical RTL. */
0ca40216
JL
4365 if (CONSTANT_P (op0))
4366 op0 = force_reg (mode, op0);
0ca40216 4367
c5d5d461
JL
4368 if (unsignedp)
4369 comparison = unsigned_condition (comparison);
a06ef755 4370
f90b7a5a
PB
4371 prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
4372 &test, &mode);
a4da41e1 4373 emit_cmp_and_jump_insn_1 (test, mode, label, prob);
b30f05db
BS
4374}
4375
77c9c6c2
RK
4376\f
4377/* Emit a library call comparison between floating point X and Y.
4378 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
4379
c5c60e15 4380static void
f90b7a5a 4381prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
ef4bddc2 4382 rtx *ptest, machine_mode *pmode)
77c9c6c2 4383{
c9034561 4384 enum rtx_code swapped = swap_condition (comparison);
b3f8d95d 4385 enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
ef4bddc2
RS
4386 machine_mode orig_mode = GET_MODE (x);
4387 machine_mode mode, cmp_mode;
6597fd0b 4388 rtx true_rtx, false_rtx;
38295e01
DM
4389 rtx value, target, equiv;
4390 rtx_insn *insns;
0a300065 4391 rtx libfunc = 0;
b3f8d95d 4392 bool reversed_p = false;
7fecf2c7 4393 cmp_mode = targetm.libgcc_cmp_return_mode ();
77c9c6c2 4394
86556d87
BE
4395 for (mode = orig_mode;
4396 mode != VOIDmode;
4397 mode = GET_MODE_WIDER_MODE (mode))
77c9c6c2 4398 {
19b5fafb
RH
4399 if (code_to_optab (comparison)
4400 && (libfunc = optab_libfunc (code_to_optab (comparison), mode)))
c9034561 4401 break;
77c9c6c2 4402
19b5fafb
RH
4403 if (code_to_optab (swapped)
4404 && (libfunc = optab_libfunc (code_to_optab (swapped), mode)))
77c9c6c2 4405 {
c9034561
ZW
4406 rtx tmp;
4407 tmp = x; x = y; y = tmp;
4408 comparison = swapped;
4409 break;
77c9c6c2 4410 }
77c9c6c2 4411
19b5fafb
RH
4412 if (code_to_optab (reversed)
4413 && (libfunc = optab_libfunc (code_to_optab (reversed), mode)))
b3f8d95d
MM
4414 {
4415 comparison = reversed;
4416 reversed_p = true;
4417 break;
4418 }
4419 }
5906d013 4420
e3feb571 4421 gcc_assert (mode != VOIDmode);
0a300065 4422
c9034561
ZW
4423 if (mode != orig_mode)
4424 {
4425 x = convert_to_mode (mode, x, 0);
4426 y = convert_to_mode (mode, y, 0);
4427 }
4428
17796a89
RS
4429 /* Attach a REG_EQUAL note describing the semantics of the libcall to
4430 the RTL. The allows the RTL optimizers to delete the libcall if the
4431 condition can be determined at compile-time. */
6597fd0b
PB
4432 if (comparison == UNORDERED
4433 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4434 {
4435 true_rtx = const_true_rtx;
4436 false_rtx = const0_rtx;
4437 }
4438 else
4439 {
4440 switch (comparison)
4441 {
4442 case EQ:
4443 true_rtx = const0_rtx;
4444 false_rtx = const_true_rtx;
4445 break;
4446
4447 case NE:
4448 true_rtx = const_true_rtx;
4449 false_rtx = const0_rtx;
4450 break;
4451
4452 case GT:
4453 true_rtx = const1_rtx;
4454 false_rtx = const0_rtx;
4455 break;
4456
4457 case GE:
4458 true_rtx = const0_rtx;
4459 false_rtx = constm1_rtx;
4460 break;
4461
4462 case LT:
4463 true_rtx = constm1_rtx;
4464 false_rtx = const0_rtx;
4465 break;
4466
4467 case LE:
4468 true_rtx = const0_rtx;
4469 false_rtx = const1_rtx;
4470 break;
4471
4472 default:
4473 gcc_unreachable ();
4474 }
4475 }
4476
17796a89
RS
4477 if (comparison == UNORDERED)
4478 {
7fecf2c7
AP
4479 rtx temp = simplify_gen_relational (NE, cmp_mode, mode, x, x);
4480 equiv = simplify_gen_relational (NE, cmp_mode, mode, y, y);
4481 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
17796a89
RS
4482 temp, const_true_rtx, equiv);
4483 }
4484 else
4485 {
7fecf2c7 4486 equiv = simplify_gen_relational (comparison, cmp_mode, mode, x, y);
17796a89 4487 if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
6597fd0b
PB
4488 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4489 equiv, true_rtx, false_rtx);
bd831d5c 4490 }
37bf20ee
RS
4491
4492 start_sequence ();
4493 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
7fecf2c7 4494 cmp_mode, 2, x, mode, y, mode);
37bf20ee
RS
4495 insns = get_insns ();
4496 end_sequence ();
4497
7fecf2c7 4498 target = gen_reg_rtx (cmp_mode);
37bf20ee
RS
4499 emit_libcall_block (insns, target, value, equiv);
4500
c9034561 4501 if (comparison == UNORDERED
6597fd0b
PB
4502 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison)
4503 || reversed_p)
4504 *ptest = gen_rtx_fmt_ee (reversed_p ? EQ : NE, VOIDmode, target, false_rtx);
4505 else
4506 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, target, const0_rtx);
c9034561 4507
7fecf2c7 4508 *pmode = cmp_mode;
77c9c6c2
RK
4509}
4510\f
4511/* Generate code to indirectly jump to a location given in the rtx LOC. */
4512
4513void
68df21f7 4514emit_indirect_jump (rtx loc ATTRIBUTE_UNUSED)
77c9c6c2 4515{
68df21f7
BS
4516#ifndef HAVE_indirect_jump
4517 sorry ("indirect jumps are not available on this target");
4518#else
a5c7d693 4519 struct expand_operand ops[1];
a5c7d693
RS
4520 create_address_operand (&ops[0], loc);
4521 expand_jump_insn (CODE_FOR_indirect_jump, 1, ops);
9649fb4d 4522 emit_barrier ();
68df21f7 4523#endif
77c9c6c2
RK
4524}
4525\f
49c4584c
DE
4526#ifdef HAVE_conditional_move
4527
4528/* Emit a conditional move instruction if the machine supports one for that
4529 condition and machine mode.
4530
4531 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4532 the mode to use should they be constants. If it is VOIDmode, they cannot
4533 both be constants.
4534
4535 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
4536 should be stored there. MODE is the mode to use should they be constants.
4537 If it is VOIDmode, they cannot both be constants.
4538
4539 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4540 is not supported. */
4541
4542rtx
0c20a65f 4543emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
ef4bddc2
RS
4544 machine_mode cmode, rtx op2, rtx op3,
4545 machine_mode mode, int unsignedp)
49c4584c 4546{
38295e01
DM
4547 rtx tem, comparison;
4548 rtx_insn *last;
49c4584c 4549 enum insn_code icode;
e5c56fd9 4550 enum rtx_code reversed;
49c4584c
DE
4551
4552 /* If one operand is constant, make it the second one. Only do this
4553 if the other operand is not constant as well. */
4554
e5c56fd9 4555 if (swap_commutative_operands_p (op0, op1))
49c4584c
DE
4556 {
4557 tem = op0;
4558 op0 = op1;
4559 op1 = tem;
4560 code = swap_condition (code);
4561 }
4562
c5c76735
JL
4563 /* get_condition will prefer to generate LT and GT even if the old
4564 comparison was against zero, so undo that canonicalization here since
4565 comparisons against zero are cheaper. */
87d9741e 4566 if (code == LT && op1 == const1_rtx)
c5c76735 4567 code = LE, op1 = const0_rtx;
87d9741e 4568 else if (code == GT && op1 == constm1_rtx)
c5c76735
JL
4569 code = GE, op1 = const0_rtx;
4570
49c4584c
DE
4571 if (cmode == VOIDmode)
4572 cmode = GET_MODE (op0);
4573
e5c56fd9
JH
4574 if (swap_commutative_operands_p (op2, op3)
4575 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4576 != UNKNOWN))
49c4584c
DE
4577 {
4578 tem = op2;
4579 op2 = op3;
4580 op3 = tem;
e5c56fd9 4581 code = reversed;
49c4584c
DE
4582 }
4583
4584 if (mode == VOIDmode)
4585 mode = GET_MODE (op2);
4586
f9621cc4 4587 icode = direct_optab_handler (movcc_optab, mode);
49c4584c
DE
4588
4589 if (icode == CODE_FOR_nothing)
4590 return 0;
4591
ad76cef8 4592 if (!target)
49c4584c
DE
4593 target = gen_reg_rtx (mode);
4594
f90b7a5a
PB
4595 code = unsignedp ? unsigned_condition (code) : code;
4596 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
49c4584c 4597
144a5f9d
JL
4598 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4599 return NULL and let the caller figure out how best to deal with this
4600 situation. */
f90b7a5a 4601 if (!COMPARISON_P (comparison))
144a5f9d 4602 return NULL_RTX;
0c20a65f 4603
7f2f0a01
JJ
4604 saved_pending_stack_adjust save;
4605 save_pending_stack_adjust (&save);
a5c7d693 4606 last = get_last_insn ();
7f2f0a01 4607 do_pending_stack_adjust ();
f90b7a5a
PB
4608 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4609 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4610 &comparison, &cmode);
a5c7d693 4611 if (comparison)
f90b7a5a 4612 {
a5c7d693 4613 struct expand_operand ops[4];
49c4584c 4614
a5c7d693
RS
4615 create_output_operand (&ops[0], target, mode);
4616 create_fixed_operand (&ops[1], comparison);
4617 create_input_operand (&ops[2], op2, mode);
4618 create_input_operand (&ops[3], op3, mode);
4619 if (maybe_expand_insn (icode, 4, ops))
4620 {
4621 if (ops[0].value != target)
4622 convert_move (target, ops[0].value, false);
4623 return target;
4624 }
4625 }
4626 delete_insns_since (last);
7f2f0a01 4627 restore_pending_stack_adjust (&save);
a5c7d693 4628 return NULL_RTX;
49c4584c
DE
4629}
4630
40f03658 4631/* Return nonzero if a conditional move of mode MODE is supported.
49c4584c
DE
4632
4633 This function is for combine so it can tell whether an insn that looks
4634 like a conditional move is actually supported by the hardware. If we
4635 guess wrong we lose a bit on optimization, but that's it. */
4636/* ??? sparc64 supports conditionally moving integers values based on fp
4637 comparisons, and vice versa. How do we handle them? */
4638
4639int
ef4bddc2 4640can_conditionally_move_p (machine_mode mode)
49c4584c 4641{
f9621cc4 4642 if (direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing)
49c4584c
DE
4643 return 1;
4644
4645 return 0;
4646}
4647
4648#endif /* HAVE_conditional_move */
068f5dea
JH
4649
4650/* Emit a conditional addition instruction if the machine supports one for that
4651 condition and machine mode.
4652
4653 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4654 the mode to use should they be constants. If it is VOIDmode, they cannot
4655 both be constants.
4656
5285c21c 4657 OP2 should be stored in TARGET if the comparison is false, otherwise OP2+OP3
068f5dea
JH
4658 should be stored there. MODE is the mode to use should they be constants.
4659 If it is VOIDmode, they cannot both be constants.
4660
4661 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4662 is not supported. */
4663
4664rtx
0c20a65f 4665emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
ef4bddc2
RS
4666 machine_mode cmode, rtx op2, rtx op3,
4667 machine_mode mode, int unsignedp)
068f5dea 4668{
38295e01
DM
4669 rtx tem, comparison;
4670 rtx_insn *last;
068f5dea 4671 enum insn_code icode;
068f5dea
JH
4672
4673 /* If one operand is constant, make it the second one. Only do this
4674 if the other operand is not constant as well. */
4675
4676 if (swap_commutative_operands_p (op0, op1))
4677 {
4678 tem = op0;
4679 op0 = op1;
4680 op1 = tem;
4681 code = swap_condition (code);
4682 }
4683
4684 /* get_condition will prefer to generate LT and GT even if the old
4685 comparison was against zero, so undo that canonicalization here since
4686 comparisons against zero are cheaper. */
87d9741e 4687 if (code == LT && op1 == const1_rtx)
068f5dea 4688 code = LE, op1 = const0_rtx;
87d9741e 4689 else if (code == GT && op1 == constm1_rtx)
068f5dea
JH
4690 code = GE, op1 = const0_rtx;
4691
4692 if (cmode == VOIDmode)
4693 cmode = GET_MODE (op0);
4694
068f5dea
JH
4695 if (mode == VOIDmode)
4696 mode = GET_MODE (op2);
4697
947131ba 4698 icode = optab_handler (addcc_optab, mode);
068f5dea
JH
4699
4700 if (icode == CODE_FOR_nothing)
4701 return 0;
4702
ad76cef8 4703 if (!target)
068f5dea
JH
4704 target = gen_reg_rtx (mode);
4705
f90b7a5a
PB
4706 code = unsignedp ? unsigned_condition (code) : code;
4707 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
068f5dea 4708
068f5dea
JH
4709 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4710 return NULL and let the caller figure out how best to deal with this
4711 situation. */
f90b7a5a 4712 if (!COMPARISON_P (comparison))
068f5dea 4713 return NULL_RTX;
0c20a65f 4714
f90b7a5a 4715 do_pending_stack_adjust ();
a5c7d693 4716 last = get_last_insn ();
f90b7a5a
PB
4717 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4718 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4719 &comparison, &cmode);
a5c7d693 4720 if (comparison)
f90b7a5a 4721 {
a5c7d693 4722 struct expand_operand ops[4];
068f5dea 4723
a5c7d693
RS
4724 create_output_operand (&ops[0], target, mode);
4725 create_fixed_operand (&ops[1], comparison);
4726 create_input_operand (&ops[2], op2, mode);
4727 create_input_operand (&ops[3], op3, mode);
4728 if (maybe_expand_insn (icode, 4, ops))
4729 {
4730 if (ops[0].value != target)
4731 convert_move (target, ops[0].value, false);
4732 return target;
4733 }
4734 }
4735 delete_insns_since (last);
4736 return NULL_RTX;
068f5dea 4737}
49c4584c 4738\f
0913e4b4
AO
4739/* These functions attempt to generate an insn body, rather than
4740 emitting the insn, but if the gen function already emits them, we
ad76cef8 4741 make no attempt to turn them back into naked patterns. */
77c9c6c2
RK
4742
4743/* Generate and return an insn body to add Y to X. */
4744
4745rtx
0c20a65f 4746gen_add2_insn (rtx x, rtx y)
77c9c6c2 4747{
2ef6ce06 4748 enum insn_code icode = optab_handler (add_optab, GET_MODE (x));
77c9c6c2 4749
2ef6ce06
RS
4750 gcc_assert (insn_operand_matches (icode, 0, x));
4751 gcc_assert (insn_operand_matches (icode, 1, x));
4752 gcc_assert (insn_operand_matches (icode, 2, y));
77c9c6c2 4753
e3feb571 4754 return GEN_FCN (icode) (x, x, y);
77c9c6c2
RK
4755}
4756
e78d8e51
ZW
4757/* Generate and return an insn body to add r1 and c,
4758 storing the result in r0. */
8a33f100 4759
e78d8e51 4760rtx
0c20a65f 4761gen_add3_insn (rtx r0, rtx r1, rtx c)
e78d8e51 4762{
2ef6ce06 4763 enum insn_code icode = optab_handler (add_optab, GET_MODE (r0));
e78d8e51 4764
7e1a450d 4765 if (icode == CODE_FOR_nothing
2ef6ce06
RS
4766 || !insn_operand_matches (icode, 0, r0)
4767 || !insn_operand_matches (icode, 1, r1)
4768 || !insn_operand_matches (icode, 2, c))
e78d8e51
ZW
4769 return NULL_RTX;
4770
e3feb571 4771 return GEN_FCN (icode) (r0, r1, c);
e78d8e51
ZW
4772}
4773
77c9c6c2 4774int
0c20a65f 4775have_add2_insn (rtx x, rtx y)
77c9c6c2 4776{
2ef6ce06 4777 enum insn_code icode;
fb7e77d7 4778
e3feb571 4779 gcc_assert (GET_MODE (x) != VOIDmode);
fb7e77d7 4780
2ef6ce06 4781 icode = optab_handler (add_optab, GET_MODE (x));
fb7e77d7
TM
4782
4783 if (icode == CODE_FOR_nothing)
4784 return 0;
4785
2ef6ce06
RS
4786 if (!insn_operand_matches (icode, 0, x)
4787 || !insn_operand_matches (icode, 1, x)
4788 || !insn_operand_matches (icode, 2, y))
fb7e77d7
TM
4789 return 0;
4790
4791 return 1;
77c9c6c2
RK
4792}
4793
72a4ddf2
AK
4794/* Generate and return an insn body to add Y to X. */
4795
4796rtx
4797gen_addptr3_insn (rtx x, rtx y, rtx z)
4798{
4799 enum insn_code icode = optab_handler (addptr3_optab, GET_MODE (x));
4800
4801 gcc_assert (insn_operand_matches (icode, 0, x));
4802 gcc_assert (insn_operand_matches (icode, 1, y));
4803 gcc_assert (insn_operand_matches (icode, 2, z));
4804
4805 return GEN_FCN (icode) (x, y, z);
4806}
4807
4808/* Return true if the target implements an addptr pattern and X, Y,
4809 and Z are valid for the pattern predicates. */
4810
4811int
4812have_addptr3_insn (rtx x, rtx y, rtx z)
4813{
4814 enum insn_code icode;
4815
4816 gcc_assert (GET_MODE (x) != VOIDmode);
4817
4818 icode = optab_handler (addptr3_optab, GET_MODE (x));
4819
4820 if (icode == CODE_FOR_nothing)
4821 return 0;
4822
4823 if (!insn_operand_matches (icode, 0, x)
4824 || !insn_operand_matches (icode, 1, y)
4825 || !insn_operand_matches (icode, 2, z))
4826 return 0;
4827
4828 return 1;
4829}
4830
77c9c6c2
RK
4831/* Generate and return an insn body to subtract Y from X. */
4832
4833rtx
0c20a65f 4834gen_sub2_insn (rtx x, rtx y)
77c9c6c2 4835{
2ef6ce06 4836 enum insn_code icode = optab_handler (sub_optab, GET_MODE (x));
77c9c6c2 4837
2ef6ce06
RS
4838 gcc_assert (insn_operand_matches (icode, 0, x));
4839 gcc_assert (insn_operand_matches (icode, 1, x));
4840 gcc_assert (insn_operand_matches (icode, 2, y));
77c9c6c2 4841
e3feb571 4842 return GEN_FCN (icode) (x, x, y);
77c9c6c2
RK
4843}
4844
ef89d648
ZW
4845/* Generate and return an insn body to subtract r1 and c,
4846 storing the result in r0. */
8a33f100 4847
ef89d648 4848rtx
0c20a65f 4849gen_sub3_insn (rtx r0, rtx r1, rtx c)
ef89d648 4850{
2ef6ce06 4851 enum insn_code icode = optab_handler (sub_optab, GET_MODE (r0));
ef89d648 4852
7e1a450d 4853 if (icode == CODE_FOR_nothing
2ef6ce06
RS
4854 || !insn_operand_matches (icode, 0, r0)
4855 || !insn_operand_matches (icode, 1, r1)
4856 || !insn_operand_matches (icode, 2, c))
ef89d648
ZW
4857 return NULL_RTX;
4858
e3feb571 4859 return GEN_FCN (icode) (r0, r1, c);
ef89d648
ZW
4860}
4861
77c9c6c2 4862int
0c20a65f 4863have_sub2_insn (rtx x, rtx y)
77c9c6c2 4864{
2ef6ce06 4865 enum insn_code icode;
fb7e77d7 4866
e3feb571 4867 gcc_assert (GET_MODE (x) != VOIDmode);
fb7e77d7 4868
2ef6ce06 4869 icode = optab_handler (sub_optab, GET_MODE (x));
fb7e77d7
TM
4870
4871 if (icode == CODE_FOR_nothing)
4872 return 0;
4873
2ef6ce06
RS
4874 if (!insn_operand_matches (icode, 0, x)
4875 || !insn_operand_matches (icode, 1, x)
4876 || !insn_operand_matches (icode, 2, y))
fb7e77d7
TM
4877 return 0;
4878
4879 return 1;
77c9c6c2 4880}
77c9c6c2 4881\f
34e56753
RS
4882/* Return the insn code used to extend FROM_MODE to TO_MODE.
4883 UNSIGNEDP specifies zero-extension instead of sign-extension. If
4884 no such operation exists, CODE_FOR_nothing will be returned. */
77c9c6c2 4885
34e56753 4886enum insn_code
ef4bddc2 4887can_extend_p (machine_mode to_mode, machine_mode from_mode,
0c20a65f 4888 int unsignedp)
77c9c6c2 4889{
85363ca0 4890 convert_optab tab;
6dd12198
SE
4891#ifdef HAVE_ptr_extend
4892 if (unsignedp < 0)
4893 return CODE_FOR_ptr_extend;
6dd12198 4894#endif
85363ca0
ZW
4895
4896 tab = unsignedp ? zext_optab : sext_optab;
947131ba 4897 return convert_optab_handler (tab, to_mode, from_mode);
77c9c6c2
RK
4898}
4899
4900/* Generate the body of an insn to extend Y (with mode MFROM)
4901 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
4902
4903rtx
ef4bddc2
RS
4904gen_extend_insn (rtx x, rtx y, machine_mode mto,
4905 machine_mode mfrom, int unsignedp)
77c9c6c2 4906{
85363ca0
ZW
4907 enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
4908 return GEN_FCN (icode) (x, y);
77c9c6c2 4909}
77c9c6c2
RK
4910\f
4911/* can_fix_p and can_float_p say whether the target machine
4912 can directly convert a given fixed point type to
4913 a given floating point type, or vice versa.
4914 The returned value is the CODE_FOR_... value to use,
5d81dc5b 4915 or CODE_FOR_nothing if these modes cannot be directly converted.
77c9c6c2 4916
5d81dc5b 4917 *TRUNCP_PTR is set to 1 if it is necessary to output
77c9c6c2
RK
4918 an explicit FTRUNC insn before the fix insn; otherwise 0. */
4919
4920static enum insn_code
ef4bddc2 4921can_fix_p (machine_mode fixmode, machine_mode fltmode,
0c20a65f 4922 int unsignedp, int *truncp_ptr)
77c9c6c2 4923{
85363ca0
ZW
4924 convert_optab tab;
4925 enum insn_code icode;
4926
4927 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
947131ba 4928 icode = convert_optab_handler (tab, fixmode, fltmode);
85363ca0
ZW
4929 if (icode != CODE_FOR_nothing)
4930 {
4931 *truncp_ptr = 0;
4932 return icode;
4933 }
77c9c6c2 4934
0e1d7f32
AH
4935 /* FIXME: This requires a port to define both FIX and FTRUNC pattern
4936 for this to work. We need to rework the fix* and ftrunc* patterns
4937 and documentation. */
85363ca0 4938 tab = unsignedp ? ufix_optab : sfix_optab;
947131ba 4939 icode = convert_optab_handler (tab, fixmode, fltmode);
85363ca0 4940 if (icode != CODE_FOR_nothing
947131ba 4941 && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
77c9c6c2
RK
4942 {
4943 *truncp_ptr = 1;
85363ca0 4944 return icode;
77c9c6c2 4945 }
85363ca0
ZW
4946
4947 *truncp_ptr = 0;
77c9c6c2
RK
4948 return CODE_FOR_nothing;
4949}
4950
ebeadd91 4951enum insn_code
ef4bddc2 4952can_float_p (machine_mode fltmode, machine_mode fixmode,
0c20a65f 4953 int unsignedp)
77c9c6c2 4954{
85363ca0
ZW
4955 convert_optab tab;
4956
4957 tab = unsignedp ? ufloat_optab : sfloat_optab;
947131ba 4958 return convert_optab_handler (tab, fltmode, fixmode);
77c9c6c2 4959}
9db8f45d
DP
4960
4961/* Function supportable_convert_operation
4962
4963 Check whether an operation represented by the code CODE is a
4964 convert operation that is supported by the target platform in
4965 vector form (i.e., when operating on arguments of type VECTYPE_IN
4966 producing a result of type VECTYPE_OUT).
4967
4968 Convert operations we currently support directly are FIX_TRUNC and FLOAT.
4969 This function checks if these operations are supported
4970 by the target platform either directly (via vector tree-codes), or via
4971 target builtins.
4972
4973 Output:
4974 - CODE1 is code of vector operation to be used when
4975 vectorizing the operation, if available.
4976 - DECL is decl of target builtin functions to be used
4977 when vectorizing the operation, if available. In this case,
4978 CODE1 is CALL_EXPR. */
4979
4980bool
4981supportable_convert_operation (enum tree_code code,
4982 tree vectype_out, tree vectype_in,
4983 tree *decl, enum tree_code *code1)
4984{
ef4bddc2 4985 machine_mode m1,m2;
9db8f45d
DP
4986 int truncp;
4987
4988 m1 = TYPE_MODE (vectype_out);
4989 m2 = TYPE_MODE (vectype_in);
4990
4991 /* First check if we can done conversion directly. */
4992 if ((code == FIX_TRUNC_EXPR
4993 && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp)
4994 != CODE_FOR_nothing)
4995 || (code == FLOAT_EXPR
4996 && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
4997 != CODE_FOR_nothing))
4998 {
4999 *code1 = code;
5000 return true;
5001 }
5002
5003 /* Now check for builtin. */
5004 if (targetm.vectorize.builtin_conversion
5005 && targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
5006 {
5007 *code1 = CALL_EXPR;
5008 *decl = targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in);
5009 return true;
5010 }
5011 return false;
5012}
5013
77c9c6c2
RK
5014\f
5015/* Generate code to convert FROM to floating point
34e56753 5016 and store in TO. FROM must be fixed point and not VOIDmode.
77c9c6c2
RK
5017 UNSIGNEDP nonzero means regard FROM as unsigned.
5018 Normally this is done by correcting the final value
5019 if it is negative. */
5020
5021void
0c20a65f 5022expand_float (rtx to, rtx from, int unsignedp)
77c9c6c2
RK
5023{
5024 enum insn_code icode;
b3694847 5025 rtx target = to;
ef4bddc2 5026 machine_mode fmode, imode;
d7735880 5027 bool can_do_signed = false;
77c9c6c2 5028
34e56753 5029 /* Crash now, because we won't be able to decide which mode to use. */
e3feb571 5030 gcc_assert (GET_MODE (from) != VOIDmode);
34e56753 5031
77c9c6c2
RK
5032 /* Look for an insn to do the conversion. Do it in the specified
5033 modes if possible; otherwise convert either input, output or both to
5034 wider mode. If the integer mode is wider than the mode of FROM,
5035 we can do the conversion signed even if the input is unsigned. */
5036
7bf0a593
AP
5037 for (fmode = GET_MODE (to); fmode != VOIDmode;
5038 fmode = GET_MODE_WIDER_MODE (fmode))
5039 for (imode = GET_MODE (from); imode != VOIDmode;
5040 imode = GET_MODE_WIDER_MODE (imode))
77c9c6c2
RK
5041 {
5042 int doing_unsigned = unsignedp;
5043
5ba02ca6 5044 if (fmode != GET_MODE (to)
69660a70 5045 && significand_size (fmode) < GET_MODE_PRECISION (GET_MODE (from)))
5ba02ca6
GK
5046 continue;
5047
77c9c6c2 5048 icode = can_float_p (fmode, imode, unsignedp);
d7735880
JM
5049 if (icode == CODE_FOR_nothing && unsignedp)
5050 {
5051 enum insn_code scode = can_float_p (fmode, imode, 0);
5052 if (scode != CODE_FOR_nothing)
5053 can_do_signed = true;
5054 if (imode != GET_MODE (from))
5055 icode = scode, doing_unsigned = 0;
5056 }
77c9c6c2
RK
5057
5058 if (icode != CODE_FOR_nothing)
5059 {
77c9c6c2
RK
5060 if (imode != GET_MODE (from))
5061 from = convert_to_mode (imode, from, unsignedp);
77c9c6c2
RK
5062
5063 if (fmode != GET_MODE (to))
5064 target = gen_reg_rtx (fmode);
5065
5066 emit_unop_insn (icode, target, from,
5067 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
5068
5069 if (target != to)
5070 convert_move (to, target, 0);
5071 return;
5072 }
7e1a450d 5073 }
77c9c6c2 5074
6ef9a246 5075 /* Unsigned integer, and no way to convert directly. Convert as signed,
cc8d36a1
UB
5076 then unconditionally adjust the result. */
5077 if (unsignedp && can_do_signed)
77c9c6c2 5078 {
38295e01 5079 rtx_code_label *label = gen_label_rtx ();
77c9c6c2
RK
5080 rtx temp;
5081 REAL_VALUE_TYPE offset;
5082
c95c47f3
PE
5083 /* Look for a usable floating mode FMODE wider than the source and at
5084 least as wide as the target. Using FMODE will avoid rounding woes
5085 with unsigned values greater than the signed maximum value. */
70864443 5086
c95c47f3
PE
5087 for (fmode = GET_MODE (to); fmode != VOIDmode;
5088 fmode = GET_MODE_WIDER_MODE (fmode))
69660a70 5089 if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
c95c47f3
PE
5090 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
5091 break;
a48fb61b 5092
c95c47f3
PE
5093 if (fmode == VOIDmode)
5094 {
a48fb61b 5095 /* There is no such mode. Pretend the target is wide enough. */
c95c47f3 5096 fmode = GET_MODE (to);
a48fb61b 5097
0f41302f 5098 /* Avoid double-rounding when TO is narrower than FROM. */
a48fb61b 5099 if ((significand_size (fmode) + 1)
69660a70 5100 < GET_MODE_PRECISION (GET_MODE (from)))
a48fb61b
RK
5101 {
5102 rtx temp1;
38295e01 5103 rtx_code_label *neglabel = gen_label_rtx ();
a48fb61b 5104
0c20a65f 5105 /* Don't use TARGET if it isn't a register, is a hard register,
70864443 5106 or is the wrong mode. */
f8cfc6aa 5107 if (!REG_P (target)
70864443
RK
5108 || REGNO (target) < FIRST_PSEUDO_REGISTER
5109 || GET_MODE (target) != fmode)
44f51d4a
RK
5110 target = gen_reg_rtx (fmode);
5111
a48fb61b
RK
5112 imode = GET_MODE (from);
5113 do_pending_stack_adjust ();
5114
5115 /* Test whether the sign bit is set. */
1c0290ea 5116 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
a06ef755 5117 0, neglabel);
a48fb61b
RK
5118
5119 /* The sign bit is not set. Convert as signed. */
5120 expand_float (target, from, 0);
5121 emit_jump_insn (gen_jump (label));
2ad79487 5122 emit_barrier ();
a48fb61b
RK
5123
5124 /* The sign bit is set.
5125 Convert to a usable (positive signed) value by shifting right
5126 one bit, while remembering if a nonzero bit was shifted
5127 out; i.e., compute (from & 1) | (from >> 1). */
5128
5129 emit_label (neglabel);
5130 temp = expand_binop (imode, and_optab, from, const1_rtx,
70864443 5131 NULL_RTX, 1, OPTAB_LIB_WIDEN);
eb6c3df1 5132 temp1 = expand_shift (RSHIFT_EXPR, imode, from, 1, NULL_RTX, 1);
0c20a65f 5133 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
70864443 5134 OPTAB_LIB_WIDEN);
a48fb61b
RK
5135 expand_float (target, temp, 0);
5136
5137 /* Multiply by 2 to undo the shift above. */
a93738eb 5138 temp = expand_binop (fmode, add_optab, target, target,
7e1a450d 5139 target, 0, OPTAB_LIB_WIDEN);
a93738eb
RK
5140 if (temp != target)
5141 emit_move_insn (target, temp);
5142
a48fb61b
RK
5143 do_pending_stack_adjust ();
5144 emit_label (label);
5145 goto done;
5146 }
c95c47f3
PE
5147 }
5148
77c9c6c2
RK
5149 /* If we are about to do some arithmetic to correct for an
5150 unsigned operand, do it in a pseudo-register. */
5151
c95c47f3 5152 if (GET_MODE (to) != fmode
f8cfc6aa 5153 || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
c95c47f3 5154 target = gen_reg_rtx (fmode);
77c9c6c2
RK
5155
5156 /* Convert as signed integer to floating. */
5157 expand_float (target, from, 0);
5158
5159 /* If FROM is negative (and therefore TO is negative),
5160 correct its value by 2**bitwidth. */
5161
5162 do_pending_stack_adjust ();
c5d5d461 5163 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
a06ef755 5164 0, label);
70864443 5165
0c20a65f 5166
69660a70 5167 real_2expN (&offset, GET_MODE_PRECISION (GET_MODE (from)), fmode);
c95c47f3 5168 temp = expand_binop (fmode, add_optab, target,
30d88916 5169 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
77c9c6c2
RK
5170 target, 0, OPTAB_LIB_WIDEN);
5171 if (temp != target)
5172 emit_move_insn (target, temp);
a48fb61b 5173
77c9c6c2
RK
5174 do_pending_stack_adjust ();
5175 emit_label (label);
70864443 5176 goto done;
77c9c6c2 5177 }
77c9c6c2 5178
85363ca0 5179 /* No hardware instruction available; call a library routine. */
77c9c6c2 5180 {
85363ca0 5181 rtx libfunc;
38295e01 5182 rtx_insn *insns;
9a7f678c 5183 rtx value;
85363ca0 5184 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
77c9c6c2 5185
50b6ee8b 5186 if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode))
77c9c6c2 5187 from = convert_to_mode (SImode, from, unsignedp);
77c9c6c2 5188
8a33f100 5189 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
e3feb571 5190 gcc_assert (libfunc);
77c9c6c2
RK
5191
5192 start_sequence ();
5193
85363ca0 5194 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
ebb1b59a
BS
5195 GET_MODE (to), 1, from,
5196 GET_MODE (from));
77c9c6c2
RK
5197 insns = get_insns ();
5198 end_sequence ();
5199
9a7f678c 5200 emit_libcall_block (insns, target, value,
d1163987
BW
5201 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FLOAT : FLOAT,
5202 GET_MODE (to), from));
77c9c6c2
RK
5203 }
5204
a48fb61b
RK
5205 done:
5206
77c9c6c2
RK
5207 /* Copy result to requested destination
5208 if we have been computing in a temp location. */
5209
5210 if (target != to)
5211 {
5212 if (GET_MODE (target) == GET_MODE (to))
5213 emit_move_insn (to, target);
5214 else
5215 convert_move (to, target, 0);
5216 }
5217}
5218\f
0e1d7f32
AH
5219/* Generate code to convert FROM to fixed point and store in TO. FROM
5220 must be floating point. */
77c9c6c2
RK
5221
5222void
0c20a65f 5223expand_fix (rtx to, rtx from, int unsignedp)
77c9c6c2
RK
5224{
5225 enum insn_code icode;
b3694847 5226 rtx target = to;
ef4bddc2 5227 machine_mode fmode, imode;
77c9c6c2 5228 int must_trunc = 0;
77c9c6c2
RK
5229
5230 /* We first try to find a pair of modes, one real and one integer, at
5231 least as wide as FROM and TO, respectively, in which we can open-code
5232 this conversion. If the integer mode is wider than the mode of TO,
5233 we can do the conversion either signed or unsigned. */
5234
3987b9db
JH
5235 for (fmode = GET_MODE (from); fmode != VOIDmode;
5236 fmode = GET_MODE_WIDER_MODE (fmode))
5237 for (imode = GET_MODE (to); imode != VOIDmode;
5238 imode = GET_MODE_WIDER_MODE (imode))
77c9c6c2
RK
5239 {
5240 int doing_unsigned = unsignedp;
5241
5242 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
5243 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
5244 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
5245
5246 if (icode != CODE_FOR_nothing)
5247 {
38295e01 5248 rtx_insn *last = get_last_insn ();
77c9c6c2
RK
5249 if (fmode != GET_MODE (from))
5250 from = convert_to_mode (fmode, from, 0);
77c9c6c2
RK
5251
5252 if (must_trunc)
0e1d7f32
AH
5253 {
5254 rtx temp = gen_reg_rtx (GET_MODE (from));
5255 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
5256 temp, 0);
5257 }
77c9c6c2
RK
5258
5259 if (imode != GET_MODE (to))
5260 target = gen_reg_rtx (imode);
5261
5e04ef8f
JH
5262 if (maybe_emit_unop_insn (icode, target, from,
5263 doing_unsigned ? UNSIGNED_FIX : FIX))
5264 {
5265 if (target != to)
5266 convert_move (to, target, unsignedp);
5267 return;
5268 }
5269 delete_insns_since (last);
77c9c6c2
RK
5270 }
5271 }
5272
77c9c6c2
RK
5273 /* For an unsigned conversion, there is one more way to do it.
5274 If we have a signed conversion, we generate code that compares
5275 the real value to the largest representable positive number. If if
5276 is smaller, the conversion is done normally. Otherwise, subtract
5277 one plus the highest signed number, convert, and add it back.
5278
5279 We only need to check all real modes, since we know we didn't find
0c20a65f 5280 anything with a wider integer mode.
0d446150
JH
5281
5282 This code used to extend FP value into mode wider than the destination.
6ef9a246
JJ
5283 This is needed for decimal float modes which cannot accurately
5284 represent one plus the highest signed number of the same size, but
5285 not for binary modes. Consider, for instance conversion from SFmode
0d446150
JH
5286 into DImode.
5287
6fc0bb99 5288 The hot path through the code is dealing with inputs smaller than 2^63
0d446150
JH
5289 and doing just the conversion, so there is no bits to lose.
5290
5291 In the other path we know the value is positive in the range 2^63..2^64-1
6ef9a246 5292 inclusive. (as for other input overflow happens and result is undefined)
e0bb17a8 5293 So we know that the most important bit set in mantissa corresponds to
0d446150
JH
5294 2^63. The subtraction of 2^63 should not generate any rounding as it
5295 simply clears out that bit. The rest is trivial. */
77c9c6c2 5296
69660a70 5297 if (unsignedp && GET_MODE_PRECISION (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
77c9c6c2
RK
5298 for (fmode = GET_MODE (from); fmode != VOIDmode;
5299 fmode = GET_MODE_WIDER_MODE (fmode))
6ef9a246
JJ
5300 if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc)
5301 && (!DECIMAL_FLOAT_MODE_P (fmode)
69660a70 5302 || GET_MODE_BITSIZE (fmode) > GET_MODE_PRECISION (GET_MODE (to))))
77c9c6c2 5303 {
e9f7ae44
RS
5304 int bitsize;
5305 REAL_VALUE_TYPE offset;
38295e01
DM
5306 rtx limit;
5307 rtx_code_label *lab1, *lab2;
5308 rtx_insn *insn;
e9f7ae44 5309
69660a70 5310 bitsize = GET_MODE_PRECISION (GET_MODE (to));
6ef9a246 5311 real_2expN (&offset, bitsize - 1, fmode);
30d88916 5312 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
e9f7ae44
RS
5313 lab1 = gen_label_rtx ();
5314 lab2 = gen_label_rtx ();
77c9c6c2 5315
77c9c6c2
RK
5316 if (fmode != GET_MODE (from))
5317 from = convert_to_mode (fmode, from, 0);
5318
5319 /* See if we need to do the subtraction. */
5320 do_pending_stack_adjust ();
c5d5d461 5321 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
a06ef755 5322 0, lab1);
77c9c6c2
RK
5323
5324 /* If not, do the signed "fix" and branch around fixup code. */
5325 expand_fix (to, from, 0);
5326 emit_jump_insn (gen_jump (lab2));
5327 emit_barrier ();
5328
5329 /* Otherwise, subtract 2**(N-1), convert to signed number,
5330 then add 2**(N-1). Do the addition using XOR since this
5331 will often generate better code. */
5332 emit_label (lab1);
5333 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
b1ec3c92 5334 NULL_RTX, 0, OPTAB_LIB_WIDEN);
77c9c6c2
RK
5335 expand_fix (to, target, 0);
5336 target = expand_binop (GET_MODE (to), xor_optab, to,
2496c7bd
LB
5337 gen_int_mode
5338 ((HOST_WIDE_INT) 1 << (bitsize - 1),
5339 GET_MODE (to)),
77c9c6c2
RK
5340 to, 1, OPTAB_LIB_WIDEN);
5341
5342 if (target != to)
5343 emit_move_insn (to, target);
5344
5345 emit_label (lab2);
5346
947131ba 5347 if (optab_handler (mov_optab, GET_MODE (to)) != CODE_FOR_nothing)
02214a5c
RK
5348 {
5349 /* Make a place for a REG_NOTE and add it. */
5350 insn = emit_move_insn (to, to);
7543f918
JR
5351 set_dst_reg_note (insn, REG_EQUAL,
5352 gen_rtx_fmt_e (UNSIGNED_FIX, GET_MODE (to),
5353 copy_rtx (from)),
5354 to);
02214a5c 5355 }
c5c76735 5356
77c9c6c2
RK
5357 return;
5358 }
77c9c6c2
RK
5359
5360 /* We can't do it with an insn, so use a library call. But first ensure
5361 that the mode of TO is at least as wide as SImode, since those are the
5362 only library calls we know about. */
5363
50b6ee8b 5364 if (GET_MODE_PRECISION (GET_MODE (to)) < GET_MODE_PRECISION (SImode))
77c9c6c2
RK
5365 {
5366 target = gen_reg_rtx (SImode);
5367
5368 expand_fix (target, from, unsignedp);
5369 }
77c9c6c2 5370 else
77c9c6c2 5371 {
38295e01 5372 rtx_insn *insns;
560f3f8a 5373 rtx value;
85363ca0 5374 rtx libfunc;
5906d013 5375
85363ca0 5376 convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
8a33f100 5377 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
e3feb571 5378 gcc_assert (libfunc);
77c9c6c2 5379
77c9c6c2
RK
5380 start_sequence ();
5381
85363ca0 5382 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
ebb1b59a
BS
5383 GET_MODE (to), 1, from,
5384 GET_MODE (from));
77c9c6c2
RK
5385 insns = get_insns ();
5386 end_sequence ();
5387
560f3f8a 5388 emit_libcall_block (insns, target, value,
9e6a5703
JC
5389 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
5390 GET_MODE (to), from));
77c9c6c2 5391 }
0c20a65f 5392
3e53ea48
RK
5393 if (target != to)
5394 {
5395 if (GET_MODE (to) == GET_MODE (target))
5396 emit_move_insn (to, target);
5397 else
5398 convert_move (to, target, 0);
5399 }
77c9c6c2 5400}
bb7f0423 5401
0f996086
CF
5402/* Generate code to convert FROM or TO a fixed-point.
5403 If UINTP is true, either TO or FROM is an unsigned integer.
5404 If SATP is true, we need to saturate the result. */
5405
5406void
5407expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
5408{
ef4bddc2
RS
5409 machine_mode to_mode = GET_MODE (to);
5410 machine_mode from_mode = GET_MODE (from);
0f996086
CF
5411 convert_optab tab;
5412 enum rtx_code this_code;
5413 enum insn_code code;
38295e01
DM
5414 rtx_insn *insns;
5415 rtx value;
0f996086
CF
5416 rtx libfunc;
5417
5418 if (to_mode == from_mode)
5419 {
5420 emit_move_insn (to, from);
5421 return;
5422 }
5423
5424 if (uintp)
5425 {
5426 tab = satp ? satfractuns_optab : fractuns_optab;
5427 this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
5428 }
5429 else
5430 {
5431 tab = satp ? satfract_optab : fract_optab;
5432 this_code = satp ? SAT_FRACT : FRACT_CONVERT;
5433 }
947131ba 5434 code = convert_optab_handler (tab, to_mode, from_mode);
0f996086
CF
5435 if (code != CODE_FOR_nothing)
5436 {
5437 emit_unop_insn (code, to, from, this_code);
5438 return;
5439 }
5440
5441 libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
5442 gcc_assert (libfunc);
5443
5444 start_sequence ();
5445 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
5446 1, from, from_mode);
5447 insns = get_insns ();
5448 end_sequence ();
5449
5450 emit_libcall_block (insns, to, value,
19b5fafb 5451 gen_rtx_fmt_e (optab_to_code (tab), to_mode, from));
0f996086
CF
5452}
5453
bb7f0423
RG
5454/* Generate code to convert FROM to fixed point and store in TO. FROM
5455 must be floating point, TO must be signed. Use the conversion optab
5456 TAB to do the conversion. */
5457
5458bool
5459expand_sfix_optab (rtx to, rtx from, convert_optab tab)
5460{
5461 enum insn_code icode;
5462 rtx target = to;
ef4bddc2 5463 machine_mode fmode, imode;
bb7f0423
RG
5464
5465 /* We first try to find a pair of modes, one real and one integer, at
5466 least as wide as FROM and TO, respectively, in which we can open-code
5467 this conversion. If the integer mode is wider than the mode of TO,
5468 we can do the conversion either signed or unsigned. */
5469
5470 for (fmode = GET_MODE (from); fmode != VOIDmode;
5471 fmode = GET_MODE_WIDER_MODE (fmode))
5472 for (imode = GET_MODE (to); imode != VOIDmode;
5473 imode = GET_MODE_WIDER_MODE (imode))
5474 {
947131ba 5475 icode = convert_optab_handler (tab, imode, fmode);
bb7f0423
RG
5476 if (icode != CODE_FOR_nothing)
5477 {
38295e01 5478 rtx_insn *last = get_last_insn ();
bb7f0423
RG
5479 if (fmode != GET_MODE (from))
5480 from = convert_to_mode (fmode, from, 0);
5481
5482 if (imode != GET_MODE (to))
5483 target = gen_reg_rtx (imode);
5484
18bd082d 5485 if (!maybe_emit_unop_insn (icode, target, from, UNKNOWN))
5e04ef8f
JH
5486 {
5487 delete_insns_since (last);
5488 continue;
5489 }
bb7f0423
RG
5490 if (target != to)
5491 convert_move (to, target, 0);
5492 return true;
5493 }
5494 }
5495
5496 return false;
5497}
77c9c6c2 5498\f
ef89d648
ZW
5499/* Report whether we have an instruction to perform the operation
5500 specified by CODE on operands of mode MODE. */
5501int
ef4bddc2 5502have_insn_for (enum rtx_code code, machine_mode mode)
ef89d648 5503{
19b5fafb
RH
5504 return (code_to_optab (code)
5505 && (optab_handler (code_to_optab (code), mode)
ef89d648
ZW
5506 != CODE_FOR_nothing));
5507}
5508
b092b471
JW
5509/* Initialize the libfunc fields of an entire group of entries in some
5510 optab. Each entry is set equal to a string consisting of a leading
5511 pair of underscores followed by a generic operation name followed by
7ef0daad 5512 a mode name (downshifted to lowercase) followed by a single character
b092b471
JW
5513 representing the number of operands for the given operation (which is
5514 usually one of the characters '2', '3', or '4').
5515
5516 OPTABLE is the table in which libfunc fields are to be initialized.
b092b471
JW
5517 OPNAME is the generic (string) name of the operation.
5518 SUFFIX is the character which specifies the number of operands for
5519 the given generic operation.
8a33f100 5520 MODE is the mode to generate for.
b092b471
JW
5521*/
5522
5523static void
cd1440b1 5524gen_libfunc (optab optable, const char *opname, int suffix,
ef4bddc2 5525 machine_mode mode)
b092b471 5526{
b3694847 5527 unsigned opname_len = strlen (opname);
8a33f100
JH
5528 const char *mname = GET_MODE_NAME (mode);
5529 unsigned mname_len = strlen (mname);
cdbf4541
BS
5530 int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
5531 int len = prefix_len + opname_len + mname_len + 1 + 1;
5532 char *libfunc_name = XALLOCAVEC (char, len);
8a33f100
JH
5533 char *p;
5534 const char *q;
b092b471 5535
8a33f100
JH
5536 p = libfunc_name;
5537 *p++ = '_';
5538 *p++ = '_';
cdbf4541
BS
5539 if (targetm.libfunc_gnu_prefix)
5540 {
5541 *p++ = 'g';
5542 *p++ = 'n';
5543 *p++ = 'u';
5544 *p++ = '_';
5545 }
8a33f100
JH
5546 for (q = opname; *q; )
5547 *p++ = *q++;
5548 for (q = mname; *q; q++)
5549 *p++ = TOLOWER (*q);
5550 *p++ = suffix;
5551 *p = '\0';
5552
5553 set_optab_libfunc (optable, mode,
5554 ggc_alloc_string (libfunc_name, p - libfunc_name));
b092b471
JW
5555}
5556
8a33f100 5557/* Like gen_libfunc, but verify that integer operation is involved. */
b092b471 5558
cd1440b1 5559void
8a33f100 5560gen_int_libfunc (optab optable, const char *opname, char suffix,
ef4bddc2 5561 machine_mode mode)
b092b471 5562{
8a33f100 5563 int maxsize = 2 * BITS_PER_WORD;
2637bd27 5564 int minsize = BITS_PER_WORD;
8a33f100
JH
5565
5566 if (GET_MODE_CLASS (mode) != MODE_INT)
5567 return;
c0510d84
DD
5568 if (maxsize < LONG_LONG_TYPE_SIZE)
5569 maxsize = LONG_LONG_TYPE_SIZE;
2637bd27
RB
5570 if (minsize > INT_TYPE_SIZE
5571 && (trapv_binoptab_p (optable)
5572 || trapv_unoptab_p (optable)))
5573 minsize = INT_TYPE_SIZE;
5574 if (GET_MODE_BITSIZE (mode) < minsize
ca0a2d5d 5575 || GET_MODE_BITSIZE (mode) > maxsize)
8a33f100
JH
5576 return;
5577 gen_libfunc (optable, opname, suffix, mode);
b092b471
JW
5578}
5579
8a33f100 5580/* Like gen_libfunc, but verify that FP and set decimal prefix if needed. */
b092b471 5581
cd1440b1 5582void
8a33f100 5583gen_fp_libfunc (optab optable, const char *opname, char suffix,
ef4bddc2 5584 machine_mode mode)
b092b471 5585{
8a33f100 5586 char *dec_opname;
79b87c74 5587
8a33f100
JH
5588 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
5589 gen_libfunc (optable, opname, suffix, mode);
5590 if (DECIMAL_FLOAT_MODE_P (mode))
5591 {
d3bfe4de 5592 dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
8a33f100
JH
5593 /* For BID support, change the name to have either a bid_ or dpd_ prefix
5594 depending on the low level floating format used. */
5595 memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
5596 strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
5597 gen_libfunc (optable, dec_opname, suffix, mode);
5598 }
5599}
79b87c74 5600
0f996086
CF
5601/* Like gen_libfunc, but verify that fixed-point operation is involved. */
5602
cd1440b1 5603void
0f996086 5604gen_fixed_libfunc (optab optable, const char *opname, char suffix,
ef4bddc2 5605 machine_mode mode)
0f996086
CF
5606{
5607 if (!ALL_FIXED_POINT_MODE_P (mode))
5608 return;
5609 gen_libfunc (optable, opname, suffix, mode);
5610}
5611
5612/* Like gen_libfunc, but verify that signed fixed-point operation is
5613 involved. */
5614
cd1440b1 5615void
0f996086 5616gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
ef4bddc2 5617 machine_mode mode)
0f996086
CF
5618{
5619 if (!SIGNED_FIXED_POINT_MODE_P (mode))
5620 return;
5621 gen_libfunc (optable, opname, suffix, mode);
5622}
5623
5624/* Like gen_libfunc, but verify that unsigned fixed-point operation is
5625 involved. */
5626
cd1440b1 5627void
0f996086 5628gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
ef4bddc2 5629 machine_mode mode)
0f996086
CF
5630{
5631 if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
5632 return;
5633 gen_libfunc (optable, opname, suffix, mode);
5634}
5635
8a33f100
JH
5636/* Like gen_libfunc, but verify that FP or INT operation is involved. */
5637
cd1440b1 5638void
8a33f100 5639gen_int_fp_libfunc (optab optable, const char *name, char suffix,
ef4bddc2 5640 machine_mode mode)
8a33f100
JH
5641{
5642 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5643 gen_fp_libfunc (optable, name, suffix, mode);
5644 if (INTEGRAL_MODE_P (mode))
5645 gen_int_libfunc (optable, name, suffix, mode);
5646}
5647
5648/* Like gen_libfunc, but verify that FP or INT operation is involved
5649 and add 'v' suffix for integer operation. */
5650
cd1440b1 5651void
8a33f100 5652gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
ef4bddc2 5653 machine_mode mode)
8a33f100
JH
5654{
5655 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5656 gen_fp_libfunc (optable, name, suffix, mode);
5657 if (GET_MODE_CLASS (mode) == MODE_INT)
5658 {
5659 int len = strlen (name);
d3bfe4de 5660 char *v_name = XALLOCAVEC (char, len + 2);
8a33f100
JH
5661 strcpy (v_name, name);
5662 v_name[len] = 'v';
5663 v_name[len + 1] = 0;
5664 gen_int_libfunc (optable, v_name, suffix, mode);
5665 }
b092b471
JW
5666}
5667
0f996086
CF
5668/* Like gen_libfunc, but verify that FP or INT or FIXED operation is
5669 involved. */
5670
cd1440b1 5671void
0f996086 5672gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
ef4bddc2 5673 machine_mode mode)
0f996086
CF
5674{
5675 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5676 gen_fp_libfunc (optable, name, suffix, mode);
5677 if (INTEGRAL_MODE_P (mode))
5678 gen_int_libfunc (optable, name, suffix, mode);
5679 if (ALL_FIXED_POINT_MODE_P (mode))
5680 gen_fixed_libfunc (optable, name, suffix, mode);
5681}
5682
5683/* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
5684 involved. */
5685
cd1440b1 5686void
0f996086 5687gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
ef4bddc2 5688 machine_mode mode)
0f996086
CF
5689{
5690 if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
5691 gen_fp_libfunc (optable, name, suffix, mode);
5692 if (INTEGRAL_MODE_P (mode))
5693 gen_int_libfunc (optable, name, suffix, mode);
5694 if (SIGNED_FIXED_POINT_MODE_P (mode))
5695 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5696}
5697
5698/* Like gen_libfunc, but verify that INT or FIXED operation is
5699 involved. */
5700
cd1440b1 5701void
0f996086 5702gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
ef4bddc2 5703 machine_mode mode)
0f996086
CF
5704{
5705 if (INTEGRAL_MODE_P (mode))
5706 gen_int_libfunc (optable, name, suffix, mode);
5707 if (ALL_FIXED_POINT_MODE_P (mode))
5708 gen_fixed_libfunc (optable, name, suffix, mode);
5709}
5710
5711/* Like gen_libfunc, but verify that INT or signed FIXED operation is
5712 involved. */
5713
cd1440b1 5714void
0f996086 5715gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
ef4bddc2 5716 machine_mode mode)
0f996086
CF
5717{
5718 if (INTEGRAL_MODE_P (mode))
5719 gen_int_libfunc (optable, name, suffix, mode);
5720 if (SIGNED_FIXED_POINT_MODE_P (mode))
5721 gen_signed_fixed_libfunc (optable, name, suffix, mode);
5722}
5723
5724/* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
5725 involved. */
5726
cd1440b1 5727void
0f996086 5728gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
ef4bddc2 5729 machine_mode mode)
0f996086
CF
5730{
5731 if (INTEGRAL_MODE_P (mode))
5732 gen_int_libfunc (optable, name, suffix, mode);
5733 if (UNSIGNED_FIXED_POINT_MODE_P (mode))
5734 gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
5735}
5736
85363ca0
ZW
5737/* Initialize the libfunc fields of an entire group of entries of an
5738 inter-mode-class conversion optab. The string formation rules are
5739 similar to the ones for init_libfuncs, above, but instead of having
5740 a mode name and an operand count these functions have two mode names
5741 and no operand count. */
8a33f100 5742
cd1440b1 5743void
8a33f100
JH
5744gen_interclass_conv_libfunc (convert_optab tab,
5745 const char *opname,
ef4bddc2
RS
5746 machine_mode tmode,
5747 machine_mode fmode)
85363ca0 5748{
85363ca0 5749 size_t opname_len = strlen (opname);
8a33f100 5750 size_t mname_len = 0;
85363ca0 5751
85363ca0
ZW
5752 const char *fname, *tname;
5753 const char *q;
cdbf4541 5754 int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
85363ca0 5755 char *libfunc_name, *suffix;
79b87c74 5756 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
85363ca0
ZW
5757 char *p;
5758
79b87c74
MM
5759 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5760 depends on which underlying decimal floating point format is used. */
5761 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5762
8a33f100 5763 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
85363ca0 5764
cdbf4541 5765 nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
79b87c74
MM
5766 nondec_name[0] = '_';
5767 nondec_name[1] = '_';
cdbf4541
BS
5768 if (targetm.libfunc_gnu_prefix)
5769 {
5770 nondec_name[2] = 'g';
5771 nondec_name[3] = 'n';
5772 nondec_name[4] = 'u';
5773 nondec_name[5] = '_';
5774 }
5775
5776 memcpy (&nondec_name[prefix_len], opname, opname_len);
5777 nondec_suffix = nondec_name + opname_len + prefix_len;
79b87c74 5778
d3bfe4de 5779 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
79b87c74
MM
5780 dec_name[0] = '_';
5781 dec_name[1] = '_';
5782 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5783 memcpy (&dec_name[2+dec_len], opname, opname_len);
5784 dec_suffix = dec_name + dec_len + opname_len + 2;
85363ca0 5785
8a33f100
JH
5786 fname = GET_MODE_NAME (fmode);
5787 tname = GET_MODE_NAME (tmode);
85363ca0 5788
c3284718 5789 if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
8a33f100
JH
5790 {
5791 libfunc_name = dec_name;
5792 suffix = dec_suffix;
5793 }
5794 else
5795 {
5796 libfunc_name = nondec_name;
5797 suffix = nondec_suffix;
5798 }
79b87c74 5799
8a33f100
JH
5800 p = suffix;
5801 for (q = fname; *q; p++, q++)
5802 *p = TOLOWER (*q);
5803 for (q = tname; *q; p++, q++)
5804 *p = TOLOWER (*q);
85363ca0 5805
8a33f100 5806 *p = '\0';
85363ca0 5807
8a33f100
JH
5808 set_conv_libfunc (tab, tmode, fmode,
5809 ggc_alloc_string (libfunc_name, p - libfunc_name));
85363ca0
ZW
5810}
5811
8a33f100
JH
5812/* Same as gen_interclass_conv_libfunc but verify that we are producing
5813 int->fp conversion. */
5814
cd1440b1 5815void
8a33f100
JH
5816gen_int_to_fp_conv_libfunc (convert_optab tab,
5817 const char *opname,
ef4bddc2
RS
5818 machine_mode tmode,
5819 machine_mode fmode)
8a33f100
JH
5820{
5821 if (GET_MODE_CLASS (fmode) != MODE_INT)
5822 return;
5823 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5824 return;
5825 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5826}
5827
5828/* ufloat_optab is special by using floatun for FP and floatuns decimal fp
5829 naming scheme. */
5830
cd1440b1 5831void
8a33f100
JH
5832gen_ufloat_conv_libfunc (convert_optab tab,
5833 const char *opname ATTRIBUTE_UNUSED,
ef4bddc2
RS
5834 machine_mode tmode,
5835 machine_mode fmode)
8a33f100
JH
5836{
5837 if (DECIMAL_FLOAT_MODE_P (tmode))
5838 gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
5839 else
5840 gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
5841}
5842
5843/* Same as gen_interclass_conv_libfunc but verify that we are producing
5844 fp->int conversion. */
5845
cd1440b1 5846void
8a33f100
JH
5847gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
5848 const char *opname,
ef4bddc2
RS
5849 machine_mode tmode,
5850 machine_mode fmode)
8a33f100
JH
5851{
5852 if (GET_MODE_CLASS (fmode) != MODE_INT)
5853 return;
5854 if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
5855 return;
5856 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5857}
5858
5859/* Same as gen_interclass_conv_libfunc but verify that we are producing
5860 fp->int conversion with no decimal floating point involved. */
5861
cd1440b1 5862void
8a33f100
JH
5863gen_fp_to_int_conv_libfunc (convert_optab tab,
5864 const char *opname,
ef4bddc2
RS
5865 machine_mode tmode,
5866 machine_mode fmode)
8a33f100
JH
5867{
5868 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5869 return;
5870 if (GET_MODE_CLASS (tmode) != MODE_INT)
5871 return;
5872 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
5873}
5874
fa10beec 5875/* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
8a33f100
JH
5876 The string formation rules are
5877 similar to the ones for init_libfunc, above. */
5878
cd1440b1 5879void
8a33f100 5880gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
ef4bddc2 5881 machine_mode tmode, machine_mode fmode)
85363ca0 5882{
85363ca0 5883 size_t opname_len = strlen (opname);
8a33f100 5884 size_t mname_len = 0;
85363ca0 5885
8a33f100 5886 const char *fname, *tname;
85363ca0 5887 const char *q;
cdbf4541 5888 int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
79b87c74 5889 char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
85363ca0
ZW
5890 char *libfunc_name, *suffix;
5891 char *p;
5892
79b87c74
MM
5893 /* If this is a decimal conversion, add the current BID vs. DPD prefix that
5894 depends on which underlying decimal floating point format is used. */
5895 const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
5896
8a33f100 5897 mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
85363ca0 5898
d3bfe4de 5899 nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
79b87c74
MM
5900 nondec_name[0] = '_';
5901 nondec_name[1] = '_';
cdbf4541
BS
5902 if (targetm.libfunc_gnu_prefix)
5903 {
5904 nondec_name[2] = 'g';
5905 nondec_name[3] = 'n';
5906 nondec_name[4] = 'u';
5907 nondec_name[5] = '_';
5908 }
5909 memcpy (&nondec_name[prefix_len], opname, opname_len);
5910 nondec_suffix = nondec_name + opname_len + prefix_len;
79b87c74 5911
d3bfe4de 5912 dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
79b87c74
MM
5913 dec_name[0] = '_';
5914 dec_name[1] = '_';
5915 memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
5916 memcpy (&dec_name[2 + dec_len], opname, opname_len);
5917 dec_suffix = dec_name + dec_len + opname_len + 2;
85363ca0 5918
8a33f100
JH
5919 fname = GET_MODE_NAME (fmode);
5920 tname = GET_MODE_NAME (tmode);
85363ca0 5921
c3284718 5922 if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
8a33f100
JH
5923 {
5924 libfunc_name = dec_name;
5925 suffix = dec_suffix;
5926 }
5927 else
5928 {
5929 libfunc_name = nondec_name;
5930 suffix = nondec_suffix;
5931 }
79b87c74 5932
8a33f100
JH
5933 p = suffix;
5934 for (q = fname; *q; p++, q++)
5935 *p = TOLOWER (*q);
5936 for (q = tname; *q; p++, q++)
5937 *p = TOLOWER (*q);
85363ca0 5938
8a33f100
JH
5939 *p++ = '2';
5940 *p = '\0';
85363ca0 5941
8a33f100
JH
5942 set_conv_libfunc (tab, tmode, fmode,
5943 ggc_alloc_string (libfunc_name, p - libfunc_name));
85363ca0
ZW
5944}
5945
8a33f100
JH
5946/* Pick proper libcall for trunc_optab. We need to chose if we do
5947 truncation or extension and interclass or intraclass. */
5948
cd1440b1 5949void
8a33f100
JH
5950gen_trunc_conv_libfunc (convert_optab tab,
5951 const char *opname,
ef4bddc2
RS
5952 machine_mode tmode,
5953 machine_mode fmode)
8a33f100
JH
5954{
5955 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5956 return;
5957 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5958 return;
5959 if (tmode == fmode)
5960 return;
5961
5962 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5963 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5964 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
b8698a0f 5965
8a33f100
JH
5966 if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
5967 return;
5968
5969 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5970 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
5971 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
5972 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
5973}
5974
5975/* Pick proper libcall for extend_optab. We need to chose if we do
5976 truncation or extension and interclass or intraclass. */
5977
cd1440b1 5978void
8a33f100
JH
5979gen_extend_conv_libfunc (convert_optab tab,
5980 const char *opname ATTRIBUTE_UNUSED,
ef4bddc2
RS
5981 machine_mode tmode,
5982 machine_mode fmode)
8a33f100
JH
5983{
5984 if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
5985 return;
5986 if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
5987 return;
5988 if (tmode == fmode)
5989 return;
5990
5991 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
5992 || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
5993 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
b8698a0f 5994
8a33f100
JH
5995 if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
5996 return;
5997
5998 if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
5999 && GET_MODE_CLASS (fmode) == MODE_FLOAT)
6000 || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
6001 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6002}
85363ca0 6003
0f996086
CF
6004/* Pick proper libcall for fract_optab. We need to chose if we do
6005 interclass or intraclass. */
6006
cd1440b1 6007void
0f996086
CF
6008gen_fract_conv_libfunc (convert_optab tab,
6009 const char *opname,
ef4bddc2
RS
6010 machine_mode tmode,
6011 machine_mode fmode)
0f996086
CF
6012{
6013 if (tmode == fmode)
6014 return;
6015 if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
6016 return;
6017
6018 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
6019 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6020 else
6021 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6022}
6023
6024/* Pick proper libcall for fractuns_optab. */
6025
cd1440b1 6026void
0f996086
CF
6027gen_fractuns_conv_libfunc (convert_optab tab,
6028 const char *opname,
ef4bddc2
RS
6029 machine_mode tmode,
6030 machine_mode fmode)
0f996086
CF
6031{
6032 if (tmode == fmode)
6033 return;
6034 /* One mode must be a fixed-point mode, and the other must be an integer
6035 mode. */
6036 if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
6037 || (ALL_FIXED_POINT_MODE_P (fmode)
6038 && GET_MODE_CLASS (tmode) == MODE_INT)))
6039 return;
6040
6041 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6042}
6043
6044/* Pick proper libcall for satfract_optab. We need to chose if we do
6045 interclass or intraclass. */
6046
cd1440b1 6047void
0f996086
CF
6048gen_satfract_conv_libfunc (convert_optab tab,
6049 const char *opname,
ef4bddc2
RS
6050 machine_mode tmode,
6051 machine_mode fmode)
0f996086
CF
6052{
6053 if (tmode == fmode)
6054 return;
6055 /* TMODE must be a fixed-point mode. */
6056 if (!ALL_FIXED_POINT_MODE_P (tmode))
6057 return;
6058
6059 if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
6060 gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
6061 else
6062 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6063}
6064
6065/* Pick proper libcall for satfractuns_optab. */
6066
cd1440b1 6067void
0f996086
CF
6068gen_satfractuns_conv_libfunc (convert_optab tab,
6069 const char *opname,
ef4bddc2
RS
6070 machine_mode tmode,
6071 machine_mode fmode)
0f996086
CF
6072{
6073 if (tmode == fmode)
6074 return;
6075 /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
6076 if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
6077 return;
6078
6079 gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
6080}
6081
61698f54 6082/* Hashtable callbacks for libfunc_decls. */
ee1315aa 6083
2a22f99c 6084struct libfunc_decl_hasher : ggc_hasher<tree>
61698f54 6085{
2a22f99c
TS
6086 static hashval_t
6087 hash (tree entry)
6088 {
6089 return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
6090 }
52859c77 6091
2a22f99c
TS
6092 static bool
6093 equal (tree decl, tree name)
6094 {
6095 return DECL_NAME (decl) == name;
6096 }
6097};
6098
6099/* A table of previously-created libfuncs, hashed by name. */
6100static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
52859c77 6101
f9417da1
RG
6102/* Build a decl for a libfunc named NAME. */
6103
6104tree
6105build_libfunc_function (const char *name)
6106{
6107 tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
6108 get_identifier (name),
6109 build_function_type (integer_type_node, NULL_TREE));
6110 /* ??? We don't have any type information except for this is
6111 a function. Pretend this is "int foo()". */
6112 DECL_ARTIFICIAL (decl) = 1;
6113 DECL_EXTERNAL (decl) = 1;
6114 TREE_PUBLIC (decl) = 1;
6115 gcc_assert (DECL_ASSEMBLER_NAME (decl));
6116
6117 /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
6118 are the flags assigned by targetm.encode_section_info. */
6119 SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
6120
6121 return decl;
6122}
6123
61698f54
RS
6124rtx
6125init_one_libfunc (const char *name)
6126{
6127 tree id, decl;
61698f54
RS
6128 hashval_t hash;
6129
6130 if (libfunc_decls == NULL)
2a22f99c 6131 libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
61698f54
RS
6132
6133 /* See if we have already created a libfunc decl for this function. */
6134 id = get_identifier (name);
eef4a603 6135 hash = IDENTIFIER_HASH_VALUE (id);
2a22f99c
TS
6136 tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
6137 decl = *slot;
61698f54
RS
6138 if (decl == NULL)
6139 {
6140 /* Create a new decl, so that it can be passed to
6141 targetm.encode_section_info. */
f9417da1 6142 decl = build_libfunc_function (name);
61698f54
RS
6143 *slot = decl;
6144 }
6145 return XEXP (DECL_RTL (decl), 0);
76095e2f
RH
6146}
6147
6b2b8871
JJ
6148/* Adjust the assembler name of libfunc NAME to ASMSPEC. */
6149
6150rtx
6151set_user_assembler_libfunc (const char *name, const char *asmspec)
6152{
6153 tree id, decl;
6b2b8871
JJ
6154 hashval_t hash;
6155
6156 id = get_identifier (name);
eef4a603 6157 hash = IDENTIFIER_HASH_VALUE (id);
2a22f99c 6158 tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
6b2b8871
JJ
6159 gcc_assert (slot);
6160 decl = (tree) *slot;
6161 set_user_assembler_name (decl, asmspec);
6162 return XEXP (DECL_RTL (decl), 0);
6163}
6164
c15c90bb
ZW
6165/* Call this to reset the function entry for one optab (OPTABLE) in mode
6166 MODE to NAME, which should be either 0 or a string constant. */
6167void
ef4bddc2 6168set_optab_libfunc (optab op, machine_mode mode, const char *name)
c15c90bb 6169{
8a33f100
JH
6170 rtx val;
6171 struct libfunc_entry e;
6172 struct libfunc_entry **slot;
cd1440b1
RH
6173
6174 e.op = op;
8a33f100
JH
6175 e.mode1 = mode;
6176 e.mode2 = VOIDmode;
6177
c15c90bb 6178 if (name)
8a33f100 6179 val = init_one_libfunc (name);
c15c90bb 6180 else
8a33f100 6181 val = 0;
2a22f99c 6182 slot = libfunc_hash->find_slot (&e, INSERT);
8a33f100 6183 if (*slot == NULL)
766090c2 6184 *slot = ggc_alloc<libfunc_entry> ();
cd1440b1 6185 (*slot)->op = op;
8a33f100
JH
6186 (*slot)->mode1 = mode;
6187 (*slot)->mode2 = VOIDmode;
6188 (*slot)->libfunc = val;
c15c90bb
ZW
6189}
6190
85363ca0
ZW
6191/* Call this to reset the function entry for one conversion optab
6192 (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
6193 either 0 or a string constant. */
6194void
ef4bddc2
RS
6195set_conv_libfunc (convert_optab optab, machine_mode tmode,
6196 machine_mode fmode, const char *name)
85363ca0 6197{
8a33f100
JH
6198 rtx val;
6199 struct libfunc_entry e;
6200 struct libfunc_entry **slot;
cd1440b1
RH
6201
6202 e.op = optab;
8a33f100
JH
6203 e.mode1 = tmode;
6204 e.mode2 = fmode;
6205
85363ca0 6206 if (name)
8a33f100 6207 val = init_one_libfunc (name);
85363ca0 6208 else
8a33f100 6209 val = 0;
2a22f99c 6210 slot = libfunc_hash->find_slot (&e, INSERT);
8a33f100 6211 if (*slot == NULL)
766090c2 6212 *slot = ggc_alloc<libfunc_entry> ();
cd1440b1 6213 (*slot)->op = optab;
8a33f100
JH
6214 (*slot)->mode1 = tmode;
6215 (*slot)->mode2 = fmode;
6216 (*slot)->libfunc = val;
85363ca0
ZW
6217}
6218
b5deb7b6 6219/* Call this to initialize the contents of the optabs
77c9c6c2
RK
6220 appropriately for the current target machine. */
6221
6222void
0c20a65f 6223init_optabs (void)
77c9c6c2 6224{
3e9c326a 6225 if (libfunc_hash)
2a22f99c 6226 libfunc_hash->empty ();
3e9c326a 6227 else
2a22f99c 6228 libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
c0742514 6229
5d81dc5b 6230 /* Fill in the optabs with the insns we support. */
135204dd 6231 init_all_optabs (this_fn_optabs);
5d81dc5b 6232
8a33f100
JH
6233 /* The ffs function operates on `int'. Fall back on it if we do not
6234 have a libgcc2 function for that width. */
6235 if (INT_TYPE_SIZE < BITS_PER_WORD)
0f900dfa
JJ
6236 set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
6237 "ffs");
76095e2f 6238
167fa32c
EC
6239 /* Explicitly initialize the bswap libfuncs since we need them to be
6240 valid for things other than word_mode. */
cdbf4541
BS
6241 if (targetm.libfunc_gnu_prefix)
6242 {
6243 set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
6244 set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
6245 }
6246 else
6247 {
6248 set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
6249 set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
6250 }
167fa32c 6251
85363ca0
ZW
6252 /* Use cabs for double complex abs, since systems generally have cabs.
6253 Don't define any libcall for float complex, so that cabs will be used. */
6254 if (complex_double_type_node)
cd1440b1
RH
6255 set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
6256 "cabs");
76095e2f 6257
9602f5a0 6258 abort_libfunc = init_one_libfunc ("abort");
76095e2f 6259 memcpy_libfunc = init_one_libfunc ("memcpy");
b215b52e 6260 memmove_libfunc = init_one_libfunc ("memmove");
76095e2f 6261 memcmp_libfunc = init_one_libfunc ("memcmp");
76095e2f 6262 memset_libfunc = init_one_libfunc ("memset");
68d28100 6263 setbits_libfunc = init_one_libfunc ("__setbits");
76095e2f 6264
6e6a07d2 6265#ifndef DONT_USE_BUILTIN_SETJMP
76095e2f
RH
6266 setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
6267 longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
27a36778 6268#else
76095e2f
RH
6269 setjmp_libfunc = init_one_libfunc ("setjmp");
6270 longjmp_libfunc = init_one_libfunc ("longjmp");
27a36778 6271#endif
52a11cbf
RH
6272 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
6273 unwind_sjlj_unregister_libfunc
6274 = init_one_libfunc ("_Unwind_SjLj_Unregister");
6adb4e3a 6275
07417085
KR
6276 /* For function entry/exit instrumentation. */
6277 profile_function_entry_libfunc
76095e2f 6278 = init_one_libfunc ("__cyg_profile_func_enter");
07417085 6279 profile_function_exit_libfunc
76095e2f 6280 = init_one_libfunc ("__cyg_profile_func_exit");
07417085 6281
68d28100 6282 gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
68d28100 6283
159c2aed 6284 /* Allow the target to add more libcalls or rename some, etc. */
c15c90bb 6285 targetm.init_libfuncs ();
77c9c6c2 6286}
b3f8d95d 6287
4b1baac8
RS
6288/* Use the current target and options to initialize
6289 TREE_OPTIMIZATION_OPTABS (OPTNODE). */
135204dd
AH
6290
6291void
4b1baac8 6292init_tree_optimization_optabs (tree optnode)
135204dd 6293{
4b1baac8
RS
6294 /* Quick exit if we have already computed optabs for this target. */
6295 if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs)
6296 return;
135204dd 6297
4b1baac8
RS
6298 /* Forget any previous information and set up for the current target. */
6299 TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs;
135204dd 6300 struct target_optabs *tmp_optabs = (struct target_optabs *)
4b1baac8
RS
6301 TREE_OPTIMIZATION_OPTABS (optnode);
6302 if (tmp_optabs)
6303 memset (tmp_optabs, 0, sizeof (struct target_optabs));
6304 else
766090c2 6305 tmp_optabs = ggc_alloc<target_optabs> ();
135204dd
AH
6306
6307 /* Generate a new set of optabs into tmp_optabs. */
6308 init_all_optabs (tmp_optabs);
6309
6310 /* If the optabs changed, record it. */
6311 if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
cc349a39 6312 TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
135204dd
AH
6313 else
6314 {
6315 TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
6316 ggc_free (tmp_optabs);
6317 }
6318}
6319
cedb4a1a
RH
6320/* A helper function for init_sync_libfuncs. Using the basename BASE,
6321 install libfuncs into TAB for BASE_N for 1 <= N <= MAX. */
6322
6323static void
6324init_sync_libfuncs_1 (optab tab, const char *base, int max)
6325{
ef4bddc2 6326 machine_mode mode;
cedb4a1a
RH
6327 char buf[64];
6328 size_t len = strlen (base);
6329 int i;
6330
6331 gcc_assert (max <= 8);
6332 gcc_assert (len + 3 < sizeof (buf));
6333
6334 memcpy (buf, base, len);
6335 buf[len] = '_';
6336 buf[len + 1] = '0';
6337 buf[len + 2] = '\0';
6338
6339 mode = QImode;
022c0cd1 6340 for (i = 1; i <= max; i *= 2)
cedb4a1a
RH
6341 {
6342 buf[len + 1] = '0' + i;
6343 set_optab_libfunc (tab, mode, buf);
6344 mode = GET_MODE_2XWIDER_MODE (mode);
6345 }
6346}
6347
6348void
6349init_sync_libfuncs (int max)
6350{
e8053cf5
RH
6351 if (!flag_sync_libcalls)
6352 return;
6353
cedb4a1a
RH
6354 init_sync_libfuncs_1 (sync_compare_and_swap_optab,
6355 "__sync_val_compare_and_swap", max);
6356 init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
6357 "__sync_lock_test_and_set", max);
6358
6359 init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
6360 init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
ff47a151 6361 init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
cedb4a1a
RH
6362 init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
6363 init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
6364 init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
6365
6366 init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
6367 init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
ff47a151 6368 init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
cedb4a1a
RH
6369 init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
6370 init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
6371 init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
6372}
6373
b3f8d95d
MM
6374/* Print information about the current contents of the optabs on
6375 STDERR. */
6376
24e47c76 6377DEBUG_FUNCTION void
b3f8d95d
MM
6378debug_optab_libfuncs (void)
6379{
cd1440b1 6380 int i, j, k;
b3f8d95d
MM
6381
6382 /* Dump the arithmetic optabs. */
cd1440b1 6383 for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i)
b3f8d95d
MM
6384 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6385 {
ef4bddc2 6386 rtx l = optab_libfunc ((optab) i, (machine_mode) j);
8a33f100 6387 if (l)
b3f8d95d 6388 {
8a33f100 6389 gcc_assert (GET_CODE (l) == SYMBOL_REF);
5906d013 6390 fprintf (stderr, "%s\t%s:\t%s\n",
cd1440b1 6391 GET_RTX_NAME (optab_to_code ((optab) i)),
b3f8d95d 6392 GET_MODE_NAME (j),
8a33f100 6393 XSTR (l, 0));
b3f8d95d
MM
6394 }
6395 }
6396
6397 /* Dump the conversion optabs. */
cd1440b1 6398 for (i = FIRST_CONV_OPTAB; i <= LAST_CONVLIB_OPTAB; ++i)
b3f8d95d
MM
6399 for (j = 0; j < NUM_MACHINE_MODES; ++j)
6400 for (k = 0; k < NUM_MACHINE_MODES; ++k)
6401 {
ef4bddc2
RS
6402 rtx l = convert_optab_libfunc ((optab) i, (machine_mode) j,
6403 (machine_mode) k);
8a33f100 6404 if (l)
b3f8d95d 6405 {
8a33f100 6406 gcc_assert (GET_CODE (l) == SYMBOL_REF);
5906d013 6407 fprintf (stderr, "%s\t%s\t%s:\t%s\n",
cd1440b1 6408 GET_RTX_NAME (optab_to_code ((optab) i)),
b3f8d95d
MM
6409 GET_MODE_NAME (j),
6410 GET_MODE_NAME (k),
8a33f100 6411 XSTR (l, 0));
b3f8d95d
MM
6412 }
6413 }
6414}
6415
7e1966ca 6416\f
e0cd0770
JC
6417/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
6418 CODE. Return 0 on failure. */
6419
6420rtx
f90b7a5a 6421gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
e0cd0770 6422{
ef4bddc2 6423 machine_mode mode = GET_MODE (op1);
842a431a
DM
6424 enum insn_code icode;
6425 rtx insn;
f90b7a5a 6426 rtx trap_rtx;
e0cd0770
JC
6427
6428 if (mode == VOIDmode)
6429 return 0;
6430
947131ba 6431 icode = optab_handler (ctrap_optab, mode);
842a431a
DM
6432 if (icode == CODE_FOR_nothing)
6433 return 0;
6434
f90b7a5a 6435 /* Some targets only accept a zero trap code. */
2ef6ce06 6436 if (!insn_operand_matches (icode, 3, tcode))
f90b7a5a
PB
6437 return 0;
6438
6439 do_pending_stack_adjust ();
842a431a 6440 start_sequence ();
f90b7a5a
PB
6441 prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
6442 &trap_rtx, &mode);
6443 if (!trap_rtx)
6444 insn = NULL_RTX;
6445 else
6446 insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
6447 tcode);
6448
6449 /* If that failed, then give up. */
6450 if (insn == 0)
d893ccde
RH
6451 {
6452 end_sequence ();
6453 return 0;
6454 }
842a431a 6455
f90b7a5a
PB
6456 emit_insn (insn);
6457 insn = get_insns ();
842a431a 6458 end_sequence ();
842a431a 6459 return insn;
e0cd0770 6460}
e2500fed 6461
7ce67fbe
DP
6462/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
6463 or unsigned operation code. */
6464
2d52a3a1 6465enum rtx_code
7ce67fbe
DP
6466get_rtx_code (enum tree_code tcode, bool unsignedp)
6467{
6468 enum rtx_code code;
6469 switch (tcode)
6470 {
6471 case EQ_EXPR:
6472 code = EQ;
6473 break;
6474 case NE_EXPR:
6475 code = NE;
6476 break;
6477 case LT_EXPR:
6478 code = unsignedp ? LTU : LT;
6479 break;
6480 case LE_EXPR:
6481 code = unsignedp ? LEU : LE;
6482 break;
6483 case GT_EXPR:
6484 code = unsignedp ? GTU : GT;
6485 break;
6486 case GE_EXPR:
6487 code = unsignedp ? GEU : GE;
6488 break;
c414ac1d 6489
7ce67fbe
DP
6490 case UNORDERED_EXPR:
6491 code = UNORDERED;
6492 break;
6493 case ORDERED_EXPR:
6494 code = ORDERED;
6495 break;
6496 case UNLT_EXPR:
6497 code = UNLT;
6498 break;
6499 case UNLE_EXPR:
6500 code = UNLE;
6501 break;
6502 case UNGT_EXPR:
6503 code = UNGT;
6504 break;
6505 case UNGE_EXPR:
6506 code = UNGE;
6507 break;
6508 case UNEQ_EXPR:
6509 code = UNEQ;
6510 break;
6511 case LTGT_EXPR:
6512 code = LTGT;
6513 break;
6514
2d52a3a1
ZC
6515 case BIT_AND_EXPR:
6516 code = AND;
6517 break;
6518
6519 case BIT_IOR_EXPR:
6520 code = IOR;
6521 break;
6522
7ce67fbe 6523 default:
e3feb571 6524 gcc_unreachable ();
7ce67fbe
DP
6525 }
6526 return code;
6527}
6528
6529/* Return comparison rtx for COND. Use UNSIGNEDP to select signed or
6530 unsigned operators. Do not generate compare instruction. */
6531
6532static rtx
e6ed43b0
MG
6533vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,
6534 bool unsignedp, enum insn_code icode)
7ce67fbe 6535{
a5c7d693 6536 struct expand_operand ops[2];
7ce67fbe 6537 rtx rtx_op0, rtx_op1;
e6ed43b0 6538 enum rtx_code rcode = get_rtx_code (tcode, unsignedp);
7ce67fbe 6539
e6ed43b0 6540 gcc_assert (TREE_CODE_CLASS (tcode) == tcc_comparison);
c414ac1d 6541
7ce67fbe 6542 /* Expand operands. */
49452c07
UB
6543 rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
6544 EXPAND_STACK_PARM);
6545 rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
6546 EXPAND_STACK_PARM);
7ce67fbe 6547
a5c7d693
RS
6548 create_input_operand (&ops[0], rtx_op0, GET_MODE (rtx_op0));
6549 create_input_operand (&ops[1], rtx_op1, GET_MODE (rtx_op1));
6550 if (!maybe_legitimize_operands (icode, 4, 2, ops))
6551 gcc_unreachable ();
6552 return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
7ce67fbe
DP
6553}
6554
cf7aa6a3
AL
6555/* Return true if VEC_PERM_EXPR of arbitrary input vectors can be expanded using
6556 SIMD extensions of the CPU. SEL may be NULL, which stands for an unknown
6557 constant. Note that additional permutations representing whole-vector shifts
6558 may also be handled via the vec_shr optab, but only where the second input
6559 vector is entirely constant zeroes; this case is not dealt with here. */
d7943c8b 6560
f90e8e2e 6561bool
ef4bddc2 6562can_vec_perm_p (machine_mode mode, bool variable,
22e4dee7 6563 const unsigned char *sel)
f90e8e2e 6564{
ef4bddc2 6565 machine_mode qimode;
d7943c8b
RH
6566
6567 /* If the target doesn't implement a vector mode for the vector type,
6568 then no operations are supported. */
6569 if (!VECTOR_MODE_P (mode))
6570 return false;
f90e8e2e 6571
22e4dee7 6572 if (!variable)
d7943c8b
RH
6573 {
6574 if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
22e4dee7
RH
6575 && (sel == NULL
6576 || targetm.vectorize.vec_perm_const_ok == NULL
6577 || targetm.vectorize.vec_perm_const_ok (mode, sel)))
d7943c8b
RH
6578 return true;
6579 }
6580
6581 if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
f90e8e2e
AS
6582 return true;
6583
d7943c8b 6584 /* We allow fallback to a QI vector mode, and adjust the mask. */
22e4dee7
RH
6585 if (GET_MODE_INNER (mode) == QImode)
6586 return false;
d7943c8b
RH
6587 qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
6588 if (!VECTOR_MODE_P (qimode))
6589 return false;
6590
6591 /* ??? For completeness, we ought to check the QImode version of
6592 vec_perm_const_optab. But all users of this implicit lowering
6593 feature implement the variable vec_perm_optab. */
6594 if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
f90e8e2e
AS
6595 return false;
6596
22e4dee7 6597 /* In order to support the lowering of variable permutations,
d7943c8b 6598 we need to support shifts and adds. */
22e4dee7 6599 if (variable)
d7943c8b
RH
6600 {
6601 if (GET_MODE_UNIT_SIZE (mode) > 2
6602 && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
6603 && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
6604 return false;
6605 if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
6606 return false;
6607 }
6608
6609 return true;
f90e8e2e
AS
6610}
6611
cf7aa6a3
AL
6612/* Checks if vec_perm mask SEL is a constant equivalent to a shift of the first
6613 vec_perm operand, assuming the second operand is a constant vector of zeroes.
6614 Return the shift distance in bits if so, or NULL_RTX if the vec_perm is not a
6615 shift. */
6616static rtx
6617shift_amt_for_vec_perm_mask (rtx sel)
6618{
6619 unsigned int i, first, nelt = GET_MODE_NUNITS (GET_MODE (sel));
6620 unsigned int bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (sel)));
6621
6622 if (GET_CODE (sel) != CONST_VECTOR)
6623 return NULL_RTX;
6624
6625 first = INTVAL (CONST_VECTOR_ELT (sel, 0));
6626 if (first >= 2*nelt)
6627 return NULL_RTX;
6628 for (i = 1; i < nelt; i++)
6629 {
6630 int idx = INTVAL (CONST_VECTOR_ELT (sel, i));
6631 unsigned int expected = (i + first) & (2 * nelt - 1);
6632 /* Indices into the second vector are all equivalent. */
6633 if (idx < 0 || (MIN (nelt, (unsigned) idx) != MIN (nelt, expected)))
6634 return NULL_RTX;
6635 }
6636
cf7aa6a3
AL
6637 return GEN_INT (first * bitsize);
6638}
6639
22e4dee7 6640/* A subroutine of expand_vec_perm for expanding one vec_perm insn. */
d7943c8b
RH
6641
6642static rtx
22e4dee7
RH
6643expand_vec_perm_1 (enum insn_code icode, rtx target,
6644 rtx v0, rtx v1, rtx sel)
f90e8e2e 6645{
ef4bddc2
RS
6646 machine_mode tmode = GET_MODE (target);
6647 machine_mode smode = GET_MODE (sel);
f90e8e2e 6648 struct expand_operand ops[4];
f90e8e2e 6649
d7943c8b
RH
6650 create_output_operand (&ops[0], target, tmode);
6651 create_input_operand (&ops[3], sel, smode);
f90e8e2e 6652
d7943c8b
RH
6653 /* Make an effort to preserve v0 == v1. The target expander is able to
6654 rely on this to determine if we're permuting a single input operand. */
6655 if (rtx_equal_p (v0, v1))
f90e8e2e 6656 {
d7943c8b
RH
6657 if (!insn_operand_matches (icode, 1, v0))
6658 v0 = force_reg (tmode, v0);
6659 gcc_checking_assert (insn_operand_matches (icode, 1, v0));
6660 gcc_checking_assert (insn_operand_matches (icode, 2, v0));
f90e8e2e 6661
d7943c8b
RH
6662 create_fixed_operand (&ops[1], v0);
6663 create_fixed_operand (&ops[2], v0);
6664 }
6665 else
6666 {
6667 create_input_operand (&ops[1], v0, tmode);
cf7aa6a3
AL
6668 /* See if this can be handled with a vec_shr. We only do this if the
6669 second vector is all zeroes. */
6670 enum insn_code shift_code = optab_handler (vec_shr_optab, GET_MODE (v0));
6671 if (v1 == CONST0_RTX (GET_MODE (v1)) && shift_code)
6672 if (rtx shift_amt = shift_amt_for_vec_perm_mask (sel))
6673 {
6674 create_convert_operand_from_type (&ops[2], shift_amt,
6675 sizetype_tab[(int) stk_sizetype]);
6676 if (maybe_expand_insn (shift_code, 3, ops))
6677 return ops[0].value;
6678 }
d7943c8b
RH
6679 create_input_operand (&ops[2], v1, tmode);
6680 }
f90e8e2e 6681
d7943c8b
RH
6682 if (maybe_expand_insn (icode, 4, ops))
6683 return ops[0].value;
6684 return NULL_RTX;
6685}
f90e8e2e 6686
22e4dee7
RH
6687/* Generate instructions for vec_perm optab given its mode
6688 and three operands. */
6689
d7943c8b 6690rtx
ef4bddc2 6691expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
d7943c8b
RH
6692{
6693 enum insn_code icode;
ef4bddc2 6694 machine_mode qimode;
d7943c8b 6695 unsigned int i, w, e, u;
4cb110fb 6696 rtx tmp, sel_qi = NULL;
22e4dee7 6697 rtvec vec;
d7943c8b 6698
22e4dee7 6699 if (!target || GET_MODE (target) != mode)
d7943c8b 6700 target = gen_reg_rtx (mode);
22e4dee7
RH
6701
6702 w = GET_MODE_SIZE (mode);
6703 e = GET_MODE_NUNITS (mode);
6704 u = GET_MODE_UNIT_SIZE (mode);
6705
6706 /* Set QIMODE to a different vector mode with byte elements.
6707 If no such mode, or if MODE already has byte elements, use VOIDmode. */
6708 qimode = VOIDmode;
6709 if (GET_MODE_INNER (mode) != QImode)
6710 {
6711 qimode = mode_for_vector (QImode, w);
6712 if (!VECTOR_MODE_P (qimode))
6713 qimode = VOIDmode;
6714 }
f90e8e2e 6715
d7943c8b 6716 /* If the input is a constant, expand it specially. */
ccdfb0e2
RH
6717 gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);
6718 if (GET_CODE (sel) == CONST_VECTOR)
d7943c8b
RH
6719 {
6720 icode = direct_optab_handler (vec_perm_const_optab, mode);
22e4dee7
RH
6721 if (icode != CODE_FOR_nothing)
6722 {
6723 tmp = expand_vec_perm_1 (icode, target, v0, v1, sel);
6724 if (tmp)
6725 return tmp;
6726 }
6727
6728 /* Fall back to a constant byte-based permutation. */
6729 if (qimode != VOIDmode)
6730 {
4cb110fb
RH
6731 vec = rtvec_alloc (w);
6732 for (i = 0; i < e; ++i)
22e4dee7 6733 {
4cb110fb 6734 unsigned int j, this_e;
22e4dee7 6735
ccdfb0e2 6736 this_e = INTVAL (CONST_VECTOR_ELT (sel, i));
4cb110fb
RH
6737 this_e &= 2 * e - 1;
6738 this_e *= u;
22e4dee7 6739
4cb110fb
RH
6740 for (j = 0; j < u; ++j)
6741 RTVEC_ELT (vec, i * u + j) = GEN_INT (this_e + j);
6742 }
6743 sel_qi = gen_rtx_CONST_VECTOR (qimode, vec);
22e4dee7 6744
4cb110fb
RH
6745 icode = direct_optab_handler (vec_perm_const_optab, qimode);
6746 if (icode != CODE_FOR_nothing)
6747 {
d8c84975
JJ
6748 tmp = mode != qimode ? gen_reg_rtx (qimode) : target;
6749 tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0),
22e4dee7
RH
6750 gen_lowpart (qimode, v1), sel_qi);
6751 if (tmp)
6752 return gen_lowpart (mode, tmp);
6753 }
6754 }
f90e8e2e
AS
6755 }
6756
22e4dee7 6757 /* Otherwise expand as a fully variable permuation. */
2205ed25 6758 icode = direct_optab_handler (vec_perm_optab, mode);
22e4dee7
RH
6759 if (icode != CODE_FOR_nothing)
6760 {
6761 tmp = expand_vec_perm_1 (icode, target, v0, v1, sel);
6762 if (tmp)
6763 return tmp;
6764 }
d7943c8b
RH
6765
6766 /* As a special case to aid several targets, lower the element-based
6767 permutation to a byte-based permutation and try again. */
22e4dee7 6768 if (qimode == VOIDmode)
d7943c8b 6769 return NULL_RTX;
d7943c8b 6770 icode = direct_optab_handler (vec_perm_optab, qimode);
f90e8e2e 6771 if (icode == CODE_FOR_nothing)
d7943c8b 6772 return NULL_RTX;
f90e8e2e 6773
4cb110fb
RH
6774 if (sel_qi == NULL)
6775 {
6776 /* Multiply each element by its byte size. */
ef4bddc2 6777 machine_mode selmode = GET_MODE (sel);
4cb110fb
RH
6778 if (u == 2)
6779 sel = expand_simple_binop (selmode, PLUS, sel, sel,
6780 sel, 0, OPTAB_DIRECT);
6781 else
6782 sel = expand_simple_binop (selmode, ASHIFT, sel,
6783 GEN_INT (exact_log2 (u)),
6784 sel, 0, OPTAB_DIRECT);
6785 gcc_assert (sel != NULL);
6786
6787 /* Broadcast the low byte each element into each of its bytes. */
6788 vec = rtvec_alloc (w);
6789 for (i = 0; i < w; ++i)
6790 {
6791 int this_e = i / u * u;
6792 if (BYTES_BIG_ENDIAN)
6793 this_e += u - 1;
6794 RTVEC_ELT (vec, i) = GEN_INT (this_e);
6795 }
6796 tmp = gen_rtx_CONST_VECTOR (qimode, vec);
6797 sel = gen_lowpart (qimode, sel);
b96d19ff 6798 sel = expand_vec_perm (qimode, sel, sel, tmp, NULL);
4cb110fb
RH
6799 gcc_assert (sel != NULL);
6800
6801 /* Add the byte offset to each byte element. */
6802 /* Note that the definition of the indicies here is memory ordering,
6803 so there should be no difference between big and little endian. */
6804 vec = rtvec_alloc (w);
6805 for (i = 0; i < w; ++i)
6806 RTVEC_ELT (vec, i) = GEN_INT (i % u);
6807 tmp = gen_rtx_CONST_VECTOR (qimode, vec);
6808 sel_qi = expand_simple_binop (qimode, PLUS, sel, tmp,
6809 sel, 0, OPTAB_DIRECT);
6810 gcc_assert (sel_qi != NULL);
6811 }
22e4dee7 6812
d8c84975
JJ
6813 tmp = mode != qimode ? gen_reg_rtx (qimode) : target;
6814 tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0),
4cb110fb 6815 gen_lowpart (qimode, v1), sel_qi);
22e4dee7
RH
6816 if (tmp)
6817 tmp = gen_lowpart (mode, tmp);
6818 return tmp;
f90e8e2e
AS
6819}
6820
e9e1d143
RG
6821/* Return insn code for a conditional operator with a comparison in
6822 mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
c414ac1d
EC
6823
6824static inline enum insn_code
ef4bddc2 6825get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
7ce67fbe
DP
6826{
6827 enum insn_code icode = CODE_FOR_nothing;
e9e1d143
RG
6828 if (uns)
6829 icode = convert_optab_handler (vcondu_optab, vmode, cmode);
7ce67fbe 6830 else
e9e1d143 6831 icode = convert_optab_handler (vcond_optab, vmode, cmode);
7ce67fbe
DP
6832 return icode;
6833}
6834
6835/* Return TRUE iff, appropriate vector insns are available
e9e1d143
RG
6836 for vector cond expr with vector type VALUE_TYPE and a comparison
6837 with operand vector types in CMP_OP_TYPE. */
7ce67fbe
DP
6838
6839bool
e9e1d143 6840expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
7ce67fbe 6841{
ef4bddc2
RS
6842 machine_mode value_mode = TYPE_MODE (value_type);
6843 machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
e9e1d143
RG
6844 if (GET_MODE_SIZE (value_mode) != GET_MODE_SIZE (cmp_op_mode)
6845 || GET_MODE_NUNITS (value_mode) != GET_MODE_NUNITS (cmp_op_mode)
6846 || get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
6847 TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
7ce67fbe
DP
6848 return false;
6849 return true;
6850}
6851
8e7aa1f9
MM
6852/* Generate insns for a VEC_COND_EXPR, given its TYPE and its
6853 three operands. */
7ce67fbe
DP
6854
6855rtx
8e7aa1f9
MM
6856expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
6857 rtx target)
7ce67fbe 6858{
a5c7d693 6859 struct expand_operand ops[6];
7ce67fbe 6860 enum insn_code icode;
a5c7d693 6861 rtx comparison, rtx_op1, rtx_op2;
ef4bddc2
RS
6862 machine_mode mode = TYPE_MODE (vec_cond_type);
6863 machine_mode cmp_op_mode;
e9e1d143 6864 bool unsignedp;
e6ed43b0
MG
6865 tree op0a, op0b;
6866 enum tree_code tcode;
e9e1d143 6867
e6ed43b0
MG
6868 if (COMPARISON_CLASS_P (op0))
6869 {
6870 op0a = TREE_OPERAND (op0, 0);
6871 op0b = TREE_OPERAND (op0, 1);
6872 tcode = TREE_CODE (op0);
6873 }
6874 else
6875 {
6876 /* Fake op0 < 0. */
6877 gcc_assert (!TYPE_UNSIGNED (TREE_TYPE (op0)));
6878 op0a = op0;
6879 op0b = build_zero_cst (TREE_TYPE (op0));
6880 tcode = LT_EXPR;
6881 }
6882 unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
6883 cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
e9e1d143 6884
e9e1d143
RG
6885
6886 gcc_assert (GET_MODE_SIZE (mode) == GET_MODE_SIZE (cmp_op_mode)
6887 && GET_MODE_NUNITS (mode) == GET_MODE_NUNITS (cmp_op_mode));
7ce67fbe 6888
e9e1d143 6889 icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
7ce67fbe
DP
6890 if (icode == CODE_FOR_nothing)
6891 return 0;
6892
e6ed43b0 6893 comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode);
8e7aa1f9 6894 rtx_op1 = expand_normal (op1);
8e7aa1f9 6895 rtx_op2 = expand_normal (op2);
7ce67fbe 6896
a5c7d693
RS
6897 create_output_operand (&ops[0], target, mode);
6898 create_input_operand (&ops[1], rtx_op1, mode);
6899 create_input_operand (&ops[2], rtx_op2, mode);
6900 create_fixed_operand (&ops[3], comparison);
6901 create_fixed_operand (&ops[4], XEXP (comparison, 0));
6902 create_fixed_operand (&ops[5], XEXP (comparison, 1));
6903 expand_insn (icode, 6, ops);
6904 return ops[0].value;
7ce67fbe 6905}
48ae6c13 6906
00f07b86
RH
6907/* Return non-zero if a highpart multiply is supported of can be synthisized.
6908 For the benefit of expand_mult_highpart, the return value is 1 for direct,
6909 2 for even/odd widening, and 3 for hi/lo widening. */
6910
6911int
ef4bddc2 6912can_mult_highpart_p (machine_mode mode, bool uns_p)
00f07b86
RH
6913{
6914 optab op;
6915 unsigned char *sel;
6916 unsigned i, nunits;
6917
6918 op = uns_p ? umul_highpart_optab : smul_highpart_optab;
6919 if (optab_handler (op, mode) != CODE_FOR_nothing)
6920 return 1;
6921
6922 /* If the mode is an integral vector, synth from widening operations. */
6923 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
6924 return 0;
6925
6926 nunits = GET_MODE_NUNITS (mode);
6927 sel = XALLOCAVEC (unsigned char, nunits);
6928
6929 op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
6930 if (optab_handler (op, mode) != CODE_FOR_nothing)
6931 {
6932 op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
6933 if (optab_handler (op, mode) != CODE_FOR_nothing)
6934 {
6935 for (i = 0; i < nunits; ++i)
6936 sel[i] = !BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0);
6937 if (can_vec_perm_p (mode, false, sel))
6938 return 2;
6939 }
6940 }
6941
6942 op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
6943 if (optab_handler (op, mode) != CODE_FOR_nothing)
6944 {
6945 op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
6946 if (optab_handler (op, mode) != CODE_FOR_nothing)
6947 {
6948 for (i = 0; i < nunits; ++i)
6949 sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1);
6950 if (can_vec_perm_p (mode, false, sel))
6951 return 3;
6952 }
6953 }
6954
6955 return 0;
6956}
6957
6958/* Expand a highpart multiply. */
6959
6960rtx
ef4bddc2 6961expand_mult_highpart (machine_mode mode, rtx op0, rtx op1,
00f07b86
RH
6962 rtx target, bool uns_p)
6963{
6964 struct expand_operand eops[3];
6965 enum insn_code icode;
6966 int method, i, nunits;
ef4bddc2 6967 machine_mode wmode;
00f07b86
RH
6968 rtx m1, m2, perm;
6969 optab tab1, tab2;
6970 rtvec v;
6971
6972 method = can_mult_highpart_p (mode, uns_p);
6973 switch (method)
6974 {
6975 case 0:
6976 return NULL_RTX;
6977 case 1:
6978 tab1 = uns_p ? umul_highpart_optab : smul_highpart_optab;
6979 return expand_binop (mode, tab1, op0, op1, target, uns_p,
6980 OPTAB_LIB_WIDEN);
6981 case 2:
6982 tab1 = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
6983 tab2 = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
6984 break;
6985 case 3:
6986 tab1 = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
6987 tab2 = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
6988 if (BYTES_BIG_ENDIAN)
6989 {
6990 optab t = tab1;
6991 tab1 = tab2;
6992 tab2 = t;
6993 }
6994 break;
6995 default:
6996 gcc_unreachable ();
6997 }
6998
6999 icode = optab_handler (tab1, mode);
7000 nunits = GET_MODE_NUNITS (mode);
7001 wmode = insn_data[icode].operand[0].mode;
7002 gcc_checking_assert (2 * GET_MODE_NUNITS (wmode) == nunits);
7003 gcc_checking_assert (GET_MODE_SIZE (wmode) == GET_MODE_SIZE (mode));
7004
7005 create_output_operand (&eops[0], gen_reg_rtx (wmode), wmode);
7006 create_input_operand (&eops[1], op0, mode);
7007 create_input_operand (&eops[2], op1, mode);
7008 expand_insn (icode, 3, eops);
7009 m1 = gen_lowpart (mode, eops[0].value);
7010
7011 create_output_operand (&eops[0], gen_reg_rtx (wmode), wmode);
7012 create_input_operand (&eops[1], op0, mode);
7013 create_input_operand (&eops[2], op1, mode);
7014 expand_insn (optab_handler (tab2, mode), 3, eops);
7015 m2 = gen_lowpart (mode, eops[0].value);
7016
7017 v = rtvec_alloc (nunits);
7018 if (method == 2)
7019 {
7020 for (i = 0; i < nunits; ++i)
7021 RTVEC_ELT (v, i) = GEN_INT (!BYTES_BIG_ENDIAN + (i & ~1)
7022 + ((i & 1) ? nunits : 0));
7023 }
7024 else
7025 {
7026 for (i = 0; i < nunits; ++i)
7027 RTVEC_ELT (v, i) = GEN_INT (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1));
7028 }
7029 perm = gen_rtx_CONST_VECTOR (mode, v);
7030
7031 return expand_vec_perm (mode, m1, m2, perm, target);
7032}
5ce9450f
JJ
7033
7034/* Return true if target supports vector masked load/store for mode. */
7035bool
ef4bddc2 7036can_vec_mask_load_store_p (machine_mode mode, bool is_load)
5ce9450f
JJ
7037{
7038 optab op = is_load ? maskload_optab : maskstore_optab;
ef4bddc2 7039 machine_mode vmode;
5ce9450f
JJ
7040 unsigned int vector_sizes;
7041
7042 /* If mode is vector mode, check it directly. */
7043 if (VECTOR_MODE_P (mode))
7044 return optab_handler (op, mode) != CODE_FOR_nothing;
7045
7046 /* Otherwise, return true if there is some vector mode with
7047 the mask load/store supported. */
7048
7049 /* See if there is any chance the mask load or store might be
7050 vectorized. If not, punt. */
7051 vmode = targetm.vectorize.preferred_simd_mode (mode);
7052 if (!VECTOR_MODE_P (vmode))
7053 return false;
7054
7055 if (optab_handler (op, vmode) != CODE_FOR_nothing)
7056 return true;
7057
7058 vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
7059 while (vector_sizes != 0)
7060 {
7061 unsigned int cur = 1 << floor_log2 (vector_sizes);
7062 vector_sizes &= ~cur;
7063 if (cur <= GET_MODE_SIZE (mode))
7064 continue;
7065 vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode));
7066 if (VECTOR_MODE_P (vmode)
7067 && optab_handler (op, vmode) != CODE_FOR_nothing)
7068 return true;
7069 }
7070 return false;
7071}
48ae6c13 7072\f
86951993 7073/* Return true if there is a compare_and_swap pattern. */
48ae6c13 7074
86951993 7075bool
ef4bddc2 7076can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
48ae6c13 7077{
86951993 7078 enum insn_code icode;
48ae6c13 7079
86951993
AM
7080 /* Check for __atomic_compare_and_swap. */
7081 icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
7082 if (icode != CODE_FOR_nothing)
cedb4a1a
RH
7083 return true;
7084
7085 /* Check for __sync_compare_and_swap. */
7086 icode = optab_handler (sync_compare_and_swap_optab, mode);
7087 if (icode != CODE_FOR_nothing)
7088 return true;
7089 if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
7090 return true;
48ae6c13 7091
86951993
AM
7092 /* No inline compare and swap. */
7093 return false;
48ae6c13
RH
7094}
7095
05409788
RH
7096/* Return true if an atomic exchange can be performed. */
7097
7098bool
ef4bddc2 7099can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
05409788
RH
7100{
7101 enum insn_code icode;
7102
7103 /* Check for __atomic_exchange. */
7104 icode = direct_optab_handler (atomic_exchange_optab, mode);
7105 if (icode != CODE_FOR_nothing)
7106 return true;
7107
7108 /* Don't check __sync_test_and_set, as on some platforms that
7109 has reduced functionality. Targets that really do support
7110 a proper exchange should simply be updated to the __atomics. */
7111
7112 return can_compare_and_swap_p (mode, allow_libcall);
7113}
7114
7115
4a77c72b
PB
7116/* Helper function to find the MODE_CC set in a sync_compare_and_swap
7117 pattern. */
7118
7119static void
7120find_cc_set (rtx x, const_rtx pat, void *data)
7121{
7122 if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
7123 && GET_CODE (pat) == SET)
7124 {
7125 rtx *p_cc_reg = (rtx *) data;
7126 gcc_assert (!*p_cc_reg);
7127 *p_cc_reg = x;
7128 }
7129}
7130
48ae6c13
RH
7131/* This is a helper function for the other atomic operations. This function
7132 emits a loop that contains SEQ that iterates until a compare-and-swap
7133 operation at the end succeeds. MEM is the memory to be modified. SEQ is
7134 a set of instructions that takes a value from OLD_REG as an input and
7135 produces a value in NEW_REG as an output. Before SEQ, OLD_REG will be
7136 set to the current contents of MEM. After SEQ, a compare-and-swap will
7137 attempt to update MEM with NEW_REG. The function returns true when the
7138 loop was generated successfully. */
7139
7140static bool
7141expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
7142{
ef4bddc2 7143 machine_mode mode = GET_MODE (mem);
38295e01
DM
7144 rtx_code_label *label;
7145 rtx cmp_reg, success, oldval;
48ae6c13
RH
7146
7147 /* The loop we want to generate looks like
7148
81ba4f39 7149 cmp_reg = mem;
48ae6c13 7150 label:
81ba4f39 7151 old_reg = cmp_reg;
48ae6c13 7152 seq;
86951993
AM
7153 (success, cmp_reg) = compare-and-swap(mem, old_reg, new_reg)
7154 if (success)
48ae6c13
RH
7155 goto label;
7156
7157 Note that we only do the plain load from memory once. Subsequent
7158 iterations use the value loaded by the compare-and-swap pattern. */
7159
7160 label = gen_label_rtx ();
81ba4f39 7161 cmp_reg = gen_reg_rtx (mode);
48ae6c13 7162
81ba4f39 7163 emit_move_insn (cmp_reg, mem);
48ae6c13 7164 emit_label (label);
81ba4f39 7165 emit_move_insn (old_reg, cmp_reg);
48ae6c13
RH
7166 if (seq)
7167 emit_insn (seq);
7168
86951993
AM
7169 success = NULL_RTX;
7170 oldval = cmp_reg;
7171 if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg,
7172 new_reg, false, MEMMODEL_SEQ_CST,
7173 MEMMODEL_RELAXED))
4a77c72b 7174 return false;
48ae6c13 7175
86951993
AM
7176 if (oldval != cmp_reg)
7177 emit_move_insn (cmp_reg, oldval);
48ae6c13 7178
a4da41e1 7179 /* Mark this jump predicted not taken. */
86951993 7180 emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
a4da41e1 7181 GET_MODE (success), 1, label, 0);
86951993
AM
7182 return true;
7183}
7184
7185
744accb2
AM
7186/* This function tries to emit an atomic_exchange intruction. VAL is written
7187 to *MEM using memory model MODEL. The previous contents of *MEM are returned,
7188 using TARGET if possible. */
7189
7190static rtx
7191maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
86951993 7192{
ef4bddc2 7193 machine_mode mode = GET_MODE (mem);
86951993 7194 enum insn_code icode;
86951993
AM
7195
7196 /* If the target supports the exchange directly, great. */
7197 icode = direct_optab_handler (atomic_exchange_optab, mode);
7198 if (icode != CODE_FOR_nothing)
4a77c72b 7199 {
86951993
AM
7200 struct expand_operand ops[4];
7201
7202 create_output_operand (&ops[0], target, mode);
7203 create_fixed_operand (&ops[1], mem);
464046a6 7204 create_input_operand (&ops[2], val, mode);
86951993
AM
7205 create_integer_operand (&ops[3], model);
7206 if (maybe_expand_insn (icode, 4, ops))
7207 return ops[0].value;
4a77c72b 7208 }
86951993 7209
744accb2
AM
7210 return NULL_RTX;
7211}
7212
7213/* This function tries to implement an atomic exchange operation using
7214 __sync_lock_test_and_set. VAL is written to *MEM using memory model MODEL.
7215 The previous contents of *MEM are returned, using TARGET if possible.
7216 Since this instructionn is an acquire barrier only, stronger memory
7217 models may require additional barriers to be emitted. */
86951993 7218
744accb2
AM
7219static rtx
7220maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
7221 enum memmodel model)
7222{
ef4bddc2 7223 machine_mode mode = GET_MODE (mem);
744accb2 7224 enum insn_code icode;
38295e01 7225 rtx_insn *last_insn = get_last_insn ();
744accb2
AM
7226
7227 icode = optab_handler (sync_lock_test_and_set_optab, mode);
7228
7229 /* Legacy sync_lock_test_and_set is an acquire barrier. If the pattern
7230 exists, and the memory model is stronger than acquire, add a release
7231 barrier before the instruction. */
86951993 7232
88e784e6
UB
7233 if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST
7234 || (model & MEMMODEL_MASK) == MEMMODEL_RELEASE
7235 || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
744accb2
AM
7236 expand_mem_thread_fence (model);
7237
7238 if (icode != CODE_FOR_nothing)
4a77c72b 7239 {
744accb2
AM
7240 struct expand_operand ops[3];
7241 create_output_operand (&ops[0], target, mode);
7242 create_fixed_operand (&ops[1], mem);
464046a6 7243 create_input_operand (&ops[2], val, mode);
744accb2
AM
7244 if (maybe_expand_insn (icode, 3, ops))
7245 return ops[0].value;
7246 }
86951993 7247
744accb2
AM
7248 /* If an external test-and-set libcall is provided, use that instead of
7249 any external compare-and-swap that we might get from the compare-and-
7250 swap-loop expansion later. */
7251 if (!can_compare_and_swap_p (mode, false))
7252 {
7253 rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, mode);
7254 if (libfunc != NULL)
0669295b 7255 {
744accb2
AM
7256 rtx addr;
7257
7258 addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
fae67e1d 7259 return emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
744accb2
AM
7260 mode, 2, addr, ptr_mode,
7261 val, mode);
0669295b 7262 }
744accb2 7263 }
48ae6c13 7264
744accb2
AM
7265 /* If the test_and_set can't be emitted, eliminate any barrier that might
7266 have been emitted. */
7267 delete_insns_since (last_insn);
7268 return NULL_RTX;
7269}
cedb4a1a 7270
744accb2
AM
7271/* This function tries to implement an atomic exchange operation using a
7272 compare_and_swap loop. VAL is written to *MEM. The previous contents of
7273 *MEM are returned, using TARGET if possible. No memory model is required
7274 since a compare_and_swap loop is seq-cst. */
cedb4a1a 7275
744accb2
AM
7276static rtx
7277maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
7278{
ef4bddc2 7279 machine_mode mode = GET_MODE (mem);
86951993 7280
cedb4a1a 7281 if (can_compare_and_swap_p (mode, true))
86951993
AM
7282 {
7283 if (!target || !register_operand (target, mode))
7284 target = gen_reg_rtx (mode);
86951993
AM
7285 if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
7286 return target;
7287 }
7288
7289 return NULL_RTX;
7290}
7291
f8a27aa6
RH
7292/* This function tries to implement an atomic test-and-set operation
7293 using the atomic_test_and_set instruction pattern. A boolean value
7294 is returned from the operation, using TARGET if possible. */
7295
744accb2
AM
7296#ifndef HAVE_atomic_test_and_set
7297#define HAVE_atomic_test_and_set 0
f8a27aa6 7298#define CODE_FOR_atomic_test_and_set CODE_FOR_nothing
744accb2
AM
7299#endif
7300
f8a27aa6
RH
7301static rtx
7302maybe_emit_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
7303{
ef4bddc2 7304 machine_mode pat_bool_mode;
15e73e06 7305 struct expand_operand ops[3];
f8a27aa6
RH
7306
7307 if (!HAVE_atomic_test_and_set)
7308 return NULL_RTX;
7309
42cf0609
RH
7310 /* While we always get QImode from __atomic_test_and_set, we get
7311 other memory modes from __sync_lock_test_and_set. Note that we
7312 use no endian adjustment here. This matches the 4.6 behavior
7313 in the Sparc backend. */
15e73e06
RH
7314 gcc_checking_assert
7315 (insn_data[CODE_FOR_atomic_test_and_set].operand[1].mode == QImode);
42cf0609
RH
7316 if (GET_MODE (mem) != QImode)
7317 mem = adjust_address_nv (mem, QImode, 0);
f8a27aa6 7318
15e73e06
RH
7319 pat_bool_mode = insn_data[CODE_FOR_atomic_test_and_set].operand[0].mode;
7320 create_output_operand (&ops[0], target, pat_bool_mode);
7321 create_fixed_operand (&ops[1], mem);
7322 create_integer_operand (&ops[2], model);
f8a27aa6 7323
15e73e06
RH
7324 if (maybe_expand_insn (CODE_FOR_atomic_test_and_set, 3, ops))
7325 return ops[0].value;
7326 return NULL_RTX;
f8a27aa6
RH
7327}
7328
744accb2
AM
7329/* This function expands the legacy _sync_lock test_and_set operation which is
7330 generally an atomic exchange. Some limited targets only allow the
7331 constant 1 to be stored. This is an ACQUIRE operation.
7332
7333 TARGET is an optional place to stick the return value.
7334 MEM is where VAL is stored. */
7335
7336rtx
7337expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
7338{
7339 rtx ret;
7340
7341 /* Try an atomic_exchange first. */
7342 ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE);
f8a27aa6
RH
7343 if (ret)
7344 return ret;
7345
7346 ret = maybe_emit_sync_lock_test_and_set (target, mem, val, MEMMODEL_ACQUIRE);
7347 if (ret)
7348 return ret;
744accb2 7349
f8a27aa6
RH
7350 ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
7351 if (ret)
7352 return ret;
744accb2
AM
7353
7354 /* If there are no other options, try atomic_test_and_set if the value
7355 being stored is 1. */
f8a27aa6
RH
7356 if (val == const1_rtx)
7357 ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE);
744accb2
AM
7358
7359 return ret;
7360}
7361
7362/* This function expands the atomic test_and_set operation:
7363 atomically store a boolean TRUE into MEM and return the previous value.
7364
7365 MEMMODEL is the memory model variant to use.
7366 TARGET is an optional place to stick the return value. */
7367
7368rtx
7369expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
7370{
ef4bddc2 7371 machine_mode mode = GET_MODE (mem);
a6de595f 7372 rtx ret, trueval, subtarget;
f8a27aa6
RH
7373
7374 ret = maybe_emit_atomic_test_and_set (target, mem, model);
7375 if (ret)
7376 return ret;
744accb2 7377
a6de595f
RH
7378 /* Be binary compatible with non-default settings of trueval, and different
7379 cpu revisions. E.g. one revision may have atomic-test-and-set, but
7380 another only has atomic-exchange. */
7381 if (targetm.atomic_test_and_set_trueval == 1)
7382 {
7383 trueval = const1_rtx;
7384 subtarget = target ? target : gen_reg_rtx (mode);
7385 }
7386 else
7387 {
7388 trueval = gen_int_mode (targetm.atomic_test_and_set_trueval, mode);
7389 subtarget = gen_reg_rtx (mode);
7390 }
744accb2 7391
a6de595f
RH
7392 /* Try the atomic-exchange optab... */
7393 ret = maybe_emit_atomic_exchange (subtarget, mem, trueval, model);
744accb2 7394
a6de595f
RH
7395 /* ... then an atomic-compare-and-swap loop ... */
7396 if (!ret)
7397 ret = maybe_emit_compare_and_swap_exchange_loop (subtarget, mem, trueval);
744accb2 7398
a6de595f
RH
7399 /* ... before trying the vaguely defined legacy lock_test_and_set. */
7400 if (!ret)
7401 ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, trueval, model);
744accb2 7402
a6de595f
RH
7403 /* Recall that the legacy lock_test_and_set optab was allowed to do magic
7404 things with the value 1. Thus we try again without trueval. */
7405 if (!ret && targetm.atomic_test_and_set_trueval != 1)
7406 ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, const1_rtx, model);
7407
7408 /* Failing all else, assume a single threaded environment and simply
7409 perform the operation. */
7410 if (!ret)
7411 {
0d03cda4
KT
7412 /* If the result is ignored skip the move to target. */
7413 if (subtarget != const0_rtx)
7414 emit_move_insn (subtarget, mem);
7415
a6de595f
RH
7416 emit_move_insn (mem, trueval);
7417 ret = subtarget;
7418 }
7419
7420 /* Recall that have to return a boolean value; rectify if trueval
7421 is not exactly one. */
7422 if (targetm.atomic_test_and_set_trueval != 1)
7423 ret = emit_store_flag_force (target, NE, ret, const0_rtx, mode, 0, 1);
7424
7425 return ret;
744accb2
AM
7426}
7427
7428/* This function expands the atomic exchange operation:
7429 atomically store VAL in MEM and return the previous value in MEM.
7430
7431 MEMMODEL is the memory model variant to use.
7432 TARGET is an optional place to stick the return value. */
7433
7434rtx
7435expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
7436{
7437 rtx ret;
7438
7439 ret = maybe_emit_atomic_exchange (target, mem, val, model);
7440
7441 /* Next try a compare-and-swap loop for the exchange. */
7442 if (!ret)
7443 ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
7444
7445 return ret;
7446}
7447
86951993
AM
7448/* This function expands the atomic compare exchange operation:
7449
7450 *PTARGET_BOOL is an optional place to store the boolean success/failure.
7451 *PTARGET_OVAL is an optional place to store the old value from memory.
7452 Both target parameters may be NULL to indicate that we do not care about
7453 that return value. Both target parameters are updated on success to
7454 the actual location of the corresponding result.
7455
7456 MEMMODEL is the memory model variant to use.
7457
7458 The return value of the function is true for success. */
7459
7460bool
7461expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
7462 rtx mem, rtx expected, rtx desired,
7463 bool is_weak, enum memmodel succ_model,
7464 enum memmodel fail_model)
7465{
ef4bddc2 7466 machine_mode mode = GET_MODE (mem);
86951993
AM
7467 struct expand_operand ops[8];
7468 enum insn_code icode;
cedb4a1a
RH
7469 rtx target_oval, target_bool = NULL_RTX;
7470 rtx libfunc;
86951993
AM
7471
7472 /* Load expected into a register for the compare and swap. */
7473 if (MEM_P (expected))
7474 expected = copy_to_reg (expected);
7475
7476 /* Make sure we always have some place to put the return oldval.
7477 Further, make sure that place is distinct from the input expected,
7478 just in case we need that path down below. */
7479 if (ptarget_oval == NULL
7480 || (target_oval = *ptarget_oval) == NULL
7481 || reg_overlap_mentioned_p (expected, target_oval))
7482 target_oval = gen_reg_rtx (mode);
7483
7484 icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
7485 if (icode != CODE_FOR_nothing)
7486 {
ef4bddc2 7487 machine_mode bool_mode = insn_data[icode].operand[0].mode;
86951993
AM
7488
7489 /* Make sure we always have a place for the bool operand. */
7490 if (ptarget_bool == NULL
7491 || (target_bool = *ptarget_bool) == NULL
7492 || GET_MODE (target_bool) != bool_mode)
7493 target_bool = gen_reg_rtx (bool_mode);
7494
7495 /* Emit the compare_and_swap. */
7496 create_output_operand (&ops[0], target_bool, bool_mode);
7497 create_output_operand (&ops[1], target_oval, mode);
7498 create_fixed_operand (&ops[2], mem);
464046a6
RH
7499 create_input_operand (&ops[3], expected, mode);
7500 create_input_operand (&ops[4], desired, mode);
86951993
AM
7501 create_integer_operand (&ops[5], is_weak);
7502 create_integer_operand (&ops[6], succ_model);
7503 create_integer_operand (&ops[7], fail_model);
8bd7070a
AK
7504 if (maybe_expand_insn (icode, 8, ops))
7505 {
7506 /* Return success/failure. */
7507 target_bool = ops[0].value;
7508 target_oval = ops[1].value;
7509 goto success;
7510 }
86951993
AM
7511 }
7512
7513 /* Otherwise fall back to the original __sync_val_compare_and_swap
7514 which is always seq-cst. */
cedb4a1a 7515 icode = optab_handler (sync_compare_and_swap_optab, mode);
86951993
AM
7516 if (icode != CODE_FOR_nothing)
7517 {
7518 rtx cc_reg;
7519
7520 create_output_operand (&ops[0], target_oval, mode);
7521 create_fixed_operand (&ops[1], mem);
464046a6
RH
7522 create_input_operand (&ops[2], expected, mode);
7523 create_input_operand (&ops[3], desired, mode);
86951993
AM
7524 if (!maybe_expand_insn (icode, 4, ops))
7525 return false;
7526
7527 target_oval = ops[0].value;
86951993
AM
7528
7529 /* If the caller isn't interested in the boolean return value,
7530 skip the computation of it. */
7531 if (ptarget_bool == NULL)
7532 goto success;
7533
7534 /* Otherwise, work out if the compare-and-swap succeeded. */
7535 cc_reg = NULL_RTX;
7536 if (have_insn_for (COMPARE, CCmode))
7537 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
cedb4a1a
RH
7538 if (cc_reg)
7539 {
7540 target_bool = emit_store_flag_force (target_bool, EQ, cc_reg,
7541 const0_rtx, VOIDmode, 0, 1);
7542 goto success;
7543 }
7544 goto success_bool_from_val;
7545 }
86951993 7546
cedb4a1a
RH
7547 /* Also check for library support for __sync_val_compare_and_swap. */
7548 libfunc = optab_libfunc (sync_compare_and_swap_optab, mode);
7549 if (libfunc != NULL)
7550 {
7551 rtx addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
fae67e1d 7552 target_oval = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
cedb4a1a
RH
7553 mode, 3, addr, ptr_mode,
7554 expected, mode, desired, mode);
7555
7556 /* Compute the boolean return value only if requested. */
7557 if (ptarget_bool)
7558 goto success_bool_from_val;
7559 else
7560 goto success;
86951993 7561 }
cedb4a1a
RH
7562
7563 /* Failure. */
86951993
AM
7564 return false;
7565
cedb4a1a
RH
7566 success_bool_from_val:
7567 target_bool = emit_store_flag_force (target_bool, EQ, target_oval,
7568 expected, VOIDmode, 1, 1);
86951993
AM
7569 success:
7570 /* Make sure that the oval output winds up where the caller asked. */
7571 if (ptarget_oval)
7572 *ptarget_oval = target_oval;
7573 if (ptarget_bool)
7574 *ptarget_bool = target_bool;
48ae6c13
RH
7575 return true;
7576}
7577
c39169c8
RH
7578/* Generate asm volatile("" : : : "memory") as the memory barrier. */
7579
7580static void
7581expand_asm_memory_barrier (void)
7582{
7583 rtx asm_op, clob;
7584
7585 asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, empty_string, empty_string, 0,
7586 rtvec_alloc (0), rtvec_alloc (0),
7587 rtvec_alloc (0), UNKNOWN_LOCATION);
7588 MEM_VOLATILE_P (asm_op) = 1;
7589
7590 clob = gen_rtx_SCRATCH (VOIDmode);
7591 clob = gen_rtx_MEM (BLKmode, clob);
7592 clob = gen_rtx_CLOBBER (VOIDmode, clob);
7593
7594 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, asm_op, clob)));
7595}
7596
7597/* This routine will either emit the mem_thread_fence pattern or issue a
7598 sync_synchronize to generate a fence for memory model MEMMODEL. */
7599
7600#ifndef HAVE_mem_thread_fence
7601# define HAVE_mem_thread_fence 0
7602# define gen_mem_thread_fence(x) (gcc_unreachable (), NULL_RTX)
7603#endif
7604#ifndef HAVE_memory_barrier
7605# define HAVE_memory_barrier 0
7606# define gen_memory_barrier() (gcc_unreachable (), NULL_RTX)
7607#endif
7608
7609void
7610expand_mem_thread_fence (enum memmodel model)
7611{
7612 if (HAVE_mem_thread_fence)
7613 emit_insn (gen_mem_thread_fence (GEN_INT (model)));
88e784e6 7614 else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
c39169c8
RH
7615 {
7616 if (HAVE_memory_barrier)
7617 emit_insn (gen_memory_barrier ());
7618 else if (synchronize_libfunc != NULL_RTX)
7619 emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
7620 else
7621 expand_asm_memory_barrier ();
7622 }
7623}
7624
7625/* This routine will either emit the mem_signal_fence pattern or issue a
7626 sync_synchronize to generate a fence for memory model MEMMODEL. */
7627
7628#ifndef HAVE_mem_signal_fence
7629# define HAVE_mem_signal_fence 0
7630# define gen_mem_signal_fence(x) (gcc_unreachable (), NULL_RTX)
7631#endif
7632
7633void
7634expand_mem_signal_fence (enum memmodel model)
7635{
7636 if (HAVE_mem_signal_fence)
7637 emit_insn (gen_mem_signal_fence (GEN_INT (model)));
88e784e6 7638 else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
c39169c8
RH
7639 {
7640 /* By default targets are coherent between a thread and the signal
7641 handler running on the same thread. Thus this really becomes a
7642 compiler barrier, in that stores must not be sunk past
7643 (or raised above) a given point. */
7644 expand_asm_memory_barrier ();
7645 }
7646}
7647
86951993
AM
7648/* This function expands the atomic load operation:
7649 return the atomically loaded value in MEM.
7650
7651 MEMMODEL is the memory model variant to use.
7652 TARGET is an option place to stick the return value. */
48ae6c13
RH
7653
7654rtx
86951993 7655expand_atomic_load (rtx target, rtx mem, enum memmodel model)
48ae6c13 7656{
ef4bddc2 7657 machine_mode mode = GET_MODE (mem);
48ae6c13 7658 enum insn_code icode;
48ae6c13 7659
86951993
AM
7660 /* If the target supports the load directly, great. */
7661 icode = direct_optab_handler (atomic_load_optab, mode);
7662 if (icode != CODE_FOR_nothing)
48ae6c13 7663 {
86951993 7664 struct expand_operand ops[3];
48ae6c13 7665
86951993
AM
7666 create_output_operand (&ops[0], target, mode);
7667 create_fixed_operand (&ops[1], mem);
7668 create_integer_operand (&ops[2], model);
7669 if (maybe_expand_insn (icode, 3, ops))
7670 return ops[0].value;
7671 }
48ae6c13 7672
86951993
AM
7673 /* If the size of the object is greater than word size on this target,
7674 then we assume that a load will not be atomic. */
7675 if (GET_MODE_PRECISION (mode) > BITS_PER_WORD)
7676 {
7677 /* Issue val = compare_and_swap (mem, 0, 0).
7678 This may cause the occasional harmless store of 0 when the value is
7679 already 0, but it seems to be OK according to the standards guys. */
c51ec0a3
AM
7680 if (expand_atomic_compare_and_swap (NULL, &target, mem, const0_rtx,
7681 const0_rtx, false, model, model))
7682 return target;
7683 else
7684 /* Otherwise there is no atomic load, leave the library call. */
7685 return NULL_RTX;
48ae6c13
RH
7686 }
7687
86951993
AM
7688 /* Otherwise assume loads are atomic, and emit the proper barriers. */
7689 if (!target || target == const0_rtx)
7690 target = gen_reg_rtx (mode);
7691
80928237 7692 /* For SEQ_CST, emit a barrier before the load. */
88e784e6 7693 if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
80928237 7694 expand_mem_thread_fence (model);
86951993
AM
7695
7696 emit_move_insn (target, mem);
7697
80928237
RH
7698 /* Emit the appropriate barrier after the load. */
7699 expand_mem_thread_fence (model);
86951993
AM
7700
7701 return target;
7702}
7703
7704/* This function expands the atomic store operation:
7705 Atomically store VAL in MEM.
7706 MEMMODEL is the memory model variant to use.
0669295b 7707 USE_RELEASE is true if __sync_lock_release can be used as a fall back.
86951993
AM
7708 function returns const0_rtx if a pattern was emitted. */
7709
7710rtx
0669295b 7711expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
86951993 7712{
ef4bddc2 7713 machine_mode mode = GET_MODE (mem);
86951993
AM
7714 enum insn_code icode;
7715 struct expand_operand ops[3];
7716
7717 /* If the target supports the store directly, great. */
7718 icode = direct_optab_handler (atomic_store_optab, mode);
48ae6c13
RH
7719 if (icode != CODE_FOR_nothing)
7720 {
a5c7d693 7721 create_fixed_operand (&ops[0], mem);
86951993
AM
7722 create_input_operand (&ops[1], val, mode);
7723 create_integer_operand (&ops[2], model);
7724 if (maybe_expand_insn (icode, 3, ops))
a5c7d693 7725 return const0_rtx;
48ae6c13
RH
7726 }
7727
0669295b
AM
7728 /* If using __sync_lock_release is a viable alternative, try it. */
7729 if (use_release)
7730 {
7731 icode = direct_optab_handler (sync_lock_release_optab, mode);
7732 if (icode != CODE_FOR_nothing)
7733 {
7734 create_fixed_operand (&ops[0], mem);
7735 create_input_operand (&ops[1], const0_rtx, mode);
7736 if (maybe_expand_insn (icode, 2, ops))
7737 {
7738 /* lock_release is only a release barrier. */
88e784e6 7739 if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
c39169c8 7740 expand_mem_thread_fence (model);
0669295b
AM
7741 return const0_rtx;
7742 }
7743 }
7744 }
7745
86951993
AM
7746 /* If the size of the object is greater than word size on this target,
7747 a default store will not be atomic, Try a mem_exchange and throw away
7748 the result. If that doesn't work, don't do anything. */
c3284718 7749 if (GET_MODE_PRECISION (mode) > BITS_PER_WORD)
48ae6c13 7750 {
744accb2
AM
7751 rtx target = maybe_emit_atomic_exchange (NULL_RTX, mem, val, model);
7752 if (!target)
7753 target = maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val);
86951993
AM
7754 if (target)
7755 return const0_rtx;
7756 else
7757 return NULL_RTX;
7758 }
48ae6c13 7759
80928237 7760 /* Otherwise assume stores are atomic, and emit the proper barriers. */
5e3b173a 7761 expand_mem_thread_fence (model);
48ae6c13 7762
86951993 7763 emit_move_insn (mem, val);
48ae6c13 7764
80928237 7765 /* For SEQ_CST, also emit a barrier after the store. */
88e784e6 7766 if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
c39169c8 7767 expand_mem_thread_fence (model);
48ae6c13 7768
86951993 7769 return const0_rtx;
48ae6c13
RH
7770}
7771
48ae6c13 7772
86951993
AM
7773/* Structure containing the pointers and values required to process the
7774 various forms of the atomic_fetch_op and atomic_op_fetch builtins. */
7775
7776struct atomic_op_functions
48ae6c13 7777{
cedb4a1a
RH
7778 direct_optab mem_fetch_before;
7779 direct_optab mem_fetch_after;
7780 direct_optab mem_no_result;
7781 optab fetch_before;
7782 optab fetch_after;
7783 direct_optab no_result;
86951993
AM
7784 enum rtx_code reverse_code;
7785};
7786
48ae6c13 7787
6ff336b4
AM
7788/* Fill in structure pointed to by OP with the various optab entries for an
7789 operation of type CODE. */
7790
7791static void
7792get_atomic_op_for_code (struct atomic_op_functions *op, enum rtx_code code)
7793{
7794 gcc_assert (op!= NULL);
7795
7796 /* If SWITCHABLE_TARGET is defined, then subtargets can be switched
7797 in the source code during compilation, and the optab entries are not
7798 computable until runtime. Fill in the values at runtime. */
48ae6c13
RH
7799 switch (code)
7800 {
7801 case PLUS:
6ff336b4
AM
7802 op->mem_fetch_before = atomic_fetch_add_optab;
7803 op->mem_fetch_after = atomic_add_fetch_optab;
7804 op->mem_no_result = atomic_add_optab;
7805 op->fetch_before = sync_old_add_optab;
7806 op->fetch_after = sync_new_add_optab;
7807 op->no_result = sync_add_optab;
7808 op->reverse_code = MINUS;
7809 break;
86951993 7810 case MINUS:
6ff336b4
AM
7811 op->mem_fetch_before = atomic_fetch_sub_optab;
7812 op->mem_fetch_after = atomic_sub_fetch_optab;
7813 op->mem_no_result = atomic_sub_optab;
7814 op->fetch_before = sync_old_sub_optab;
7815 op->fetch_after = sync_new_sub_optab;
7816 op->no_result = sync_sub_optab;
7817 op->reverse_code = PLUS;
7818 break;
48ae6c13 7819 case XOR:
6ff336b4
AM
7820 op->mem_fetch_before = atomic_fetch_xor_optab;
7821 op->mem_fetch_after = atomic_xor_fetch_optab;
7822 op->mem_no_result = atomic_xor_optab;
7823 op->fetch_before = sync_old_xor_optab;
7824 op->fetch_after = sync_new_xor_optab;
7825 op->no_result = sync_xor_optab;
7826 op->reverse_code = XOR;
7827 break;
48ae6c13 7828 case AND:
6ff336b4
AM
7829 op->mem_fetch_before = atomic_fetch_and_optab;
7830 op->mem_fetch_after = atomic_and_fetch_optab;
7831 op->mem_no_result = atomic_and_optab;
7832 op->fetch_before = sync_old_and_optab;
7833 op->fetch_after = sync_new_and_optab;
7834 op->no_result = sync_and_optab;
7835 op->reverse_code = UNKNOWN;
7836 break;
86951993 7837 case IOR:
6ff336b4
AM
7838 op->mem_fetch_before = atomic_fetch_or_optab;
7839 op->mem_fetch_after = atomic_or_fetch_optab;
7840 op->mem_no_result = atomic_or_optab;
7841 op->fetch_before = sync_old_ior_optab;
7842 op->fetch_after = sync_new_ior_optab;
7843 op->no_result = sync_ior_optab;
7844 op->reverse_code = UNKNOWN;
7845 break;
f12b785d 7846 case NOT:
6ff336b4
AM
7847 op->mem_fetch_before = atomic_fetch_nand_optab;
7848 op->mem_fetch_after = atomic_nand_fetch_optab;
7849 op->mem_no_result = atomic_nand_optab;
7850 op->fetch_before = sync_old_nand_optab;
7851 op->fetch_after = sync_new_nand_optab;
7852 op->no_result = sync_nand_optab;
7853 op->reverse_code = UNKNOWN;
7854 break;
48ae6c13
RH
7855 default:
7856 gcc_unreachable ();
7857 }
86951993
AM
7858}
7859
91f59d8b
AM
7860/* See if there is a more optimal way to implement the operation "*MEM CODE VAL"
7861 using memory order MODEL. If AFTER is true the operation needs to return
7862 the value of *MEM after the operation, otherwise the previous value.
7863 TARGET is an optional place to place the result. The result is unused if
7864 it is const0_rtx.
7865 Return the result if there is a better sequence, otherwise NULL_RTX. */
7866
7867static rtx
7868maybe_optimize_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
7869 enum memmodel model, bool after)
7870{
7871 /* If the value is prefetched, or not used, it may be possible to replace
7872 the sequence with a native exchange operation. */
7873 if (!after || target == const0_rtx)
7874 {
7875 /* fetch_and (&x, 0, m) can be replaced with exchange (&x, 0, m). */
7876 if (code == AND && val == const0_rtx)
7877 {
7878 if (target == const0_rtx)
7879 target = gen_reg_rtx (GET_MODE (mem));
7880 return maybe_emit_atomic_exchange (target, mem, val, model);
7881 }
7882
7883 /* fetch_or (&x, -1, m) can be replaced with exchange (&x, -1, m). */
7884 if (code == IOR && val == constm1_rtx)
7885 {
7886 if (target == const0_rtx)
7887 target = gen_reg_rtx (GET_MODE (mem));
7888 return maybe_emit_atomic_exchange (target, mem, val, model);
7889 }
7890 }
7891
7892 return NULL_RTX;
7893}
7894
86951993
AM
7895/* Try to emit an instruction for a specific operation varaition.
7896 OPTAB contains the OP functions.
7897 TARGET is an optional place to return the result. const0_rtx means unused.
7898 MEM is the memory location to operate on.
7899 VAL is the value to use in the operation.
7900 USE_MEMMODEL is TRUE if the variation with a memory model should be tried.
7901 MODEL is the memory model, if used.
7902 AFTER is true if the returned result is the value after the operation. */
7903
7904static rtx
7905maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
7906 rtx val, bool use_memmodel, enum memmodel model, bool after)
7907{
ef4bddc2 7908 machine_mode mode = GET_MODE (mem);
86951993
AM
7909 struct expand_operand ops[4];
7910 enum insn_code icode;
7911 int op_counter = 0;
7912 int num_ops;
48ae6c13 7913
86951993
AM
7914 /* Check to see if there is a result returned. */
7915 if (target == const0_rtx)
48ae6c13 7916 {
86951993
AM
7917 if (use_memmodel)
7918 {
cedb4a1a 7919 icode = direct_optab_handler (optab->mem_no_result, mode);
86951993
AM
7920 create_integer_operand (&ops[2], model);
7921 num_ops = 3;
7922 }
7923 else
7924 {
cedb4a1a 7925 icode = direct_optab_handler (optab->no_result, mode);
86951993 7926 num_ops = 2;
48ae6c13
RH
7927 }
7928 }
86951993 7929 /* Otherwise, we need to generate a result. */
48ae6c13
RH
7930 else
7931 {
86951993
AM
7932 if (use_memmodel)
7933 {
cedb4a1a
RH
7934 icode = direct_optab_handler (after ? optab->mem_fetch_after
7935 : optab->mem_fetch_before, mode);
86951993 7936 create_integer_operand (&ops[3], model);
cedb4a1a 7937 num_ops = 4;
86951993
AM
7938 }
7939 else
48ae6c13 7940 {
cedb4a1a
RH
7941 icode = optab_handler (after ? optab->fetch_after
7942 : optab->fetch_before, mode);
86951993 7943 num_ops = 3;
48ae6c13 7944 }
86951993 7945 create_output_operand (&ops[op_counter++], target, mode);
48ae6c13 7946 }
86951993
AM
7947 if (icode == CODE_FOR_nothing)
7948 return NULL_RTX;
7949
7950 create_fixed_operand (&ops[op_counter++], mem);
7951 /* VAL may have been promoted to a wider mode. Shrink it if so. */
7952 create_convert_operand_to (&ops[op_counter++], val, mode, true);
7953
7954 if (maybe_expand_insn (icode, num_ops, ops))
cedb4a1a 7955 return (target == const0_rtx ? const0_rtx : ops[0].value);
86951993
AM
7956
7957 return NULL_RTX;
7958}
7959
7960
7961/* This function expands an atomic fetch_OP or OP_fetch operation:
7962 TARGET is an option place to stick the return value. const0_rtx indicates
7963 the result is unused.
7964 atomically fetch MEM, perform the operation with VAL and return it to MEM.
7965 CODE is the operation being performed (OP)
7966 MEMMODEL is the memory model variant to use.
7967 AFTER is true to return the result of the operation (OP_fetch).
cd8b6dc5
AM
7968 AFTER is false to return the value before the operation (fetch_OP).
7969
7970 This function will *only* generate instructions if there is a direct
7971 optab. No compare and swap loops or libcalls will be generated. */
7972
7973static rtx
7974expand_atomic_fetch_op_no_fallback (rtx target, rtx mem, rtx val,
7975 enum rtx_code code, enum memmodel model,
7976 bool after)
86951993 7977{
ef4bddc2 7978 machine_mode mode = GET_MODE (mem);
6ff336b4 7979 struct atomic_op_functions optab;
86951993
AM
7980 rtx result;
7981 bool unused_result = (target == const0_rtx);
7982
6ff336b4 7983 get_atomic_op_for_code (&optab, code);
86951993 7984
91f59d8b
AM
7985 /* Check to see if there are any better instructions. */
7986 result = maybe_optimize_fetch_op (target, mem, val, code, model, after);
7987 if (result)
7988 return result;
7989
86951993
AM
7990 /* Check for the case where the result isn't used and try those patterns. */
7991 if (unused_result)
48ae6c13 7992 {
86951993 7993 /* Try the memory model variant first. */
6ff336b4 7994 result = maybe_emit_op (&optab, target, mem, val, true, model, true);
86951993
AM
7995 if (result)
7996 return result;
48ae6c13 7997
86951993 7998 /* Next try the old style withuot a memory model. */
6ff336b4 7999 result = maybe_emit_op (&optab, target, mem, val, false, model, true);
86951993
AM
8000 if (result)
8001 return result;
f12b785d 8002
86951993
AM
8003 /* There is no no-result pattern, so try patterns with a result. */
8004 target = NULL_RTX;
8005 }
48ae6c13 8006
86951993 8007 /* Try the __atomic version. */
6ff336b4 8008 result = maybe_emit_op (&optab, target, mem, val, true, model, after);
86951993
AM
8009 if (result)
8010 return result;
8011
8012 /* Try the older __sync version. */
6ff336b4 8013 result = maybe_emit_op (&optab, target, mem, val, false, model, after);
86951993
AM
8014 if (result)
8015 return result;
8016
8017 /* If the fetch value can be calculated from the other variation of fetch,
8018 try that operation. */
cedb4a1a 8019 if (after || unused_result || optab.reverse_code != UNKNOWN)
86951993
AM
8020 {
8021 /* Try the __atomic version, then the older __sync version. */
6ff336b4 8022 result = maybe_emit_op (&optab, target, mem, val, true, model, !after);
86951993 8023 if (!result)
6ff336b4 8024 result = maybe_emit_op (&optab, target, mem, val, false, model, !after);
86951993
AM
8025
8026 if (result)
8027 {
8028 /* If the result isn't used, no need to do compensation code. */
8029 if (unused_result)
2b894715 8030 return result;
86951993
AM
8031
8032 /* Issue compensation code. Fetch_after == fetch_before OP val.
8033 Fetch_before == after REVERSE_OP val. */
8034 if (!after)
6ff336b4 8035 code = optab.reverse_code;
154b68db
AM
8036 if (code == NOT)
8037 {
8038 result = expand_simple_binop (mode, AND, result, val, NULL_RTX,
8039 true, OPTAB_LIB_WIDEN);
8040 result = expand_simple_unop (mode, NOT, result, target, true);
8041 }
8042 else
8043 result = expand_simple_binop (mode, code, result, val, target,
8044 true, OPTAB_LIB_WIDEN);
86951993 8045 return result;
48ae6c13
RH
8046 }
8047 }
8048
cd8b6dc5
AM
8049 /* No direct opcode can be generated. */
8050 return NULL_RTX;
8051}
8052
8053
8054
8055/* This function expands an atomic fetch_OP or OP_fetch operation:
8056 TARGET is an option place to stick the return value. const0_rtx indicates
8057 the result is unused.
8058 atomically fetch MEM, perform the operation with VAL and return it to MEM.
8059 CODE is the operation being performed (OP)
8060 MEMMODEL is the memory model variant to use.
8061 AFTER is true to return the result of the operation (OP_fetch).
8062 AFTER is false to return the value before the operation (fetch_OP). */
8063rtx
8064expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
8065 enum memmodel model, bool after)
8066{
ef4bddc2 8067 machine_mode mode = GET_MODE (mem);
cd8b6dc5
AM
8068 rtx result;
8069 bool unused_result = (target == const0_rtx);
8070
8071 result = expand_atomic_fetch_op_no_fallback (target, mem, val, code, model,
8072 after);
8073
8074 if (result)
8075 return result;
8076
8077 /* Add/sub can be implemented by doing the reverse operation with -(val). */
8078 if (code == PLUS || code == MINUS)
8079 {
8080 rtx tmp;
8081 enum rtx_code reverse = (code == PLUS ? MINUS : PLUS);
8082
8083 start_sequence ();
8084 tmp = expand_simple_unop (mode, NEG, val, NULL_RTX, true);
8085 result = expand_atomic_fetch_op_no_fallback (target, mem, tmp, reverse,
8086 model, after);
8087 if (result)
8088 {
8089 /* PLUS worked so emit the insns and return. */
8090 tmp = get_insns ();
8091 end_sequence ();
8092 emit_insn (tmp);
8093 return result;
8094 }
8095
8096 /* PLUS did not work, so throw away the negation code and continue. */
8097 end_sequence ();
8098 }
8099
cedb4a1a
RH
8100 /* Try the __sync libcalls only if we can't do compare-and-swap inline. */
8101 if (!can_compare_and_swap_p (mode, false))
8102 {
8103 rtx libfunc;
8104 bool fixup = false;
79cd6f15 8105 enum rtx_code orig_code = code;
cd8b6dc5 8106 struct atomic_op_functions optab;
cedb4a1a 8107
cd8b6dc5 8108 get_atomic_op_for_code (&optab, code);
cedb4a1a
RH
8109 libfunc = optab_libfunc (after ? optab.fetch_after
8110 : optab.fetch_before, mode);
8111 if (libfunc == NULL
8112 && (after || unused_result || optab.reverse_code != UNKNOWN))
8113 {
8114 fixup = true;
8115 if (!after)
8116 code = optab.reverse_code;
8117 libfunc = optab_libfunc (after ? optab.fetch_before
8118 : optab.fetch_after, mode);
8119 }
8120 if (libfunc != NULL)
8121 {
8122 rtx addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
8123 result = emit_library_call_value (libfunc, NULL, LCT_NORMAL, mode,
8124 2, addr, ptr_mode, val, mode);
8125
2b894715 8126 if (!unused_result && fixup)
cedb4a1a
RH
8127 result = expand_simple_binop (mode, code, result, val, target,
8128 true, OPTAB_LIB_WIDEN);
8129 return result;
8130 }
79cd6f15
HPN
8131
8132 /* We need the original code for any further attempts. */
8133 code = orig_code;
cedb4a1a
RH
8134 }
8135
86951993 8136 /* If nothing else has succeeded, default to a compare and swap loop. */
cedb4a1a 8137 if (can_compare_and_swap_p (mode, true))
48ae6c13 8138 {
38295e01 8139 rtx_insn *insn;
48ae6c13
RH
8140 rtx t0 = gen_reg_rtx (mode), t1;
8141
48ae6c13
RH
8142 start_sequence ();
8143
86951993
AM
8144 /* If the result is used, get a register for it. */
8145 if (!unused_result)
8146 {
8147 if (!target || !register_operand (target, mode))
8148 target = gen_reg_rtx (mode);
8149 /* If fetch_before, copy the value now. */
8150 if (!after)
8151 emit_move_insn (target, t0);
8152 }
8153 else
8154 target = const0_rtx;
8155
f12b785d 8156 t1 = t0;
48ae6c13 8157 if (code == NOT)
86951993 8158 {
23462d4d
UB
8159 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
8160 true, OPTAB_LIB_WIDEN);
8161 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
48ae6c13 8162 }
23462d4d 8163 else
86951993
AM
8164 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX, true,
8165 OPTAB_LIB_WIDEN);
48ae6c13 8166
86951993
AM
8167 /* For after, copy the value now. */
8168 if (!unused_result && after)
8169 emit_move_insn (target, t1);
48ae6c13
RH
8170 insn = get_insns ();
8171 end_sequence ();
8172
8173 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
86951993 8174 return target;
48ae6c13
RH
8175 }
8176
8177 return NULL_RTX;
8178}
2ef6ce06
RS
8179\f
8180/* Return true if OPERAND is suitable for operand number OPNO of
8181 instruction ICODE. */
8182
8183bool
8184insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand)
8185{
8186 return (!insn_data[(int) icode].operand[opno].predicate
8187 || (insn_data[(int) icode].operand[opno].predicate
8188 (operand, insn_data[(int) icode].operand[opno].mode)));
8189}
a5c7d693 8190\f
02972eaf
RS
8191/* TARGET is a target of a multiword operation that we are going to
8192 implement as a series of word-mode operations. Return true if
8193 TARGET is suitable for this purpose. */
8194
8195bool
8196valid_multiword_target_p (rtx target)
8197{
ef4bddc2 8198 machine_mode mode;
02972eaf
RS
8199 int i;
8200
8201 mode = GET_MODE (target);
8202 for (i = 0; i < GET_MODE_SIZE (mode); i += UNITS_PER_WORD)
8203 if (!validate_subreg (word_mode, mode, target, i))
8204 return false;
8205 return true;
8206}
8207
4fd3a105
RS
8208/* Like maybe_legitimize_operand, but do not change the code of the
8209 current rtx value. */
8210
8211static bool
8212maybe_legitimize_operand_same_code (enum insn_code icode, unsigned int opno,
8213 struct expand_operand *op)
8214{
8215 /* See if the operand matches in its current form. */
8216 if (insn_operand_matches (icode, opno, op->value))
8217 return true;
8218
8219 /* If the operand is a memory whose address has no side effects,
431e1124
RS
8220 try forcing the address into a non-virtual pseudo register.
8221 The check for side effects is important because copy_to_mode_reg
8222 cannot handle things like auto-modified addresses. */
8223 if (insn_data[(int) icode].operand[opno].allows_mem && MEM_P (op->value))
8224 {
8225 rtx addr, mem;
8226
8227 mem = op->value;
8228 addr = XEXP (mem, 0);
8229 if (!(REG_P (addr) && REGNO (addr) > LAST_VIRTUAL_REGISTER)
8230 && !side_effects_p (addr))
4fd3a105 8231 {
38295e01 8232 rtx_insn *last;
ef4bddc2 8233 machine_mode mode;
431e1124
RS
8234
8235 last = get_last_insn ();
372d6395 8236 mode = get_address_mode (mem);
431e1124
RS
8237 mem = replace_equiv_address (mem, copy_to_mode_reg (mode, addr));
8238 if (insn_operand_matches (icode, opno, mem))
8239 {
8240 op->value = mem;
8241 return true;
8242 }
8243 delete_insns_since (last);
4fd3a105 8244 }
4fd3a105
RS
8245 }
8246
8247 return false;
8248}
8249
a5c7d693
RS
8250/* Try to make OP match operand OPNO of instruction ICODE. Return true
8251 on success, storing the new operand value back in OP. */
8252
8253static bool
8254maybe_legitimize_operand (enum insn_code icode, unsigned int opno,
8255 struct expand_operand *op)
8256{
ef4bddc2 8257 machine_mode mode, imode;
a5c7d693
RS
8258 bool old_volatile_ok, result;
8259
a5c7d693 8260 mode = op->mode;
a5c7d693
RS
8261 switch (op->type)
8262 {
8263 case EXPAND_FIXED:
4fd3a105 8264 old_volatile_ok = volatile_ok;
a5c7d693 8265 volatile_ok = true;
4fd3a105
RS
8266 result = maybe_legitimize_operand_same_code (icode, opno, op);
8267 volatile_ok = old_volatile_ok;
8268 return result;
a5c7d693
RS
8269
8270 case EXPAND_OUTPUT:
8271 gcc_assert (mode != VOIDmode);
4fd3a105
RS
8272 if (op->value
8273 && op->value != const0_rtx
8274 && GET_MODE (op->value) == mode
8275 && maybe_legitimize_operand_same_code (icode, opno, op))
8276 return true;
8277
8278 op->value = gen_reg_rtx (mode);
a5c7d693
RS
8279 break;
8280
8281 case EXPAND_INPUT:
8282 input:
8283 gcc_assert (mode != VOIDmode);
8284 gcc_assert (GET_MODE (op->value) == VOIDmode
8285 || GET_MODE (op->value) == mode);
4fd3a105
RS
8286 if (maybe_legitimize_operand_same_code (icode, opno, op))
8287 return true;
8288
8289 op->value = copy_to_mode_reg (mode, op->value);
a5c7d693
RS
8290 break;
8291
8292 case EXPAND_CONVERT_TO:
8293 gcc_assert (mode != VOIDmode);
8294 op->value = convert_to_mode (mode, op->value, op->unsigned_p);
8295 goto input;
8296
8297 case EXPAND_CONVERT_FROM:
8298 if (GET_MODE (op->value) != VOIDmode)
8299 mode = GET_MODE (op->value);
8300 else
8301 /* The caller must tell us what mode this value has. */
8302 gcc_assert (mode != VOIDmode);
8303
8304 imode = insn_data[(int) icode].operand[opno].mode;
8305 if (imode != VOIDmode && imode != mode)
8306 {
8307 op->value = convert_modes (imode, mode, op->value, op->unsigned_p);
8308 mode = imode;
8309 }
8310 goto input;
8311
8312 case EXPAND_ADDRESS:
8313 gcc_assert (mode != VOIDmode);
8314 op->value = convert_memory_address (mode, op->value);
8315 goto input;
8316
8317 case EXPAND_INTEGER:
8318 mode = insn_data[(int) icode].operand[opno].mode;
8319 if (mode != VOIDmode && const_int_operand (op->value, mode))
8320 goto input;
8321 break;
8322 }
4fd3a105 8323 return insn_operand_matches (icode, opno, op->value);
a5c7d693
RS
8324}
8325
8326/* Make OP describe an input operand that should have the same value
8327 as VALUE, after any mode conversion that the target might request.
8328 TYPE is the type of VALUE. */
8329
8330void
8331create_convert_operand_from_type (struct expand_operand *op,
8332 rtx value, tree type)
8333{
8334 create_convert_operand_from (op, value, TYPE_MODE (type),
8335 TYPE_UNSIGNED (type));
8336}
8337
8338/* Try to make operands [OPS, OPS + NOPS) match operands [OPNO, OPNO + NOPS)
8339 of instruction ICODE. Return true on success, leaving the new operand
8340 values in the OPS themselves. Emit no code on failure. */
8341
8342bool
8343maybe_legitimize_operands (enum insn_code icode, unsigned int opno,
8344 unsigned int nops, struct expand_operand *ops)
8345{
38295e01 8346 rtx_insn *last;
a5c7d693
RS
8347 unsigned int i;
8348
8349 last = get_last_insn ();
8350 for (i = 0; i < nops; i++)
8351 if (!maybe_legitimize_operand (icode, opno + i, &ops[i]))
8352 {
8353 delete_insns_since (last);
8354 return false;
8355 }
8356 return true;
8357}
8358
8359/* Try to generate instruction ICODE, using operands [OPS, OPS + NOPS)
8360 as its operands. Return the instruction pattern on success,
8361 and emit any necessary set-up code. Return null and emit no
8362 code on failure. */
8363
8364rtx
8365maybe_gen_insn (enum insn_code icode, unsigned int nops,
8366 struct expand_operand *ops)
8367{
f04713ee 8368 gcc_assert (nops == (unsigned int) insn_data[(int) icode].n_generator_args);
a5c7d693
RS
8369 if (!maybe_legitimize_operands (icode, 0, nops, ops))
8370 return NULL_RTX;
8371
8372 switch (nops)
8373 {
8374 case 1:
8375 return GEN_FCN (icode) (ops[0].value);
8376 case 2:
8377 return GEN_FCN (icode) (ops[0].value, ops[1].value);
8378 case 3:
8379 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value);
8380 case 4:
8381 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
8382 ops[3].value);
8383 case 5:
8384 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
8385 ops[3].value, ops[4].value);
8386 case 6:
8387 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
8388 ops[3].value, ops[4].value, ops[5].value);
86951993
AM
8389 case 7:
8390 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
8391 ops[3].value, ops[4].value, ops[5].value,
8392 ops[6].value);
8393 case 8:
8394 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
8395 ops[3].value, ops[4].value, ops[5].value,
8396 ops[6].value, ops[7].value);
82bb7d4e
JH
8397 case 9:
8398 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
8399 ops[3].value, ops[4].value, ops[5].value,
8400 ops[6].value, ops[7].value, ops[8].value);
a5c7d693
RS
8401 }
8402 gcc_unreachable ();
8403}
8404
8405/* Try to emit instruction ICODE, using operands [OPS, OPS + NOPS)
8406 as its operands. Return true on success and emit no code on failure. */
8407
8408bool
8409maybe_expand_insn (enum insn_code icode, unsigned int nops,
8410 struct expand_operand *ops)
8411{
8412 rtx pat = maybe_gen_insn (icode, nops, ops);
8413 if (pat)
8414 {
8415 emit_insn (pat);
8416 return true;
8417 }
8418 return false;
8419}
8420
8421/* Like maybe_expand_insn, but for jumps. */
8422
8423bool
8424maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
8425 struct expand_operand *ops)
8426{
8427 rtx pat = maybe_gen_insn (icode, nops, ops);
8428 if (pat)
8429 {
8430 emit_jump_insn (pat);
8431 return true;
8432 }
8433 return false;
8434}
8435
8436/* Emit instruction ICODE, using operands [OPS, OPS + NOPS)
8437 as its operands. */
8438
8439void
8440expand_insn (enum insn_code icode, unsigned int nops,
8441 struct expand_operand *ops)
8442{
8443 if (!maybe_expand_insn (icode, nops, ops))
8444 gcc_unreachable ();
8445}
8446
8447/* Like expand_insn, but for jumps. */
8448
8449void
8450expand_jump_insn (enum insn_code icode, unsigned int nops,
8451 struct expand_operand *ops)
8452{
8453 if (!maybe_expand_jump_insn (icode, nops, ops))
8454 gcc_unreachable ();
8455}
48ae6c13 8456
fcdd52b7
RS
8457/* Reduce conditional compilation elsewhere. */
8458#ifndef HAVE_insv
8459#define HAVE_insv 0
8460#define CODE_FOR_insv CODE_FOR_nothing
8461#endif
8462#ifndef HAVE_extv
8463#define HAVE_extv 0
8464#define CODE_FOR_extv CODE_FOR_nothing
8465#endif
8466#ifndef HAVE_extzv
8467#define HAVE_extzv 0
8468#define CODE_FOR_extzv CODE_FOR_nothing
8469#endif
8470
8471/* Enumerates the possible types of structure operand to an
8472 extraction_insn. */
8473enum extraction_type { ET_unaligned_mem, ET_reg };
8474
8475/* Check whether insv, extv or extzv pattern ICODE can be used for an
8476 insertion or extraction of type TYPE on a structure of mode MODE.
8477 Return true if so and fill in *INSN accordingly. STRUCT_OP is the
8478 operand number of the structure (the first sign_extract or zero_extract
8479 operand) and FIELD_OP is the operand number of the field (the other
8480 side of the set from the sign_extract or zero_extract). */
8481
8482static bool
8483get_traditional_extraction_insn (extraction_insn *insn,
8484 enum extraction_type type,
ef4bddc2 8485 machine_mode mode,
fcdd52b7
RS
8486 enum insn_code icode,
8487 int struct_op, int field_op)
8488{
8489 const struct insn_data_d *data = &insn_data[icode];
8490
ef4bddc2 8491 machine_mode struct_mode = data->operand[struct_op].mode;
fcdd52b7
RS
8492 if (struct_mode == VOIDmode)
8493 struct_mode = word_mode;
8494 if (mode != struct_mode)
8495 return false;
8496
ef4bddc2 8497 machine_mode field_mode = data->operand[field_op].mode;
fcdd52b7
RS
8498 if (field_mode == VOIDmode)
8499 field_mode = word_mode;
8500
ef4bddc2 8501 machine_mode pos_mode = data->operand[struct_op + 2].mode;
fcdd52b7
RS
8502 if (pos_mode == VOIDmode)
8503 pos_mode = word_mode;
8504
8505 insn->icode = icode;
8506 insn->field_mode = field_mode;
8507 insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
8508 insn->pos_mode = pos_mode;
8509 return true;
8510}
8511
d2eeb2d1
RS
8512/* Return true if an optab exists to perform an insertion or extraction
8513 of type TYPE in mode MODE. Describe the instruction in *INSN if so.
8514
8515 REG_OPTAB is the optab to use for register structures and
8516 MISALIGN_OPTAB is the optab to use for misaligned memory structures.
8517 POS_OP is the operand number of the bit position. */
8518
8519static bool
8520get_optab_extraction_insn (struct extraction_insn *insn,
8521 enum extraction_type type,
ef4bddc2 8522 machine_mode mode, direct_optab reg_optab,
d2eeb2d1
RS
8523 direct_optab misalign_optab, int pos_op)
8524{
8525 direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
8526 enum insn_code icode = direct_optab_handler (optab, mode);
8527 if (icode == CODE_FOR_nothing)
8528 return false;
8529
8530 const struct insn_data_d *data = &insn_data[icode];
8531
8532 insn->icode = icode;
8533 insn->field_mode = mode;
8534 insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode);
8535 insn->pos_mode = data->operand[pos_op].mode;
8536 if (insn->pos_mode == VOIDmode)
8537 insn->pos_mode = word_mode;
8538 return true;
8539}
8540
fcdd52b7
RS
8541/* Return true if an instruction exists to perform an insertion or
8542 extraction (PATTERN says which) of type TYPE in mode MODE.
8543 Describe the instruction in *INSN if so. */
8544
8545static bool
8546get_extraction_insn (extraction_insn *insn,
8547 enum extraction_pattern pattern,
8548 enum extraction_type type,
ef4bddc2 8549 machine_mode mode)
fcdd52b7
RS
8550{
8551 switch (pattern)
8552 {
8553 case EP_insv:
8554 if (HAVE_insv
8555 && get_traditional_extraction_insn (insn, type, mode,
8556 CODE_FOR_insv, 0, 3))
8557 return true;
d2eeb2d1
RS
8558 return get_optab_extraction_insn (insn, type, mode, insv_optab,
8559 insvmisalign_optab, 2);
fcdd52b7
RS
8560
8561 case EP_extv:
8562 if (HAVE_extv
8563 && get_traditional_extraction_insn (insn, type, mode,
8564 CODE_FOR_extv, 1, 0))
8565 return true;
d2eeb2d1
RS
8566 return get_optab_extraction_insn (insn, type, mode, extv_optab,
8567 extvmisalign_optab, 3);
fcdd52b7
RS
8568
8569 case EP_extzv:
8570 if (HAVE_extzv
8571 && get_traditional_extraction_insn (insn, type, mode,
8572 CODE_FOR_extzv, 1, 0))
8573 return true;
d2eeb2d1
RS
8574 return get_optab_extraction_insn (insn, type, mode, extzv_optab,
8575 extzvmisalign_optab, 3);
fcdd52b7
RS
8576
8577 default:
8578 gcc_unreachable ();
8579 }
8580}
8581
8582/* Return true if an instruction exists to access a field of mode
8583 FIELDMODE in a structure that has STRUCT_BITS significant bits.
8584 Describe the "best" such instruction in *INSN if so. PATTERN and
8585 TYPE describe the type of insertion or extraction we want to perform.
8586
8587 For an insertion, the number of significant structure bits includes
8588 all bits of the target. For an extraction, it need only include the
8589 most significant bit of the field. Larger widths are acceptable
8590 in both cases. */
8591
8592static bool
8593get_best_extraction_insn (extraction_insn *insn,
8594 enum extraction_pattern pattern,
8595 enum extraction_type type,
8596 unsigned HOST_WIDE_INT struct_bits,
ef4bddc2 8597 machine_mode field_mode)
fcdd52b7 8598{
ef4bddc2 8599 machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
fcdd52b7
RS
8600 while (mode != VOIDmode)
8601 {
8602 if (get_extraction_insn (insn, pattern, type, mode))
8603 {
8604 while (mode != VOIDmode
8605 && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (field_mode)
8606 && !TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
8607 field_mode))
8608 {
8609 get_extraction_insn (insn, pattern, type, mode);
8610 mode = GET_MODE_WIDER_MODE (mode);
8611 }
8612 return true;
8613 }
8614 mode = GET_MODE_WIDER_MODE (mode);
8615 }
8616 return false;
8617}
8618
8619/* Return true if an instruction exists to access a field of mode
8620 FIELDMODE in a register structure that has STRUCT_BITS significant bits.
8621 Describe the "best" such instruction in *INSN if so. PATTERN describes
8622 the type of insertion or extraction we want to perform.
8623
8624 For an insertion, the number of significant structure bits includes
8625 all bits of the target. For an extraction, it need only include the
8626 most significant bit of the field. Larger widths are acceptable
8627 in both cases. */
8628
8629bool
8630get_best_reg_extraction_insn (extraction_insn *insn,
8631 enum extraction_pattern pattern,
8632 unsigned HOST_WIDE_INT struct_bits,
ef4bddc2 8633 machine_mode field_mode)
fcdd52b7
RS
8634{
8635 return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
8636 field_mode);
8637}
8638
8639/* Return true if an instruction exists to access a field of BITSIZE
8640 bits starting BITNUM bits into a memory structure. Describe the
8641 "best" such instruction in *INSN if so. PATTERN describes the type
8642 of insertion or extraction we want to perform and FIELDMODE is the
8643 natural mode of the extracted field.
8644
8645 The instructions considered here only access bytes that overlap
8646 the bitfield; they do not touch any surrounding bytes. */
8647
8648bool
8649get_best_mem_extraction_insn (extraction_insn *insn,
8650 enum extraction_pattern pattern,
8651 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
ef4bddc2 8652 machine_mode field_mode)
fcdd52b7
RS
8653{
8654 unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
8655 + bitsize
8656 + BITS_PER_UNIT - 1);
8657 struct_bits -= struct_bits % BITS_PER_UNIT;
8658 return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
8659 struct_bits, field_mode);
8660}
8661
73049af5
JJ
8662/* Determine whether "1 << x" is relatively cheap in word_mode. */
8663
8664bool
8665lshift_cheap_p (bool speed_p)
8666{
8667 /* FIXME: This should be made target dependent via this "this_target"
8668 mechanism, similar to e.g. can_copy_init_p in gcse.c. */
8669 static bool init[2] = { false, false };
8670 static bool cheap[2] = { true, true };
8671
8672 /* If the targer has no lshift in word_mode, the operation will most
8673 probably not be cheap. ??? Does GCC even work for such targets? */
8674 if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
8675 return false;
8676
8677 if (!init[speed_p])
8678 {
8679 rtx reg = gen_raw_REG (word_mode, 10000);
8680 int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
8681 speed_p);
8682 cheap[speed_p] = cost < COSTS_N_INSNS (3);
8683 init[speed_p] = true;
8684 }
8685
8686 return cheap[speed_p];
8687}
8688
e2500fed 8689#include "gt-optabs.h"