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