1 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
2 Copyright (C) 1987-2018 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "target.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "memmodel.h"
29 #include "predict.h"
30 #include "tm_p.h"
31 #include "expmed.h"
32 #include "optabs.h"
33 #include "emit-rtl.h"
34 #include "recog.h"
35 #include "diagnostic-core.h"
36 #include "rtx-vector-builder.h"
37
38 /* Include insn-config.h before expr.h so that HAVE_conditional_move
39 is properly defined. */
40 #include "stor-layout.h"
41 #include "except.h"
42 #include "dojump.h"
43 #include "explow.h"
44 #include "expr.h"
45 #include "optabs-tree.h"
46 #include "libfuncs.h"
47
48 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
49 machine_mode *);
50 static rtx expand_unop_direct (machine_mode, optab, rtx, rtx, int);
51 static void emit_libcall_block_1 (rtx_insn *, rtx, rtx, rtx, bool);
52
53 /* Debug facility for use in GDB. */
54 void debug_optab_libfuncs (void);
55
56 /* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
57 the result of operation CODE applied to OP0 (and OP1 if it is a binary
58 operation). OP0_MODE is OP0's mode.
59
60 If the last insn does not set TARGET, don't do anything, but return 1.
61
62 If the last insn or a previous insn sets TARGET and TARGET is one of OP0
63 or OP1, don't add the REG_EQUAL note but return 0. Our caller can then
64 try again, ensuring that TARGET is not one of the operands. */
65
66 static int
add_equal_note(rtx_insn * insns,rtx target,enum rtx_code code,rtx op0,rtx op1,machine_mode op0_mode)67 add_equal_note (rtx_insn *insns, rtx target, enum rtx_code code, rtx op0,
68 rtx op1, machine_mode op0_mode)
69 {
70 rtx_insn *last_insn;
71 rtx set;
72 rtx note;
73
74 gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
75
76 if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
77 && GET_RTX_CLASS (code) != RTX_BIN_ARITH
78 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
79 && GET_RTX_CLASS (code) != RTX_COMPARE
80 && GET_RTX_CLASS (code) != RTX_UNARY)
81 return 1;
82
83 if (GET_CODE (target) == ZERO_EXTRACT)
84 return 1;
85
86 for (last_insn = insns;
87 NEXT_INSN (last_insn) != NULL_RTX;
88 last_insn = NEXT_INSN (last_insn))
89 ;
90
91 /* If TARGET is in OP0 or OP1, punt. We'd end up with a note referencing
92 a value changing in the insn, so the note would be invalid for CSE. */
93 if (reg_overlap_mentioned_p (target, op0)
94 || (op1 && reg_overlap_mentioned_p (target, op1)))
95 {
96 if (MEM_P (target)
97 && (rtx_equal_p (target, op0)
98 || (op1 && rtx_equal_p (target, op1))))
99 {
100 /* For MEM target, with MEM = MEM op X, prefer no REG_EQUAL note
101 over expanding it as temp = MEM op X, MEM = temp. If the target
102 supports MEM = MEM op X instructions, it is sometimes too hard
103 to reconstruct that form later, especially if X is also a memory,
104 and due to multiple occurrences of addresses the address might
105 be forced into register unnecessarily.
106 Note that not emitting the REG_EQUIV note might inhibit
107 CSE in some cases. */
108 set = single_set (last_insn);
109 if (set
110 && GET_CODE (SET_SRC (set)) == code
111 && MEM_P (SET_DEST (set))
112 && (rtx_equal_p (SET_DEST (set), XEXP (SET_SRC (set), 0))
113 || (op1 && rtx_equal_p (SET_DEST (set),
114 XEXP (SET_SRC (set), 1)))))
115 return 1;
116 }
117 return 0;
118 }
119
120 set = set_for_reg_notes (last_insn);
121 if (set == NULL_RTX)
122 return 1;
123
124 if (! rtx_equal_p (SET_DEST (set), target)
125 /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it. */
126 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
127 || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
128 return 1;
129
130 if (GET_RTX_CLASS (code) == RTX_UNARY)
131 switch (code)
132 {
133 case FFS:
134 case CLZ:
135 case CTZ:
136 case CLRSB:
137 case POPCOUNT:
138 case PARITY:
139 case BSWAP:
140 if (op0_mode != VOIDmode && GET_MODE (target) != op0_mode)
141 {
142 note = gen_rtx_fmt_e (code, op0_mode, copy_rtx (op0));
143 if (GET_MODE_UNIT_SIZE (op0_mode)
144 > GET_MODE_UNIT_SIZE (GET_MODE (target)))
145 note = simplify_gen_unary (TRUNCATE, GET_MODE (target),
146 note, op0_mode);
147 else
148 note = simplify_gen_unary (ZERO_EXTEND, GET_MODE (target),
149 note, op0_mode);
150 break;
151 }
152 /* FALLTHRU */
153 default:
154 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
155 break;
156 }
157 else
158 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
159
160 set_unique_reg_note (last_insn, REG_EQUAL, note);
161
162 return 1;
163 }
164
165 /* Given two input operands, OP0 and OP1, determine what the correct from_mode
166 for a widening operation would be. In most cases this would be OP0, but if
167 that's a constant it'll be VOIDmode, which isn't useful. */
168
169 static machine_mode
widened_mode(machine_mode to_mode,rtx op0,rtx op1)170 widened_mode (machine_mode to_mode, rtx op0, rtx op1)
171 {
172 machine_mode m0 = GET_MODE (op0);
173 machine_mode m1 = GET_MODE (op1);
174 machine_mode result;
175
176 if (m0 == VOIDmode && m1 == VOIDmode)
177 return to_mode;
178 else if (m0 == VOIDmode || GET_MODE_UNIT_SIZE (m0) < GET_MODE_UNIT_SIZE (m1))
179 result = m1;
180 else
181 result = m0;
182
183 if (GET_MODE_UNIT_SIZE (result) > GET_MODE_UNIT_SIZE (to_mode))
184 return to_mode;
185
186 return result;
187 }
188
189 /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
190 says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
191 not actually do a sign-extend or zero-extend, but can leave the
192 higher-order bits of the result rtx undefined, for example, in the case
193 of logical operations, but not right shifts. */
194
195 static rtx
widen_operand(rtx op,machine_mode mode,machine_mode oldmode,int unsignedp,int no_extend)196 widen_operand (rtx op, machine_mode mode, machine_mode oldmode,
197 int unsignedp, int no_extend)
198 {
199 rtx result;
200 scalar_int_mode int_mode;
201
202 /* If we don't have to extend and this is a constant, return it. */
203 if (no_extend && GET_MODE (op) == VOIDmode)
204 return op;
205
206 /* If we must extend do so. If OP is a SUBREG for a promoted object, also
207 extend since it will be more efficient to do so unless the signedness of
208 a promoted object differs from our extension. */
209 if (! no_extend
210 || !is_a <scalar_int_mode> (mode, &int_mode)
211 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
212 && SUBREG_CHECK_PROMOTED_SIGN (op, unsignedp)))
213 return convert_modes (mode, oldmode, op, unsignedp);
214
215 /* If MODE is no wider than a single word, we return a lowpart or paradoxical
216 SUBREG. */
217 if (GET_MODE_SIZE (int_mode) <= UNITS_PER_WORD)
218 return gen_lowpart (int_mode, force_reg (GET_MODE (op), op));
219
220 /* Otherwise, get an object of MODE, clobber it, and set the low-order
221 part to OP. */
222
223 result = gen_reg_rtx (int_mode);
224 emit_clobber (result);
225 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
226 return result;
227 }
228
229 /* Expand vector widening operations.
230
231 There are two different classes of operations handled here:
232 1) Operations whose result is wider than all the arguments to the operation.
233 Examples: VEC_UNPACK_HI/LO_EXPR, VEC_WIDEN_MULT_HI/LO_EXPR
234 In this case OP0 and optionally OP1 would be initialized,
235 but WIDE_OP wouldn't (not relevant for this case).
236 2) Operations whose result is of the same size as the last argument to the
237 operation, but wider than all the other arguments to the operation.
238 Examples: WIDEN_SUM_EXPR, VEC_DOT_PROD_EXPR.
239 In the case WIDE_OP, OP0 and optionally OP1 would be initialized.
240
241 E.g, when called to expand the following operations, this is how
242 the arguments will be initialized:
243 nops OP0 OP1 WIDE_OP
244 widening-sum 2 oprnd0 - oprnd1
245 widening-dot-product 3 oprnd0 oprnd1 oprnd2
246 widening-mult 2 oprnd0 oprnd1 -
247 type-promotion (vec-unpack) 1 oprnd0 - - */
248
249 rtx
expand_widen_pattern_expr(sepops ops,rtx op0,rtx op1,rtx wide_op,rtx target,int unsignedp)250 expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
251 rtx target, int unsignedp)
252 {
253 struct expand_operand eops[4];
254 tree oprnd0, oprnd1, oprnd2;
255 machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
256 optab widen_pattern_optab;
257 enum insn_code icode;
258 int nops = TREE_CODE_LENGTH (ops->code);
259 int op;
260
261 oprnd0 = ops->op0;
262 tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
263 widen_pattern_optab =
264 optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default);
265 if (ops->code == WIDEN_MULT_PLUS_EXPR
266 || ops->code == WIDEN_MULT_MINUS_EXPR)
267 icode = find_widening_optab_handler (widen_pattern_optab,
268 TYPE_MODE (TREE_TYPE (ops->op2)),
269 tmode0);
270 else
271 icode = optab_handler (widen_pattern_optab, tmode0);
272 gcc_assert (icode != CODE_FOR_nothing);
273
274 if (nops >= 2)
275 {
276 oprnd1 = ops->op1;
277 tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
278 }
279
280 /* The last operand is of a wider mode than the rest of the operands. */
281 if (nops == 2)
282 wmode = tmode1;
283 else if (nops == 3)
284 {
285 gcc_assert (tmode1 == tmode0);
286 gcc_assert (op1);
287 oprnd2 = ops->op2;
288 wmode = TYPE_MODE (TREE_TYPE (oprnd2));
289 }
290
291 op = 0;
292 create_output_operand (&eops[op++], target, TYPE_MODE (ops->type));
293 create_convert_operand_from (&eops[op++], op0, tmode0, unsignedp);
294 if (op1)
295 create_convert_operand_from (&eops[op++], op1, tmode1, unsignedp);
296 if (wide_op)
297 create_convert_operand_from (&eops[op++], wide_op, wmode, unsignedp);
298 expand_insn (icode, op, eops);
299 return eops[0].value;
300 }
301
302 /* Generate code to perform an operation specified by TERNARY_OPTAB
303 on operands OP0, OP1 and OP2, with result having machine-mode MODE.
304
305 UNSIGNEDP is for the case where we have to widen the operands
306 to perform the operation. It says to use zero-extension.
307
308 If TARGET is nonzero, the value
309 is generated there, if it is convenient to do so.
310 In all cases an rtx is returned for the locus of the value;
311 this may or may not be TARGET. */
312
313 rtx
expand_ternary_op(machine_mode mode,optab ternary_optab,rtx op0,rtx op1,rtx op2,rtx target,int unsignedp)314 expand_ternary_op (machine_mode mode, optab ternary_optab, rtx op0,
315 rtx op1, rtx op2, rtx target, int unsignedp)
316 {
317 struct expand_operand ops[4];
318 enum insn_code icode = optab_handler (ternary_optab, mode);
319
320 gcc_assert (optab_handler (ternary_optab, mode) != CODE_FOR_nothing);
321
322 create_output_operand (&ops[0], target, mode);
323 create_convert_operand_from (&ops[1], op0, mode, unsignedp);
324 create_convert_operand_from (&ops[2], op1, mode, unsignedp);
325 create_convert_operand_from (&ops[3], op2, mode, unsignedp);
326 expand_insn (icode, 4, ops);
327 return ops[0].value;
328 }
329
330
331 /* Like expand_binop, but return a constant rtx if the result can be
332 calculated at compile time. The arguments and return value are
333 otherwise the same as for expand_binop. */
334
335 rtx
simplify_expand_binop(machine_mode mode,optab binoptab,rtx op0,rtx op1,rtx target,int unsignedp,enum optab_methods methods)336 simplify_expand_binop (machine_mode mode, optab binoptab,
337 rtx op0, rtx op1, rtx target, int unsignedp,
338 enum optab_methods methods)
339 {
340 if (CONSTANT_P (op0) && CONSTANT_P (op1))
341 {
342 rtx x = simplify_binary_operation (optab_to_code (binoptab),
343 mode, op0, op1);
344 if (x)
345 return x;
346 }
347
348 return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
349 }
350
351 /* Like simplify_expand_binop, but always put the result in TARGET.
352 Return true if the expansion succeeded. */
353
354 bool
force_expand_binop(machine_mode mode,optab binoptab,rtx op0,rtx op1,rtx target,int unsignedp,enum optab_methods methods)355 force_expand_binop (machine_mode mode, optab binoptab,
356 rtx op0, rtx op1, rtx target, int unsignedp,
357 enum optab_methods methods)
358 {
359 rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
360 target, unsignedp, methods);
361 if (x == 0)
362 return false;
363 if (x != target)
364 emit_move_insn (target, x);
365 return true;
366 }
367
368 /* Create a new vector value in VMODE with all elements set to OP. The
369 mode of OP must be the element mode of VMODE. If OP is a constant,
370 then the return value will be a constant. */
371
372 rtx
expand_vector_broadcast(machine_mode vmode,rtx op)373 expand_vector_broadcast (machine_mode vmode, rtx op)
374 {
375 int n;
376 rtvec vec;
377
378 gcc_checking_assert (VECTOR_MODE_P (vmode));
379
380 if (valid_for_const_vector_p (vmode, op))
381 return gen_const_vec_duplicate (vmode, op);
382
383 insn_code icode = optab_handler (vec_duplicate_optab, vmode);
384 if (icode != CODE_FOR_nothing)
385 {
386 struct expand_operand ops[2];
387 create_output_operand (&ops[0], NULL_RTX, vmode);
388 create_input_operand (&ops[1], op, GET_MODE (op));
389 expand_insn (icode, 2, ops);
390 return ops[0].value;
391 }
392
393 if (!GET_MODE_NUNITS (vmode).is_constant (&n))
394 return NULL;
395
396 /* ??? If the target doesn't have a vec_init, then we have no easy way
397 of performing this operation. Most of this sort of generic support
398 is hidden away in the vector lowering support in gimple. */
399 icode = convert_optab_handler (vec_init_optab, vmode,
400 GET_MODE_INNER (vmode));
401 if (icode == CODE_FOR_nothing)
402 return NULL;
403
404 vec = rtvec_alloc (n);
405 for (int i = 0; i < n; ++i)
406 RTVEC_ELT (vec, i) = op;
407 rtx ret = gen_reg_rtx (vmode);
408 emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
409
410 return ret;
411 }
412
413 /* This subroutine of expand_doubleword_shift handles the cases in which
414 the effective shift value is >= BITS_PER_WORD. The arguments and return
415 value are the same as for the parent routine, except that SUPERWORD_OP1
416 is the shift count to use when shifting OUTOF_INPUT into INTO_TARGET.
417 INTO_TARGET may be null if the caller has decided to calculate it. */
418
419 static bool
expand_superword_shift(optab binoptab,rtx outof_input,rtx superword_op1,rtx outof_target,rtx into_target,int unsignedp,enum optab_methods methods)420 expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
421 rtx outof_target, rtx into_target,
422 int unsignedp, enum optab_methods methods)
423 {
424 if (into_target != 0)
425 if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
426 into_target, unsignedp, methods))
427 return false;
428
429 if (outof_target != 0)
430 {
431 /* For a signed right shift, we must fill OUTOF_TARGET with copies
432 of the sign bit, otherwise we must fill it with zeros. */
433 if (binoptab != ashr_optab)
434 emit_move_insn (outof_target, CONST0_RTX (word_mode));
435 else
436 if (!force_expand_binop (word_mode, binoptab, outof_input,
437 gen_int_shift_amount (word_mode,
438 BITS_PER_WORD - 1),
439 outof_target, unsignedp, methods))
440 return false;
441 }
442 return true;
443 }
444
445 /* This subroutine of expand_doubleword_shift handles the cases in which
446 the effective shift value is < BITS_PER_WORD. The arguments and return
447 value are the same as for the parent routine. */
448
449 static bool
expand_subword_shift(scalar_int_mode op1_mode,optab binoptab,rtx outof_input,rtx into_input,rtx op1,rtx outof_target,rtx into_target,int unsignedp,enum optab_methods methods,unsigned HOST_WIDE_INT shift_mask)450 expand_subword_shift (scalar_int_mode op1_mode, optab binoptab,
451 rtx outof_input, rtx into_input, rtx op1,
452 rtx outof_target, rtx into_target,
453 int unsignedp, enum optab_methods methods,
454 unsigned HOST_WIDE_INT shift_mask)
455 {
456 optab reverse_unsigned_shift, unsigned_shift;
457 rtx tmp, carries;
458
459 reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
460 unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
461
462 /* The low OP1 bits of INTO_TARGET come from the high bits of OUTOF_INPUT.
463 We therefore need to shift OUTOF_INPUT by (BITS_PER_WORD - OP1) bits in
464 the opposite direction to BINOPTAB. */
465 if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
466 {
467 carries = outof_input;
468 tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD,
469 op1_mode), op1_mode);
470 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
471 0, true, methods);
472 }
473 else
474 {
475 /* We must avoid shifting by BITS_PER_WORD bits since that is either
476 the same as a zero shift (if shift_mask == BITS_PER_WORD - 1) or
477 has unknown behavior. Do a single shift first, then shift by the
478 remainder. It's OK to use ~OP1 as the remainder if shift counts
479 are truncated to the mode size. */
480 carries = expand_binop (word_mode, reverse_unsigned_shift,
481 outof_input, const1_rtx, 0, unsignedp, methods);
482 if (shift_mask == BITS_PER_WORD - 1)
483 {
484 tmp = immed_wide_int_const
485 (wi::minus_one (GET_MODE_PRECISION (op1_mode)), op1_mode);
486 tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
487 0, true, methods);
488 }
489 else
490 {
491 tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD - 1,
492 op1_mode), op1_mode);
493 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
494 0, true, methods);
495 }
496 }
497 if (tmp == 0 || carries == 0)
498 return false;
499 carries = expand_binop (word_mode, reverse_unsigned_shift,
500 carries, tmp, 0, unsignedp, methods);
501 if (carries == 0)
502 return false;
503
504 /* Shift INTO_INPUT logically by OP1. This is the last use of INTO_INPUT
505 so the result can go directly into INTO_TARGET if convenient. */
506 tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
507 into_target, unsignedp, methods);
508 if (tmp == 0)
509 return false;
510
511 /* Now OR in the bits carried over from OUTOF_INPUT. */
512 if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
513 into_target, unsignedp, methods))
514 return false;
515
516 /* Use a standard word_mode shift for the out-of half. */
517 if (outof_target != 0)
518 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
519 outof_target, unsignedp, methods))
520 return false;
521
522 return true;
523 }
524
525
526 /* Try implementing expand_doubleword_shift using conditional moves.
527 The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
528 otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1
529 are the shift counts to use in the former and latter case. All other
530 arguments are the same as the parent routine. */
531
532 static bool
expand_doubleword_shift_condmove(scalar_int_mode op1_mode,optab binoptab,enum rtx_code cmp_code,rtx cmp1,rtx cmp2,rtx outof_input,rtx into_input,rtx subword_op1,rtx superword_op1,rtx outof_target,rtx into_target,int unsignedp,enum optab_methods methods,unsigned HOST_WIDE_INT shift_mask)533 expand_doubleword_shift_condmove (scalar_int_mode op1_mode, optab binoptab,
534 enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
535 rtx outof_input, rtx into_input,
536 rtx subword_op1, rtx superword_op1,
537 rtx outof_target, rtx into_target,
538 int unsignedp, enum optab_methods methods,
539 unsigned HOST_WIDE_INT shift_mask)
540 {
541 rtx outof_superword, into_superword;
542
543 /* Put the superword version of the output into OUTOF_SUPERWORD and
544 INTO_SUPERWORD. */
545 outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
546 if (outof_target != 0 && subword_op1 == superword_op1)
547 {
548 /* The value INTO_TARGET >> SUBWORD_OP1, which we later store in
549 OUTOF_TARGET, is the same as the value of INTO_SUPERWORD. */
550 into_superword = outof_target;
551 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
552 outof_superword, 0, unsignedp, methods))
553 return false;
554 }
555 else
556 {
557 into_superword = gen_reg_rtx (word_mode);
558 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
559 outof_superword, into_superword,
560 unsignedp, methods))
561 return false;
562 }
563
564 /* Put the subword version directly in OUTOF_TARGET and INTO_TARGET. */
565 if (!expand_subword_shift (op1_mode, binoptab,
566 outof_input, into_input, subword_op1,
567 outof_target, into_target,
568 unsignedp, methods, shift_mask))
569 return false;
570
571 /* Select between them. Do the INTO half first because INTO_SUPERWORD
572 might be the current value of OUTOF_TARGET. */
573 if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
574 into_target, into_superword, word_mode, false))
575 return false;
576
577 if (outof_target != 0)
578 if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
579 outof_target, outof_superword,
580 word_mode, false))
581 return false;
582
583 return true;
584 }
585
586 /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
587 OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
588 input operand; the shift moves bits in the direction OUTOF_INPUT->
589 INTO_TARGET. OUTOF_TARGET and INTO_TARGET are the equivalent words
590 of the target. OP1 is the shift count and OP1_MODE is its mode.
591 If OP1 is constant, it will have been truncated as appropriate
592 and is known to be nonzero.
593
594 If SHIFT_MASK is zero, the result of word shifts is undefined when the
595 shift count is outside the range [0, BITS_PER_WORD). This routine must
596 avoid generating such shifts for OP1s in the range [0, BITS_PER_WORD * 2).
597
598 If SHIFT_MASK is nonzero, all word-mode shift counts are effectively
599 masked by it and shifts in the range [BITS_PER_WORD, SHIFT_MASK) will
600 fill with zeros or sign bits as appropriate.
601
602 If SHIFT_MASK is BITS_PER_WORD - 1, this routine will synthesize
603 a doubleword shift whose equivalent mask is BITS_PER_WORD * 2 - 1.
604 Doing this preserves semantics required by SHIFT_COUNT_TRUNCATED.
605 In all other cases, shifts by values outside [0, BITS_PER_UNIT * 2)
606 are undefined.
607
608 BINOPTAB, UNSIGNEDP and METHODS are as for expand_binop. This function
609 may not use INTO_INPUT after modifying INTO_TARGET, and similarly for
610 OUTOF_INPUT and OUTOF_TARGET. OUTOF_TARGET can be null if the parent
611 function wants to calculate it itself.
612
613 Return true if the shift could be successfully synthesized. */
614
615 static bool
expand_doubleword_shift(scalar_int_mode op1_mode,optab binoptab,rtx outof_input,rtx into_input,rtx op1,rtx outof_target,rtx into_target,int unsignedp,enum optab_methods methods,unsigned HOST_WIDE_INT shift_mask)616 expand_doubleword_shift (scalar_int_mode op1_mode, optab binoptab,
617 rtx outof_input, rtx into_input, rtx op1,
618 rtx outof_target, rtx into_target,
619 int unsignedp, enum optab_methods methods,
620 unsigned HOST_WIDE_INT shift_mask)
621 {
622 rtx superword_op1, tmp, cmp1, cmp2;
623 enum rtx_code cmp_code;
624
625 /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
626 fill the result with sign or zero bits as appropriate. If so, the value
627 of OUTOF_TARGET will always be (SHIFT OUTOF_INPUT OP1). Recursively call
628 this routine to calculate INTO_TARGET (which depends on both OUTOF_INPUT
629 and INTO_INPUT), then emit code to set up OUTOF_TARGET.
630
631 This isn't worthwhile for constant shifts since the optimizers will
632 cope better with in-range shift counts. */
633 if (shift_mask >= BITS_PER_WORD
634 && outof_target != 0
635 && !CONSTANT_P (op1))
636 {
637 if (!expand_doubleword_shift (op1_mode, binoptab,
638 outof_input, into_input, op1,
639 0, into_target,
640 unsignedp, methods, shift_mask))
641 return false;
642 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
643 outof_target, unsignedp, methods))
644 return false;
645 return true;
646 }
647
648 /* Set CMP_CODE, CMP1 and CMP2 so that the rtx (CMP_CODE CMP1 CMP2)
649 is true when the effective shift value is less than BITS_PER_WORD.
650 Set SUPERWORD_OP1 to the shift count that should be used to shift
651 OUTOF_INPUT into INTO_TARGET when the condition is false. */
652 tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD, op1_mode), op1_mode);
653 if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
654 {
655 /* Set CMP1 to OP1 & BITS_PER_WORD. The result is zero iff OP1
656 is a subword shift count. */
657 cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
658 0, true, methods);
659 cmp2 = CONST0_RTX (op1_mode);
660 cmp_code = EQ;
661 superword_op1 = op1;
662 }
663 else
664 {
665 /* Set CMP1 to OP1 - BITS_PER_WORD. */
666 cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
667 0, true, methods);
668 cmp2 = CONST0_RTX (op1_mode);
669 cmp_code = LT;
670 superword_op1 = cmp1;
671 }
672 if (cmp1 == 0)
673 return false;
674
675 /* If we can compute the condition at compile time, pick the
676 appropriate subroutine. */
677 tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
678 if (tmp != 0 && CONST_INT_P (tmp))
679 {
680 if (tmp == const0_rtx)
681 return expand_superword_shift (binoptab, outof_input, superword_op1,
682 outof_target, into_target,
683 unsignedp, methods);
684 else
685 return expand_subword_shift (op1_mode, binoptab,
686 outof_input, into_input, op1,
687 outof_target, into_target,
688 unsignedp, methods, shift_mask);
689 }
690
691 /* Try using conditional moves to generate straight-line code. */
692 if (HAVE_conditional_move)
693 {
694 rtx_insn *start = get_last_insn ();
695 if (expand_doubleword_shift_condmove (op1_mode, binoptab,
696 cmp_code, cmp1, cmp2,
697 outof_input, into_input,
698 op1, superword_op1,
699 outof_target, into_target,
700 unsignedp, methods, shift_mask))
701 return true;
702 delete_insns_since (start);
703 }
704
705 /* As a last resort, use branches to select the correct alternative. */
706 rtx_code_label *subword_label = gen_label_rtx ();
707 rtx_code_label *done_label = gen_label_rtx ();
708
709 NO_DEFER_POP;
710 do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
711 0, 0, subword_label,
712 profile_probability::uninitialized ());
713 OK_DEFER_POP;
714
715 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
716 outof_target, into_target,
717 unsignedp, methods))
718 return false;
719
720 emit_jump_insn (targetm.gen_jump (done_label));
721 emit_barrier ();
722 emit_label (subword_label);
723
724 if (!expand_subword_shift (op1_mode, binoptab,
725 outof_input, into_input, op1,
726 outof_target, into_target,
727 unsignedp, methods, shift_mask))
728 return false;
729
730 emit_label (done_label);
731 return true;
732 }
733
734 /* Subroutine of expand_binop. Perform a double word multiplication of
735 operands OP0 and OP1 both of mode MODE, which is exactly twice as wide
736 as the target's word_mode. This function return NULL_RTX if anything
737 goes wrong, in which case it may have already emitted instructions
738 which need to be deleted.
739
740 If we want to multiply two two-word values and have normal and widening
741 multiplies of single-word values, we can do this with three smaller
742 multiplications.
743
744 The multiplication proceeds as follows:
745 _______________________
746 [__op0_high_|__op0_low__]
747 _______________________
748 * [__op1_high_|__op1_low__]
749 _______________________________________________
750 _______________________
751 (1) [__op0_low__*__op1_low__]
752 _______________________
753 (2a) [__op0_low__*__op1_high_]
754 _______________________
755 (2b) [__op0_high_*__op1_low__]
756 _______________________
757 (3) [__op0_high_*__op1_high_]
758
759
760 This gives a 4-word result. Since we are only interested in the
761 lower 2 words, partial result (3) and the upper words of (2a) and
762 (2b) don't need to be calculated. Hence (2a) and (2b) can be
763 calculated using non-widening multiplication.
764
765 (1), however, needs to be calculated with an unsigned widening
766 multiplication. If this operation is not directly supported we
767 try using a signed widening multiplication and adjust the result.
768 This adjustment works as follows:
769
770 If both operands are positive then no adjustment is needed.
771
772 If the operands have different signs, for example op0_low < 0 and
773 op1_low >= 0, the instruction treats the most significant bit of
774 op0_low as a sign bit instead of a bit with significance
775 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
776 with 2**BITS_PER_WORD - op0_low, and two's complements the
777 result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
778 the result.
779
780 Similarly, if both operands are negative, we need to add
781 (op0_low + op1_low) * 2**BITS_PER_WORD.
782
783 We use a trick to adjust quickly. We logically shift op0_low right
784 (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
785 op0_high (op1_high) before it is used to calculate 2b (2a). If no
786 logical shift exists, we do an arithmetic right shift and subtract
787 the 0 or -1. */
788
789 static rtx
expand_doubleword_mult(machine_mode mode,rtx op0,rtx op1,rtx target,bool umulp,enum optab_methods methods)790 expand_doubleword_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
791 bool umulp, enum optab_methods methods)
792 {
793 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
794 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
795 rtx wordm1 = (umulp ? NULL_RTX
796 : gen_int_shift_amount (word_mode, BITS_PER_WORD - 1));
797 rtx product, adjust, product_high, temp;
798
799 rtx op0_high = operand_subword_force (op0, high, mode);
800 rtx op0_low = operand_subword_force (op0, low, mode);
801 rtx op1_high = operand_subword_force (op1, high, mode);
802 rtx op1_low = operand_subword_force (op1, low, mode);
803
804 /* If we're using an unsigned multiply to directly compute the product
805 of the low-order words of the operands and perform any required
806 adjustments of the operands, we begin by trying two more multiplications
807 and then computing the appropriate sum.
808
809 We have checked above that the required addition is provided.
810 Full-word addition will normally always succeed, especially if
811 it is provided at all, so we don't worry about its failure. The
812 multiplication may well fail, however, so we do handle that. */
813
814 if (!umulp)
815 {
816 /* ??? This could be done with emit_store_flag where available. */
817 temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
818 NULL_RTX, 1, methods);
819 if (temp)
820 op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
821 NULL_RTX, 0, OPTAB_DIRECT);
822 else
823 {
824 temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
825 NULL_RTX, 0, methods);
826 if (!temp)
827 return NULL_RTX;
828 op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
829 NULL_RTX, 0, OPTAB_DIRECT);
830 }
831
832 if (!op0_high)
833 return NULL_RTX;
834 }
835
836 adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
837 NULL_RTX, 0, OPTAB_DIRECT);
838 if (!adjust)
839 return NULL_RTX;
840
841 /* OP0_HIGH should now be dead. */
842
843 if (!umulp)
844 {
845 /* ??? This could be done with emit_store_flag where available. */
846 temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
847 NULL_RTX, 1, methods);
848 if (temp)
849 op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
850 NULL_RTX, 0, OPTAB_DIRECT);
851 else
852 {
853 temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
854 NULL_RTX, 0, methods);
855 if (!temp)
856 return NULL_RTX;
857 op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
858 NULL_RTX, 0, OPTAB_DIRECT);
859 }
860
861 if (!op1_high)
862 return NULL_RTX;
863 }
864
865 temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
866 NULL_RTX, 0, OPTAB_DIRECT);
867 if (!temp)
868 return NULL_RTX;
869
870 /* OP1_HIGH should now be dead. */
871
872 adjust = expand_binop (word_mode, add_optab, adjust, temp,
873 NULL_RTX, 0, OPTAB_DIRECT);
874
875 if (target && !REG_P (target))
876 target = NULL_RTX;
877
878 /* *_widen_optab needs to determine operand mode, make sure at least
879 one operand has non-VOID mode. */
880 if (GET_MODE (op0_low) == VOIDmode && GET_MODE (op1_low) == VOIDmode)
881 op0_low = force_reg (word_mode, op0_low);
882
883 if (umulp)
884 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
885 target, 1, OPTAB_DIRECT);
886 else
887 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
888 target, 1, OPTAB_DIRECT);
889
890 if (!product)
891 return NULL_RTX;
892
893 product_high = operand_subword (product, high, 1, mode);
894 adjust = expand_binop (word_mode, add_optab, product_high, adjust,
895 NULL_RTX, 0, OPTAB_DIRECT);
896 emit_move_insn (product_high, adjust);
897 return product;
898 }
899
900 /* Wrapper around expand_binop which takes an rtx code to specify
901 the operation to perform, not an optab pointer. All other
902 arguments are the same. */
903 rtx
expand_simple_binop(machine_mode mode,enum rtx_code code,rtx op0,rtx op1,rtx target,int unsignedp,enum optab_methods methods)904 expand_simple_binop (machine_mode mode, enum rtx_code code, rtx op0,
905 rtx op1, rtx target, int unsignedp,
906 enum optab_methods methods)
907 {
908 optab binop = code_to_optab (code);
909 gcc_assert (binop);
910
911 return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
912 }
913
914 /* Return whether OP0 and OP1 should be swapped when expanding a commutative
915 binop. Order them according to commutative_operand_precedence and, if
916 possible, try to put TARGET or a pseudo first. */
917 static bool
swap_commutative_operands_with_target(rtx target,rtx op0,rtx op1)918 swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
919 {
920 int op0_prec = commutative_operand_precedence (op0);
921 int op1_prec = commutative_operand_precedence (op1);
922
923 if (op0_prec < op1_prec)
924 return true;
925
926 if (op0_prec > op1_prec)
927 return false;
928
929 /* With equal precedence, both orders are ok, but it is better if the
930 first operand is TARGET, or if both TARGET and OP0 are pseudos. */
931 if (target == 0 || REG_P (target))
932 return (REG_P (op1) && !REG_P (op0)) || target == op1;
933 else
934 return rtx_equal_p (op1, target);
935 }
936
937 /* Return true if BINOPTAB implements a shift operation. */
938
939 static bool
shift_optab_p(optab binoptab)940 shift_optab_p (optab binoptab)
941 {
942 switch (optab_to_code (binoptab))
943 {
944 case ASHIFT:
945 case SS_ASHIFT:
946 case US_ASHIFT:
947 case ASHIFTRT:
948 case LSHIFTRT:
949 case ROTATE:
950 case ROTATERT:
951 return true;
952
953 default:
954 return false;
955 }
956 }
957
958 /* Return true if BINOPTAB implements a commutative binary operation. */
959
960 static bool
commutative_optab_p(optab binoptab)961 commutative_optab_p (optab binoptab)
962 {
963 return (GET_RTX_CLASS (optab_to_code (binoptab)) == RTX_COMM_ARITH
964 || binoptab == smul_widen_optab
965 || binoptab == umul_widen_optab
966 || binoptab == smul_highpart_optab
967 || binoptab == umul_highpart_optab);
968 }
969
970 /* X is to be used in mode MODE as operand OPN to BINOPTAB. If we're
971 optimizing, and if the operand is a constant that costs more than
972 1 instruction, force the constant into a register and return that
973 register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */
974
975 static rtx
avoid_expensive_constant(machine_mode mode,optab binoptab,int opn,rtx x,bool unsignedp)976 avoid_expensive_constant (machine_mode mode, optab binoptab,
977 int opn, rtx x, bool unsignedp)
978 {
979 bool speed = optimize_insn_for_speed_p ();
980
981 if (mode != VOIDmode
982 && optimize
983 && CONSTANT_P (x)
984 && (rtx_cost (x, mode, optab_to_code (binoptab), opn, speed)
985 > set_src_cost (x, mode, speed)))
986 {
987 if (CONST_INT_P (x))
988 {
989 HOST_WIDE_INT intval = trunc_int_for_mode (INTVAL (x), mode);
990 if (intval != INTVAL (x))
991 x = GEN_INT (intval);
992 }
993 else
994 x = convert_modes (mode, VOIDmode, x, unsignedp);
995 x = force_reg (mode, x);
996 }
997 return x;
998 }
999
1000 /* Helper function for expand_binop: handle the case where there
1001 is an insn ICODE that directly implements the indicated operation.
1002 Returns null if this is not possible. */
1003 static rtx
expand_binop_directly(enum insn_code icode,machine_mode mode,optab binoptab,rtx op0,rtx op1,rtx target,int unsignedp,enum optab_methods methods,rtx_insn * last)1004 expand_binop_directly (enum insn_code icode, machine_mode mode, optab binoptab,
1005 rtx op0, rtx op1,
1006 rtx target, int unsignedp, enum optab_methods methods,
1007 rtx_insn *last)
1008 {
1009 machine_mode xmode0 = insn_data[(int) icode].operand[1].mode;
1010 machine_mode xmode1 = insn_data[(int) icode].operand[2].mode;
1011 machine_mode mode0, mode1, tmp_mode;
1012 struct expand_operand ops[3];
1013 bool commutative_p;
1014 rtx_insn *pat;
1015 rtx xop0 = op0, xop1 = op1;
1016 bool canonicalize_op1 = false;
1017
1018 /* If it is a commutative operator and the modes would match
1019 if we would swap the operands, we can save the conversions. */
1020 commutative_p = commutative_optab_p (binoptab);
1021 if (commutative_p
1022 && GET_MODE (xop0) != xmode0 && GET_MODE (xop1) != xmode1
1023 && GET_MODE (xop0) == xmode1 && GET_MODE (xop1) == xmode1)
1024 std::swap (xop0, xop1);
1025
1026 /* If we are optimizing, force expensive constants into a register. */
1027 xop0 = avoid_expensive_constant (xmode0, binoptab, 0, xop0, unsignedp);
1028 if (!shift_optab_p (binoptab))
1029 xop1 = avoid_expensive_constant (xmode1, binoptab, 1, xop1, unsignedp);
1030 else
1031 /* Shifts and rotates often use a different mode for op1 from op0;
1032 for VOIDmode constants we don't know the mode, so force it
1033 to be canonicalized using convert_modes. */
1034 canonicalize_op1 = true;
1035
1036 /* In case the insn wants input operands in modes different from
1037 those of the actual operands, convert the operands. It would
1038 seem that we don't need to convert CONST_INTs, but we do, so
1039 that they're properly zero-extended, sign-extended or truncated
1040 for their mode. */
1041
1042 mode0 = GET_MODE (xop0) != VOIDmode ? GET_MODE (xop0) : mode;
1043 if (xmode0 != VOIDmode && xmode0 != mode0)
1044 {
1045 xop0 = convert_modes (xmode0, mode0, xop0, unsignedp);
1046 mode0 = xmode0;
1047 }
1048
1049 mode1 = ((GET_MODE (xop1) != VOIDmode || canonicalize_op1)
1050 ? GET_MODE (xop1) : mode);
1051 if (xmode1 != VOIDmode && xmode1 != mode1)
1052 {
1053 xop1 = convert_modes (xmode1, mode1, xop1, unsignedp);
1054 mode1 = xmode1;
1055 }
1056
1057 /* If operation is commutative,
1058 try to make the first operand a register.
1059 Even better, try to make it the same as the target.
1060 Also try to make the last operand a constant. */
1061 if (commutative_p
1062 && swap_commutative_operands_with_target (target, xop0, xop1))
1063 std::swap (xop0, xop1);
1064
1065 /* Now, if insn's predicates don't allow our operands, put them into
1066 pseudo regs. */
1067
1068 if (binoptab == vec_pack_trunc_optab
1069 || binoptab == vec_pack_usat_optab
1070 || binoptab == vec_pack_ssat_optab
1071 || binoptab == vec_pack_ufix_trunc_optab
1072 || binoptab == vec_pack_sfix_trunc_optab)
1073 {
1074 /* The mode of the result is different then the mode of the
1075 arguments. */
1076 tmp_mode = insn_data[(int) icode].operand[0].mode;
1077 if (VECTOR_MODE_P (mode)
1078 && maybe_ne (GET_MODE_NUNITS (tmp_mode), 2 * GET_MODE_NUNITS (mode)))
1079 {
1080 delete_insns_since (last);
1081 return NULL_RTX;
1082 }
1083 }
1084 else
1085 tmp_mode = mode;
1086
1087 create_output_operand (&ops[0], target, tmp_mode);
1088 create_input_operand (&ops[1], xop0, mode0);
1089 create_input_operand (&ops[2], xop1, mode1);
1090 pat = maybe_gen_insn (icode, 3, ops);
1091 if (pat)
1092 {
1093 /* If PAT is composed of more than one insn, try to add an appropriate
1094 REG_EQUAL note to it. If we can't because TEMP conflicts with an
1095 operand, call expand_binop again, this time without a target. */
1096 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
1097 && ! add_equal_note (pat, ops[0].value,
1098 optab_to_code (binoptab),
1099 ops[1].value, ops[2].value, mode0))
1100 {
1101 delete_insns_since (last);
1102 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
1103 unsignedp, methods);
1104 }
1105
1106 emit_insn (pat);
1107 return ops[0].value;
1108 }
1109 delete_insns_since (last);
1110 return NULL_RTX;
1111 }
1112
1113 /* Generate code to perform an operation specified by BINOPTAB
1114 on operands OP0 and OP1, with result having machine-mode MODE.
1115
1116 UNSIGNEDP is for the case where we have to widen the operands
1117 to perform the operation. It says to use zero-extension.
1118
1119 If TARGET is nonzero, the value
1120 is generated there, if it is convenient to do so.
1121 In all cases an rtx is returned for the locus of the value;
1122 this may or may not be TARGET. */
1123
1124 rtx
expand_binop(machine_mode mode,optab binoptab,rtx op0,rtx op1,rtx target,int unsignedp,enum optab_methods methods)1125 expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
1126 rtx target, int unsignedp, enum optab_methods methods)
1127 {
1128 enum optab_methods next_methods
1129 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
1130 ? OPTAB_WIDEN : methods);
1131 enum mode_class mclass;
1132 enum insn_code icode;
1133 machine_mode wider_mode;
1134 scalar_int_mode int_mode;
1135 rtx libfunc;
1136 rtx temp;
1137 rtx_insn *entry_last = get_last_insn ();
1138 rtx_insn *last;
1139
1140 mclass = GET_MODE_CLASS (mode);
1141
1142 /* If subtracting an integer constant, convert this into an addition of
1143 the negated constant. */
1144
1145 if (binoptab == sub_optab && CONST_INT_P (op1))
1146 {
1147 op1 = negate_rtx (mode, op1);
1148 binoptab = add_optab;
1149 }
1150 /* For shifts, constant invalid op1 might be expanded from different
1151 mode than MODE. As those are invalid, force them to a register
1152 to avoid further problems during expansion. */
1153 else if (CONST_INT_P (op1)
1154 && shift_optab_p (binoptab)
1155 && UINTVAL (op1) >= GET_MODE_BITSIZE (GET_MODE_INNER (mode)))
1156 {
1157 op1 = gen_int_mode (INTVAL (op1), GET_MODE_INNER (mode));
1158 op1 = force_reg (GET_MODE_INNER (mode), op1);
1159 }
1160
1161 /* Record where to delete back to if we backtrack. */
1162 last = get_last_insn ();
1163
1164 /* If we can do it with a three-operand insn, do so. */
1165
1166 if (methods != OPTAB_MUST_WIDEN)
1167 {
1168 if (convert_optab_p (binoptab))
1169 {
1170 machine_mode from_mode = widened_mode (mode, op0, op1);
1171 icode = find_widening_optab_handler (binoptab, mode, from_mode);
1172 }
1173 else
1174 icode = optab_handler (binoptab, mode);
1175 if (icode != CODE_FOR_nothing)
1176 {
1177 temp = expand_binop_directly (icode, mode, binoptab, op0, op1,
1178 target, unsignedp, methods, last);
1179 if (temp)
1180 return temp;
1181 }
1182 }
1183
1184 /* If we were trying to rotate, and that didn't work, try rotating
1185 the other direction before falling back to shifts and bitwise-or. */
1186 if (((binoptab == rotl_optab
1187 && (icode = optab_handler (rotr_optab, mode)) != CODE_FOR_nothing)
1188 || (binoptab == rotr_optab
1189 && (icode = optab_handler (rotl_optab, mode)) != CODE_FOR_nothing))
1190 && is_int_mode (mode, &int_mode))
1191 {
1192 optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
1193 rtx newop1;
1194 unsigned int bits = GET_MODE_PRECISION (int_mode);
1195
1196 if (CONST_INT_P (op1))
1197 newop1 = gen_int_shift_amount (int_mode, bits - INTVAL (op1));
1198 else if (targetm.shift_truncation_mask (int_mode) == bits - 1)
1199 newop1 = negate_rtx (GET_MODE (op1), op1);
1200 else
1201 newop1 = expand_binop (GET_MODE (op1), sub_optab,
1202 gen_int_mode (bits, GET_MODE (op1)), op1,
1203 NULL_RTX, unsignedp, OPTAB_DIRECT);
1204
1205 temp = expand_binop_directly (icode, int_mode, otheroptab, op0, newop1,
1206 target, unsignedp, methods, last);
1207 if (temp)
1208 return temp;
1209 }
1210
1211 /* If this is a multiply, see if we can do a widening operation that
1212 takes operands of this mode and makes a wider mode. */
1213
1214 if (binoptab == smul_optab
1215 && GET_MODE_2XWIDER_MODE (mode).exists (&wider_mode)
1216 && (convert_optab_handler ((unsignedp
1217 ? umul_widen_optab
1218 : smul_widen_optab),
1219 wider_mode, mode) != CODE_FOR_nothing))
1220 {
1221 /* *_widen_optab needs to determine operand mode, make sure at least
1222 one operand has non-VOID mode. */
1223 if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
1224 op0 = force_reg (mode, op0);
1225 temp = expand_binop (wider_mode,
1226 unsignedp ? umul_widen_optab : smul_widen_optab,
1227 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
1228
1229 if (temp != 0)
1230 {
1231 if (GET_MODE_CLASS (mode) == MODE_INT
1232 && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (temp)))
1233 return gen_lowpart (mode, temp);
1234 else
1235 return convert_to_mode (mode, temp, unsignedp);
1236 }
1237 }
1238
1239 /* If this is a vector shift by a scalar, see if we can do a vector
1240 shift by a vector. If so, broadcast the scalar into a vector. */
1241 if (mclass == MODE_VECTOR_INT)
1242 {
1243 optab otheroptab = unknown_optab;
1244
1245 if (binoptab == ashl_optab)
1246 otheroptab = vashl_optab;
1247 else if (binoptab == ashr_optab)
1248 otheroptab = vashr_optab;
1249 else if (binoptab == lshr_optab)
1250 otheroptab = vlshr_optab;
1251 else if (binoptab == rotl_optab)
1252 otheroptab = vrotl_optab;
1253 else if (binoptab == rotr_optab)
1254 otheroptab = vrotr_optab;
1255
1256 if (otheroptab
1257 && (icode = optab_handler (otheroptab, mode)) != CODE_FOR_nothing)
1258 {
1259 /* The scalar may have been extended to be too wide. Truncate
1260 it back to the proper size to fit in the broadcast vector. */
1261 scalar_mode inner_mode = GET_MODE_INNER (mode);
1262 if (!CONST_INT_P (op1)
1263 && (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (op1)))
1264 > GET_MODE_BITSIZE (inner_mode)))
1265 op1 = force_reg (inner_mode,
1266 simplify_gen_unary (TRUNCATE, inner_mode, op1,
1267 GET_MODE (op1)));
1268 rtx vop1 = expand_vector_broadcast (mode, op1);
1269 if (vop1)
1270 {
1271 temp = expand_binop_directly (icode, mode, otheroptab, op0, vop1,
1272 target, unsignedp, methods, last);
1273 if (temp)
1274 return temp;
1275 }
1276 }
1277 }
1278
1279 /* Look for a wider mode of the same class for which we think we
1280 can open-code the operation. Check for a widening multiply at the
1281 wider mode as well. */
1282
1283 if (CLASS_HAS_WIDER_MODES_P (mclass)
1284 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
1285 FOR_EACH_WIDER_MODE (wider_mode, mode)
1286 {
1287 machine_mode next_mode;
1288 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
1289 || (binoptab == smul_optab
1290 && GET_MODE_WIDER_MODE (wider_mode).exists (&next_mode)
1291 && (find_widening_optab_handler ((unsignedp
1292 ? umul_widen_optab
1293 : smul_widen_optab),
1294 next_mode, mode)
1295 != CODE_FOR_nothing)))
1296 {
1297 rtx xop0 = op0, xop1 = op1;
1298 int no_extend = 0;
1299
1300 /* For certain integer operations, we need not actually extend
1301 the narrow operands, as long as we will truncate
1302 the results to the same narrowness. */
1303
1304 if ((binoptab == ior_optab || binoptab == and_optab
1305 || binoptab == xor_optab
1306 || binoptab == add_optab || binoptab == sub_optab
1307 || binoptab == smul_optab || binoptab == ashl_optab)
1308 && mclass == MODE_INT)
1309 {
1310 no_extend = 1;
1311 xop0 = avoid_expensive_constant (mode, binoptab, 0,
1312 xop0, unsignedp);
1313 if (binoptab != ashl_optab)
1314 xop1 = avoid_expensive_constant (mode, binoptab, 1,
1315 xop1, unsignedp);
1316 }
1317
1318 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
1319
1320 /* The second operand of a shift must always be extended. */
1321 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1322 no_extend && binoptab != ashl_optab);
1323
1324 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1325 unsignedp, OPTAB_DIRECT);
1326 if (temp)
1327 {
1328 if (mclass != MODE_INT
1329 || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
1330 {
1331 if (target == 0)
1332 target = gen_reg_rtx (mode);
1333 convert_move (target, temp, 0);
1334 return target;
1335 }
1336 else
1337 return gen_lowpart (mode, temp);
1338 }
1339 else
1340 delete_insns_since (last);
1341 }
1342 }
1343
1344 /* If operation is commutative,
1345 try to make the first operand a register.
1346 Even better, try to make it the same as the target.
1347 Also try to make the last operand a constant. */
1348 if (commutative_optab_p (binoptab)
1349 && swap_commutative_operands_with_target (target, op0, op1))
1350 std::swap (op0, op1);
1351
1352 /* These can be done a word at a time. */
1353 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
1354 && is_int_mode (mode, &int_mode)
1355 && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD
1356 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
1357 {
1358 int i;
1359 rtx_insn *insns;
1360
1361 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1362 won't be accurate, so use a new target. */
1363 if (target == 0
1364 || target == op0
1365 || target == op1
1366 || !valid_multiword_target_p (target))
1367 target = gen_reg_rtx (int_mode);
1368
1369 start_sequence ();
1370
1371 /* Do the actual arithmetic. */
1372 for (i = 0; i < GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD; i++)
1373 {
1374 rtx target_piece = operand_subword (target, i, 1, int_mode);
1375 rtx x = expand_binop (word_mode, binoptab,
1376 operand_subword_force (op0, i, int_mode),
1377 operand_subword_force (op1, i, int_mode),
1378 target_piece, unsignedp, next_methods);
1379
1380 if (x == 0)
1381 break;
1382
1383 if (target_piece != x)
1384 emit_move_insn (target_piece, x);
1385 }
1386
1387 insns = get_insns ();
1388 end_sequence ();
1389
1390 if (i == GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD)
1391 {
1392 emit_insn (insns);
1393 return target;
1394 }
1395 }
1396
1397 /* Synthesize double word shifts from single word shifts. */
1398 if ((binoptab == lshr_optab || binoptab == ashl_optab
1399 || binoptab == ashr_optab)
1400 && is_int_mode (mode, &int_mode)
1401 && (CONST_INT_P (op1) || optimize_insn_for_speed_p ())
1402 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
1403 && GET_MODE_PRECISION (int_mode) == GET_MODE_BITSIZE (int_mode)
1404 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing
1405 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1406 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
1407 {
1408 unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
1409 scalar_int_mode op1_mode;
1410
1411 double_shift_mask = targetm.shift_truncation_mask (int_mode);
1412 shift_mask = targetm.shift_truncation_mask (word_mode);
1413 op1_mode = (GET_MODE (op1) != VOIDmode
1414 ? as_a <scalar_int_mode> (GET_MODE (op1))
1415 : word_mode);
1416
1417 /* Apply the truncation to constant shifts. */
1418 if (double_shift_mask > 0 && CONST_INT_P (op1))
1419 op1 = gen_int_mode (INTVAL (op1) & double_shift_mask, op1_mode);
1420
1421 if (op1 == CONST0_RTX (op1_mode))
1422 return op0;
1423
1424 /* Make sure that this is a combination that expand_doubleword_shift
1425 can handle. See the comments there for details. */
1426 if (double_shift_mask == 0
1427 || (shift_mask == BITS_PER_WORD - 1
1428 && double_shift_mask == BITS_PER_WORD * 2 - 1))
1429 {
1430 rtx_insn *insns;
1431 rtx into_target, outof_target;
1432 rtx into_input, outof_input;
1433 int left_shift, outof_word;
1434
1435 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1436 won't be accurate, so use a new target. */
1437 if (target == 0
1438 || target == op0
1439 || target == op1
1440 || !valid_multiword_target_p (target))
1441 target = gen_reg_rtx (int_mode);
1442
1443 start_sequence ();
1444
1445 /* OUTOF_* is the word we are shifting bits away from, and
1446 INTO_* is the word that we are shifting bits towards, thus
1447 they differ depending on the direction of the shift and
1448 WORDS_BIG_ENDIAN. */
1449
1450 left_shift = binoptab == ashl_optab;
1451 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1452
1453 outof_target = operand_subword (target, outof_word, 1, int_mode);
1454 into_target = operand_subword (target, 1 - outof_word, 1, int_mode);
1455
1456 outof_input = operand_subword_force (op0, outof_word, int_mode);
1457 into_input = operand_subword_force (op0, 1 - outof_word, int_mode);
1458
1459 if (expand_doubleword_shift (op1_mode, binoptab,
1460 outof_input, into_input, op1,
1461 outof_target, into_target,
1462 unsignedp, next_methods, shift_mask))
1463 {
1464 insns = get_insns ();
1465 end_sequence ();
1466
1467 emit_insn (insns);
1468 return target;
1469 }
1470 end_sequence ();
1471 }
1472 }
1473
1474 /* Synthesize double word rotates from single word shifts. */
1475 if ((binoptab == rotl_optab || binoptab == rotr_optab)
1476 && is_int_mode (mode, &int_mode)
1477 && CONST_INT_P (op1)
1478 && GET_MODE_PRECISION (int_mode) == 2 * BITS_PER_WORD
1479 && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
1480 && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
1481 {
1482 rtx_insn *insns;
1483 rtx into_target, outof_target;
1484 rtx into_input, outof_input;
1485 rtx inter;
1486 int shift_count, left_shift, outof_word;
1487
1488 /* If TARGET is the same as one of the operands, the REG_EQUAL note
1489 won't be accurate, so use a new target. Do this also if target is not
1490 a REG, first because having a register instead may open optimization
1491 opportunities, and second because if target and op0 happen to be MEMs
1492 designating the same location, we would risk clobbering it too early
1493 in the code sequence we generate below. */
1494 if (target == 0
1495 || target == op0
1496 || target == op1
1497 || !REG_P (target)
1498 || !valid_multiword_target_p (target))
1499 target = gen_reg_rtx (int_mode);
1500
1501 start_sequence ();
1502
1503 shift_count = INTVAL (op1);
1504
1505 /* OUTOF_* is the word we are shifting bits away from, and
1506 INTO_* is the word that we are shifting bits towards, thus
1507 they differ depending on the direction of the shift and
1508 WORDS_BIG_ENDIAN. */
1509
1510 left_shift = (binoptab == rotl_optab);
1511 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
1512
1513 outof_target = operand_subword (target, outof_word, 1, int_mode);
1514 into_target = operand_subword (target, 1 - outof_word, 1, int_mode);
1515
1516 outof_input = operand_subword_force (op0, outof_word, int_mode);
1517 into_input = operand_subword_force (op0, 1 - outof_word, int_mode);
1518
1519 if (shift_count == BITS_PER_WORD)
1520 {
1521 /* This is just a word swap. */
1522 emit_move_insn (outof_target, into_input);
1523 emit_move_insn (into_target, outof_input);
1524 inter = const0_rtx;
1525 }
1526 else
1527 {
1528 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
1529 HOST_WIDE_INT first_shift_count, second_shift_count;
1530 optab reverse_unsigned_shift, unsigned_shift;
1531
1532 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1533 ? lshr_optab : ashl_optab);
1534
1535 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
1536 ? ashl_optab : lshr_optab);
1537
1538 if (shift_count > BITS_PER_WORD)
1539 {
1540 first_shift_count = shift_count - BITS_PER_WORD;
1541 second_shift_count = 2 * BITS_PER_WORD - shift_count;
1542 }
1543 else
1544 {
1545 first_shift_count = BITS_PER_WORD - shift_count;
1546 second_shift_count = shift_count;
1547 }
1548 rtx first_shift_count_rtx
1549 = gen_int_shift_amount (word_mode, first_shift_count);
1550 rtx second_shift_count_rtx
1551 = gen_int_shift_amount (word_mode, second_shift_count);
1552
1553 into_temp1 = expand_binop (word_mode, unsigned_shift,
1554 outof_input, first_shift_count_rtx,
1555 NULL_RTX, unsignedp, next_methods);
1556 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1557 into_input, second_shift_count_rtx,
1558 NULL_RTX, unsignedp, next_methods);
1559
1560 if (into_temp1 != 0 && into_temp2 != 0)
1561 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
1562 into_target, unsignedp, next_methods);
1563 else
1564 inter = 0;
1565
1566 if (inter != 0 && inter != into_target)
1567 emit_move_insn (into_target, inter);
1568
1569 outof_temp1 = expand_binop (word_mode, unsigned_shift,
1570 into_input, first_shift_count_rtx,
1571 NULL_RTX, unsignedp, next_methods);
1572 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
1573 outof_input, second_shift_count_rtx,
1574 NULL_RTX, unsignedp, next_methods);
1575
1576 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
1577 inter = expand_binop (word_mode, ior_optab,
1578 outof_temp1, outof_temp2,
1579 outof_target, unsignedp, next_methods);
1580
1581 if (inter != 0 && inter != outof_target)
1582 emit_move_insn (outof_target, inter);
1583 }
1584
1585 insns = get_insns ();
1586 end_sequence ();
1587
1588 if (inter != 0)
1589 {
1590 emit_insn (insns);
1591 return target;
1592 }
1593 }
1594
1595 /* These can be done a word at a time by propagating carries. */
1596 if ((binoptab == add_optab || binoptab == sub_optab)
1597 && is_int_mode (mode, &int_mode)
1598 && GET_MODE_SIZE (int_mode) >= 2 * UNITS_PER_WORD
1599 && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
1600 {
1601 unsigned int i;
1602 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1603 const unsigned int nwords = GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD;
1604 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1605 rtx xop0, xop1, xtarget;
1606
1607 /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
1608 value is one of those, use it. Otherwise, use 1 since it is the
1609 one easiest to get. */
1610 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
1611 int normalizep = STORE_FLAG_VALUE;
1612 #else
1613 int normalizep = 1;
1614 #endif
1615
1616 /* Prepare the operands. */
1617 xop0 = force_reg (int_mode, op0);
1618 xop1 = force_reg (int_mode, op1);
1619
1620 xtarget = gen_reg_rtx (int_mode);
1621
1622 if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
1623 target = xtarget;
1624
1625 /* Indicate for flow that the entire target reg is being set. */
1626 if (REG_P (target))
1627 emit_clobber (xtarget);
1628
1629 /* Do the actual arithmetic. */
1630 for (i = 0; i < nwords; i++)
1631 {
1632 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1633 rtx target_piece = operand_subword (xtarget, index, 1, int_mode);
1634 rtx op0_piece = operand_subword_force (xop0, index, int_mode);
1635 rtx op1_piece = operand_subword_force (xop1, index, int_mode);
1636 rtx x;
1637
1638 /* Main add/subtract of the input operands. */
1639 x = expand_binop (word_mode, binoptab,
1640 op0_piece, op1_piece,
1641 target_piece, unsignedp, next_methods);
1642 if (x == 0)
1643 break;
1644
1645 if (i + 1 < nwords)
1646 {
1647 /* Store carry from main add/subtract. */
1648 carry_out = gen_reg_rtx (word_mode);
1649 carry_out = emit_store_flag_force (carry_out,
1650 (binoptab == add_optab
1651 ? LT : GT),
1652 x, op0_piece,
1653 word_mode, 1, normalizep);
1654 }
1655
1656 if (i > 0)
1657 {
1658 rtx newx;
1659
1660 /* Add/subtract previous carry to main result. */
1661 newx = expand_binop (word_mode,
1662 normalizep == 1 ? binoptab : otheroptab,
1663 x, carry_in,
1664 NULL_RTX, 1, next_methods);
1665
1666 if (i + 1 < nwords)
1667 {
1668 /* Get out carry from adding/subtracting carry in. */
1669 rtx carry_tmp = gen_reg_rtx (word_mode);
1670 carry_tmp = emit_store_flag_force (carry_tmp,
1671 (binoptab == add_optab
1672 ? LT : GT),
1673 newx, x,
1674 word_mode, 1, normalizep);
1675
1676 /* Logical-ior the two poss. carry together. */
1677 carry_out = expand_binop (word_mode, ior_optab,
1678 carry_out, carry_tmp,
1679 carry_out, 0, next_methods);
1680 if (carry_out == 0)
1681 break;
1682 }
1683 emit_move_insn (target_piece, newx);
1684 }
1685 else
1686 {
1687 if (x != target_piece)
1688 emit_move_insn (target_piece, x);
1689 }
1690
1691 carry_in = carry_out;
1692 }
1693
1694 if (i == GET_MODE_BITSIZE (int_mode) / (unsigned) BITS_PER_WORD)
1695 {
1696 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing
1697 || ! rtx_equal_p (target, xtarget))
1698 {
1699 rtx_insn *temp = emit_move_insn (target, xtarget);
1700
1701 set_dst_reg_note (temp, REG_EQUAL,
1702 gen_rtx_fmt_ee (optab_to_code (binoptab),
1703 int_mode, copy_rtx (xop0),
1704 copy_rtx (xop1)),
1705 target);
1706 }
1707 else
1708 target = xtarget;
1709
1710 return target;
1711 }
1712
1713 else
1714 delete_insns_since (last);
1715 }
1716
1717 /* Attempt to synthesize double word multiplies using a sequence of word
1718 mode multiplications. We first attempt to generate a sequence using a
1719 more efficient unsigned widening multiply, and if that fails we then
1720 try using a signed widening multiply. */
1721
1722 if (binoptab == smul_optab
1723 && is_int_mode (mode, &int_mode)
1724 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
1725 && optab_handler (smul_optab, word_mode) != CODE_FOR_nothing
1726 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)
1727 {
1728 rtx product = NULL_RTX;
1729 if (convert_optab_handler (umul_widen_optab, int_mode, word_mode)
1730 != CODE_FOR_nothing)
1731 {
1732 product = expand_doubleword_mult (int_mode, op0, op1, target,
1733 true, methods);
1734 if (!product)
1735 delete_insns_since (last);
1736 }
1737
1738 if (product == NULL_RTX
1739 && (convert_optab_handler (smul_widen_optab, int_mode, word_mode)
1740 != CODE_FOR_nothing))
1741 {
1742 product = expand_doubleword_mult (int_mode, op0, op1, target,
1743 false, methods);
1744 if (!product)
1745 delete_insns_since (last);
1746 }
1747
1748 if (product != NULL_RTX)
1749 {
1750 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
1751 {
1752 rtx_insn *move = emit_move_insn (target ? target : product,
1753 product);
1754 set_dst_reg_note (move,
1755 REG_EQUAL,
1756 gen_rtx_fmt_ee (MULT, int_mode,
1757 copy_rtx (op0),
1758 copy_rtx (op1)),
1759 target ? target : product);
1760 }
1761 return product;
1762 }
1763 }
1764
1765 /* It can't be open-coded in this mode.
1766 Use a library call if one is available and caller says that's ok. */
1767
1768 libfunc = optab_libfunc (binoptab, mode);
1769 if (libfunc
1770 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
1771 {
1772 rtx_insn *insns;
1773 rtx op1x = op1;
1774 machine_mode op1_mode = mode;
1775 rtx value;
1776
1777 start_sequence ();
1778
1779 if (shift_optab_p (binoptab))
1780 {
1781 op1_mode = targetm.libgcc_shift_count_mode ();
1782 /* Specify unsigned here,
1783 since negative shift counts are meaningless. */
1784 op1x = convert_to_mode (op1_mode, op1, 1);
1785 }
1786
1787 if (GET_MODE (op0) != VOIDmode
1788 && GET_MODE (op0) != mode)
1789 op0 = convert_to_mode (mode, op0, unsignedp);
1790
1791 /* Pass 1 for NO_QUEUE so we don't lose any increments
1792 if the libcall is cse'd or moved. */
1793 value = emit_library_call_value (libfunc,
1794 NULL_RTX, LCT_CONST, mode,
1795 op0, mode, op1x, op1_mode);
1796
1797 insns = get_insns ();
1798 end_sequence ();
1799
1800 bool trapv = trapv_binoptab_p (binoptab);
1801 target = gen_reg_rtx (mode);
1802 emit_libcall_block_1 (insns, target, value,
1803 trapv ? NULL_RTX
1804 : gen_rtx_fmt_ee (optab_to_code (binoptab),
1805 mode, op0, op1), trapv);
1806
1807 return target;
1808 }
1809
1810 delete_insns_since (last);
1811
1812 /* It can't be done in this mode. Can we do it in a wider mode? */
1813
1814 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
1815 || methods == OPTAB_MUST_WIDEN))
1816 {
1817 /* Caller says, don't even try. */
1818 delete_insns_since (entry_last);
1819 return 0;
1820 }
1821
1822 /* Compute the value of METHODS to pass to recursive calls.
1823 Don't allow widening to be tried recursively. */
1824
1825 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
1826
1827 /* Look for a wider mode of the same class for which it appears we can do
1828 the operation. */
1829
1830 if (CLASS_HAS_WIDER_MODES_P (mclass))
1831 {
1832 /* This code doesn't make sense for conversion optabs, since we
1833 wouldn't then want to extend the operands to be the same size
1834 as the result. */
1835 gcc_assert (!convert_optab_p (binoptab));
1836 FOR_EACH_WIDER_MODE (wider_mode, mode)
1837 {
1838 if (optab_handler (binoptab, wider_mode)
1839 || (methods == OPTAB_LIB
1840 && optab_libfunc (binoptab, wider_mode)))
1841 {
1842 rtx xop0 = op0, xop1 = op1;
1843 int no_extend = 0;
1844
1845 /* For certain integer operations, we need not actually extend
1846 the narrow operands, as long as we will truncate
1847 the results to the same narrowness. */
1848
1849 if ((binoptab == ior_optab || binoptab == and_optab
1850 || binoptab == xor_optab
1851 || binoptab == add_optab || binoptab == sub_optab
1852 || binoptab == smul_optab || binoptab == ashl_optab)
1853 && mclass == MODE_INT)
1854 no_extend = 1;
1855
1856 xop0 = widen_operand (xop0, wider_mode, mode,
1857 unsignedp, no_extend);
1858
1859 /* The second operand of a shift must always be extended. */
1860 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
1861 no_extend && binoptab != ashl_optab);
1862
1863 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
1864 unsignedp, methods);
1865 if (temp)
1866 {
1867 if (mclass != MODE_INT
1868 || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
1869 {
1870 if (target == 0)
1871 target = gen_reg_rtx (mode);
1872 convert_move (target, temp, 0);
1873 return target;
1874 }
1875 else
1876 return gen_lowpart (mode, temp);
1877 }
1878 else
1879 delete_insns_since (last);
1880 }
1881 }
1882 }
1883
1884 delete_insns_since (entry_last);
1885 return 0;
1886 }
1887
1888 /* Expand a binary operator which has both signed and unsigned forms.
1889 UOPTAB is the optab for unsigned operations, and SOPTAB is for
1890 signed operations.
1891
1892 If we widen unsigned operands, we may use a signed wider operation instead
1893 of an unsigned wider operation, since the result would be the same. */
1894
1895 rtx
sign_expand_binop(machine_mode mode,optab uoptab,optab soptab,rtx op0,rtx op1,rtx target,int unsignedp,enum optab_methods methods)1896 sign_expand_binop (machine_mode mode, optab uoptab, optab soptab,
1897 rtx op0, rtx op1, rtx target, int unsignedp,
1898 enum optab_methods methods)
1899 {
1900 rtx temp;
1901 optab direct_optab = unsignedp ? uoptab : soptab;
1902 bool save_enable;
1903
1904 /* Do it without widening, if possible. */
1905 temp = expand_binop (mode, direct_optab, op0, op1, target,
1906 unsignedp, OPTAB_DIRECT);
1907 if (temp || methods == OPTAB_DIRECT)
1908 return temp;
1909
1910 /* Try widening to a signed int. Disable any direct use of any
1911 signed insn in the current mode. */
1912 save_enable = swap_optab_enable (soptab, mode, false);
1913
1914 temp = expand_binop (mode, soptab, op0, op1, target,
1915 unsignedp, OPTAB_WIDEN);
1916
1917 /* For unsigned operands, try widening to an unsigned int. */
1918 if (!temp && unsignedp)
1919 temp = expand_binop (mode, uoptab, op0, op1, target,
1920 unsignedp, OPTAB_WIDEN);
1921 if (temp || methods == OPTAB_WIDEN)
1922 goto egress;
1923
1924 /* Use the right width libcall if that exists. */
1925 temp = expand_binop (mode, direct_optab, op0, op1, target,
1926 unsignedp, OPTAB_LIB);
1927 if (temp || methods == OPTAB_LIB)
1928 goto egress;
1929
1930 /* Must widen and use a libcall, use either signed or unsigned. */
1931 temp = expand_binop (mode, soptab, op0, op1, target,
1932 unsignedp, methods);
1933 if (!temp && unsignedp)
1934 temp = expand_binop (mode, uoptab, op0, op1, target,
1935 unsignedp, methods);
1936
1937 egress:
1938 /* Undo the fiddling above. */
1939 if (save_enable)
1940 swap_optab_enable (soptab, mode, true);
1941 return temp;
1942 }
1943
1944 /* Generate code to perform an operation specified by UNOPPTAB
1945 on operand OP0, with two results to TARG0 and TARG1.
1946 We assume that the order of the operands for the instruction
1947 is TARG0, TARG1, OP0.
1948
1949 Either TARG0 or TARG1 may be zero, but what that means is that
1950 the result is not actually wanted. We will generate it into
1951 a dummy pseudo-reg and discard it. They may not both be zero.
1952
1953 Returns 1 if this operation can be performed; 0 if not. */
1954
1955 int
expand_twoval_unop(optab unoptab,rtx op0,rtx targ0,rtx targ1,int unsignedp)1956 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
1957 int unsignedp)
1958 {
1959 machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
1960 enum mode_class mclass;
1961 machine_mode wider_mode;
1962 rtx_insn *entry_last = get_last_insn ();
1963 rtx_insn *last;
1964
1965 mclass = GET_MODE_CLASS (mode);
1966
1967 if (!targ0)
1968 targ0 = gen_reg_rtx (mode);
1969 if (!targ1)
1970 targ1 = gen_reg_rtx (mode);
1971
1972 /* Record where to go back to if we fail. */
1973 last = get_last_insn ();
1974
1975 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
1976 {
1977 struct expand_operand ops[3];
1978 enum insn_code icode = optab_handler (unoptab, mode);
1979
1980 create_fixed_operand (&ops[0], targ0);
1981 create_fixed_operand (&ops[1], targ1);
1982 create_convert_operand_from (&ops[2], op0, mode, unsignedp);
1983 if (maybe_expand_insn (icode, 3, ops))
1984 return 1;
1985 }
1986
1987 /* It can't be done in this mode. Can we do it in a wider mode? */
1988
1989 if (CLASS_HAS_WIDER_MODES_P (mclass))
1990 {
1991 FOR_EACH_WIDER_MODE (wider_mode, mode)
1992 {
1993 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
1994 {
1995 rtx t0 = gen_reg_rtx (wider_mode);
1996 rtx t1 = gen_reg_rtx (wider_mode);
1997 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
1998
1999 if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
2000 {
2001 convert_move (targ0, t0, unsignedp);
2002 convert_move (targ1, t1, unsignedp);
2003 return 1;
2004 }
2005 else
2006 delete_insns_since (last);
2007 }
2008 }
2009 }
2010
2011 delete_insns_since (entry_last);
2012 return 0;
2013 }
2014
2015 /* Generate code to perform an operation specified by BINOPTAB
2016 on operands OP0 and OP1, with two results to TARG1 and TARG2.
2017 We assume that the order of the operands for the instruction
2018 is TARG0, OP0, OP1, TARG1, which would fit a pattern like
2019 [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
2020
2021 Either TARG0 or TARG1 may be zero, but what that means is that
2022 the result is not actually wanted. We will generate it into
2023 a dummy pseudo-reg and discard it. They may not both be zero.
2024
2025 Returns 1 if this operation can be performed; 0 if not. */
2026
2027 int
expand_twoval_binop(optab binoptab,rtx op0,rtx op1,rtx targ0,rtx targ1,int unsignedp)2028 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
2029 int unsignedp)
2030 {
2031 machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
2032 enum mode_class mclass;
2033 machine_mode wider_mode;
2034 rtx_insn *entry_last = get_last_insn ();
2035 rtx_insn *last;
2036
2037 mclass = GET_MODE_CLASS (mode);
2038
2039 if (!targ0)
2040 targ0 = gen_reg_rtx (mode);
2041 if (!targ1)
2042 targ1 = gen_reg_rtx (mode);
2043
2044 /* Record where to go back to if we fail. */
2045 last = get_last_insn ();
2046
2047 if (optab_handler (binoptab, mode) != CODE_FOR_nothing)
2048 {
2049 struct expand_operand ops[4];
2050 enum insn_code icode = optab_handler (binoptab, mode);
2051 machine_mode mode0 = insn_data[icode].operand[1].mode;
2052 machine_mode mode1 = insn_data[icode].operand[2].mode;
2053 rtx xop0 = op0, xop1 = op1;
2054
2055 /* If we are optimizing, force expensive constants into a register. */
2056 xop0 = avoid_expensive_constant (mode0, binoptab, 0, xop0, unsignedp);
2057 xop1 = avoid_expensive_constant (mode1, binoptab, 1, xop1, unsignedp);
2058
2059 create_fixed_operand (&ops[0], targ0);
2060 create_convert_operand_from (&ops[1], op0, mode, unsignedp);
2061 create_convert_operand_from (&ops[2], op1, mode, unsignedp);
2062 create_fixed_operand (&ops[3], targ1);
2063 if (maybe_expand_insn (icode, 4, ops))
2064 return 1;
2065 delete_insns_since (last);
2066 }
2067
2068 /* It can't be done in this mode. Can we do it in a wider mode? */
2069
2070 if (CLASS_HAS_WIDER_MODES_P (mclass))
2071 {
2072 FOR_EACH_WIDER_MODE (wider_mode, mode)
2073 {
2074 if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing)
2075 {
2076 rtx t0 = gen_reg_rtx (wider_mode);
2077 rtx t1 = gen_reg_rtx (wider_mode);
2078 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
2079 rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
2080
2081 if (expand_twoval_binop (binoptab, cop0, cop1,
2082 t0, t1, unsignedp))
2083 {
2084 convert_move (targ0, t0, unsignedp);
2085 convert_move (targ1, t1, unsignedp);
2086 return 1;
2087 }
2088 else
2089 delete_insns_since (last);
2090 }
2091 }
2092 }
2093
2094 delete_insns_since (entry_last);
2095 return 0;
2096 }
2097
2098 /* Expand the two-valued library call indicated by BINOPTAB, but
2099 preserve only one of the values. If TARG0 is non-NULL, the first
2100 value is placed into TARG0; otherwise the second value is placed
2101 into TARG1. Exactly one of TARG0 and TARG1 must be non-NULL. The
2102 value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
2103 This routine assumes that the value returned by the library call is
2104 as if the return value was of an integral mode twice as wide as the
2105 mode of OP0. Returns 1 if the call was successful. */
2106
2107 bool
expand_twoval_binop_libfunc(optab binoptab,rtx op0,rtx op1,rtx targ0,rtx targ1,enum rtx_code code)2108 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
2109 rtx targ0, rtx targ1, enum rtx_code code)
2110 {
2111 machine_mode mode;
2112 machine_mode libval_mode;
2113 rtx libval;
2114 rtx_insn *insns;
2115 rtx libfunc;
2116
2117 /* Exactly one of TARG0 or TARG1 should be non-NULL. */
2118 gcc_assert (!targ0 != !targ1);
2119
2120 mode = GET_MODE (op0);
2121 libfunc = optab_libfunc (binoptab, mode);
2122 if (!libfunc)
2123 return false;
2124
2125 /* The value returned by the library function will have twice as
2126 many bits as the nominal MODE. */
2127 libval_mode = smallest_int_mode_for_size (2 * GET_MODE_BITSIZE (mode));
2128 start_sequence ();
2129 libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
2130 libval_mode,
2131 op0, mode,
2132 op1, mode);
2133 /* Get the part of VAL containing the value that we want. */
2134 libval = simplify_gen_subreg (mode, libval, libval_mode,
2135 targ0 ? 0 : GET_MODE_SIZE (mode));
2136 insns = get_insns ();
2137 end_sequence ();
2138 /* Move the into the desired location. */
2139 emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
2140 gen_rtx_fmt_ee (code, mode, op0, op1));
2141
2142 return true;
2143 }
2144
2145
2146 /* Wrapper around expand_unop which takes an rtx code to specify
2147 the operation to perform, not an optab pointer. All other
2148 arguments are the same. */
2149 rtx
expand_simple_unop(machine_mode mode,enum rtx_code code,rtx op0,rtx target,int unsignedp)2150 expand_simple_unop (machine_mode mode, enum rtx_code code, rtx op0,
2151 rtx target, int unsignedp)
2152 {
2153 optab unop = code_to_optab (code);
2154 gcc_assert (unop);
2155
2156 return expand_unop (mode, unop, op0, target, unsignedp);
2157 }
2158
2159 /* Try calculating
2160 (clz:narrow x)
2161 as
2162 (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)).
2163
2164 A similar operation can be used for clrsb. UNOPTAB says which operation
2165 we are trying to expand. */
2166 static rtx
widen_leading(scalar_int_mode mode,rtx op0,rtx target,optab unoptab)2167 widen_leading (scalar_int_mode mode, rtx op0, rtx target, optab unoptab)
2168 {
2169 opt_scalar_int_mode wider_mode_iter;
2170 FOR_EACH_WIDER_MODE (wider_mode_iter, mode)
2171 {
2172 scalar_int_mode wider_mode = wider_mode_iter.require ();
2173 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
2174 {
2175 rtx xop0, temp;
2176 rtx_insn *last;
2177
2178 last = get_last_insn ();
2179
2180 if (target == 0)
2181 target = gen_reg_rtx (mode);
2182 xop0 = widen_operand (op0, wider_mode, mode,
2183 unoptab != clrsb_optab, false);
2184 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2185 unoptab != clrsb_optab);
2186 if (temp != 0)
2187 temp = expand_binop
2188 (wider_mode, sub_optab, temp,
2189 gen_int_mode (GET_MODE_PRECISION (wider_mode)
2190 - GET_MODE_PRECISION (mode),
2191 wider_mode),
2192 target, true, OPTAB_DIRECT);
2193 if (temp == 0)
2194 delete_insns_since (last);
2195
2196 return temp;
2197 }
2198 }
2199 return 0;
2200 }
2201
2202 /* Try calculating clz of a double-word quantity as two clz's of word-sized
2203 quantities, choosing which based on whether the high word is nonzero. */
2204 static rtx
expand_doubleword_clz(scalar_int_mode mode,rtx op0,rtx target)2205 expand_doubleword_clz (scalar_int_mode mode, rtx op0, rtx target)
2206 {
2207 rtx xop0 = force_reg (mode, op0);
2208 rtx subhi = gen_highpart (word_mode, xop0);
2209 rtx sublo = gen_lowpart (word_mode, xop0);
2210 rtx_code_label *hi0_label = gen_label_rtx ();
2211 rtx_code_label *after_label = gen_label_rtx ();
2212 rtx_insn *seq;
2213 rtx temp, result;
2214
2215 /* If we were not given a target, use a word_mode register, not a
2216 'mode' register. The result will fit, and nobody is expecting
2217 anything bigger (the return type of __builtin_clz* is int). */
2218 if (!target)
2219 target = gen_reg_rtx (word_mode);
2220
2221 /* In any case, write to a word_mode scratch in both branches of the
2222 conditional, so we can ensure there is a single move insn setting
2223 'target' to tag a REG_EQUAL note on. */
2224 result = gen_reg_rtx (word_mode);
2225
2226 start_sequence ();
2227
2228 /* If the high word is not equal to zero,
2229 then clz of the full value is clz of the high word. */
2230 emit_cmp_and_jump_insns (subhi, CONST0_RTX (word_mode), EQ, 0,
2231 word_mode, true, hi0_label);
2232
2233 temp = expand_unop_direct (word_mode, clz_optab, subhi, result, true);
2234 if (!temp)
2235 goto fail;
2236
2237 if (temp != result)
2238 convert_move (result, temp, true);
2239
2240 emit_jump_insn (targetm.gen_jump (after_label));
2241 emit_barrier ();
2242
2243 /* Else clz of the full value is clz of the low word plus the number
2244 of bits in the high word. */
2245 emit_label (hi0_label);
2246
2247 temp = expand_unop_direct (word_mode, clz_optab, sublo, 0, true);
2248 if (!temp)
2249 goto fail;
2250 temp = expand_binop (word_mode, add_optab, temp,
2251 gen_int_mode (GET_MODE_BITSIZE (word_mode), word_mode),
2252 result, true, OPTAB_DIRECT);
2253 if (!temp)
2254 goto fail;
2255 if (temp != result)
2256 convert_move (result, temp, true);
2257
2258 emit_label (after_label);
2259 convert_move (target, result, true);
2260
2261 seq = get_insns ();
2262 end_sequence ();
2263
2264 add_equal_note (seq, target, CLZ, xop0, NULL_RTX, mode);
2265 emit_insn (seq);
2266 return target;
2267
2268 fail:
2269 end_sequence ();
2270 return 0;
2271 }
2272
2273 /* Try calculating popcount of a double-word quantity as two popcount's of
2274 word-sized quantities and summing up the results. */
2275 static rtx
expand_doubleword_popcount(scalar_int_mode mode,rtx op0,rtx target)2276 expand_doubleword_popcount (scalar_int_mode mode, rtx op0, rtx target)
2277 {
2278 rtx t0, t1, t;
2279 rtx_insn *seq;
2280
2281 start_sequence ();
2282
2283 t0 = expand_unop_direct (word_mode, popcount_optab,
2284 operand_subword_force (op0, 0, mode), NULL_RTX,
2285 true);
2286 t1 = expand_unop_direct (word_mode, popcount_optab,
2287 operand_subword_force (op0, 1, mode), NULL_RTX,
2288 true);
2289 if (!t0 || !t1)
2290 {
2291 end_sequence ();
2292 return NULL_RTX;
2293 }
2294
2295 /* If we were not given a target, use a word_mode register, not a
2296 'mode' register. The result will fit, and nobody is expecting
2297 anything bigger (the return type of __builtin_popcount* is int). */
2298 if (!target)
2299 target = gen_reg_rtx (word_mode);
2300
2301 t = expand_binop (word_mode, add_optab, t0, t1, target, 0, OPTAB_DIRECT);
2302
2303 seq = get_insns ();
2304 end_sequence ();
2305
2306 add_equal_note (seq, t, POPCOUNT, op0, NULL_RTX, mode);
2307 emit_insn (seq);
2308 return t;
2309 }
2310
2311 /* Try calculating
2312 (parity:wide x)
2313 as
2314 (parity:narrow (low (x) ^ high (x))) */
2315 static rtx
expand_doubleword_parity(scalar_int_mode mode,rtx op0,rtx target)2316 expand_doubleword_parity (scalar_int_mode mode, rtx op0, rtx target)
2317 {
2318 rtx t = expand_binop (word_mode, xor_optab,
2319 operand_subword_force (op0, 0, mode),
2320 operand_subword_force (op0, 1, mode),
2321 NULL_RTX, 0, OPTAB_DIRECT);
2322 return expand_unop (word_mode, parity_optab, t, target, true);
2323 }
2324
2325 /* Try calculating
2326 (bswap:narrow x)
2327 as
2328 (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */
2329 static rtx
widen_bswap(scalar_int_mode mode,rtx op0,rtx target)2330 widen_bswap (scalar_int_mode mode, rtx op0, rtx target)
2331 {
2332 rtx x;
2333 rtx_insn *last;
2334 opt_scalar_int_mode wider_mode_iter;
2335
2336 FOR_EACH_WIDER_MODE (wider_mode_iter, mode)
2337 if (optab_handler (bswap_optab, wider_mode_iter.require ())
2338 != CODE_FOR_nothing)
2339 break;
2340
2341 if (!wider_mode_iter.exists ())
2342 return NULL_RTX;
2343
2344 scalar_int_mode wider_mode = wider_mode_iter.require ();
2345 last = get_last_insn ();
2346
2347 x = widen_operand (op0, wider_mode, mode, true, true);
2348 x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
2349
2350 gcc_assert (GET_MODE_PRECISION (wider_mode) == GET_MODE_BITSIZE (wider_mode)
2351 && GET_MODE_PRECISION (mode) == GET_MODE_BITSIZE (mode));
2352 if (x != 0)
2353 x = expand_shift (RSHIFT_EXPR, wider_mode, x,
2354 GET_MODE_BITSIZE (wider_mode)
2355 - GET_MODE_BITSIZE (mode),
2356 NULL_RTX, true);
2357
2358 if (x != 0)
2359 {
2360 if (target == 0)
2361 target = gen_reg_rtx (mode);
2362 emit_move_insn (target, gen_lowpart (mode, x));
2363 }
2364 else
2365 delete_insns_since (last);
2366
2367 return target;
2368 }
2369
2370 /* Try calculating bswap as two bswaps of two word-sized operands. */
2371
2372 static rtx
expand_doubleword_bswap(machine_mode mode,rtx op,rtx target)2373 expand_doubleword_bswap (machine_mode mode, rtx op, rtx target)
2374 {
2375 rtx t0, t1;
2376
2377 t1 = expand_unop (word_mode, bswap_optab,
2378 operand_subword_force (op, 0, mode), NULL_RTX, true);
2379 t0 = expand_unop (word_mode, bswap_optab,
2380 operand_subword_force (op, 1, mode), NULL_RTX, true);
2381
2382 if (target == 0 || !valid_multiword_target_p (target))
2383 target = gen_reg_rtx (mode);
2384 if (REG_P (target))
2385 emit_clobber (target);
2386 emit_move_insn (operand_subword (target, 0, 1, mode), t0);
2387 emit_move_insn (operand_subword (target, 1, 1, mode), t1);
2388
2389 return target;
2390 }
2391
2392 /* Try calculating (parity x) as (and (popcount x) 1), where
2393 popcount can also be done in a wider mode. */
2394 static rtx
expand_parity(scalar_int_mode mode,rtx op0,rtx target)2395 expand_parity (scalar_int_mode mode, rtx op0, rtx target)
2396 {
2397 enum mode_class mclass = GET_MODE_CLASS (mode);
2398 opt_scalar_int_mode wider_mode_iter;
2399 FOR_EACH_MODE_FROM (wider_mode_iter, mode)
2400 {
2401 scalar_int_mode wider_mode = wider_mode_iter.require ();
2402 if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
2403 {
2404 rtx xop0, temp;
2405 rtx_insn *last;
2406
2407 last = get_last_insn ();
2408
2409 if (target == 0 || GET_MODE (target) != wider_mode)
2410 target = gen_reg_rtx (wider_mode);
2411
2412 xop0 = widen_operand (op0, wider_mode, mode, true, false);
2413 temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
2414 true);
2415 if (temp != 0)
2416 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
2417 target, true, OPTAB_DIRECT);
2418
2419 if (temp)
2420 {
2421 if (mclass != MODE_INT
2422 || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
2423 return convert_to_mode (mode, temp, 0);
2424 else
2425 return gen_lowpart (mode, temp);
2426 }
2427 else
2428 delete_insns_since (last);
2429 }
2430 }
2431 return 0;
2432 }
2433
2434 /* Try calculating ctz(x) as K - clz(x & -x) ,
2435 where K is GET_MODE_PRECISION(mode) - 1.
2436
2437 Both __builtin_ctz and __builtin_clz are undefined at zero, so we
2438 don't have to worry about what the hardware does in that case. (If
2439 the clz instruction produces the usual value at 0, which is K, the
2440 result of this code sequence will be -1; expand_ffs, below, relies
2441 on this. It might be nice to have it be K instead, for consistency
2442 with the (very few) processors that provide a ctz with a defined
2443 value, but that would take one more instruction, and it would be
2444 less convenient for expand_ffs anyway. */
2445
2446 static rtx
expand_ctz(scalar_int_mode mode,rtx op0,rtx target)2447 expand_ctz (scalar_int_mode mode, rtx op0, rtx target)
2448 {
2449 rtx_insn *seq;
2450 rtx temp;
2451
2452 if (optab_handler (clz_optab, mode) == CODE_FOR_nothing)
2453 return 0;
2454
2455 start_sequence ();
2456
2457 temp = expand_unop_direct (mode, neg_optab, op0, NULL_RTX, true);
2458 if (temp)
2459 temp = expand_binop (mode, and_optab, op0, temp, NULL_RTX,
2460 true, OPTAB_DIRECT);
2461 if (temp)
2462 temp = expand_unop_direct (mode, clz_optab, temp, NULL_RTX, true);
2463 if (temp)
2464 temp = expand_binop (mode, sub_optab,
2465 gen_int_mode (GET_MODE_PRECISION (mode) - 1, mode),
2466 temp, target,
2467 true, OPTAB_DIRECT);
2468 if (temp == 0)
2469 {
2470 end_sequence ();
2471 return 0;
2472 }
2473
2474 seq = get_insns ();
2475 end_sequence ();
2476
2477 add_equal_note (seq, temp, CTZ, op0, NULL_RTX, mode);
2478 emit_insn (seq);
2479 return temp;
2480 }
2481
2482
2483 /* Try calculating ffs(x) using ctz(x) if we have that instruction, or
2484 else with the sequence used by expand_clz.
2485
2486 The ffs builtin promises to return zero for a zero value and ctz/clz
2487 may have an undefined value in that case. If they do not give us a
2488 convenient value, we have to generate a test and branch. */
2489 static rtx
expand_ffs(scalar_int_mode mode,rtx op0,rtx target)2490 expand_ffs (scalar_int_mode mode, rtx op0, rtx target)
2491 {
2492 HOST_WIDE_INT val = 0;
2493 bool defined_at_zero = false;
2494 rtx temp;
2495 rtx_insn *seq;
2496
2497 if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing)
2498 {
2499 start_sequence ();
2500
2501 temp = expand_unop_direct (mode, ctz_optab, op0, 0, true);
2502 if (!temp)
2503 goto fail;
2504
2505 defined_at_zero = (CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2);
2506 }
2507 else if (optab_handler (clz_optab, mode) != CODE_FOR_nothing)
2508 {
2509 start_sequence ();
2510 temp = expand_ctz (mode, op0, 0);
2511 if (!temp)
2512 goto fail;
2513
2514 if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
2515 {
2516 defined_at_zero = true;
2517 val = (GET_MODE_PRECISION (mode) - 1) - val;
2518 }
2519 }
2520 else
2521 return 0;
2522
2523 if (defined_at_zero && val == -1)
2524 /* No correction needed at zero. */;
2525 else
2526 {
2527 /* We don't try to do anything clever with the situation found
2528 on some processors (eg Alpha) where ctz(0:mode) ==
2529 bitsize(mode). If someone can think of a way to send N to -1
2530 and leave alone all values in the range 0..N-1 (where N is a
2531 power of two), cheaper than this test-and-branch, please add it.
2532
2533 The test-and-branch is done after the operation itself, in case
2534 the operation sets condition codes that can be recycled for this.
2535 (This is true on i386, for instance.) */
2536
2537 rtx_code_label *nonzero_label = gen_label_rtx ();
2538 emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
2539 mode, true, nonzero_label);
2540
2541 convert_move (temp, GEN_INT (-1), false);
2542 emit_label (nonzero_label);
2543 }
2544
2545 /* temp now has a value in the range -1..bitsize-1. ffs is supposed
2546 to produce a value in the range 0..bitsize. */
2547 temp = expand_binop (mode, add_optab, temp, gen_int_mode (1, mode),
2548 target, false, OPTAB_DIRECT);
2549 if (!temp)
2550 goto fail;
2551
2552 seq = get_insns ();
2553 end_sequence ();
2554
2555 add_equal_note (seq, temp, FFS, op0, NULL_RTX, mode);
2556 emit_insn (seq);
2557 return temp;
2558
2559 fail:
2560 end_sequence ();
2561 return 0;
2562 }
2563
2564 /* Extract the OMODE lowpart from VAL, which has IMODE. Under certain
2565 conditions, VAL may already be a SUBREG against which we cannot generate
2566 a further SUBREG. In this case, we expect forcing the value into a
2567 register will work around the situation. */
2568
2569 static rtx
lowpart_subreg_maybe_copy(machine_mode omode,rtx val,machine_mode imode)2570 lowpart_subreg_maybe_copy (machine_mode omode, rtx val,
2571 machine_mode imode)
2572 {
2573 rtx ret;
2574 ret = lowpart_subreg (omode, val, imode);
2575 if (ret == NULL)
2576 {
2577 val = force_reg (imode, val);
2578 ret = lowpart_subreg (omode, val, imode);
2579 gcc_assert (ret != NULL);
2580 }
2581 return ret;
2582 }
2583
2584 /* Expand a floating point absolute value or negation operation via a
2585 logical operation on the sign bit. */
2586
2587 static rtx
expand_absneg_bit(enum rtx_code code,scalar_float_mode mode,rtx op0,rtx target)2588 expand_absneg_bit (enum rtx_code code, scalar_float_mode mode,
2589 rtx op0, rtx target)
2590 {
2591 const struct real_format *fmt;
2592 int bitpos, word, nwords, i;
2593 scalar_int_mode imode;
2594 rtx temp;
2595 rtx_insn *insns;
2596
2597 /* The format has to have a simple sign bit. */
2598 fmt = REAL_MODE_FORMAT (mode);
2599 if (fmt == NULL)
2600 return NULL_RTX;
2601
2602 bitpos = fmt->signbit_rw;
2603 if (bitpos < 0)
2604 return NULL_RTX;
2605
2606 /* Don't create negative zeros if the format doesn't support them. */
2607 if (code == NEG && !fmt->has_signed_zero)
2608 return NULL_RTX;
2609
2610 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
2611 {
2612 if (!int_mode_for_mode (mode).exists (&imode))
2613 return NULL_RTX;
2614 word = 0;
2615 nwords = 1;
2616 }
2617 else
2618 {
2619 imode = word_mode;
2620
2621 if (FLOAT_WORDS_BIG_ENDIAN)
2622 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
2623 else
2624 word = bitpos / BITS_PER_WORD;
2625 bitpos = bitpos % BITS_PER_WORD;
2626 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
2627 }
2628
2629 wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
2630 if (code == ABS)
2631 mask = ~mask;
2632
2633 if (target == 0
2634 || target == op0
2635 || (nwords > 1 && !valid_multiword_target_p (target)))
2636 target = gen_reg_rtx (mode);
2637
2638 if (nwords > 1)
2639 {
2640 start_sequence ();
2641
2642 for (i = 0; i < nwords; ++i)
2643 {
2644 rtx targ_piece = operand_subword (target, i, 1, mode);
2645 rtx op0_piece = operand_subword_force (op0, i, mode);
2646
2647 if (i == word)
2648 {
2649 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2650 op0_piece,
2651 immed_wide_int_const (mask, imode),
2652 targ_piece, 1, OPTAB_LIB_WIDEN);
2653 if (temp != targ_piece)
2654 emit_move_insn (targ_piece, temp);
2655 }
2656 else
2657 emit_move_insn (targ_piece, op0_piece);
2658 }
2659
2660 insns = get_insns ();
2661 end_sequence ();
2662
2663 emit_insn (insns);
2664 }
2665 else
2666 {
2667 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
2668 gen_lowpart (imode, op0),
2669 immed_wide_int_const (mask, imode),
2670 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
2671 target = lowpart_subreg_maybe_copy (mode, temp, imode);
2672
2673 set_dst_reg_note (get_last_insn (), REG_EQUAL,
2674 gen_rtx_fmt_e (code, mode, copy_rtx (op0)),
2675 target);
2676 }
2677
2678 return target;
2679 }
2680
2681 /* As expand_unop, but will fail rather than attempt the operation in a
2682 different mode or with a libcall. */
2683 static rtx
expand_unop_direct(machine_mode mode,optab unoptab,rtx op0,rtx target,int unsignedp)2684 expand_unop_direct (machine_mode mode, optab unoptab, rtx op0, rtx target,
2685 int unsignedp)
2686 {
2687 if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
2688 {
2689 struct expand_operand ops[2];
2690 enum insn_code icode = optab_handler (unoptab, mode);
2691 rtx_insn *last = get_last_insn ();
2692 rtx_insn *pat;
2693
2694 create_output_operand (&ops[0], target, mode);
2695 create_convert_operand_from (&ops[1], op0, mode, unsignedp);
2696 pat = maybe_gen_insn (icode, 2, ops);
2697 if (pat)
2698 {
2699 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
2700 && ! add_equal_note (pat, ops[0].value,
2701 optab_to_code (unoptab),
2702 ops[1].value, NULL_RTX, mode))
2703 {
2704 delete_insns_since (last);
2705 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
2706 }
2707
2708 emit_insn (pat);
2709
2710 return ops[0].value;
2711 }
2712 }
2713 return 0;
2714 }
2715
2716 /* Generate code to perform an operation specified by UNOPTAB
2717 on operand OP0, with result having machine-mode MODE.
2718
2719 UNSIGNEDP is for the case where we have to widen the operands
2720 to perform the operation. It says to use zero-extension.
2721
2722 If TARGET is nonzero, the value
2723 is generated there, if it is convenient to do so.
2724 In all cases an rtx is returned for the locus of the value;
2725 this may or may not be TARGET. */
2726
2727 rtx
expand_unop(machine_mode mode,optab unoptab,rtx op0,rtx target,int unsignedp)2728 expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
2729 int unsignedp)
2730 {
2731 enum mode_class mclass = GET_MODE_CLASS (mode);
2732 machine_mode wider_mode;
2733 scalar_int_mode int_mode;
2734 scalar_float_mode float_mode;
2735 rtx temp;
2736 rtx libfunc;
2737
2738 temp = expand_unop_direct (mode, unoptab, op0, target, unsignedp);
2739 if (temp)
2740 return temp;
2741
2742 /* It can't be done in this mode. Can we open-code it in a wider mode? */
2743
2744 /* Widening (or narrowing) clz needs special treatment. */
2745 if (unoptab == clz_optab)
2746 {
2747 if (is_a <scalar_int_mode> (mode, &int_mode))
2748 {
2749 temp = widen_leading (int_mode, op0, target, unoptab);
2750 if (temp)
2751 return temp;
2752
2753 if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
2754 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
2755 {
2756 temp = expand_doubleword_clz (int_mode, op0, target);
2757 if (temp)
2758 return temp;
2759 }
2760 }
2761
2762 goto try_libcall;
2763 }
2764
2765 if (unoptab == clrsb_optab)
2766 {
2767 if (is_a <scalar_int_mode> (mode, &int_mode))
2768 {
2769 temp = widen_leading (int_mode, op0, target, unoptab);
2770 if (temp)
2771 return temp;
2772 }
2773 goto try_libcall;
2774 }
2775
2776 if (unoptab == popcount_optab
2777 && is_a <scalar_int_mode> (mode, &int_mode)
2778 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
2779 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing
2780 && optimize_insn_for_speed_p ())
2781 {
2782 temp = expand_doubleword_popcount (int_mode, op0, target);
2783 if (temp)
2784 return temp;
2785 }
2786
2787 if (unoptab == parity_optab
2788 && is_a <scalar_int_mode> (mode, &int_mode)
2789 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
2790 && (optab_handler (unoptab, word_mode) != CODE_FOR_nothing
2791 || optab_handler (popcount_optab, word_mode) != CODE_FOR_nothing)
2792 && optimize_insn_for_speed_p ())
2793 {
2794 temp = expand_doubleword_parity (int_mode, op0, target);
2795 if (temp)
2796 return temp;
2797 }
2798
2799 /* Widening (or narrowing) bswap needs special treatment. */
2800 if (unoptab == bswap_optab)
2801 {
2802 /* HImode is special because in this mode BSWAP is equivalent to ROTATE
2803 or ROTATERT. First try these directly; if this fails, then try the
2804 obvious pair of shifts with allowed widening, as this will probably
2805 be always more efficient than the other fallback methods. */
2806 if (mode == HImode)
2807 {
2808 rtx_insn *last;
2809 rtx temp1, temp2;
2810
2811 if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing)
2812 {
2813 temp = expand_binop (mode, rotl_optab, op0,
2814 gen_int_shift_amount (mode, 8),
2815 target, unsignedp, OPTAB_DIRECT);
2816 if (temp)
2817 return temp;
2818 }
2819
2820 if (optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
2821 {
2822 temp = expand_binop (mode, rotr_optab, op0,
2823 gen_int_shift_amount (mode, 8),
2824 target, unsignedp, OPTAB_DIRECT);
2825 if (temp)
2826 return temp;
2827 }
2828
2829 last = get_last_insn ();
2830
2831 temp1 = expand_binop (mode, ashl_optab, op0,
2832 gen_int_shift_amount (mode, 8), NULL_RTX,
2833 unsignedp, OPTAB_WIDEN);
2834 temp2 = expand_binop (mode, lshr_optab, op0,
2835 gen_int_shift_amount (mode, 8), NULL_RTX,
2836 unsignedp, OPTAB_WIDEN);
2837 if (temp1 && temp2)
2838 {
2839 temp = expand_binop (mode, ior_optab, temp1, temp2, target,
2840 unsignedp, OPTAB_WIDEN);
2841 if (temp)
2842 return temp;
2843 }
2844
2845 delete_insns_since (last);
2846 }
2847
2848 if (is_a <scalar_int_mode> (mode, &int_mode))
2849 {
2850 temp = widen_bswap (int_mode, op0, target);
2851 if (temp)
2852 return temp;
2853
2854 if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
2855 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
2856 {
2857 temp = expand_doubleword_bswap (mode, op0, target);
2858 if (temp)
2859 return temp;
2860 }
2861 }
2862
2863 goto try_libcall;
2864 }
2865
2866 if (CLASS_HAS_WIDER_MODES_P (mclass))
2867 FOR_EACH_WIDER_MODE (wider_mode, mode)
2868 {
2869 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
2870 {
2871 rtx xop0 = op0;
2872 rtx_insn *last = get_last_insn ();
2873
2874 /* For certain operations, we need not actually extend
2875 the narrow operand, as long as we will truncate the
2876 results to the same narrowness. */
2877
2878 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2879 (unoptab == neg_optab
2880 || unoptab == one_cmpl_optab)
2881 && mclass == MODE_INT);
2882
2883 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
2884 unsignedp);
2885
2886 if (temp)
2887 {
2888 if (mclass != MODE_INT
2889 || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
2890 {
2891 if (target == 0)
2892 target = gen_reg_rtx (mode);
2893 convert_move (target, temp, 0);
2894 return target;
2895 }
2896 else
2897 return gen_lowpart (mode, temp);
2898 }
2899 else
2900 delete_insns_since (last);
2901 }
2902 }
2903
2904 /* These can be done a word at a time. */
2905 if (unoptab == one_cmpl_optab
2906 && is_int_mode (mode, &int_mode)
2907 && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD
2908 && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
2909 {
2910 int i;
2911 rtx_insn *insns;
2912
2913 if (target == 0 || target == op0 || !valid_multiword_target_p (target))
2914 target = gen_reg_rtx (int_mode);
2915
2916 start_sequence ();
2917
2918 /* Do the actual arithmetic. */
2919 for (i = 0; i < GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD; i++)
2920 {
2921 rtx target_piece = operand_subword (target, i, 1, int_mode);
2922 rtx x = expand_unop (word_mode, unoptab,
2923 operand_subword_force (op0, i, int_mode),
2924 target_piece, unsignedp);
2925
2926 if (target_piece != x)
2927 emit_move_insn (target_piece, x);
2928 }
2929
2930 insns = get_insns ();
2931 end_sequence ();
2932
2933 emit_insn (insns);
2934 return target;
2935 }
2936
2937 if (optab_to_code (unoptab) == NEG)
2938 {
2939 /* Try negating floating point values by flipping the sign bit. */
2940 if (is_a <scalar_float_mode> (mode, &float_mode))
2941 {
2942 temp = expand_absneg_bit (NEG, float_mode, op0, target);
2943 if (temp)
2944 return temp;
2945 }
2946
2947 /* If there is no negation pattern, and we have no negative zero,
2948 try subtracting from zero. */
2949 if (!HONOR_SIGNED_ZEROS (mode))
2950 {
2951 temp = expand_binop (mode, (unoptab == negv_optab
2952 ? subv_optab : sub_optab),
2953 CONST0_RTX (mode), op0, target,
2954 unsignedp, OPTAB_DIRECT);
2955 if (temp)
2956 return temp;
2957 }
2958 }
2959
2960 /* Try calculating parity (x) as popcount (x) % 2. */
2961 if (unoptab == parity_optab && is_a <scalar_int_mode> (mode, &int_mode))
2962 {
2963 temp = expand_parity (int_mode, op0, target);
2964 if (temp)
2965 return temp;
2966 }
2967
2968 /* Try implementing ffs (x) in terms of clz (x). */
2969 if (unoptab == ffs_optab && is_a <scalar_int_mode> (mode, &int_mode))
2970 {
2971 temp = expand_ffs (int_mode, op0, target);
2972 if (temp)
2973 return temp;
2974 }
2975
2976 /* Try implementing ctz (x) in terms of clz (x). */
2977 if (unoptab == ctz_optab && is_a <scalar_int_mode> (mode, &int_mode))
2978 {
2979 temp = expand_ctz (int_mode, op0, target);
2980 if (temp)
2981 return temp;
2982 }
2983
2984 try_libcall:
2985 /* Now try a library call in this mode. */
2986 libfunc = optab_libfunc (unoptab, mode);
2987 if (libfunc)
2988 {
2989 rtx_insn *insns;
2990 rtx value;
2991 rtx eq_value;
2992 machine_mode outmode = mode;
2993
2994 /* All of these functions return small values. Thus we choose to
2995 have them return something that isn't a double-word. */
2996 if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
2997 || unoptab == clrsb_optab || unoptab == popcount_optab
2998 || unoptab == parity_optab)
2999 outmode
3000 = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
3001 optab_libfunc (unoptab, mode)));
3002
3003 start_sequence ();
3004
3005 /* Pass 1 for NO_QUEUE so we don't lose any increments
3006 if the libcall is cse'd or moved. */
3007 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, outmode,
3008 op0, mode);
3009 insns = get_insns ();
3010 end_sequence ();
3011
3012 target = gen_reg_rtx (outmode);
3013 bool trapv = trapv_unoptab_p (unoptab);
3014 if (trapv)
3015 eq_value = NULL_RTX;
3016 else
3017 {
3018 eq_value = gen_rtx_fmt_e (optab_to_code (unoptab), mode, op0);
3019 if (GET_MODE_UNIT_SIZE (outmode) < GET_MODE_UNIT_SIZE (mode))
3020 eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
3021 else if (GET_MODE_UNIT_SIZE (outmode) > GET_MODE_UNIT_SIZE (mode))
3022 eq_value = simplify_gen_unary (ZERO_EXTEND,
3023 outmode, eq_value, mode);
3024 }
3025 emit_libcall_block_1 (insns, target, value, eq_value, trapv);
3026
3027 return target;
3028 }
3029
3030 /* It can't be done in this mode. Can we do it in a wider mode? */
3031
3032 if (CLASS_HAS_WIDER_MODES_P (mclass))
3033 {
3034 FOR_EACH_WIDER_MODE (wider_mode, mode)
3035 {
3036 if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing
3037 || optab_libfunc (unoptab, wider_mode))
3038 {
3039 rtx xop0 = op0;
3040 rtx_insn *last = get_last_insn ();
3041
3042 /* For certain operations, we need not actually extend
3043 the narrow operand, as long as we will truncate the
3044 results to the same narrowness. */
3045 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
3046 (unoptab == neg_optab
3047 || unoptab == one_cmpl_optab
3048 || unoptab == bswap_optab)
3049 && mclass == MODE_INT);
3050
3051 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
3052 unsignedp);
3053
3054 /* If we are generating clz using wider mode, adjust the
3055 result. Similarly for clrsb. */
3056 if ((unoptab == clz_optab || unoptab == clrsb_optab)
3057 && temp != 0)
3058 {
3059 scalar_int_mode wider_int_mode
3060 = as_a <scalar_int_mode> (wider_mode);
3061 int_mode = as_a <scalar_int_mode> (mode);
3062 temp = expand_binop
3063 (wider_mode, sub_optab, temp,
3064 gen_int_mode (GET_MODE_PRECISION (wider_int_mode)
3065 - GET_MODE_PRECISION (int_mode),
3066 wider_int_mode),
3067 target, true, OPTAB_DIRECT);
3068 }
3069
3070 /* Likewise for bswap. */
3071 if (unoptab == bswap_optab && temp != 0)
3072 {
3073 scalar_int_mode wider_int_mode
3074 = as_a <scalar_int_mode> (wider_mode);
3075 int_mode = as_a <scalar_int_mode> (mode);
3076 gcc_assert (GET_MODE_PRECISION (wider_int_mode)
3077 == GET_MODE_BITSIZE (wider_int_mode)
3078 && GET_MODE_PRECISION (int_mode)
3079 == GET_MODE_BITSIZE (int_mode));
3080
3081 temp = expand_shift (RSHIFT_EXPR, wider_int_mode, temp,
3082 GET_MODE_BITSIZE (wider_int_mode)
3083 - GET_MODE_BITSIZE (int_mode),
3084 NULL_RTX, true);
3085 }
3086
3087 if (temp)
3088 {
3089 if (mclass != MODE_INT)
3090 {
3091 if (target == 0)
3092 target = gen_reg_rtx (mode);
3093 convert_move (target, temp, 0);
3094 return target;
3095 }
3096 else
3097 return gen_lowpart (mode, temp);
3098 }
3099 else
3100 delete_insns_since (last);
3101 }
3102 }
3103 }
3104
3105 /* One final attempt at implementing negation via subtraction,
3106 this time allowing widening of the operand. */
3107 if (optab_to_code (unoptab) == NEG && !HONOR_SIGNED_ZEROS (mode))
3108 {
3109 rtx temp;
3110 temp = expand_binop (mode,
3111 unoptab == negv_optab ? subv_optab : sub_optab,
3112 CONST0_RTX (mode), op0,
3113 target, unsignedp, OPTAB_LIB_WIDEN);
3114 if (temp)
3115 return temp;
3116 }
3117
3118 return 0;
3119 }
3120
3121 /* Emit code to compute the absolute value of OP0, with result to
3122 TARGET if convenient. (TARGET may be 0.) The return value says
3123 where the result actually is to be found.
3124
3125 MODE is the mode of the operand; the mode of the result is
3126 different but can be deduced from MODE.
3127
3128 */
3129
3130 rtx
expand_abs_nojump(machine_mode mode,rtx op0,rtx target,int result_unsignedp)3131 expand_abs_nojump (machine_mode mode, rtx op0, rtx target,
3132 int result_unsignedp)
3133 {
3134 rtx temp;
3135
3136 if (GET_MODE_CLASS (mode) != MODE_INT
3137 || ! flag_trapv)
3138 result_unsignedp = 1;
3139
3140 /* First try to do it with a special abs instruction. */
3141 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
3142 op0, target, 0);
3143 if (temp != 0)
3144 return temp;
3145
3146 /* For floating point modes, try clearing the sign bit. */
3147 scalar_float_mode float_mode;
3148 if (is_a <scalar_float_mode> (mode, &float_mode))
3149 {
3150 temp = expand_absneg_bit (ABS, float_mode, op0, target);
3151 if (temp)
3152 return temp;
3153 }
3154
3155 /* If we have a MAX insn, we can do this as MAX (x, -x). */
3156 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing
3157 && !HONOR_SIGNED_ZEROS (mode))
3158 {
3159 rtx_insn *last = get_last_insn ();
3160
3161 temp = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3162 op0, NULL_RTX, 0);
3163 if (temp != 0)
3164 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3165 OPTAB_WIDEN);
3166
3167 if (temp != 0)
3168 return temp;
3169
3170 delete_insns_since (last);
3171 }
3172
3173 /* If this machine has expensive jumps, we can do integer absolute
3174 value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
3175 where W is the width of MODE. */
3176
3177 scalar_int_mode int_mode;
3178 if (is_int_mode (mode, &int_mode)
3179 && BRANCH_COST (optimize_insn_for_speed_p (),
3180 false) >= 2)
3181 {
3182 rtx extended = expand_shift (RSHIFT_EXPR, int_mode, op0,
3183 GET_MODE_PRECISION (int_mode) - 1,
3184 NULL_RTX, 0);
3185
3186 temp = expand_binop (int_mode, xor_optab, extended, op0, target, 0,
3187 OPTAB_LIB_WIDEN);
3188 if (temp != 0)
3189 temp = expand_binop (int_mode,
3190 result_unsignedp ? sub_optab : subv_optab,
3191 temp, extended, target, 0, OPTAB_LIB_WIDEN);
3192
3193 if (temp != 0)
3194 return temp;
3195 }
3196
3197 return NULL_RTX;
3198 }
3199
3200 rtx
expand_abs(machine_mode mode,rtx op0,rtx target,int result_unsignedp,int safe)3201 expand_abs (machine_mode mode, rtx op0, rtx target,
3202 int result_unsignedp, int safe)
3203 {
3204 rtx temp;
3205 rtx_code_label *op1;
3206
3207 if (GET_MODE_CLASS (mode) != MODE_INT
3208 || ! flag_trapv)
3209 result_unsignedp = 1;
3210
3211 temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
3212 if (temp != 0)
3213 return temp;
3214
3215 /* If that does not win, use conditional jump and negate. */
3216
3217 /* It is safe to use the target if it is the same
3218 as the source if this is also a pseudo register */
3219 if (op0 == target && REG_P (op0)
3220 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
3221 safe = 1;
3222
3223 op1 = gen_label_rtx ();
3224 if (target == 0 || ! safe
3225 || GET_MODE (target) != mode
3226 || (MEM_P (target) && MEM_VOLATILE_P (target))
3227 || (REG_P (target)
3228 && REGNO (target) < FIRST_PSEUDO_REGISTER))
3229 target = gen_reg_rtx (mode);
3230
3231 emit_move_insn (target, op0);
3232 NO_DEFER_POP;
3233
3234 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
3235 NULL_RTX, NULL, op1,
3236 profile_probability::uninitialized ());
3237
3238 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
3239 target, target, 0);
3240 if (op0 != target)
3241 emit_move_insn (target, op0);
3242 emit_label (op1);
3243 OK_DEFER_POP;
3244 return target;
3245 }
3246
3247 /* Emit code to compute the one's complement absolute value of OP0
3248 (if (OP0 < 0) OP0 = ~OP0), with result to TARGET if convenient.
3249 (TARGET may be NULL_RTX.) The return value says where the result
3250 actually is to be found.
3251
3252 MODE is the mode of the operand; the mode of the result is
3253 different but can be deduced from MODE. */
3254
3255 rtx
expand_one_cmpl_abs_nojump(machine_mode mode,rtx op0,rtx target)3256 expand_one_cmpl_abs_nojump (machine_mode mode, rtx op0, rtx target)
3257 {
3258 rtx temp;
3259
3260 /* Not applicable for floating point modes. */
3261 if (FLOAT_MODE_P (mode))
3262 return NULL_RTX;
3263
3264 /* If we have a MAX insn, we can do this as MAX (x, ~x). */
3265 if (optab_handler (smax_optab, mode) != CODE_FOR_nothing)
3266 {
3267 rtx_insn *last = get_last_insn ();
3268
3269 temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
3270 if (temp != 0)
3271 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
3272 OPTAB_WIDEN);
3273
3274 if (temp != 0)
3275 return temp;
3276
3277 delete_insns_since (last);
3278 }
3279
3280 /* If this machine has expensive jumps, we can do one's complement
3281 absolute value of X as (((signed) x >> (W-1)) ^ x). */
3282
3283 scalar_int_mode int_mode;
3284 if (is_int_mode (mode, &int_mode)
3285 && BRANCH_COST (optimize_insn_for_speed_p (),
3286 false) >= 2)
3287 {
3288 rtx extended = expand_shift (RSHIFT_EXPR, int_mode, op0,
3289 GET_MODE_PRECISION (int_mode) - 1,
3290 NULL_RTX, 0);
3291
3292 temp = expand_binop (int_mode, xor_optab, extended, op0, target, 0,
3293 OPTAB_LIB_WIDEN);
3294
3295 if (temp != 0)
3296 return temp;
3297 }
3298
3299 return NULL_RTX;
3300 }
3301
3302 /* A subroutine of expand_copysign, perform the copysign operation using the
3303 abs and neg primitives advertised to exist on the target. The assumption
3304 is that we have a split register file, and leaving op0 in fp registers,
3305 and not playing with subregs so much, will help the register allocator. */
3306
3307 static rtx
expand_copysign_absneg(scalar_float_mode mode,rtx op0,rtx op1,rtx target,int bitpos,bool op0_is_abs)3308 expand_copysign_absneg (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
3309 int bitpos, bool op0_is_abs)
3310 {
3311 scalar_int_mode imode;
3312 enum insn_code icode;
3313 rtx sign;
3314 rtx_code_label *label;
3315
3316 if (target == op1)
3317 target = NULL_RTX;
3318
3319 /* Check if the back end provides an insn that handles signbit for the
3320 argument's mode. */
3321 icode = optab_handler (signbit_optab, mode);
3322 if (icode != CODE_FOR_nothing)
3323 {
3324 imode = as_a <scalar_int_mode> (insn_data[(int) icode].operand[0].mode);
3325 sign = gen_reg_rtx (imode);
3326 emit_unop_insn (icode, sign, op1, UNKNOWN);
3327 }
3328 else
3329 {
3330 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3331 {
3332 if (!int_mode_for_mode (mode).exists (&imode))
3333 return NULL_RTX;
3334 op1 = gen_lowpart (imode, op1);
3335 }
3336 else
3337 {
3338 int word;
3339
3340 imode = word_mode;
3341 if (FLOAT_WORDS_BIG_ENDIAN)
3342 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3343 else
3344 word = bitpos / BITS_PER_WORD;
3345 bitpos = bitpos % BITS_PER_WORD;
3346 op1 = operand_subword_force (op1, word, mode);
3347 }
3348
3349 wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
3350 sign = expand_binop (imode, and_optab, op1,
3351 immed_wide_int_const (mask, imode),
3352 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3353 }
3354
3355 if (!op0_is_abs)
3356 {
3357 op0 = expand_unop (mode, abs_optab, op0, target, 0);
3358 if (op0 == NULL)
3359 return NULL_RTX;
3360 target = op0;
3361 }
3362 else
3363 {
3364 if (target == NULL_RTX)
3365 target = copy_to_reg (op0);
3366 else
3367 emit_move_insn (target, op0);
3368 }
3369
3370 label = gen_label_rtx ();
3371 emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
3372
3373 if (CONST_DOUBLE_AS_FLOAT_P (op0))
3374 op0 = simplify_unary_operation (NEG, mode, op0, mode);
3375 else
3376 op0 = expand_unop (mode, neg_optab, op0, target, 0);
3377 if (op0 != target)
3378 emit_move_insn (target, op0);
3379
3380 emit_label (label);
3381
3382 return target;
3383 }
3384
3385
3386 /* A subroutine of expand_copysign, perform the entire copysign operation
3387 with integer bitmasks. BITPOS is the position of the sign bit; OP0_IS_ABS
3388 is true if op0 is known to have its sign bit clear. */
3389
3390 static rtx
expand_copysign_bit(scalar_float_mode mode,rtx op0,rtx op1,rtx target,int bitpos,bool op0_is_abs)3391 expand_copysign_bit (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
3392 int bitpos, bool op0_is_abs)
3393 {
3394 scalar_int_mode imode;
3395 int word, nwords, i;
3396 rtx temp;
3397 rtx_insn *insns;
3398
3399 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
3400 {
3401 if (!int_mode_for_mode (mode).exists (&imode))
3402 return NULL_RTX;
3403 word = 0;
3404 nwords = 1;
3405 }
3406 else
3407 {
3408 imode = word_mode;
3409
3410 if (FLOAT_WORDS_BIG_ENDIAN)
3411 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
3412 else
3413 word = bitpos / BITS_PER_WORD;
3414 bitpos = bitpos % BITS_PER_WORD;
3415 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
3416 }
3417
3418 wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode));
3419
3420 if (target == 0
3421 || target == op0
3422 || target == op1
3423 || (nwords > 1 && !valid_multiword_target_p (target)))
3424 target = gen_reg_rtx (mode);
3425
3426 if (nwords > 1)
3427 {
3428 start_sequence ();
3429
3430 for (i = 0; i < nwords; ++i)
3431 {
3432 rtx targ_piece = operand_subword (target, i, 1, mode);
3433 rtx op0_piece = operand_subword_force (op0, i, mode);
3434
3435 if (i == word)
3436 {
3437 if (!op0_is_abs)
3438 op0_piece
3439 = expand_binop (imode, and_optab, op0_piece,
3440 immed_wide_int_const (~mask, imode),
3441 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3442 op1 = expand_binop (imode, and_optab,
3443 operand_subword_force (op1, i, mode),
3444 immed_wide_int_const (mask, imode),
3445 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3446
3447 temp = expand_binop (imode, ior_optab, op0_piece, op1,
3448 targ_piece, 1, OPTAB_LIB_WIDEN);
3449 if (temp != targ_piece)
3450 emit_move_insn (targ_piece, temp);
3451 }
3452 else
3453 emit_move_insn (targ_piece, op0_piece);
3454 }
3455
3456 insns = get_insns ();
3457 end_sequence ();
3458
3459 emit_insn (insns);
3460 }
3461 else
3462 {
3463 op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
3464 immed_wide_int_const (mask, imode),
3465 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3466
3467 op0 = gen_lowpart (imode, op0);
3468 if (!op0_is_abs)
3469 op0 = expand_binop (imode, and_optab, op0,
3470 immed_wide_int_const (~mask, imode),
3471 NULL_RTX, 1, OPTAB_LIB_WIDEN);
3472
3473 temp = expand_binop (imode, ior_optab, op0, op1,
3474 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
3475 target = lowpart_subreg_maybe_copy (mode, temp, imode);
3476 }
3477
3478 return target;
3479 }
3480
3481 /* Expand the C99 copysign operation. OP0 and OP1 must be the same
3482 scalar floating point mode. Return NULL if we do not know how to
3483 expand the operation inline. */
3484
3485 rtx
expand_copysign(rtx op0,rtx op1,rtx target)3486 expand_copysign (rtx op0, rtx op1, rtx target)
3487 {
3488 scalar_float_mode mode;
3489 const struct real_format *fmt;
3490 bool op0_is_abs;
3491 rtx temp;
3492
3493 mode = as_a <scalar_float_mode> (GET_MODE (op0));
3494 gcc_assert (GET_MODE (op1) == mode);
3495
3496 /* First try to do it with a special instruction. */
3497 temp = expand_binop (mode, copysign_optab, op0, op1,
3498 target, 0, OPTAB_DIRECT);
3499 if (temp)
3500 return temp;
3501
3502 fmt = REAL_MODE_FORMAT (mode);
3503 if (fmt == NULL || !fmt->has_signed_zero)
3504 return NULL_RTX;
3505
3506 op0_is_abs = false;
3507 if (CONST_DOUBLE_AS_FLOAT_P (op0))
3508 {
3509 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
3510 op0 = simplify_unary_operation (ABS, mode, op0, mode);
3511 op0_is_abs = true;
3512 }
3513
3514 if (fmt->signbit_ro >= 0
3515 && (CONST_DOUBLE_AS_FLOAT_P (op0)
3516 || (optab_handler (neg_optab, mode) != CODE_FOR_nothing
3517 && optab_handler (abs_optab, mode) != CODE_FOR_nothing)))
3518 {
3519 temp = expand_copysign_absneg (mode, op0, op1, target,
3520 fmt->signbit_ro, op0_is_abs);
3521 if (temp)
3522 return temp;
3523 }
3524
3525 if (fmt->signbit_rw < 0)
3526 return NULL_RTX;
3527 return expand_copysign_bit (mode, op0, op1, target,
3528 fmt->signbit_rw, op0_is_abs);
3529 }
3530
3531 /* Generate an instruction whose insn-code is INSN_CODE,
3532 with two operands: an output TARGET and an input OP0.
3533 TARGET *must* be nonzero, and the output is always stored there.
3534 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3535 the value that is stored into TARGET.
3536
3537 Return false if expansion failed. */
3538
3539 bool
maybe_emit_unop_insn(enum insn_code icode,rtx target,rtx op0,enum rtx_code code)3540 maybe_emit_unop_insn (enum insn_code icode, rtx target, rtx op0,
3541 enum rtx_code code)
3542 {
3543 struct expand_operand ops[2];
3544 rtx_insn *pat;
3545
3546 create_output_operand (&ops[0], target, GET_MODE (target));
3547 create_input_operand (&ops[1], op0, GET_MODE (op0));
3548 pat = maybe_gen_insn (icode, 2, ops);
3549 if (!pat)
3550 return false;
3551
3552 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
3553 && code != UNKNOWN)
3554 add_equal_note (pat, ops[0].value, code, ops[1].value, NULL_RTX,
3555 GET_MODE (op0));
3556
3557 emit_insn (pat);
3558
3559 if (ops[0].value != target)
3560 emit_move_insn (target, ops[0].value);
3561 return true;
3562 }
3563 /* Generate an instruction whose insn-code is INSN_CODE,
3564 with two operands: an output TARGET and an input OP0.
3565 TARGET *must* be nonzero, and the output is always stored there.
3566 CODE is an rtx code such that (CODE OP0) is an rtx that describes
3567 the value that is stored into TARGET. */
3568
3569 void
emit_unop_insn(enum insn_code icode,rtx target,rtx op0,enum rtx_code code)3570 emit_unop_insn (enum insn_code icode, rtx target, rtx op0, enum rtx_code code)
3571 {
3572 bool ok = maybe_emit_unop_insn (icode, target, op0, code);
3573 gcc_assert (ok);
3574 }
3575
3576 struct no_conflict_data
3577 {
3578 rtx target;
3579 rtx_insn *first, *insn;
3580 bool must_stay;
3581 };
3582
3583 /* Called via note_stores by emit_libcall_block. Set P->must_stay if
3584 the currently examined clobber / store has to stay in the list of
3585 insns that constitute the actual libcall block. */
3586 static void
no_conflict_move_test(rtx dest,const_rtx set,void * p0)3587 no_conflict_move_test (rtx dest, const_rtx set, void *p0)
3588 {
3589 struct no_conflict_data *p= (struct no_conflict_data *) p0;
3590
3591 /* If this inns directly contributes to setting the target, it must stay. */
3592 if (reg_overlap_mentioned_p (p->target, dest))
3593 p->must_stay = true;
3594 /* If we haven't committed to keeping any other insns in the list yet,
3595 there is nothing more to check. */
3596 else if (p->insn == p->first)
3597 return;
3598 /* If this insn sets / clobbers a register that feeds one of the insns
3599 already in the list, this insn has to stay too. */
3600 else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
3601 || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
3602 || reg_used_between_p (dest, p->first, p->insn)
3603 /* Likewise if this insn depends on a register set by a previous
3604 insn in the list, or if it sets a result (presumably a hard
3605 register) that is set or clobbered by a previous insn.
3606 N.B. the modified_*_p (SET_DEST...) tests applied to a MEM
3607 SET_DEST perform the former check on the address, and the latter
3608 check on the MEM. */
3609 || (GET_CODE (set) == SET
3610 && (modified_in_p (SET_SRC (set), p->first)
3611 || modified_in_p (SET_DEST (set), p->first)
3612 || modified_between_p (SET_SRC (set), p->first, p->insn)
3613 || modified_between_p (SET_DEST (set), p->first, p->insn))))
3614 p->must_stay = true;
3615 }
3616
3617
3618 /* Emit code to make a call to a constant function or a library call.
3619
3620 INSNS is a list containing all insns emitted in the call.
3621 These insns leave the result in RESULT. Our block is to copy RESULT
3622 to TARGET, which is logically equivalent to EQUIV.
3623
3624 We first emit any insns that set a pseudo on the assumption that these are
3625 loading constants into registers; doing so allows them to be safely cse'ed
3626 between blocks. Then we emit all the other insns in the block, followed by
3627 an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
3628 note with an operand of EQUIV. */
3629
3630 static void
emit_libcall_block_1(rtx_insn * insns,rtx target,rtx result,rtx equiv,bool equiv_may_trap)3631 emit_libcall_block_1 (rtx_insn *insns, rtx target, rtx result, rtx equiv,
3632 bool equiv_may_trap)
3633 {
3634 rtx final_dest = target;
3635 rtx_insn *next, *last, *insn;
3636
3637 /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
3638 into a MEM later. Protect the libcall block from this change. */
3639 if (! REG_P (target) || REG_USERVAR_P (target))
3640 target = gen_reg_rtx (GET_MODE (target));
3641
3642 /* If we're using non-call exceptions, a libcall corresponding to an
3643 operation that may trap may also trap. */
3644 /* ??? See the comment in front of make_reg_eh_region_note. */
3645 if (cfun->can_throw_non_call_exceptions
3646 && (equiv_may_trap || may_trap_p (equiv)))
3647 {
3648 for (insn = insns; insn; insn = NEXT_INSN (insn))
3649 if (CALL_P (insn))
3650 {
3651 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3652 if (note)
3653 {
3654 int lp_nr = INTVAL (XEXP (note, 0));
3655 if (lp_nr == 0 || lp_nr == INT_MIN)
3656 remove_note (insn, note);
3657 }
3658 }
3659 }
3660 else
3661 {
3662 /* Look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
3663 reg note to indicate that this call cannot throw or execute a nonlocal
3664 goto (unless there is already a REG_EH_REGION note, in which case
3665 we update it). */
3666 for (insn = insns; insn; insn = NEXT_INSN (insn))
3667 if (CALL_P (insn))
3668 make_reg_eh_region_note_nothrow_nononlocal (insn);
3669 }
3670
3671 /* First emit all insns that set pseudos. Remove them from the list as
3672 we go. Avoid insns that set pseudos which were referenced in previous
3673 insns. These can be generated by move_by_pieces, for example,
3674 to update an address. Similarly, avoid insns that reference things
3675 set in previous insns. */
3676
3677 for (insn = insns; insn; insn = next)
3678 {
3679 rtx set = single_set (insn);
3680
3681 next = NEXT_INSN (insn);
3682
3683 if (set != 0 && REG_P (SET_DEST (set))
3684 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
3685 {
3686 struct no_conflict_data data;
3687
3688 data.target = const0_rtx;
3689 data.first = insns;
3690 data.insn = insn;
3691 data.must_stay = 0;
3692 note_stores (PATTERN (insn), no_conflict_move_test, &data);
3693 if (! data.must_stay)
3694 {
3695 if (PREV_INSN (insn))
3696 SET_NEXT_INSN (PREV_INSN (insn)) = next;
3697 else
3698 insns = next;
3699
3700 if (next)
3701 SET_PREV_INSN (next) = PREV_INSN (insn);
3702
3703 add_insn (insn);
3704 }
3705 }
3706
3707 /* Some ports use a loop to copy large arguments onto the stack.
3708 Don't move anything outside such a loop. */
3709 if (LABEL_P (insn))
3710 break;
3711 }
3712
3713 /* Write the remaining insns followed by the final copy. */
3714 for (insn = insns; insn; insn = next)
3715 {
3716 next = NEXT_INSN (insn);
3717
3718 add_insn (insn);
3719 }
3720
3721 last = emit_move_insn (target, result);
3722 if (equiv)
3723 set_dst_reg_note (last, REG_EQUAL, copy_rtx (equiv), target);
3724
3725 if (final_dest != target)
3726 emit_move_insn (final_dest, target);
3727 }
3728
3729 void
emit_libcall_block(rtx_insn * insns,rtx target,rtx result,rtx equiv)3730 emit_libcall_block (rtx_insn *insns, rtx target, rtx result, rtx equiv)
3731 {
3732 emit_libcall_block_1 (insns, target, result, equiv, false);
3733 }
3734
3735 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
3736 PURPOSE describes how this comparison will be used. CODE is the rtx
3737 comparison code we will be using.
3738
3739 ??? Actually, CODE is slightly weaker than that. A target is still
3740 required to implement all of the normal bcc operations, but not
3741 required to implement all (or any) of the unordered bcc operations. */
3742
3743 int
can_compare_p(enum rtx_code code,machine_mode mode,enum can_compare_purpose purpose)3744 can_compare_p (enum rtx_code code, machine_mode mode,
3745 enum can_compare_purpose purpose)
3746 {
3747 rtx test;
3748 test = gen_rtx_fmt_ee (code, mode, const0_rtx, const0_rtx);
3749 do
3750 {
3751 enum insn_code icode;
3752
3753 if (purpose == ccp_jump
3754 && (icode = optab_handler (cbranch_optab, mode)) != CODE_FOR_nothing
3755 && insn_operand_matches (icode, 0, test))
3756 return 1;
3757 if (purpose == ccp_store_flag
3758 && (icode = optab_handler (cstore_optab, mode)) != CODE_FOR_nothing
3759 && insn_operand_matches (icode, 1, test))
3760 return 1;
3761 if (purpose == ccp_cmov
3762 && optab_handler (cmov_optab, mode) != CODE_FOR_nothing)
3763 return 1;
3764
3765 mode = GET_MODE_WIDER_MODE (mode).else_void ();
3766 PUT_MODE (test, mode);
3767 }
3768 while (mode != VOIDmode);
3769
3770 return 0;
3771 }
3772
3773 /* This function is called when we are going to emit a compare instruction that
3774 compares the values found in X and Y, using the rtl operator COMPARISON.
3775
3776 If they have mode BLKmode, then SIZE specifies the size of both operands.
3777
3778 UNSIGNEDP nonzero says that the operands are unsigned;
3779 this matters if they need to be widened (as given by METHODS).
3780
3781 *PTEST is where the resulting comparison RTX is returned or NULL_RTX
3782 if we failed to produce one.
3783
3784 *PMODE is the mode of the inputs (in case they are const_int).
3785
3786 This function performs all the setup necessary so that the caller only has
3787 to emit a single comparison insn. This setup can involve doing a BLKmode
3788 comparison or emitting a library call to perform the comparison if no insn
3789 is available to handle it.
3790 The values which are passed in through pointers can be modified; the caller
3791 should perform the comparison on the modified values. Constant
3792 comparisons must have already been folded. */
3793
3794 static void
prepare_cmp_insn(rtx x,rtx y,enum rtx_code comparison,rtx size,int unsignedp,enum optab_methods methods,rtx * ptest,machine_mode * pmode)3795 prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
3796 int unsignedp, enum optab_methods methods,
3797 rtx *ptest, machine_mode *pmode)
3798 {
3799 machine_mode mode = *pmode;
3800 rtx libfunc, test;
3801 machine_mode cmp_mode;
3802 enum mode_class mclass;
3803
3804 /* The other methods are not needed. */
3805 gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN
3806 || methods == OPTAB_LIB_WIDEN);
3807
3808 /* If we are optimizing, force expensive constants into a register. */
3809 if (CONSTANT_P (x) && optimize
3810 && (rtx_cost (x, mode, COMPARE, 0, optimize_insn_for_speed_p ())
3811 > COSTS_N_INSNS (1)))
3812 x = force_reg (mode, x);
3813
3814 if (CONSTANT_P (y) && optimize
3815 && (rtx_cost (y, mode, COMPARE, 1, optimize_insn_for_speed_p ())
3816 > COSTS_N_INSNS (1)))
3817 y = force_reg (mode, y);
3818
3819 #if HAVE_cc0
3820 /* Make sure if we have a canonical comparison. The RTL
3821 documentation states that canonical comparisons are required only
3822 for targets which have cc0. */
3823 gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
3824 #endif
3825
3826 /* Don't let both operands fail to indicate the mode. */
3827 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
3828 x = force_reg (mode, x);
3829 if (mode == VOIDmode)
3830 mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : GET_MODE (y);
3831
3832 /* Handle all BLKmode compares. */
3833
3834 if (mode == BLKmode)
3835 {
3836 machine_mode result_mode;
3837 enum insn_code cmp_code;
3838 rtx result;
3839 rtx opalign
3840 = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
3841
3842 gcc_assert (size);
3843
3844 /* Try to use a memory block compare insn - either cmpstr
3845 or cmpmem will do. */
3846 opt_scalar_int_mode cmp_mode_iter;
3847 FOR_EACH_MODE_IN_CLASS (cmp_mode_iter, MODE_INT)
3848 {
3849 scalar_int_mode cmp_mode = cmp_mode_iter.require ();
3850 cmp_code = direct_optab_handler (cmpmem_optab, cmp_mode);
3851 if (cmp_code == CODE_FOR_nothing)
3852 cmp_code = direct_optab_handler (cmpstr_optab, cmp_mode);
3853 if (cmp_code == CODE_FOR_nothing)
3854 cmp_code = direct_optab_handler (cmpstrn_optab, cmp_mode);
3855 if (cmp_code == CODE_FOR_nothing)
3856 continue;
3857
3858 /* Must make sure the size fits the insn's mode. */
3859 if (CONST_INT_P (size)
3860 ? UINTVAL (size) > GET_MODE_MASK (cmp_mode)
3861 : (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (size)))
3862 > GET_MODE_BITSIZE (cmp_mode)))
3863 continue;
3864
3865 result_mode = insn_data[cmp_code].operand[0].mode;
3866 result = gen_reg_rtx (result_mode);
3867 size = convert_to_mode (cmp_mode, size, 1);
3868 emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
3869
3870 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, result, const0_rtx);
3871 *pmode = result_mode;
3872 return;
3873 }
3874
3875 if (methods != OPTAB_LIB && methods != OPTAB_LIB_WIDEN)
3876 goto fail;
3877
3878 /* Otherwise call a library function. */
3879 result = emit_block_comp_via_libcall (x, y, size);
3880
3881 x = result;
3882 y = const0_rtx;
3883 mode = TYPE_MODE (integer_type_node);
3884 methods = OPTAB_LIB_WIDEN;
3885 unsignedp = false;
3886 }
3887
3888 /* Don't allow operands to the compare to trap, as that can put the
3889 compare and branch in different basic blocks. */
3890 if (cfun->can_throw_non_call_exceptions)
3891 {
3892 if (may_trap_p (x))
3893 x = copy_to_reg (x);
3894 if (may_trap_p (y))
3895 y = copy_to_reg (y);
3896 }
3897
3898 if (GET_MODE_CLASS (mode) == MODE_CC)
3899 {
3900 enum insn_code icode = optab_handler (cbranch_optab, CCmode);
3901 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
3902 gcc_assert (icode != CODE_FOR_nothing
3903 && insn_operand_matches (icode, 0, test));
3904 *ptest = test;
3905 return;
3906 }
3907
3908 mclass = GET_MODE_CLASS (mode);
3909 test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
3910 FOR_EACH_MODE_FROM (cmp_mode, mode)
3911 {
3912 enum insn_code icode;
3913 icode = optab_handler (cbranch_optab, cmp_mode);
3914 if (icode != CODE_FOR_nothing
3915 && insn_operand_matches (icode, 0, test))
3916 {
3917 rtx_insn *last = get_last_insn ();
3918 rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp);
3919 rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp);
3920 if (op0 && op1
3921 && insn_operand_matches (icode, 1, op0)
3922 && insn_operand_matches (icode, 2, op1))
3923 {
3924 XEXP (test, 0) = op0;
3925 XEXP (test, 1) = op1;
3926 *ptest = test;
3927 *pmode = cmp_mode;
3928 return;
3929 }
3930 delete_insns_since (last);
3931 }
3932
3933 if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
3934 break;
3935 }
3936
3937 if (methods != OPTAB_LIB_WIDEN)
3938 goto fail;
3939
3940 if (SCALAR_FLOAT_MODE_P (mode))
3941 {
3942 /* Small trick if UNORDERED isn't implemented by the hardware. */
3943 if (comparison == UNORDERED && rtx_equal_p (x, y))
3944 {
3945 prepare_cmp_insn (x, y, UNLT, NULL_RTX, unsignedp, OPTAB_WIDEN,
3946 ptest, pmode);
3947 if (*ptest)
3948 return;
3949 }
3950
3951 prepare_float_lib_cmp (x, y, comparison, ptest, pmode);
3952 }
3953 else
3954 {
3955 rtx result;
3956 machine_mode ret_mode;
3957
3958 /* Handle a libcall just for the mode we are using. */
3959 libfunc = optab_libfunc (cmp_optab, mode);
3960 gcc_assert (libfunc);
3961
3962 /* If we want unsigned, and this mode has a distinct unsigned
3963 comparison routine, use that. */
3964 if (unsignedp)
3965 {
3966 rtx ulibfunc = optab_libfunc (ucmp_optab, mode);
3967 if (ulibfunc)
3968 libfunc = ulibfunc;
3969 }
3970
3971 ret_mode = targetm.libgcc_cmp_return_mode ();
3972 result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
3973 ret_mode, x, mode, y, mode);
3974
3975 /* There are two kinds of comparison routines. Biased routines
3976 return 0/1/2, and unbiased routines return -1/0/1. Other parts
3977 of gcc expect that the comparison operation is equivalent
3978 to the modified comparison. For signed comparisons compare the
3979 result against 1 in the biased case, and zero in the unbiased
3980 case. For unsigned comparisons always compare against 1 after
3981 biasing the unbiased result by adding 1. This gives us a way to
3982 represent LTU.
3983 The comparisons in the fixed-point helper library are always
3984 biased. */
3985 x = result;
3986 y = const1_rtx;
3987
3988 if (!TARGET_LIB_INT_CMP_BIASED && !ALL_FIXED_POINT_MODE_P (mode))
3989 {
3990 if (unsignedp)
3991 x = plus_constant (ret_mode, result, 1);
3992 else
3993 y = const0_rtx;
3994 }
3995
3996 *pmode = ret_mode;
3997 prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods,
3998 ptest, pmode);
3999 }
4000
4001 return;
4002
4003 fail:
4004 *ptest = NULL_RTX;
4005 }
4006
4007 /* Before emitting an insn with code ICODE, make sure that X, which is going
4008 to be used for operand OPNUM of the insn, is converted from mode MODE to
4009 WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
4010 that it is accepted by the operand predicate. Return the new value. */
4011
4012 rtx
prepare_operand(enum insn_code icode,rtx x,int opnum,machine_mode mode,machine_mode wider_mode,int unsignedp)4013 prepare_operand (enum insn_code icode, rtx x, int opnum, machine_mode mode,
4014 machine_mode wider_mode, int unsignedp)
4015 {
4016 if (mode != wider_mode)
4017 x = convert_modes (wider_mode, mode, x, unsignedp);
4018
4019 if (!insn_operand_matches (icode, opnum, x))
4020 {
4021 machine_mode op_mode = insn_data[(int) icode].operand[opnum].mode;
4022 if (reload_completed)
4023 return NULL_RTX;
4024 if (GET_MODE (x) != op_mode && GET_MODE (x) != VOIDmode)
4025 return NULL_RTX;
4026 x = copy_to_mode_reg (op_mode, x);
4027 }
4028
4029 return x;
4030 }
4031
4032 /* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
4033 we can do the branch. */
4034
4035 static void
emit_cmp_and_jump_insn_1(rtx test,machine_mode mode,rtx label,profile_probability prob)4036 emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
4037 profile_probability prob)
4038 {
4039 machine_mode optab_mode;
4040 enum mode_class mclass;
4041 enum insn_code icode;
4042 rtx_insn *insn;
4043
4044 mclass = GET_MODE_CLASS (mode);
4045 optab_mode = (mclass == MODE_CC) ? CCmode : mode;
4046 icode = optab_handler (cbranch_optab, optab_mode);
4047
4048 gcc_assert (icode != CODE_FOR_nothing);
4049 gcc_assert (insn_operand_matches (icode, 0, test));
4050 insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
4051 XEXP (test, 1), label));
4052 if (prob.initialized_p ()
4053 && profile_status_for_fn (cfun) != PROFILE_ABSENT
4054 && insn
4055 && JUMP_P (insn)
4056 && any_condjump_p (insn)
4057 && !find_reg_note (insn, REG_BR_PROB, 0))
4058 add_reg_br_prob_note (insn, prob);
4059 }
4060
4061 /* Generate code to compare X with Y so that the condition codes are
4062 set and to jump to LABEL if the condition is true. If X is a
4063 constant and Y is not a constant, then the comparison is swapped to
4064 ensure that the comparison RTL has the canonical form.
4065
4066 UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
4067 need to be widened. UNSIGNEDP is also used to select the proper
4068 branch condition code.
4069
4070 If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
4071
4072 MODE is the mode of the inputs (in case they are const_int).
4073
4074 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
4075 It will be potentially converted into an unsigned variant based on
4076 UNSIGNEDP to select a proper jump instruction.
4077
4078 PROB is the probability of jumping to LABEL. */
4079
4080 void
emit_cmp_and_jump_insns(rtx x,rtx y,enum rtx_code comparison,rtx size,machine_mode mode,int unsignedp,rtx label,profile_probability prob)4081 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
4082 machine_mode mode, int unsignedp, rtx label,
4083 profile_probability prob)
4084 {
4085 rtx op0 = x, op1 = y;
4086 rtx test;
4087
4088 /* Swap operands and condition to ensure canonical RTL. */
4089 if (swap_commutative_operands_p (x, y)
4090 && can_compare_p (swap_condition (comparison), mode, ccp_jump))
4091 {
4092 op0 = y, op1 = x;
4093 comparison = swap_condition (comparison);
4094 }
4095
4096 /* If OP0 is still a constant, then both X and Y must be constants
4097 or the opposite comparison is not supported. Force X into a register
4098 to create canonical RTL. */
4099 if (CONSTANT_P (op0))
4100 op0 = force_reg (mode, op0);
4101
4102 if (unsignedp)
4103 comparison = unsigned_condition (comparison);
4104
4105 prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
4106 &test, &mode);
4107 emit_cmp_and_jump_insn_1 (test, mode, label, prob);
4108 }
4109
4110
4111 /* Emit a library call comparison between floating point X and Y.
4112 COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
4113
4114 static void
prepare_float_lib_cmp(rtx x,rtx y,enum rtx_code comparison,rtx * ptest,machine_mode * pmode)4115 prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
4116 rtx *ptest, machine_mode *pmode)
4117 {
4118 enum rtx_code swapped = swap_condition (comparison);
4119 enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
4120 machine_mode orig_mode = GET_MODE (x);
4121 machine_mode mode;
4122 rtx true_rtx, false_rtx;
4123 rtx value, target, equiv;
4124 rtx_insn *insns;
4125 rtx libfunc = 0;
4126 bool reversed_p = false;
4127 scalar_int_mode cmp_mode = targetm.libgcc_cmp_return_mode ();
4128
4129 FOR_EACH_MODE_FROM (mode, orig_mode)
4130 {
4131 if (code_to_optab (comparison)
4132 && (libfunc = optab_libfunc (code_to_optab (comparison), mode)))
4133 break;
4134
4135 if (code_to_optab (swapped)
4136 && (libfunc = optab_libfunc (code_to_optab (swapped), mode)))
4137 {
4138 std::swap (x, y);
4139 comparison = swapped;
4140 break;
4141 }
4142
4143 if (code_to_optab (reversed)
4144 && (libfunc = optab_libfunc (code_to_optab (reversed), mode)))
4145 {
4146 comparison = reversed;
4147 reversed_p = true;
4148 break;
4149 }
4150 }
4151
4152 gcc_assert (mode != VOIDmode);
4153
4154 if (mode != orig_mode)
4155 {
4156 x = convert_to_mode (mode, x, 0);
4157 y = convert_to_mode (mode, y, 0);
4158 }
4159
4160 /* Attach a REG_EQUAL note describing the semantics of the libcall to
4161 the RTL. The allows the RTL optimizers to delete the libcall if the
4162 condition can be determined at compile-time. */
4163 if (comparison == UNORDERED
4164 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4165 {
4166 true_rtx = const_true_rtx;
4167 false_rtx = const0_rtx;
4168 }
4169 else
4170 {
4171 switch (comparison)
4172 {
4173 case EQ:
4174 true_rtx = const0_rtx;
4175 false_rtx = const_true_rtx;
4176 break;
4177
4178 case NE:
4179 true_rtx = const_true_rtx;
4180 false_rtx = const0_rtx;
4181 break;
4182
4183 case GT:
4184 true_rtx = const1_rtx;
4185 false_rtx = const0_rtx;
4186 break;
4187
4188 case GE:
4189 true_rtx = const0_rtx;
4190 false_rtx = constm1_rtx;
4191 break;
4192
4193 case LT:
4194 true_rtx = constm1_rtx;
4195 false_rtx = const0_rtx;
4196 break;
4197
4198 case LE:
4199 true_rtx = const0_rtx;
4200 false_rtx = const1_rtx;
4201 break;
4202
4203 default:
4204 gcc_unreachable ();
4205 }
4206 }
4207
4208 if (comparison == UNORDERED)
4209 {
4210 rtx temp = simplify_gen_relational (NE, cmp_mode, mode, x, x);
4211 equiv = simplify_gen_relational (NE, cmp_mode, mode, y, y);
4212 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4213 temp, const_true_rtx, equiv);
4214 }
4215 else
4216 {
4217 equiv = simplify_gen_relational (comparison, cmp_mode, mode, x, y);
4218 if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4219 equiv = simplify_gen_ternary (IF_THEN_ELSE, cmp_mode, cmp_mode,
4220 equiv, true_rtx, false_rtx);
4221 }
4222
4223 start_sequence ();
4224 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4225 cmp_mode, x, mode, y, mode);
4226 insns = get_insns ();
4227 end_sequence ();
4228
4229 target = gen_reg_rtx (cmp_mode);
4230 emit_libcall_block (insns, target, value, equiv);
4231
4232 if (comparison == UNORDERED
4233 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison)
4234 || reversed_p)
4235 *ptest = gen_rtx_fmt_ee (reversed_p ? EQ : NE, VOIDmode, target, false_rtx);
4236 else
4237 *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, target, const0_rtx);
4238
4239 *pmode = cmp_mode;
4240 }
4241
4242 /* Generate code to indirectly jump to a location given in the rtx LOC. */
4243
4244 void
emit_indirect_jump(rtx loc)4245 emit_indirect_jump (rtx loc)
4246 {
4247 if (!targetm.have_indirect_jump ())
4248 sorry ("indirect jumps are not available on this target");
4249 else
4250 {
4251 struct expand_operand ops[1];
4252 create_address_operand (&ops[0], loc);
4253 expand_jump_insn (targetm.code_for_indirect_jump, 1, ops);
4254 emit_barrier ();
4255 }
4256 }
4257
4258
4259 /* Emit a conditional move instruction if the machine supports one for that
4260 condition and machine mode.
4261
4262 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4263 the mode to use should they be constants. If it is VOIDmode, they cannot
4264 both be constants.
4265
4266 OP2 should be stored in TARGET if the comparison is true, otherwise OP3
4267 should be stored there. MODE is the mode to use should they be constants.
4268 If it is VOIDmode, they cannot both be constants.
4269
4270 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4271 is not supported. */
4272
4273 rtx
emit_conditional_move(rtx target,enum rtx_code code,rtx op0,rtx op1,machine_mode cmode,rtx op2,rtx op3,machine_mode mode,int unsignedp)4274 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
4275 machine_mode cmode, rtx op2, rtx op3,
4276 machine_mode mode, int unsignedp)
4277 {
4278 rtx comparison;
4279 rtx_insn *last;
4280 enum insn_code icode;
4281 enum rtx_code reversed;
4282
4283 /* If the two source operands are identical, that's just a move. */
4284
4285 if (rtx_equal_p (op2, op3))
4286 {
4287 if (!target)
4288 target = gen_reg_rtx (mode);
4289
4290 emit_move_insn (target, op3);
4291 return target;
4292 }
4293
4294 /* If one operand is constant, make it the second one. Only do this
4295 if the other operand is not constant as well. */
4296
4297 if (swap_commutative_operands_p (op0, op1))
4298 {
4299 std::swap (op0, op1);
4300 code = swap_condition (code);
4301 }
4302
4303 /* get_condition will prefer to generate LT and GT even if the old
4304 comparison was against zero, so undo that canonicalization here since
4305 comparisons against zero are cheaper. */
4306 if (code == LT && op1 == const1_rtx)
4307 code = LE, op1 = const0_rtx;
4308 else if (code == GT && op1 == constm1_rtx)
4309 code = GE, op1 = const0_rtx;
4310
4311 if (cmode == VOIDmode)
4312 cmode = GET_MODE (op0);
4313
4314 enum rtx_code orig_code = code;
4315 bool swapped = false;
4316 if (swap_commutative_operands_p (op2, op3)
4317 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
4318 != UNKNOWN))
4319 {
4320 std::swap (op2, op3);
4321 code = reversed;
4322 swapped = true;
4323 }
4324
4325 if (mode == VOIDmode)
4326 mode = GET_MODE (op2);
4327
4328 icode = direct_optab_handler (movcc_optab, mode);
4329
4330 if (icode == CODE_FOR_nothing)
4331 return NULL_RTX;
4332
4333 if (!target)
4334 target = gen_reg_rtx (mode);
4335
4336 for (int pass = 0; ; pass++)
4337 {
4338 code = unsignedp ? unsigned_condition (code) : code;
4339 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4340
4341 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4342 punt and let the caller figure out how best to deal with this
4343 situation. */
4344 if (COMPARISON_P (comparison))
4345 {
4346 saved_pending_stack_adjust save;
4347 save_pending_stack_adjust (&save);
4348 last = get_last_insn ();
4349 do_pending_stack_adjust ();
4350 machine_mode cmpmode = cmode;
4351 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4352 GET_CODE (comparison), NULL_RTX, unsignedp,
4353 OPTAB_WIDEN, &comparison, &cmpmode);
4354 if (comparison)
4355 {
4356 struct expand_operand ops[4];
4357
4358 create_output_operand (&ops[0], target, mode);
4359 create_fixed_operand (&ops[1], comparison);
4360 create_input_operand (&ops[2], op2, mode);
4361 create_input_operand (&ops[3], op3, mode);
4362 if (maybe_expand_insn (icode, 4, ops))
4363 {
4364 if (ops[0].value != target)
4365 convert_move (target, ops[0].value, false);
4366 return target;
4367 }
4368 }
4369 delete_insns_since (last);
4370 restore_pending_stack_adjust (&save);
4371 }
4372
4373 if (pass == 1)
4374 return NULL_RTX;
4375
4376 /* If the preferred op2/op3 order is not usable, retry with other
4377 operand order, perhaps it will expand successfully. */
4378 if (swapped)
4379 code = orig_code;
4380 else if ((reversed = reversed_comparison_code_parts (orig_code, op0, op1,
4381 NULL))
4382 != UNKNOWN)
4383 code = reversed;
4384 else
4385 return NULL_RTX;
4386 std::swap (op2, op3);
4387 }
4388 }
4389
4390
4391 /* Emit a conditional negate or bitwise complement using the
4392 negcc or notcc optabs if available. Return NULL_RTX if such operations
4393 are not available. Otherwise return the RTX holding the result.
4394 TARGET is the desired destination of the result. COMP is the comparison
4395 on which to negate. If COND is true move into TARGET the negation
4396 or bitwise complement of OP1. Otherwise move OP2 into TARGET.
4397 CODE is either NEG or NOT. MODE is the machine mode in which the
4398 operation is performed. */
4399
4400 rtx
emit_conditional_neg_or_complement(rtx target,rtx_code code,machine_mode mode,rtx cond,rtx op1,rtx op2)4401 emit_conditional_neg_or_complement (rtx target, rtx_code code,
4402 machine_mode mode, rtx cond, rtx op1,
4403 rtx op2)
4404 {
4405 optab op = unknown_optab;
4406 if (code == NEG)
4407 op = negcc_optab;
4408 else if (code == NOT)
4409 op = notcc_optab;
4410 else
4411 gcc_unreachable ();
4412
4413 insn_code icode = direct_optab_handler (op, mode);
4414
4415 if (icode == CODE_FOR_nothing)
4416 return NULL_RTX;
4417
4418 if (!target)
4419 target = gen_reg_rtx (mode);
4420
4421 rtx_insn *last = get_last_insn ();
4422 struct expand_operand ops[4];
4423
4424 create_output_operand (&ops[0], target, mode);
4425 create_fixed_operand (&ops[1], cond);
4426 create_input_operand (&ops[2], op1, mode);
4427 create_input_operand (&ops[3], op2, mode);
4428
4429 if (maybe_expand_insn (icode, 4, ops))
4430 {
4431 if (ops[0].value != target)
4432 convert_move (target, ops[0].value, false);
4433
4434 return target;
4435 }
4436 delete_insns_since (last);
4437 return NULL_RTX;
4438 }
4439
4440 /* Emit a conditional addition instruction if the machine supports one for that
4441 condition and machine mode.
4442
4443 OP0 and OP1 are the operands that should be compared using CODE. CMODE is
4444 the mode to use should they be constants. If it is VOIDmode, they cannot
4445 both be constants.
4446
4447 OP2 should be stored in TARGET if the comparison is false, otherwise OP2+OP3
4448 should be stored there. MODE is the mode to use should they be constants.
4449 If it is VOIDmode, they cannot both be constants.
4450
4451 The result is either TARGET (perhaps modified) or NULL_RTX if the operation
4452 is not supported. */
4453
4454 rtx
emit_conditional_add(rtx target,enum rtx_code code,rtx op0,rtx op1,machine_mode cmode,rtx op2,rtx op3,machine_mode mode,int unsignedp)4455 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
4456 machine_mode cmode, rtx op2, rtx op3,
4457 machine_mode mode, int unsignedp)
4458 {
4459 rtx comparison;
4460 rtx_insn *last;
4461 enum insn_code icode;
4462
4463 /* If one operand is constant, make it the second one. Only do this
4464 if the other operand is not constant as well. */
4465
4466 if (swap_commutative_operands_p (op0, op1))
4467 {
4468 std::swap (op0, op1);
4469 code = swap_condition (code);
4470 }
4471
4472 /* get_condition will prefer to generate LT and GT even if the old
4473 comparison was against zero, so undo that canonicalization here since
4474 comparisons against zero are cheaper. */
4475 if (code == LT && op1 == const1_rtx)
4476 code = LE, op1 = const0_rtx;
4477 else if (code == GT && op1 == constm1_rtx)
4478 code = GE, op1 = const0_rtx;
4479
4480 if (cmode == VOIDmode)
4481 cmode = GET_MODE (op0);
4482
4483 if (mode == VOIDmode)
4484 mode = GET_MODE (op2);
4485
4486 icode = optab_handler (addcc_optab, mode);
4487
4488 if (icode == CODE_FOR_nothing)
4489 return 0;
4490
4491 if (!target)
4492 target = gen_reg_rtx (mode);
4493
4494 code = unsignedp ? unsigned_condition (code) : code;
4495 comparison = simplify_gen_relational (code, VOIDmode, cmode, op0, op1);
4496
4497 /* We can get const0_rtx or const_true_rtx in some circumstances. Just
4498 return NULL and let the caller figure out how best to deal with this
4499 situation. */
4500 if (!COMPARISON_P (comparison))
4501 return NULL_RTX;
4502
4503 do_pending_stack_adjust ();
4504 last = get_last_insn ();
4505 prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
4506 GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
4507 &comparison, &cmode);
4508 if (comparison)
4509 {
4510 struct expand_operand ops[4];
4511
4512 create_output_operand (&ops[0], target, mode);
4513 create_fixed_operand (&ops[1], comparison);
4514 create_input_operand (&ops[2], op2, mode);
4515 create_input_operand (&ops[3], op3, mode);
4516 if (maybe_expand_insn (icode, 4, ops))
4517 {
4518 if (ops[0].value != target)
4519 convert_move (target, ops[0].value, false);
4520 return target;
4521 }
4522 }
4523 delete_insns_since (last);
4524 return NULL_RTX;
4525 }
4526
4527 /* These functions attempt to generate an insn body, rather than
4528 emitting the insn, but if the gen function already emits them, we
4529 make no attempt to turn them back into naked patterns. */
4530
4531 /* Generate and return an insn body to add Y to X. */
4532
4533 rtx_insn *
gen_add2_insn(rtx x,rtx y)4534 gen_add2_insn (rtx x, rtx y)
4535 {
4536 enum insn_code icode = optab_handler (add_optab, GET_MODE (x));
4537
4538 gcc_assert (insn_operand_matches (icode, 0, x));
4539 gcc_assert (insn_operand_matches (icode, 1, x));
4540 gcc_assert (insn_operand_matches (icode, 2, y));
4541
4542 return GEN_FCN (icode) (x, x, y);
4543 }
4544
4545 /* Generate and return an insn body to add r1 and c,
4546 storing the result in r0. */
4547
4548 rtx_insn *
gen_add3_insn(rtx r0,rtx r1,rtx c)4549 gen_add3_insn (rtx r0, rtx r1, rtx c)
4550 {
4551 enum insn_code icode = optab_handler (add_optab, GET_MODE (r0));
4552
4553 if (icode == CODE_FOR_nothing
4554 || !insn_operand_matches (icode, 0, r0)
4555 || !insn_operand_matches (icode, 1, r1)
4556 || !insn_operand_matches (icode, 2, c))
4557 return NULL;
4558
4559 return GEN_FCN (icode) (r0, r1, c);
4560 }
4561
4562 int
have_add2_insn(rtx x,rtx y)4563 have_add2_insn (rtx x, rtx y)
4564 {
4565 enum insn_code icode;
4566
4567 gcc_assert (GET_MODE (x) != VOIDmode);
4568
4569 icode = optab_handler (add_optab, GET_MODE (x));
4570
4571 if (icode == CODE_FOR_nothing)
4572 return 0;
4573
4574 if (!insn_operand_matches (icode, 0, x)
4575 || !insn_operand_matches (icode, 1, x)
4576 || !insn_operand_matches (icode, 2, y))
4577 return 0;
4578
4579 return 1;
4580 }
4581
4582 /* Generate and return an insn body to add Y to X. */
4583
4584 rtx_insn *
gen_addptr3_insn(rtx x,rtx y,rtx z)4585 gen_addptr3_insn (rtx x, rtx y, rtx z)
4586 {
4587 enum insn_code icode = optab_handler (addptr3_optab, GET_MODE (x));
4588
4589 gcc_assert (insn_operand_matches (icode, 0, x));
4590 gcc_assert (insn_operand_matches (icode, 1, y));
4591 gcc_assert (insn_operand_matches (icode, 2, z));
4592
4593 return GEN_FCN (icode) (x, y, z);
4594 }
4595
4596 /* Return true if the target implements an addptr pattern and X, Y,
4597 and Z are valid for the pattern predicates. */
4598
4599 int
have_addptr3_insn(rtx x,rtx y,rtx z)4600 have_addptr3_insn (rtx x, rtx y, rtx z)
4601 {
4602 enum insn_code icode;
4603
4604 gcc_assert (GET_MODE (x) != VOIDmode);
4605
4606 icode = optab_handler (addptr3_optab, GET_MODE (x));
4607
4608 if (icode == CODE_FOR_nothing)
4609 return 0;
4610
4611 if (!insn_operand_matches (icode, 0, x)
4612 || !insn_operand_matches (icode, 1, y)
4613 || !insn_operand_matches (icode, 2, z))
4614 return 0;
4615
4616 return 1;
4617 }
4618
4619 /* Generate and return an insn body to subtract Y from X. */
4620
4621 rtx_insn *
gen_sub2_insn(rtx x,rtx y)4622 gen_sub2_insn (rtx x, rtx y)
4623 {
4624 enum insn_code icode = optab_handler (sub_optab, GET_MODE (x));
4625
4626 gcc_assert (insn_operand_matches (icode, 0, x));
4627 gcc_assert (insn_operand_matches (icode, 1, x));
4628 gcc_assert (insn_operand_matches (icode, 2, y));
4629
4630 return GEN_FCN (icode) (x, x, y);
4631 }
4632
4633 /* Generate and return an insn body to subtract r1 and c,
4634 storing the result in r0. */
4635
4636 rtx_insn *
gen_sub3_insn(rtx r0,rtx r1,rtx c)4637 gen_sub3_insn (rtx r0, rtx r1, rtx c)
4638 {
4639 enum insn_code icode = optab_handler (sub_optab, GET_MODE (r0));
4640
4641 if (icode == CODE_FOR_nothing
4642 || !insn_operand_matches (icode, 0, r0)
4643 || !insn_operand_matches (icode, 1, r1)
4644 || !insn_operand_matches (icode, 2, c))
4645 return NULL;
4646
4647 return GEN_FCN (icode) (r0, r1, c);
4648 }
4649
4650 int
have_sub2_insn(rtx x,rtx y)4651 have_sub2_insn (rtx x, rtx y)
4652 {
4653 enum insn_code icode;
4654
4655 gcc_assert (GET_MODE (x) != VOIDmode);
4656
4657 icode = optab_handler (sub_optab, GET_MODE (x));
4658
4659 if (icode == CODE_FOR_nothing)
4660 return 0;
4661
4662 if (!insn_operand_matches (icode, 0, x)
4663 || !insn_operand_matches (icode, 1, x)
4664 || !insn_operand_matches (icode, 2, y))
4665 return 0;
4666
4667 return 1;
4668 }
4669
4670 /* Generate the body of an insn to extend Y (with mode MFROM)
4671 into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
4672
4673 rtx_insn *
gen_extend_insn(rtx x,rtx y,machine_mode mto,machine_mode mfrom,int unsignedp)4674 gen_extend_insn (rtx x, rtx y, machine_mode mto,
4675 machine_mode mfrom, int unsignedp)
4676 {
4677 enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
4678 return GEN_FCN (icode) (x, y);
4679 }
4680
4681 /* Generate code to convert FROM to floating point
4682 and store in TO. FROM must be fixed point and not VOIDmode.
4683 UNSIGNEDP nonzero means regard FROM as unsigned.
4684 Normally this is done by correcting the final value
4685 if it is negative. */
4686
4687 void
expand_float(rtx to,rtx from,int unsignedp)4688 expand_float (rtx to, rtx from, int unsignedp)
4689 {
4690 enum insn_code icode;
4691 rtx target = to;
4692 scalar_mode from_mode, to_mode;
4693 machine_mode fmode, imode;
4694 bool can_do_signed = false;
4695
4696 /* Crash now, because we won't be able to decide which mode to use. */
4697 gcc_assert (GET_MODE (from) != VOIDmode);
4698
4699 /* Look for an insn to do the conversion. Do it in the specified
4700 modes if possible; otherwise convert either input, output or both to
4701 wider mode. If the integer mode is wider than the mode of FROM,
4702 we can do the conversion signed even if the input is unsigned. */
4703
4704 FOR_EACH_MODE_FROM (fmode, GET_MODE (to))
4705 FOR_EACH_MODE_FROM (imode, GET_MODE (from))
4706 {
4707 int doing_unsigned = unsignedp;
4708
4709 if (fmode != GET_MODE (to)
4710 && (significand_size (fmode)
4711 < GET_MODE_UNIT_PRECISION (GET_MODE (from))))
4712 continue;
4713
4714 icode = can_float_p (fmode, imode, unsignedp);
4715 if (icode == CODE_FOR_nothing && unsignedp)
4716 {
4717 enum insn_code scode = can_float_p (fmode, imode, 0);
4718 if (scode != CODE_FOR_nothing)
4719 can_do_signed = true;
4720 if (imode != GET_MODE (from))
4721 icode = scode, doing_unsigned = 0;
4722 }
4723
4724 if (icode != CODE_FOR_nothing)
4725 {
4726 if (imode != GET_MODE (from))
4727 from = convert_to_mode (imode, from, unsignedp);
4728
4729 if (fmode != GET_MODE (to))
4730 target = gen_reg_rtx (fmode);
4731
4732 emit_unop_insn (icode, target, from,
4733 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
4734
4735 if (target != to)
4736 convert_move (to, target, 0);
4737 return;
4738 }
4739 }
4740
4741 /* Unsigned integer, and no way to convert directly. Convert as signed,
4742 then unconditionally adjust the result. */
4743 if (unsignedp
4744 && can_do_signed
4745 && is_a <scalar_mode> (GET_MODE (to), &to_mode)
4746 && is_a <scalar_mode> (GET_MODE (from), &from_mode))
4747 {
4748 opt_scalar_mode fmode_iter;
4749 rtx_code_label *label = gen_label_rtx ();
4750 rtx temp;
4751 REAL_VALUE_TYPE offset;
4752
4753 /* Look for a usable floating mode FMODE wider than the source and at
4754 least as wide as the target. Using FMODE will avoid rounding woes
4755 with unsigned values greater than the signed maximum value. */
4756
4757 FOR_EACH_MODE_FROM (fmode_iter, to_mode)
4758 {
4759 scalar_mode fmode = fmode_iter.require ();
4760 if (GET_MODE_PRECISION (from_mode) < GET_MODE_BITSIZE (fmode)
4761 && can_float_p (fmode, from_mode, 0) != CODE_FOR_nothing)
4762 break;
4763 }
4764
4765 if (!fmode_iter.exists (&fmode))
4766 {
4767 /* There is no such mode. Pretend the target is wide enough. */
4768 fmode = to_mode;
4769
4770 /* Avoid double-rounding when TO is narrower than FROM. */
4771 if ((significand_size (fmode) + 1)
4772 < GET_MODE_PRECISION (from_mode))
4773 {
4774 rtx temp1;
4775 rtx_code_label *neglabel = gen_label_rtx ();
4776
4777 /* Don't use TARGET if it isn't a register, is a hard register,
4778 or is the wrong mode. */
4779 if (!REG_P (target)
4780 || REGNO (target) < FIRST_PSEUDO_REGISTER
4781 || GET_MODE (target) != fmode)
4782 target = gen_reg_rtx (fmode);
4783
4784 imode = from_mode;
4785 do_pending_stack_adjust ();
4786
4787 /* Test whether the sign bit is set. */
4788 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
4789 0, neglabel);
4790
4791 /* The sign bit is not set. Convert as signed. */
4792 expand_float (target, from, 0);
4793 emit_jump_insn (targetm.gen_jump (label));
4794 emit_barrier ();
4795
4796 /* The sign bit is set.
4797 Convert to a usable (positive signed) value by shifting right
4798 one bit, while remembering if a nonzero bit was shifted
4799 out; i.e., compute (from & 1) | (from >> 1). */
4800
4801 emit_label (neglabel);
4802 temp = expand_binop (imode, and_optab, from, const1_rtx,
4803 NULL_RTX, 1, OPTAB_LIB_WIDEN);
4804 temp1 = expand_shift (RSHIFT_EXPR, imode, from, 1, NULL_RTX, 1);
4805 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
4806 OPTAB_LIB_WIDEN);
4807 expand_float (target, temp, 0);
4808
4809 /* Multiply by 2 to undo the shift above. */
4810 temp = expand_binop (fmode, add_optab, target, target,
4811 target, 0, OPTAB_LIB_WIDEN);
4812 if (temp != target)
4813 emit_move_insn (target, temp);
4814
4815 do_pending_stack_adjust ();
4816 emit_label (label);
4817 goto done;
4818 }
4819 }
4820
4821 /* If we are about to do some arithmetic to correct for an
4822 unsigned operand, do it in a pseudo-register. */
4823
4824 if (to_mode != fmode
4825 || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
4826 target = gen_reg_rtx (fmode);
4827
4828 /* Convert as signed integer to floating. */
4829 expand_float (target, from, 0);
4830
4831 /* If FROM is negative (and therefore TO is negative),
4832 correct its value by 2**bitwidth. */
4833
4834 do_pending_stack_adjust ();
4835 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, from_mode,
4836 0, label);
4837
4838
4839 real_2expN (&offset, GET_MODE_PRECISION (from_mode), fmode);
4840 temp = expand_binop (fmode, add_optab, target,
4841 const_double_from_real_value (offset, fmode),
4842 target, 0, OPTAB_LIB_WIDEN);
4843 if (temp != target)
4844 emit_move_insn (target, temp);
4845
4846 do_pending_stack_adjust ();
4847 emit_label (label);
4848 goto done;
4849 }
4850
4851 /* No hardware instruction available; call a library routine. */
4852 {
4853 rtx libfunc;
4854 rtx_insn *insns;
4855 rtx value;
4856 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
4857
4858 if (is_narrower_int_mode (GET_MODE (from), SImode))
4859 from = convert_to_mode (SImode, from, unsignedp);
4860
4861 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
4862 gcc_assert (libfunc);
4863
4864 start_sequence ();
4865
4866 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4867 GET_MODE (to), from, GET_MODE (from));
4868 insns = get_insns ();
4869 end_sequence ();
4870
4871 emit_libcall_block (insns, target, value,
4872 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FLOAT : FLOAT,
4873 GET_MODE (to), from));
4874 }
4875
4876 done:
4877
4878 /* Copy result to requested destination
4879 if we have been computing in a temp location. */
4880
4881 if (target != to)
4882 {
4883 if (GET_MODE (target) == GET_MODE (to))
4884 emit_move_insn (to, target);
4885 else
4886 convert_move (to, target, 0);
4887 }
4888 }
4889
4890 /* Generate code to convert FROM to fixed point and store in TO. FROM
4891 must be floating point. */
4892
4893 void
expand_fix(rtx to,rtx from,int unsignedp)4894 expand_fix (rtx to, rtx from, int unsignedp)
4895 {
4896 enum insn_code icode;
4897 rtx target = to;
4898 machine_mode fmode, imode;
4899 opt_scalar_mode fmode_iter;
4900 bool must_trunc = false;
4901
4902 /* We first try to find a pair of modes, one real and one integer, at
4903 least as wide as FROM and TO, respectively, in which we can open-code
4904 this conversion. If the integer mode is wider than the mode of TO,
4905 we can do the conversion either signed or unsigned. */
4906
4907 FOR_EACH_MODE_FROM (fmode, GET_MODE (from))
4908 FOR_EACH_MODE_FROM (imode, GET_MODE (to))
4909 {
4910 int doing_unsigned = unsignedp;
4911
4912 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
4913 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
4914 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
4915
4916 if (icode != CODE_FOR_nothing)
4917 {
4918 rtx_insn *last = get_last_insn ();
4919 if (fmode != GET_MODE (from))
4920 from = convert_to_mode (fmode, from, 0);
4921
4922 if (must_trunc)
4923 {
4924 rtx temp = gen_reg_rtx (GET_MODE (from));
4925 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
4926 temp, 0);
4927 }
4928
4929 if (imode != GET_MODE (to))
4930 target = gen_reg_rtx (imode);
4931
4932 if (maybe_emit_unop_insn (icode, target, from,
4933 doing_unsigned ? UNSIGNED_FIX : FIX))
4934 {
4935 if (target != to)
4936 convert_move (to, target, unsignedp);
4937 return;
4938 }
4939 delete_insns_since (last);
4940 }
4941 }
4942
4943 /* For an unsigned conversion, there is one more way to do it.
4944 If we have a signed conversion, we generate code that compares
4945 the real value to the largest representable positive number. If if
4946 is smaller, the conversion is done normally. Otherwise, subtract
4947 one plus the highest signed number, convert, and add it back.
4948
4949 We only need to check all real modes, since we know we didn't find
4950 anything with a wider integer mode.
4951
4952 This code used to extend FP value into mode wider than the destination.
4953 This is needed for decimal float modes which cannot accurately
4954 represent one plus the highest signed number of the same size, but
4955 not for binary modes. Consider, for instance conversion from SFmode
4956 into DImode.
4957
4958 The hot path through the code is dealing with inputs smaller than 2^63
4959 and doing just the conversion, so there is no bits to lose.
4960
4961 In the other path we know the value is positive in the range 2^63..2^64-1
4962 inclusive. (as for other input overflow happens and result is undefined)
4963 So we know that the most important bit set in mantissa corresponds to
4964 2^63. The subtraction of 2^63 should not generate any rounding as it
4965 simply clears out that bit. The rest is trivial. */
4966
4967 scalar_int_mode to_mode;
4968 if (unsignedp
4969 && is_a <scalar_int_mode> (GET_MODE (to), &to_mode)
4970 && HWI_COMPUTABLE_MODE_P (to_mode))
4971 FOR_EACH_MODE_FROM (fmode_iter, as_a <scalar_mode> (GET_MODE (from)))
4972 {
4973 scalar_mode fmode = fmode_iter.require ();
4974 if (CODE_FOR_nothing != can_fix_p (to_mode, fmode,
4975 0, &must_trunc)
4976 && (!DECIMAL_FLOAT_MODE_P (fmode)
4977 || (GET_MODE_BITSIZE (fmode) > GET_MODE_PRECISION (to_mode))))
4978 {
4979 int bitsize;
4980 REAL_VALUE_TYPE offset;
4981 rtx limit;
4982 rtx_code_label *lab1, *lab2;
4983 rtx_insn *insn;
4984
4985 bitsize = GET_MODE_PRECISION (to_mode);
4986 real_2expN (&offset, bitsize - 1, fmode);
4987 limit = const_double_from_real_value (offset, fmode);
4988 lab1 = gen_label_rtx ();
4989 lab2 = gen_label_rtx ();
4990
4991 if (fmode != GET_MODE (from))
4992 from = convert_to_mode (fmode, from, 0);
4993
4994 /* See if we need to do the subtraction. */
4995 do_pending_stack_adjust ();
4996 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX,
4997 GET_MODE (from), 0, lab1);
4998
4999 /* If not, do the signed "fix" and branch around fixup code. */
5000 expand_fix (to, from, 0);
5001 emit_jump_insn (targetm.gen_jump (lab2));
5002 emit_barrier ();
5003
5004 /* Otherwise, subtract 2**(N-1), convert to signed number,
5005 then add 2**(N-1). Do the addition using XOR since this
5006 will often generate better code. */
5007 emit_label (lab1);
5008 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
5009 NULL_RTX, 0, OPTAB_LIB_WIDEN);
5010 expand_fix (to, target, 0);
5011 target = expand_binop (to_mode, xor_optab, to,
5012 gen_int_mode
5013 (HOST_WIDE_INT_1 << (bitsize - 1),
5014 to_mode),
5015 to, 1, OPTAB_LIB_WIDEN);
5016
5017 if (target != to)
5018 emit_move_insn (to, target);
5019
5020 emit_label (lab2);
5021
5022 if (optab_handler (mov_optab, to_mode) != CODE_FOR_nothing)
5023 {
5024 /* Make a place for a REG_NOTE and add it. */
5025 insn = emit_move_insn (to, to);
5026 set_dst_reg_note (insn, REG_EQUAL,
5027 gen_rtx_fmt_e (UNSIGNED_FIX, to_mode,
5028 copy_rtx (from)),
5029 to);
5030 }
5031
5032 return;
5033 }
5034 }
5035
5036 /* We can't do it with an insn, so use a library call. But first ensure
5037 that the mode of TO is at least as wide as SImode, since those are the
5038 only library calls we know about. */
5039
5040 if (is_narrower_int_mode (GET_MODE (to), SImode))
5041 {
5042 target = gen_reg_rtx (SImode);
5043
5044 expand_fix (target, from, unsignedp);
5045 }
5046 else
5047 {
5048 rtx_insn *insns;
5049 rtx value;
5050 rtx libfunc;
5051
5052 convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
5053 libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
5054 gcc_assert (libfunc);
5055
5056 start_sequence ();
5057
5058 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
5059 GET_MODE (to), from, GET_MODE (from));
5060 insns = get_insns ();
5061 end_sequence ();
5062
5063 emit_libcall_block (insns, target, value,
5064 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
5065 GET_MODE (to), from));
5066 }
5067
5068 if (target != to)
5069 {
5070 if (GET_MODE (to) == GET_MODE (target))
5071 emit_move_insn (to, target);
5072 else
5073 convert_move (to, target, 0);
5074 }
5075 }
5076
5077
5078 /* Promote integer arguments for a libcall if necessary.
5079 emit_library_call_value cannot do the promotion because it does not
5080 know if it should do a signed or unsigned promotion. This is because
5081 there are no tree types defined for libcalls. */
5082
5083 static rtx
prepare_libcall_arg(rtx arg,int uintp)5084 prepare_libcall_arg (rtx arg, int uintp)
5085 {
5086 scalar_int_mode mode;
5087 machine_mode arg_mode;
5088 if (is_a <scalar_int_mode> (GET_MODE (arg), &mode))
5089 {
5090 /* If we need to promote the integer function argument we need to do
5091 it here instead of inside emit_library_call_value because in
5092 emit_library_call_value we don't know if we should do a signed or
5093 unsigned promotion. */
5094
5095 int unsigned_p = 0;
5096 arg_mode = promote_function_mode (NULL_TREE, mode,
5097 &unsigned_p, NULL_TREE, 0);
5098 if (arg_mode != mode)
5099 return convert_to_mode (arg_mode, arg, uintp);
5100 }
5101 return arg;
5102 }
5103
5104 /* Generate code to convert FROM or TO a fixed-point.
5105 If UINTP is true, either TO or FROM is an unsigned integer.
5106 If SATP is true, we need to saturate the result. */
5107
5108 void
expand_fixed_convert(rtx to,rtx from,int uintp,int satp)5109 expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
5110 {
5111 machine_mode to_mode = GET_MODE (to);
5112 machine_mode from_mode = GET_MODE (from);
5113 convert_optab tab;
5114 enum rtx_code this_code;
5115 enum insn_code code;
5116 rtx_insn *insns;
5117 rtx value;
5118 rtx libfunc;
5119
5120 if (to_mode == from_mode)
5121 {
5122 emit_move_insn (to, from);
5123 return;
5124 }
5125
5126 if (uintp)
5127 {
5128 tab = satp ? satfractuns_optab : fractuns_optab;
5129 this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
5130 }
5131 else
5132 {
5133 tab = satp ? satfract_optab : fract_optab;
5134 this_code = satp ? SAT_FRACT : FRACT_CONVERT;
5135 }
5136 code = convert_optab_handler (tab, to_mode, from_mode);
5137 if (code != CODE_FOR_nothing)
5138 {
5139 emit_unop_insn (code, to, from, this_code);
5140 return;
5141 }
5142
5143 libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
5144 gcc_assert (libfunc);
5145
5146 from = prepare_libcall_arg (from, uintp);
5147 from_mode = GET_MODE (from);
5148
5149 start_sequence ();
5150 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
5151 from, from_mode);
5152 insns = get_insns ();
5153 end_sequence ();
5154
5155 emit_libcall_block (insns, to, value,
5156 gen_rtx_fmt_e (optab_to_code (tab), to_mode, from));
5157 }
5158
5159 /* Generate code to convert FROM to fixed point and store in TO. FROM
5160 must be floating point, TO must be signed. Use the conversion optab
5161 TAB to do the conversion. */
5162
5163 bool
expand_sfix_optab(rtx to,rtx from,convert_optab tab)5164 expand_sfix_optab (rtx to, rtx from, convert_optab tab)
5165 {
5166 enum insn_code icode;
5167 rtx target = to;
5168 machine_mode fmode, imode;
5169
5170 /* We first try to find a pair of modes, one real and one integer, at
5171 least as wide as FROM and TO, respectively, in which we can open-code
5172 this conversion. If the integer mode is wider than the mode of TO,
5173 we can do the conversion either signed or unsigned. */
5174
5175 FOR_EACH_MODE_FROM (fmode, GET_MODE (from))
5176 FOR_EACH_MODE_FROM (imode, GET_MODE (to))
5177 {
5178 icode = convert_optab_handler (tab, imode, fmode);
5179 if (icode != CODE_FOR_nothing)
5180 {
5181 rtx_insn *last = get_last_insn ();
5182 if (fmode != GET_MODE (from))
5183 from = convert_to_mode (fmode, from, 0);
5184
5185 if (imode != GET_MODE (to))
5186 target = gen_reg_rtx (imode);
5187
5188 if (!maybe_emit_unop_insn (icode, target, from, UNKNOWN))
5189 {
5190 delete_insns_since (last);
5191 continue;
5192 }
5193 if (target != to)
5194 convert_move (to, target, 0);
5195 return true;
5196 }
5197 }
5198
5199 return false;
5200 }
5201
5202 /* Report whether we have an instruction to perform the operation
5203 specified by CODE on operands of mode MODE. */
5204 int
have_insn_for(enum rtx_code code,machine_mode mode)5205 have_insn_for (enum rtx_code code, machine_mode mode)
5206 {
5207 return (code_to_optab (code)
5208 && (optab_handler (code_to_optab (code), mode)
5209 != CODE_FOR_nothing));
5210 }
5211
5212 /* Print information about the current contents of the optabs on
5213 STDERR. */
5214
5215 DEBUG_FUNCTION void
debug_optab_libfuncs(void)5216 debug_optab_libfuncs (void)
5217 {
5218 int i, j, k;
5219
5220 /* Dump the arithmetic optabs. */
5221 for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i)
5222 for (j = 0; j < NUM_MACHINE_MODES; ++j)
5223 {
5224 rtx l = optab_libfunc ((optab) i, (machine_mode) j);
5225 if (l)
5226 {
5227 gcc_assert (GET_CODE (l) == SYMBOL_REF);
5228 fprintf (stderr, "%s\t%s:\t%s\n",
5229 GET_RTX_NAME (optab_to_code ((optab) i)),
5230 GET_MODE_NAME (j),
5231 XSTR (l, 0));
5232 }
5233 }
5234
5235 /* Dump the conversion optabs. */
5236 for (i = FIRST_CONV_OPTAB; i <= LAST_CONVLIB_OPTAB; ++i)
5237 for (j = 0; j < NUM_MACHINE_MODES; ++j)
5238 for (k = 0; k < NUM_MACHINE_MODES; ++k)
5239 {
5240 rtx l = convert_optab_libfunc ((optab) i, (machine_mode) j,
5241 (machine_mode) k);
5242 if (l)
5243 {
5244 gcc_assert (GET_CODE (l) == SYMBOL_REF);
5245 fprintf (stderr, "%s\t%s\t%s:\t%s\n",
5246 GET_RTX_NAME (optab_to_code ((optab) i)),
5247 GET_MODE_NAME (j),
5248 GET_MODE_NAME (k),
5249 XSTR (l, 0));
5250 }
5251 }
5252 }
5253
5254 /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
5255 CODE. Return 0 on failure. */
5256
5257 rtx_insn *
gen_cond_trap(enum rtx_code code,rtx op1,rtx op2,rtx tcode)5258 gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
5259 {
5260 machine_mode mode = GET_MODE (op1);
5261 enum insn_code icode;
5262 rtx_insn *insn;
5263 rtx trap_rtx;
5264
5265 if (mode == VOIDmode)
5266 return 0;
5267
5268 icode = optab_handler (ctrap_optab, mode);
5269 if (icode == CODE_FOR_nothing)
5270 return 0;
5271
5272 /* Some targets only accept a zero trap code. */
5273 if (!insn_operand_matches (icode, 3, tcode))
5274 return 0;
5275
5276 do_pending_stack_adjust ();
5277 start_sequence ();
5278 prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
5279 &trap_rtx, &mode);
5280 if (!trap_rtx)
5281 insn = NULL;
5282 else
5283 insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
5284 tcode);
5285
5286 /* If that failed, then give up. */
5287 if (insn == 0)
5288 {
5289 end_sequence ();
5290 return 0;
5291 }
5292
5293 emit_insn (insn);
5294 insn = get_insns ();
5295 end_sequence ();
5296 return insn;
5297 }
5298
5299 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
5300 or unsigned operation code. */
5301
5302 enum rtx_code
get_rtx_code(enum tree_code tcode,bool unsignedp)5303 get_rtx_code (enum tree_code tcode, bool unsignedp)
5304 {
5305 enum rtx_code code;
5306 switch (tcode)
5307 {
5308 case EQ_EXPR:
5309 code = EQ;
5310 break;
5311 case NE_EXPR:
5312 code = NE;
5313 break;
5314 case LT_EXPR:
5315 code = unsignedp ? LTU : LT;
5316 break;
5317 case LE_EXPR:
5318 code = unsignedp ? LEU : LE;
5319 break;
5320 case GT_EXPR:
5321 code = unsignedp ? GTU : GT;
5322 break;
5323 case GE_EXPR:
5324 code = unsignedp ? GEU : GE;
5325 break;
5326
5327 case UNORDERED_EXPR:
5328 code = UNORDERED;
5329 break;
5330 case ORDERED_EXPR:
5331 code = ORDERED;
5332 break;
5333 case UNLT_EXPR:
5334 code = UNLT;
5335 break;
5336 case UNLE_EXPR:
5337 code = UNLE;
5338 break;
5339 case UNGT_EXPR:
5340 code = UNGT;
5341 break;
5342 case UNGE_EXPR:
5343 code = UNGE;
5344 break;
5345 case UNEQ_EXPR:
5346 code = UNEQ;
5347 break;
5348 case LTGT_EXPR:
5349 code = LTGT;
5350 break;
5351
5352 case BIT_AND_EXPR:
5353 code = AND;
5354 break;
5355
5356 case BIT_IOR_EXPR:
5357 code = IOR;
5358 break;
5359
5360 default:
5361 gcc_unreachable ();
5362 }
5363 return code;
5364 }
5365
5366 /* Return a comparison rtx of mode CMP_MODE for COND. Use UNSIGNEDP to
5367 select signed or unsigned operators. OPNO holds the index of the
5368 first comparison operand for insn ICODE. Do not generate the
5369 compare instruction itself. */
5370
5371 static rtx
vector_compare_rtx(machine_mode cmp_mode,enum tree_code tcode,tree t_op0,tree t_op1,bool unsignedp,enum insn_code icode,unsigned int opno)5372 vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
5373 tree t_op0, tree t_op1, bool unsignedp,
5374 enum insn_code icode, unsigned int opno)
5375 {
5376 struct expand_operand ops[2];
5377 rtx rtx_op0, rtx_op1;
5378 machine_mode m0, m1;
5379 enum rtx_code rcode = get_rtx_code (tcode, unsignedp);
5380
5381 gcc_assert (TREE_CODE_CLASS (tcode) == tcc_comparison);
5382
5383 /* Expand operands. For vector types with scalar modes, e.g. where int64x1_t
5384 has mode DImode, this can produce a constant RTX of mode VOIDmode; in such
5385 cases, use the original mode. */
5386 rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
5387 EXPAND_STACK_PARM);
5388 m0 = GET_MODE (rtx_op0);
5389 if (m0 == VOIDmode)
5390 m0 = TYPE_MODE (TREE_TYPE (t_op0));
5391
5392 rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
5393 EXPAND_STACK_PARM);
5394 m1 = GET_MODE (rtx_op1);
5395 if (m1 == VOIDmode)
5396 m1 = TYPE_MODE (TREE_TYPE (t_op1));
5397
5398 create_input_operand (&ops[0], rtx_op0, m0);
5399 create_input_operand (&ops[1], rtx_op1, m1);
5400 if (!maybe_legitimize_operands (icode, opno, 2, ops))
5401 gcc_unreachable ();
5402 return gen_rtx_fmt_ee (rcode, cmp_mode, ops[0].value, ops[1].value);
5403 }
5404
5405 /* Check if vec_perm mask SEL is a constant equivalent to a shift of
5406 the first vec_perm operand, assuming the second operand is a constant
5407 vector of zeros. Return the shift distance in bits if so, or NULL_RTX
5408 if the vec_perm is not a shift. MODE is the mode of the value being
5409 shifted. */
5410 static rtx
shift_amt_for_vec_perm_mask(machine_mode mode,const vec_perm_indices & sel)5411 shift_amt_for_vec_perm_mask (machine_mode mode, const vec_perm_indices &sel)
5412 {
5413 unsigned int bitsize = GET_MODE_UNIT_BITSIZE (mode);
5414 poly_int64 first = sel[0];
5415 if (maybe_ge (sel[0], GET_MODE_NUNITS (mode)))
5416 return NULL_RTX;
5417
5418 if (!sel.series_p (0, 1, first, 1))
5419 {
5420 unsigned int nelt;
5421 if (!GET_MODE_NUNITS (mode).is_constant (&nelt))
5422 return NULL_RTX;
5423 for (unsigned int i = 1; i < nelt; i++)
5424 {
5425 poly_int64 expected = i + first;
5426 /* Indices into the second vector are all equivalent. */
5427 if (maybe_lt (sel[i], nelt)
5428 ? maybe_ne (sel[i], expected)
5429 : maybe_lt (expected, nelt))
5430 return NULL_RTX;
5431 }
5432 }
5433
5434 return gen_int_shift_amount (mode, first * bitsize);
5435 }
5436
5437 /* A subroutine of expand_vec_perm_var for expanding one vec_perm insn. */
5438
5439 static rtx
expand_vec_perm_1(enum insn_code icode,rtx target,rtx v0,rtx v1,rtx sel)5440 expand_vec_perm_1 (enum insn_code icode, rtx target,
5441 rtx v0, rtx v1, rtx sel)
5442 {
5443 machine_mode tmode = GET_MODE (target);
5444 machine_mode smode = GET_MODE (sel);
5445 struct expand_operand ops[4];
5446
5447 gcc_assert (GET_MODE_CLASS (smode) == MODE_VECTOR_INT
5448 || mode_for_int_vector (tmode).require () == smode);
5449 create_output_operand (&ops[0], target, tmode);
5450 create_input_operand (&ops[3], sel, smode);
5451
5452 /* Make an effort to preserve v0 == v1. The target expander is able to
5453 rely on this to determine if we're permuting a single input operand. */
5454 if (rtx_equal_p (v0, v1))
5455 {
5456 if (!insn_operand_matches (icode, 1, v0))
5457 v0 = force_reg (tmode, v0);
5458 gcc_checking_assert (insn_operand_matches (icode, 1, v0));
5459 gcc_checking_assert (insn_operand_matches (icode, 2, v0));
5460
5461 create_fixed_operand (&ops[1], v0);
5462 create_fixed_operand (&ops[2], v0);
5463 }
5464 else
5465 {
5466 create_input_operand (&ops[1], v0, tmode);
5467 create_input_operand (&ops[2], v1, tmode);
5468 }
5469
5470 if (maybe_expand_insn (icode, 4, ops))
5471 return ops[0].value;
5472 return NULL_RTX;
5473 }
5474
5475 /* Implement a permutation of vectors v0 and v1 using the permutation
5476 vector in SEL and return the result. Use TARGET to hold the result
5477 if nonnull and convenient.
5478
5479 MODE is the mode of the vectors being permuted (V0 and V1). SEL_MODE
5480 is the TYPE_MODE associated with SEL, or BLKmode if SEL isn't known
5481 to have a particular mode. */
5482
5483 rtx
expand_vec_perm_const(machine_mode mode,rtx v0,rtx v1,const vec_perm_builder & sel,machine_mode sel_mode,rtx target)5484 expand_vec_perm_const (machine_mode mode, rtx v0, rtx v1,
5485 const vec_perm_builder &sel, machine_mode sel_mode,
5486 rtx target)
5487 {
5488 if (!target || !register_operand (target, mode))
5489 target = gen_reg_rtx (mode);
5490
5491 /* Set QIMODE to a different vector mode with byte elements.
5492 If no such mode, or if MODE already has byte elements, use VOIDmode. */
5493 machine_mode qimode;
5494 if (!qimode_for_vec_perm (mode).exists (&qimode))
5495 qimode = VOIDmode;
5496
5497 rtx_insn *last = get_last_insn ();
5498
5499 bool single_arg_p = rtx_equal_p (v0, v1);
5500 /* Always specify two input vectors here and leave the target to handle
5501 cases in which the inputs are equal. Not all backends can cope with
5502 the single-input representation when testing for a double-input
5503 target instruction. */
5504 vec_perm_indices indices (sel, 2, GET_MODE_NUNITS (mode));
5505
5506 /* See if this can be handled with a vec_shr. We only do this if the
5507 second vector is all zeroes. */
5508 insn_code shift_code = optab_handler (vec_shr_optab, mode);
5509 insn_code shift_code_qi = ((qimode != VOIDmode && qimode != mode)
5510 ? optab_handler (vec_shr_optab, qimode)
5511 : CODE_FOR_nothing);
5512
5513 if (v1 == CONST0_RTX (GET_MODE (v1))
5514 && (shift_code != CODE_FOR_nothing
5515 || shift_code_qi != CODE_FOR_nothing))
5516 {
5517 rtx shift_amt = shift_amt_for_vec_perm_mask (mode, indices);
5518 if (shift_amt)
5519 {
5520 struct expand_operand ops[3];
5521 if (shift_code != CODE_FOR_nothing)
5522 {
5523 create_output_operand (&ops[0], target, mode);
5524 create_input_operand (&ops[1], v0, mode);
5525 create_convert_operand_from_type (&ops[2], shift_amt, sizetype);
5526 if (maybe_expand_insn (shift_code, 3, ops))
5527 return ops[0].value;
5528 }
5529 if (shift_code_qi != CODE_FOR_nothing)
5530 {
5531 rtx tmp = gen_reg_rtx (qimode);
5532 create_output_operand (&ops[0], tmp, qimode);
5533 create_input_operand (&ops[1], gen_lowpart (qimode, v0), qimode);
5534 create_convert_operand_from_type (&ops[2], shift_amt, sizetype);
5535 if (maybe_expand_insn (shift_code_qi, 3, ops))
5536 return gen_lowpart (mode, ops[0].value);
5537 }
5538 }
5539 }
5540
5541 if (targetm.vectorize.vec_perm_const != NULL)
5542 {
5543 v0 = force_reg (mode, v0);
5544 if (single_arg_p)
5545 v1 = v0;
5546 else
5547 v1 = force_reg (mode, v1);
5548
5549 if (targetm.vectorize.vec_perm_const (mode, target, v0, v1, indices))
5550 return target;
5551 }
5552
5553 /* Fall back to a constant byte-based permutation. */
5554 vec_perm_indices qimode_indices;
5555 rtx target_qi = NULL_RTX, v0_qi = NULL_RTX, v1_qi = NULL_RTX;
5556 if (qimode != VOIDmode)
5557 {
5558 qimode_indices.new_expanded_vector (indices, GET_MODE_UNIT_SIZE (mode));
5559 target_qi = gen_reg_rtx (qimode);
5560 v0_qi = gen_lowpart (qimode, v0);
5561 v1_qi = gen_lowpart (qimode, v1);
5562 if (targetm.vectorize.vec_perm_const != NULL
5563 && targetm.vectorize.vec_perm_const (qimode, target_qi, v0_qi,
5564 v1_qi, qimode_indices))
5565 return gen_lowpart (mode, target_qi);
5566 }
5567
5568 /* Otherwise expand as a fully variable permuation. */
5569
5570 /* The optabs are only defined for selectors with the same width
5571 as the values being permuted. */
5572 machine_mode required_sel_mode;
5573 if (!mode_for_int_vector (mode).exists (&required_sel_mode)
5574 || !VECTOR_MODE_P (required_sel_mode))
5575 {
5576 delete_insns_since (last);
5577 return NULL_RTX;
5578 }
5579
5580 /* We know that it is semantically valid to treat SEL as having SEL_MODE.
5581 If that isn't the mode we want then we need to prove that using
5582 REQUIRED_SEL_MODE is OK. */
5583 if (sel_mode != required_sel_mode)
5584 {
5585 if (!selector_fits_mode_p (required_sel_mode, indices))
5586 {
5587 delete_insns_since (last);
5588 return NULL_RTX;
5589 }
5590 sel_mode = required_sel_mode;
5591 }
5592
5593 insn_code icode = direct_optab_handler (vec_perm_optab, mode);
5594 if (icode != CODE_FOR_nothing)
5595 {
5596 rtx sel_rtx = vec_perm_indices_to_rtx (sel_mode, indices);
5597 rtx tmp = expand_vec_perm_1 (icode, target, v0, v1, sel_rtx);
5598 if (tmp)
5599 return tmp;
5600 }
5601
5602 if (qimode != VOIDmode
5603 && selector_fits_mode_p (qimode, qimode_indices))
5604 {
5605 icode = direct_optab_handler (vec_perm_optab, qimode);
5606 if (icode != CODE_FOR_nothing)
5607 {
5608 rtx sel_qi = vec_perm_indices_to_rtx (qimode, qimode_indices);
5609 rtx tmp = expand_vec_perm_1 (icode, target_qi, v0_qi, v1_qi, sel_qi);
5610 if (tmp)
5611 return gen_lowpart (mode, tmp);
5612 }
5613 }
5614
5615 delete_insns_since (last);
5616 return NULL_RTX;
5617 }
5618
5619 /* Implement a permutation of vectors v0 and v1 using the permutation
5620 vector in SEL and return the result. Use TARGET to hold the result
5621 if nonnull and convenient.
5622
5623 MODE is the mode of the vectors being permuted (V0 and V1).
5624 SEL must have the integer equivalent of MODE and is known to be
5625 unsuitable for permutes with a constant permutation vector. */
5626
5627 rtx
expand_vec_perm_var(machine_mode mode,rtx v0,rtx v1,rtx sel,rtx target)5628 expand_vec_perm_var (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
5629 {
5630 enum insn_code icode;
5631 unsigned int i, u;
5632 rtx tmp, sel_qi;
5633
5634 u = GET_MODE_UNIT_SIZE (mode);
5635
5636 if (!target || GET_MODE (target) != mode)
5637 target = gen_reg_rtx (mode);
5638
5639 icode = direct_optab_handler (vec_perm_optab, mode);
5640 if (icode != CODE_FOR_nothing)
5641 {
5642 tmp = expand_vec_perm_1 (icode, target, v0, v1, sel);
5643 if (tmp)
5644 return tmp;
5645 }
5646
5647 /* As a special case to aid several targets, lower the element-based
5648 permutation to a byte-based permutation and try again. */
5649 machine_mode qimode;
5650 if (!qimode_for_vec_perm (mode).exists (&qimode)
5651 || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1))
5652 return NULL_RTX;
5653 icode = direct_optab_handler (vec_perm_optab, qimode);
5654 if (icode == CODE_FOR_nothing)
5655 return NULL_RTX;
5656
5657 /* Multiply each element by its byte size. */
5658 machine_mode selmode = GET_MODE (sel);
5659 if (u == 2)
5660 sel = expand_simple_binop (selmode, PLUS, sel, sel,
5661 NULL, 0, OPTAB_DIRECT);
5662 else
5663 sel = expand_simple_binop (selmode, ASHIFT, sel,
5664 gen_int_shift_amount (selmode, exact_log2 (u)),
5665 NULL, 0, OPTAB_DIRECT);
5666 gcc_assert (sel != NULL);
5667
5668 /* Broadcast the low byte each element into each of its bytes.
5669 The encoding has U interleaved stepped patterns, one for each
5670 byte of an element. */
5671 vec_perm_builder const_sel (GET_MODE_SIZE (mode), u, 3);
5672 unsigned int low_byte_in_u = BYTES_BIG_ENDIAN ? u - 1 : 0;
5673 for (i = 0; i < 3; ++i)
5674 for (unsigned int j = 0; j < u; ++j)
5675 const_sel.quick_push (i * u + low_byte_in_u);
5676 sel = gen_lowpart (qimode, sel);
5677 sel = expand_vec_perm_const (qimode, sel, sel, const_sel, qimode, NULL);
5678 gcc_assert (sel != NULL);
5679
5680 /* Add the byte offset to each byte element. */
5681 /* Note that the definition of the indicies here is memory ordering,
5682 so there should be no difference between big and little endian. */
5683 rtx_vector_builder byte_indices (qimode, u, 1);
5684 for (i = 0; i < u; ++i)
5685 byte_indices.quick_push (GEN_INT (i));
5686 tmp = byte_indices.build ();
5687 sel_qi = expand_simple_binop (qimode, PLUS, sel, tmp,
5688 sel, 0, OPTAB_DIRECT);
5689 gcc_assert (sel_qi != NULL);
5690
5691 tmp = mode != qimode ? gen_reg_rtx (qimode) : target;
5692 tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0),
5693 gen_lowpart (qimode, v1), sel_qi);
5694 if (tmp)
5695 tmp = gen_lowpart (mode, tmp);
5696 return tmp;
5697 }
5698
5699 /* Generate insns for a VEC_COND_EXPR with mask, given its TYPE and its
5700 three operands. */
5701
5702 rtx
expand_vec_cond_mask_expr(tree vec_cond_type,tree op0,tree op1,tree op2,rtx target)5703 expand_vec_cond_mask_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
5704 rtx target)
5705 {
5706 struct expand_operand ops[4];
5707 machine_mode mode = TYPE_MODE (vec_cond_type);
5708 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
5709 enum insn_code icode = get_vcond_mask_icode (mode, mask_mode);
5710 rtx mask, rtx_op1, rtx_op2;
5711
5712 if (icode == CODE_FOR_nothing)
5713 return 0;
5714
5715 mask = expand_normal (op0);
5716 rtx_op1 = expand_normal (op1);
5717 rtx_op2 = expand_normal (op2);
5718
5719 mask = force_reg (mask_mode, mask);
5720 rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
5721
5722 create_output_operand (&ops[0], target, mode);
5723 create_input_operand (&ops[1], rtx_op1, mode);
5724 create_input_operand (&ops[2], rtx_op2, mode);
5725 create_input_operand (&ops[3], mask, mask_mode);
5726 expand_insn (icode, 4, ops);
5727
5728 return ops[0].value;
5729 }
5730
5731 /* Generate insns for a VEC_COND_EXPR, given its TYPE and its
5732 three operands. */
5733
5734 rtx
expand_vec_cond_expr(tree vec_cond_type,tree op0,tree op1,tree op2,rtx target)5735 expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
5736 rtx target)
5737 {
5738 struct expand_operand ops[6];
5739 enum insn_code icode;
5740 rtx comparison, rtx_op1, rtx_op2;
5741 machine_mode mode = TYPE_MODE (vec_cond_type);
5742 machine_mode cmp_op_mode;
5743 bool unsignedp;
5744 tree op0a, op0b;
5745 enum tree_code tcode;
5746
5747 if (COMPARISON_CLASS_P (op0))
5748 {
5749 op0a = TREE_OPERAND (op0, 0);
5750 op0b = TREE_OPERAND (op0, 1);
5751 tcode = TREE_CODE (op0);
5752 }
5753 else
5754 {
5755 gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
5756 if (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
5757 != CODE_FOR_nothing)
5758 return expand_vec_cond_mask_expr (vec_cond_type, op0, op1,
5759 op2, target);
5760 /* Fake op0 < 0. */
5761 else
5762 {
5763 gcc_assert (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (op0)))
5764 == MODE_VECTOR_INT);
5765 op0a = op0;
5766 op0b = build_zero_cst (TREE_TYPE (op0));
5767 tcode = LT_EXPR;
5768 }
5769 }
5770 cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
5771 unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
5772
5773
5774 gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode))
5775 && known_eq (GET_MODE_NUNITS (mode),
5776 GET_MODE_NUNITS (cmp_op_mode)));
5777
5778 icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
5779 if (icode == CODE_FOR_nothing)
5780 {
5781 if (tcode == EQ_EXPR || tcode == NE_EXPR)
5782 icode = get_vcond_eq_icode (mode, cmp_op_mode);
5783 if (icode == CODE_FOR_nothing)
5784 return 0;
5785 }
5786
5787 comparison = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp,
5788 icode, 4);
5789 rtx_op1 = expand_normal (op1);
5790 rtx_op2 = expand_normal (op2);
5791
5792 create_output_operand (&ops[0], target, mode);
5793 create_input_operand (&ops[1], rtx_op1, mode);
5794 create_input_operand (&ops[2], rtx_op2, mode);
5795 create_fixed_operand (&ops[3], comparison);
5796 create_fixed_operand (&ops[4], XEXP (comparison, 0));
5797 create_fixed_operand (&ops[5], XEXP (comparison, 1));
5798 expand_insn (icode, 6, ops);
5799 return ops[0].value;
5800 }
5801
5802 /* Generate VEC_SERIES_EXPR <OP0, OP1>, returning a value of mode VMODE.
5803 Use TARGET for the result if nonnull and convenient. */
5804
5805 rtx
expand_vec_series_expr(machine_mode vmode,rtx op0,rtx op1,rtx target)5806 expand_vec_series_expr (machine_mode vmode, rtx op0, rtx op1, rtx target)
5807 {
5808 struct expand_operand ops[3];
5809 enum insn_code icode;
5810 machine_mode emode = GET_MODE_INNER (vmode);
5811
5812 icode = direct_optab_handler (vec_series_optab, vmode);
5813 gcc_assert (icode != CODE_FOR_nothing);
5814
5815 create_output_operand (&ops[0], target, vmode);
5816 create_input_operand (&ops[1], op0, emode);
5817 create_input_operand (&ops[2], op1, emode);
5818
5819 expand_insn (icode, 3, ops);
5820 return ops[0].value;
5821 }
5822
5823 /* Generate insns for a vector comparison into a mask. */
5824
5825 rtx
expand_vec_cmp_expr(tree type,tree exp,rtx target)5826 expand_vec_cmp_expr (tree type, tree exp, rtx target)
5827 {
5828 struct expand_operand ops[4];
5829 enum insn_code icode;
5830 rtx comparison;
5831 machine_mode mask_mode = TYPE_MODE (type);
5832 machine_mode vmode;
5833 bool unsignedp;
5834 tree op0a, op0b;
5835 enum tree_code tcode;
5836
5837 op0a = TREE_OPERAND (exp, 0);
5838 op0b = TREE_OPERAND (exp, 1);
5839 tcode = TREE_CODE (exp);
5840
5841 unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
5842 vmode = TYPE_MODE (TREE_TYPE (op0a));
5843
5844 icode = get_vec_cmp_icode (vmode, mask_mode, unsignedp);
5845 if (icode == CODE_FOR_nothing)
5846 {
5847 if (tcode == EQ_EXPR || tcode == NE_EXPR)
5848 icode = get_vec_cmp_eq_icode (vmode, mask_mode);
5849 if (icode == CODE_FOR_nothing)
5850 return 0;
5851 }
5852
5853 comparison = vector_compare_rtx (mask_mode, tcode, op0a, op0b,
5854 unsignedp, icode, 2);
5855 create_output_operand (&ops[0], target, mask_mode);
5856 create_fixed_operand (&ops[1], comparison);
5857 create_fixed_operand (&ops[2], XEXP (comparison, 0));
5858 create_fixed_operand (&ops[3], XEXP (comparison, 1));
5859 expand_insn (icode, 4, ops);
5860 return ops[0].value;
5861 }
5862
5863 /* Expand a highpart multiply. */
5864
5865 rtx
expand_mult_highpart(machine_mode mode,rtx op0,rtx op1,rtx target,bool uns_p)5866 expand_mult_highpart (machine_mode mode, rtx op0, rtx op1,
5867 rtx target, bool uns_p)
5868 {
5869 struct expand_operand eops[3];
5870 enum insn_code icode;
5871 int method, i;
5872 machine_mode wmode;
5873 rtx m1, m2;
5874 optab tab1, tab2;
5875
5876 method = can_mult_highpart_p (mode, uns_p);
5877 switch (method)
5878 {
5879 case 0:
5880 return NULL_RTX;
5881 case 1:
5882 tab1 = uns_p ? umul_highpart_optab : smul_highpart_optab;
5883 return expand_binop (mode, tab1, op0, op1, target, uns_p,
5884 OPTAB_LIB_WIDEN);
5885 case 2:
5886 tab1 = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
5887 tab2 = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
5888 break;
5889 case 3:
5890 tab1 = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
5891 tab2 = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
5892 if (BYTES_BIG_ENDIAN)
5893 std::swap (tab1, tab2);
5894 break;
5895 default:
5896 gcc_unreachable ();
5897 }
5898
5899 icode = optab_handler (tab1, mode);
5900 wmode = insn_data[icode].operand[0].mode;
5901 gcc_checking_assert (known_eq (2 * GET_MODE_NUNITS (wmode),
5902 GET_MODE_NUNITS (mode)));
5903 gcc_checking_assert (known_eq (GET_MODE_SIZE (wmode), GET_MODE_SIZE (mode)));
5904
5905 create_output_operand (&eops[0], gen_reg_rtx (wmode), wmode);
5906 create_input_operand (&eops[1], op0, mode);
5907 create_input_operand (&eops[2], op1, mode);
5908 expand_insn (icode, 3, eops);
5909 m1 = gen_lowpart (mode, eops[0].value);
5910
5911 create_output_operand (&eops[0], gen_reg_rtx (wmode), wmode);
5912 create_input_operand (&eops[1], op0, mode);
5913 create_input_operand (&eops[2], op1, mode);
5914 expand_insn (optab_handler (tab2, mode), 3, eops);
5915 m2 = gen_lowpart (mode, eops[0].value);
5916
5917 vec_perm_builder sel;
5918 if (method == 2)
5919 {
5920 /* The encoding has 2 interleaved stepped patterns. */
5921 sel.new_vector (GET_MODE_NUNITS (mode), 2, 3);
5922 for (i = 0; i < 6; ++i)
5923 sel.quick_push (!BYTES_BIG_ENDIAN + (i & ~1)
5924 + ((i & 1) ? GET_MODE_NUNITS (mode) : 0));
5925 }
5926 else
5927 {
5928 /* The encoding has a single interleaved stepped pattern. */
5929 sel.new_vector (GET_MODE_NUNITS (mode), 1, 3);
5930 for (i = 0; i < 3; ++i)
5931 sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1));
5932 }
5933
5934 return expand_vec_perm_const (mode, m1, m2, sel, BLKmode, target);
5935 }
5936
5937 /* Helper function to find the MODE_CC set in a sync_compare_and_swap
5938 pattern. */
5939
5940 static void
find_cc_set(rtx x,const_rtx pat,void * data)5941 find_cc_set (rtx x, const_rtx pat, void *data)
5942 {
5943 if (REG_P (x) && GET_MODE_CLASS (GET_MODE (x)) == MODE_CC
5944 && GET_CODE (pat) == SET)
5945 {
5946 rtx *p_cc_reg = (rtx *) data;
5947 gcc_assert (!*p_cc_reg);
5948 *p_cc_reg = x;
5949 }
5950 }
5951
5952 /* This is a helper function for the other atomic operations. This function
5953 emits a loop that contains SEQ that iterates until a compare-and-swap
5954 operation at the end succeeds. MEM is the memory to be modified. SEQ is
5955 a set of instructions that takes a value from OLD_REG as an input and
5956 produces a value in NEW_REG as an output. Before SEQ, OLD_REG will be
5957 set to the current contents of MEM. After SEQ, a compare-and-swap will
5958 attempt to update MEM with NEW_REG. The function returns true when the
5959 loop was generated successfully. */
5960
5961 static bool
expand_compare_and_swap_loop(rtx mem,rtx old_reg,rtx new_reg,rtx seq)5962 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
5963 {
5964 machine_mode mode = GET_MODE (mem);
5965 rtx_code_label *label;
5966 rtx cmp_reg, success, oldval;
5967
5968 /* The loop we want to generate looks like
5969
5970 cmp_reg = mem;
5971 label:
5972 old_reg = cmp_reg;
5973 seq;
5974 (success, cmp_reg) = compare-and-swap(mem, old_reg, new_reg)
5975 if (success)
5976 goto label;
5977
5978 Note that we only do the plain load from memory once. Subsequent
5979 iterations use the value loaded by the compare-and-swap pattern. */
5980
5981 label = gen_label_rtx ();
5982 cmp_reg = gen_reg_rtx (mode);
5983
5984 emit_move_insn (cmp_reg, mem);
5985 emit_label (label);
5986 emit_move_insn (old_reg, cmp_reg);
5987 if (seq)
5988 emit_insn (seq);
5989
5990 success = NULL_RTX;
5991 oldval = cmp_reg;
5992 if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg,
5993 new_reg, false, MEMMODEL_SYNC_SEQ_CST,
5994 MEMMODEL_RELAXED))
5995 return false;
5996
5997 if (oldval != cmp_reg)
5998 emit_move_insn (cmp_reg, oldval);
5999
6000 /* Mark this jump predicted not taken. */
6001 emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
6002 GET_MODE (success), 1, label,
6003 profile_probability::guessed_never ());
6004 return true;
6005 }
6006
6007
6008 /* This function tries to emit an atomic_exchange intruction. VAL is written
6009 to *MEM using memory model MODEL. The previous contents of *MEM are returned,
6010 using TARGET if possible. */
6011
6012 static rtx
maybe_emit_atomic_exchange(rtx target,rtx mem,rtx val,enum memmodel model)6013 maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
6014 {
6015 machine_mode mode = GET_MODE (mem);
6016 enum insn_code icode;
6017
6018 /* If the target supports the exchange directly, great. */
6019 icode = direct_optab_handler (atomic_exchange_optab, mode);
6020 if (icode != CODE_FOR_nothing)
6021 {
6022 struct expand_operand ops[4];
6023
6024 create_output_operand (&ops[0], target, mode);
6025 create_fixed_operand (&ops[1], mem);
6026 create_input_operand (&ops[2], val, mode);
6027 create_integer_operand (&ops[3], model);
6028 if (maybe_expand_insn (icode, 4, ops))
6029 return ops[0].value;
6030 }
6031
6032 return NULL_RTX;
6033 }
6034
6035 /* This function tries to implement an atomic exchange operation using
6036 __sync_lock_test_and_set. VAL is written to *MEM using memory model MODEL.
6037 The previous contents of *MEM are returned, using TARGET if possible.
6038 Since this instructionn is an acquire barrier only, stronger memory
6039 models may require additional barriers to be emitted. */
6040
6041 static rtx
maybe_emit_sync_lock_test_and_set(rtx target,rtx mem,rtx val,enum memmodel model)6042 maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
6043 enum memmodel model)
6044 {
6045 machine_mode mode = GET_MODE (mem);
6046 enum insn_code icode;
6047 rtx_insn *last_insn = get_last_insn ();
6048
6049 icode = optab_handler (sync_lock_test_and_set_optab, mode);
6050
6051 /* Legacy sync_lock_test_and_set is an acquire barrier. If the pattern
6052 exists, and the memory model is stronger than acquire, add a release
6053 barrier before the instruction. */
6054
6055 if (is_mm_seq_cst (model) || is_mm_release (model) || is_mm_acq_rel (model))
6056 expand_mem_thread_fence (model);
6057
6058 if (icode != CODE_FOR_nothing)
6059 {
6060 struct expand_operand ops[3];
6061 create_output_operand (&ops[0], target, mode);
6062 create_fixed_operand (&ops[1], mem);
6063 create_input_operand (&ops[2], val, mode);
6064 if (maybe_expand_insn (icode, 3, ops))
6065 return ops[0].value;
6066 }
6067
6068 /* If an external test-and-set libcall is provided, use that instead of
6069 any external compare-and-swap that we might get from the compare-and-
6070 swap-loop expansion later. */
6071 if (!can_compare_and_swap_p (mode, false))
6072 {
6073 rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, mode);
6074 if (libfunc != NULL)
6075 {
6076 rtx addr;
6077
6078 addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
6079 return emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
6080 mode, addr, ptr_mode,
6081 val, mode);
6082 }
6083 }
6084
6085 /* If the test_and_set can't be emitted, eliminate any barrier that might
6086 have been emitted. */
6087 delete_insns_since (last_insn);
6088 return NULL_RTX;
6089 }
6090
6091 /* This function tries to implement an atomic exchange operation using a
6092 compare_and_swap loop. VAL is written to *MEM. The previous contents of
6093 *MEM are returned, using TARGET if possible. No memory model is required
6094 since a compare_and_swap loop is seq-cst. */
6095
6096 static rtx
maybe_emit_compare_and_swap_exchange_loop(rtx target,rtx mem,rtx val)6097 maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
6098 {
6099 machine_mode mode = GET_MODE (mem);
6100
6101 if (can_compare_and_swap_p (mode, true))
6102 {
6103 if (!target || !register_operand (target, mode))
6104 target = gen_reg_rtx (mode);
6105 if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
6106 return target;
6107 }
6108
6109 return NULL_RTX;
6110 }
6111
6112 /* This function tries to implement an atomic test-and-set operation
6113 using the atomic_test_and_set instruction pattern. A boolean value
6114 is returned from the operation, using TARGET if possible. */
6115
6116 static rtx
maybe_emit_atomic_test_and_set(rtx target,rtx mem,enum memmodel model)6117 maybe_emit_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
6118 {
6119 machine_mode pat_bool_mode;
6120 struct expand_operand ops[3];
6121
6122 if (!targetm.have_atomic_test_and_set ())
6123 return NULL_RTX;
6124
6125 /* While we always get QImode from __atomic_test_and_set, we get
6126 other memory modes from __sync_lock_test_and_set. Note that we
6127 use no endian adjustment here. This matches the 4.6 behavior
6128 in the Sparc backend. */
6129 enum insn_code icode = targetm.code_for_atomic_test_and_set;
6130 gcc_checking_assert (insn_data[icode].operand[1].mode == QImode);
6131 if (GET_MODE (mem) != QImode)
6132 mem = adjust_address_nv (mem, QImode, 0);
6133
6134 pat_bool_mode = insn_data[icode].operand[0].mode;
6135 create_output_operand (&ops[0], target, pat_bool_mode);
6136 create_fixed_operand (&ops[1], mem);
6137 create_integer_operand (&ops[2], model);
6138
6139 if (maybe_expand_insn (icode, 3, ops))
6140 return ops[0].value;
6141 return NULL_RTX;
6142 }
6143
6144 /* This function expands the legacy _sync_lock test_and_set operation which is
6145 generally an atomic exchange. Some limited targets only allow the
6146 constant 1 to be stored. This is an ACQUIRE operation.
6147
6148 TARGET is an optional place to stick the return value.
6149 MEM is where VAL is stored. */
6150
6151 rtx
expand_sync_lock_test_and_set(rtx target,rtx mem,rtx val)6152 expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
6153 {
6154 rtx ret;
6155
6156 /* Try an atomic_exchange first. */
6157 ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_SYNC_ACQUIRE);
6158 if (ret)
6159 return ret;
6160
6161 ret = maybe_emit_sync_lock_test_and_set (target, mem, val,
6162 MEMMODEL_SYNC_ACQUIRE);
6163 if (ret)
6164 return ret;
6165
6166 ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
6167 if (ret)
6168 return ret;
6169
6170 /* If there are no other options, try atomic_test_and_set if the value
6171 being stored is 1. */
6172 if (val == const1_rtx)
6173 ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_SYNC_ACQUIRE);
6174
6175 return ret;
6176 }
6177
6178 /* This function expands the atomic test_and_set operation:
6179 atomically store a boolean TRUE into MEM and return the previous value.
6180
6181 MEMMODEL is the memory model variant to use.
6182 TARGET is an optional place to stick the return value. */
6183
6184 rtx
expand_atomic_test_and_set(rtx target,rtx mem,enum memmodel model)6185 expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
6186 {
6187 machine_mode mode = GET_MODE (mem);
6188 rtx ret, trueval, subtarget;
6189
6190 ret = maybe_emit_atomic_test_and_set (target, mem, model);
6191 if (ret)
6192 return ret;
6193
6194 /* Be binary compatible with non-default settings of trueval, and different
6195 cpu revisions. E.g. one revision may have atomic-test-and-set, but
6196 another only has atomic-exchange. */
6197 if (targetm.atomic_test_and_set_trueval == 1)
6198 {
6199 trueval = const1_rtx;
6200 subtarget = target ? target : gen_reg_rtx (mode);
6201 }
6202 else
6203 {
6204 trueval = gen_int_mode (targetm.atomic_test_and_set_trueval, mode);
6205 subtarget = gen_reg_rtx (mode);
6206 }
6207
6208 /* Try the atomic-exchange optab... */
6209 ret = maybe_emit_atomic_exchange (subtarget, mem, trueval, model);
6210
6211 /* ... then an atomic-compare-and-swap loop ... */
6212 if (!ret)
6213 ret = maybe_emit_compare_and_swap_exchange_loop (subtarget, mem, trueval);
6214
6215 /* ... before trying the vaguely defined legacy lock_test_and_set. */
6216 if (!ret)
6217 ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, trueval, model);
6218
6219 /* Recall that the legacy lock_test_and_set optab was allowed to do magic
6220 things with the value 1. Thus we try again without trueval. */
6221 if (!ret && targetm.atomic_test_and_set_trueval != 1)
6222 ret = maybe_emit_sync_lock_test_and_set (subtarget, mem, const1_rtx, model);
6223
6224 /* Failing all else, assume a single threaded environment and simply
6225 perform the operation. */
6226 if (!ret)
6227 {
6228 /* If the result is ignored skip the move to target. */
6229 if (subtarget != const0_rtx)
6230 emit_move_insn (subtarget, mem);
6231
6232 emit_move_insn (mem, trueval);
6233 ret = subtarget;
6234 }
6235
6236 /* Recall that have to return a boolean value; rectify if trueval
6237 is not exactly one. */
6238 if (targetm.atomic_test_and_set_trueval != 1)
6239 ret = emit_store_flag_force (target, NE, ret, const0_rtx, mode, 0, 1);
6240
6241 return ret;
6242 }
6243
6244 /* This function expands the atomic exchange operation:
6245 atomically store VAL in MEM and return the previous value in MEM.
6246
6247 MEMMODEL is the memory model variant to use.
6248 TARGET is an optional place to stick the return value. */
6249
6250 rtx
expand_atomic_exchange(rtx target,rtx mem,rtx val,enum memmodel model)6251 expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
6252 {
6253 machine_mode mode = GET_MODE (mem);
6254 rtx ret;
6255
6256 /* If loads are not atomic for the required size and we are not called to
6257 provide a __sync builtin, do not do anything so that we stay consistent
6258 with atomic loads of the same size. */
6259 if (!can_atomic_load_p (mode) && !is_mm_sync (model))
6260 return NULL_RTX;
6261
6262 ret = maybe_emit_atomic_exchange (target, mem, val, model);
6263
6264 /* Next try a compare-and-swap loop for the exchange. */
6265 if (!ret)
6266 ret = maybe_emit_compare_and_swap_exchange_loop (target, mem, val);
6267
6268 return ret;
6269 }
6270
6271 /* This function expands the atomic compare exchange operation:
6272
6273 *PTARGET_BOOL is an optional place to store the boolean success/failure.
6274 *PTARGET_OVAL is an optional place to store the old value from memory.
6275 Both target parameters may be NULL or const0_rtx to indicate that we do
6276 not care about that return value. Both target parameters are updated on
6277 success to the actual location of the corresponding result.
6278
6279 MEMMODEL is the memory model variant to use.
6280
6281 The return value of the function is true for success. */
6282
6283 bool
expand_atomic_compare_and_swap(rtx * ptarget_bool,rtx * ptarget_oval,rtx mem,rtx expected,rtx desired,bool is_weak,enum memmodel succ_model,enum memmodel fail_model)6284 expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
6285 rtx mem, rtx expected, rtx desired,
6286 bool is_weak, enum memmodel succ_model,
6287 enum memmodel fail_model)
6288 {
6289 machine_mode mode = GET_MODE (mem);
6290 struct expand_operand ops[8];
6291 enum insn_code icode;
6292 rtx target_oval, target_bool = NULL_RTX;
6293 rtx libfunc;
6294
6295 /* If loads are not atomic for the required size and we are not called to
6296 provide a __sync builtin, do not do anything so that we stay consistent
6297 with atomic loads of the same size. */
6298 if (!can_atomic_load_p (mode) && !is_mm_sync (succ_model))
6299 return false;
6300
6301 /* Load expected into a register for the compare and swap. */
6302 if (MEM_P (expected))
6303 expected = copy_to_reg (expected);
6304
6305 /* Make sure we always have some place to put the return oldval.
6306 Further, make sure that place is distinct from the input expected,
6307 just in case we need that path down below. */
6308 if (ptarget_oval && *ptarget_oval == const0_rtx)
6309 ptarget_oval = NULL;
6310
6311 if (ptarget_oval == NULL
6312 || (target_oval = *ptarget_oval) == NULL
6313 || reg_overlap_mentioned_p (expected, target_oval))
6314 target_oval = gen_reg_rtx (mode);
6315
6316 icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
6317 if (icode != CODE_FOR_nothing)
6318 {
6319 machine_mode bool_mode = insn_data[icode].operand[0].mode;
6320
6321 if (ptarget_bool && *ptarget_bool == const0_rtx)
6322 ptarget_bool = NULL;
6323
6324 /* Make sure we always have a place for the bool operand. */
6325 if (ptarget_bool == NULL
6326 || (target_bool = *ptarget_bool) == NULL
6327 || GET_MODE (target_bool) != bool_mode)
6328 target_bool = gen_reg_rtx (bool_mode);
6329
6330 /* Emit the compare_and_swap. */
6331 create_output_operand (&ops[0], target_bool, bool_mode);
6332 create_output_operand (&ops[1], target_oval, mode);
6333 create_fixed_operand (&ops[2], mem);
6334 create_input_operand (&ops[3], expected, mode);
6335 create_input_operand (&ops[4], desired, mode);
6336 create_integer_operand (&ops[5], is_weak);
6337 create_integer_operand (&ops[6], succ_model);
6338 create_integer_operand (&ops[7], fail_model);
6339 if (maybe_expand_insn (icode, 8, ops))
6340 {
6341 /* Return success/failure. */
6342 target_bool = ops[0].value;
6343 target_oval = ops[1].value;
6344 goto success;
6345 }
6346 }
6347
6348 /* Otherwise fall back to the original __sync_val_compare_and_swap
6349 which is always seq-cst. */
6350 icode = optab_handler (sync_compare_and_swap_optab, mode);
6351 if (icode != CODE_FOR_nothing)
6352 {
6353 rtx cc_reg;
6354
6355 create_output_operand (&ops[0], target_oval, mode);
6356 create_fixed_operand (&ops[1], mem);
6357 create_input_operand (&ops[2], expected, mode);
6358 create_input_operand (&ops[3], desired, mode);
6359 if (!maybe_expand_insn (icode, 4, ops))
6360 return false;
6361
6362 target_oval = ops[0].value;
6363
6364 /* If the caller isn't interested in the boolean return value,
6365 skip the computation of it. */
6366 if (ptarget_bool == NULL)
6367 goto success;
6368
6369 /* Otherwise, work out if the compare-and-swap succeeded. */
6370 cc_reg = NULL_RTX;
6371 if (have_insn_for (COMPARE, CCmode))
6372 note_stores (PATTERN (get_last_insn ()), find_cc_set, &cc_reg);
6373 if (cc_reg)
6374 {
6375 target_bool = emit_store_flag_force (target_bool, EQ, cc_reg,
6376 const0_rtx, VOIDmode, 0, 1);
6377 goto success;
6378 }
6379 goto success_bool_from_val;
6380 }
6381
6382 /* Also check for library support for __sync_val_compare_and_swap. */
6383 libfunc = optab_libfunc (sync_compare_and_swap_optab, mode);
6384 if (libfunc != NULL)
6385 {
6386 rtx addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
6387 rtx target = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
6388 mode, addr, ptr_mode,
6389 expected, mode, desired, mode);
6390 emit_move_insn (target_oval, target);
6391
6392 /* Compute the boolean return value only if requested. */
6393 if (ptarget_bool)
6394 goto success_bool_from_val;
6395 else
6396 goto success;
6397 }
6398
6399 /* Failure. */
6400 return false;
6401
6402 success_bool_from_val:
6403 target_bool = emit_store_flag_force (target_bool, EQ, target_oval,
6404 expected, VOIDmode, 1, 1);
6405 success:
6406 /* Make sure that the oval output winds up where the caller asked. */
6407 if (ptarget_oval)
6408 *ptarget_oval = target_oval;
6409 if (ptarget_bool)
6410 *ptarget_bool = target_bool;
6411 return true;
6412 }
6413
6414 /* Generate asm volatile("" : : : "memory") as the memory blockage. */
6415
6416 static void
expand_asm_memory_blockage(void)6417 expand_asm_memory_blockage (void)
6418 {
6419 rtx asm_op, clob;
6420
6421 asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, "", "", 0,
6422 rtvec_alloc (0), rtvec_alloc (0),
6423 rtvec_alloc (0), UNKNOWN_LOCATION);
6424 MEM_VOLATILE_P (asm_op) = 1;
6425
6426 clob = gen_rtx_SCRATCH (VOIDmode);
6427 clob = gen_rtx_MEM (BLKmode, clob);
6428 clob = gen_rtx_CLOBBER (VOIDmode, clob);
6429
6430 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, asm_op, clob)));
6431 }
6432
6433 /* Do not propagate memory accesses across this point. */
6434
6435 static void
expand_memory_blockage(void)6436 expand_memory_blockage (void)
6437 {
6438 if (targetm.have_memory_blockage ())
6439 emit_insn (targetm.gen_memory_blockage ());
6440 else
6441 expand_asm_memory_blockage ();
6442 }
6443
6444 /* This routine will either emit the mem_thread_fence pattern or issue a
6445 sync_synchronize to generate a fence for memory model MEMMODEL. */
6446
6447 void
expand_mem_thread_fence(enum memmodel model)6448 expand_mem_thread_fence (enum memmodel model)
6449 {
6450 if (is_mm_relaxed (model))
6451 return;
6452 if (targetm.have_mem_thread_fence ())
6453 {
6454 emit_insn (targetm.gen_mem_thread_fence (GEN_INT (model)));
6455 expand_memory_blockage ();
6456 }
6457 else if (targetm.have_memory_barrier ())
6458 emit_insn (targetm.gen_memory_barrier ());
6459 else if (synchronize_libfunc != NULL_RTX)
6460 emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode);
6461 else
6462 expand_memory_blockage ();
6463 }
6464
6465 /* Emit a signal fence with given memory model. */
6466
6467 void
expand_mem_signal_fence(enum memmodel model)6468 expand_mem_signal_fence (enum memmodel model)
6469 {
6470 /* No machine barrier is required to implement a signal fence, but
6471 a compiler memory barrier must be issued, except for relaxed MM. */
6472 if (!is_mm_relaxed (model))
6473 expand_memory_blockage ();
6474 }
6475
6476 /* This function expands the atomic load operation:
6477 return the atomically loaded value in MEM.
6478
6479 MEMMODEL is the memory model variant to use.
6480 TARGET is an option place to stick the return value. */
6481
6482 rtx
expand_atomic_load(rtx target,rtx mem,enum memmodel model)6483 expand_atomic_load (rtx target, rtx mem, enum memmodel model)
6484 {
6485 machine_mode mode = GET_MODE (mem);
6486 enum insn_code icode;
6487
6488 /* If the target supports the load directly, great. */
6489 icode = direct_optab_handler (atomic_load_optab, mode);
6490 if (icode != CODE_FOR_nothing)
6491 {
6492 struct expand_operand ops[3];
6493 rtx_insn *last = get_last_insn ();
6494 if (is_mm_seq_cst (model))
6495 expand_memory_blockage ();
6496
6497 create_output_operand (&ops[0], target, mode);
6498 create_fixed_operand (&ops[1], mem);
6499 create_integer_operand (&ops[2], model);
6500 if (maybe_expand_insn (icode, 3, ops))
6501 {
6502 if (!is_mm_relaxed (model))
6503 expand_memory_blockage ();
6504 return ops[0].value;
6505 }
6506 delete_insns_since (last);
6507 }
6508
6509 /* If the size of the object is greater than word size on this target,
6510 then we assume that a load will not be atomic. We could try to
6511 emulate a load with a compare-and-swap operation, but the store that
6512 doing this could result in would be incorrect if this is a volatile
6513 atomic load or targetting read-only-mapped memory. */
6514 if (maybe_gt (GET_MODE_PRECISION (mode), BITS_PER_WORD))
6515 /* If there is no atomic load, leave the library call. */
6516 return NULL_RTX;
6517
6518 /* Otherwise assume loads are atomic, and emit the proper barriers. */
6519 if (!target || target == const0_rtx)
6520 target = gen_reg_rtx (mode);
6521
6522 /* For SEQ_CST, emit a barrier before the load. */
6523 if (is_mm_seq_cst (model))
6524 expand_mem_thread_fence (model);
6525
6526 emit_move_insn (target, mem);
6527
6528 /* Emit the appropriate barrier after the load. */
6529 expand_mem_thread_fence (model);
6530
6531 return target;
6532 }
6533
6534 /* This function expands the atomic store operation:
6535 Atomically store VAL in MEM.
6536 MEMMODEL is the memory model variant to use.
6537 USE_RELEASE is true if __sync_lock_release can be used as a fall back.
6538 function returns const0_rtx if a pattern was emitted. */
6539
6540 rtx
expand_atomic_store(rtx mem,rtx val,enum memmodel model,bool use_release)6541 expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
6542 {
6543 machine_mode mode = GET_MODE (mem);
6544 enum insn_code icode;
6545 struct expand_operand ops[3];
6546
6547 /* If the target supports the store directly, great. */
6548 icode = direct_optab_handler (atomic_store_optab, mode);
6549 if (icode != CODE_FOR_nothing)
6550 {
6551 rtx_insn *last = get_last_insn ();
6552 if (!is_mm_relaxed (model))
6553 expand_memory_blockage ();
6554 create_fixed_operand (&ops[0], mem);
6555 create_input_operand (&ops[1], val, mode);
6556 create_integer_operand (&ops[2], model);
6557 if (maybe_expand_insn (icode, 3, ops))
6558 {
6559 if (is_mm_seq_cst (model))
6560 expand_memory_blockage ();
6561 return const0_rtx;
6562 }
6563 delete_insns_since (last);
6564 }
6565
6566 /* If using __sync_lock_release is a viable alternative, try it.
6567 Note that this will not be set to true if we are expanding a generic
6568 __atomic_store_n. */
6569 if (use_release)
6570 {
6571 icode = direct_optab_handler (sync_lock_release_optab, mode);
6572 if (icode != CODE_FOR_nothing)
6573 {
6574 create_fixed_operand (&ops[0], mem);
6575 create_input_operand (&ops[1], const0_rtx, mode);
6576 if (maybe_expand_insn (icode, 2, ops))
6577 {
6578 /* lock_release is only a release barrier. */
6579 if (is_mm_seq_cst (model))
6580 expand_mem_thread_fence (model);
6581 return const0_rtx;
6582 }
6583 }
6584 }
6585
6586 /* If the size of the object is greater than word size on this target,
6587 a default store will not be atomic. */
6588 if (maybe_gt (GET_MODE_PRECISION (mode), BITS_PER_WORD))
6589 {
6590 /* If loads are atomic or we are called to provide a __sync builtin,
6591 we can try a atomic_exchange and throw away the result. Otherwise,
6592 don't do anything so that we do not create an inconsistency between
6593 loads and stores. */
6594 if (can_atomic_load_p (mode) || is_mm_sync (model))
6595 {
6596 rtx target = maybe_emit_atomic_exchange (NULL_RTX, mem, val, model);
6597 if (!target)
6598 target = maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem,
6599 val);
6600 if (target)
6601 return const0_rtx;
6602 }
6603 return NULL_RTX;
6604 }
6605
6606 /* Otherwise assume stores are atomic, and emit the proper barriers. */
6607 expand_mem_thread_fence (model);
6608
6609 emit_move_insn (mem, val);
6610
6611 /* For SEQ_CST, also emit a barrier after the store. */
6612 if (is_mm_seq_cst (model))
6613 expand_mem_thread_fence (model);
6614
6615 return const0_rtx;
6616 }
6617
6618
6619 /* Structure containing the pointers and values required to process the
6620 various forms of the atomic_fetch_op and atomic_op_fetch builtins. */
6621
6622 struct atomic_op_functions
6623 {
6624 direct_optab mem_fetch_before;
6625 direct_optab mem_fetch_after;
6626 direct_optab mem_no_result;
6627 optab fetch_before;
6628 optab fetch_after;
6629 direct_optab no_result;
6630 enum rtx_code reverse_code;
6631 };
6632
6633
6634 /* Fill in structure pointed to by OP with the various optab entries for an
6635 operation of type CODE. */
6636
6637 static void
get_atomic_op_for_code(struct atomic_op_functions * op,enum rtx_code code)6638 get_atomic_op_for_code (struct atomic_op_functions *op, enum rtx_code code)
6639 {
6640 gcc_assert (op!= NULL);
6641
6642 /* If SWITCHABLE_TARGET is defined, then subtargets can be switched
6643 in the source code during compilation, and the optab entries are not
6644 computable until runtime. Fill in the values at runtime. */
6645 switch (code)
6646 {
6647 case PLUS:
6648 op->mem_fetch_before = atomic_fetch_add_optab;
6649 op->mem_fetch_after = atomic_add_fetch_optab;
6650 op->mem_no_result = atomic_add_optab;
6651 op->fetch_before = sync_old_add_optab;
6652 op->fetch_after = sync_new_add_optab;
6653 op->no_result = sync_add_optab;
6654 op->reverse_code = MINUS;
6655 break;
6656 case MINUS:
6657 op->mem_fetch_before = atomic_fetch_sub_optab;
6658 op->mem_fetch_after = atomic_sub_fetch_optab;
6659 op->mem_no_result = atomic_sub_optab;
6660 op->fetch_before = sync_old_sub_optab;
6661 op->fetch_after = sync_new_sub_optab;
6662 op->no_result = sync_sub_optab;
6663 op->reverse_code = PLUS;
6664 break;
6665 case XOR:
6666 op->mem_fetch_before = atomic_fetch_xor_optab;
6667 op->mem_fetch_after = atomic_xor_fetch_optab;
6668 op->mem_no_result = atomic_xor_optab;
6669 op->fetch_before = sync_old_xor_optab;
6670 op->fetch_after = sync_new_xor_optab;
6671 op->no_result = sync_xor_optab;
6672 op->reverse_code = XOR;
6673 break;
6674 case AND:
6675 op->mem_fetch_before = atomic_fetch_and_optab;
6676 op->mem_fetch_after = atomic_and_fetch_optab;
6677 op->mem_no_result = atomic_and_optab;
6678 op->fetch_before = sync_old_and_optab;
6679 op->fetch_after = sync_new_and_optab;
6680 op->no_result = sync_and_optab;
6681 op->reverse_code = UNKNOWN;
6682 break;
6683 case IOR:
6684 op->mem_fetch_before = atomic_fetch_or_optab;
6685 op->mem_fetch_after = atomic_or_fetch_optab;
6686 op->mem_no_result = atomic_or_optab;
6687 op->fetch_before = sync_old_ior_optab;
6688 op->fetch_after = sync_new_ior_optab;
6689 op->no_result = sync_ior_optab;
6690 op->reverse_code = UNKNOWN;
6691 break;
6692 case NOT:
6693 op->mem_fetch_before = atomic_fetch_nand_optab;
6694 op->mem_fetch_after = atomic_nand_fetch_optab;
6695 op->mem_no_result = atomic_nand_optab;
6696 op->fetch_before = sync_old_nand_optab;
6697 op->fetch_after = sync_new_nand_optab;
6698 op->no_result = sync_nand_optab;
6699 op->reverse_code = UNKNOWN;
6700 break;
6701 default:
6702 gcc_unreachable ();
6703 }
6704 }
6705
6706 /* See if there is a more optimal way to implement the operation "*MEM CODE VAL"
6707 using memory order MODEL. If AFTER is true the operation needs to return
6708 the value of *MEM after the operation, otherwise the previous value.
6709 TARGET is an optional place to place the result. The result is unused if
6710 it is const0_rtx.
6711 Return the result if there is a better sequence, otherwise NULL_RTX. */
6712
6713 static rtx
maybe_optimize_fetch_op(rtx target,rtx mem,rtx val,enum rtx_code code,enum memmodel model,bool after)6714 maybe_optimize_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
6715 enum memmodel model, bool after)
6716 {
6717 /* If the value is prefetched, or not used, it may be possible to replace
6718 the sequence with a native exchange operation. */
6719 if (!after || target == const0_rtx)
6720 {
6721 /* fetch_and (&x, 0, m) can be replaced with exchange (&x, 0, m). */
6722 if (code == AND && val == const0_rtx)
6723 {
6724 if (target == const0_rtx)
6725 target = gen_reg_rtx (GET_MODE (mem));
6726 return maybe_emit_atomic_exchange (target, mem, val, model);
6727 }
6728
6729 /* fetch_or (&x, -1, m) can be replaced with exchange (&x, -1, m). */
6730 if (code == IOR && val == constm1_rtx)
6731 {
6732 if (target == const0_rtx)
6733 target = gen_reg_rtx (GET_MODE (mem));
6734 return maybe_emit_atomic_exchange (target, mem, val, model);
6735 }
6736 }
6737
6738 return NULL_RTX;
6739 }
6740
6741 /* Try to emit an instruction for a specific operation varaition.
6742 OPTAB contains the OP functions.
6743 TARGET is an optional place to return the result. const0_rtx means unused.
6744 MEM is the memory location to operate on.
6745 VAL is the value to use in the operation.
6746 USE_MEMMODEL is TRUE if the variation with a memory model should be tried.
6747 MODEL is the memory model, if used.
6748 AFTER is true if the returned result is the value after the operation. */
6749
6750 static rtx
maybe_emit_op(const struct atomic_op_functions * optab,rtx target,rtx mem,rtx val,bool use_memmodel,enum memmodel model,bool after)6751 maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
6752 rtx val, bool use_memmodel, enum memmodel model, bool after)
6753 {
6754 machine_mode mode = GET_MODE (mem);
6755 struct expand_operand ops[4];
6756 enum insn_code icode;
6757 int op_counter = 0;
6758 int num_ops;
6759
6760 /* Check to see if there is a result returned. */
6761 if (target == const0_rtx)
6762 {
6763 if (use_memmodel)
6764 {
6765 icode = direct_optab_handler (optab->mem_no_result, mode);
6766 create_integer_operand (&ops[2], model);
6767 num_ops = 3;
6768 }
6769 else
6770 {
6771 icode = direct_optab_handler (optab->no_result, mode);
6772 num_ops = 2;
6773 }
6774 }
6775 /* Otherwise, we need to generate a result. */
6776 else
6777 {
6778 if (use_memmodel)
6779 {
6780 icode = direct_optab_handler (after ? optab->mem_fetch_after
6781 : optab->mem_fetch_before, mode);
6782 create_integer_operand (&ops[3], model);
6783 num_ops = 4;
6784 }
6785 else
6786 {
6787 icode = optab_handler (after ? optab->fetch_after
6788 : optab->fetch_before, mode);
6789 num_ops = 3;
6790 }
6791 create_output_operand (&ops[op_counter++], target, mode);
6792 }
6793 if (icode == CODE_FOR_nothing)
6794 return NULL_RTX;
6795
6796 create_fixed_operand (&ops[op_counter++], mem);
6797 /* VAL may have been promoted to a wider mode. Shrink it if so. */
6798 create_convert_operand_to (&ops[op_counter++], val, mode, true);
6799
6800 if (maybe_expand_insn (icode, num_ops, ops))
6801 return (target == const0_rtx ? const0_rtx : ops[0].value);
6802
6803 return NULL_RTX;
6804 }
6805
6806
6807 /* This function expands an atomic fetch_OP or OP_fetch operation:
6808 TARGET is an option place to stick the return value. const0_rtx indicates
6809 the result is unused.
6810 atomically fetch MEM, perform the operation with VAL and return it to MEM.
6811 CODE is the operation being performed (OP)
6812 MEMMODEL is the memory model variant to use.
6813 AFTER is true to return the result of the operation (OP_fetch).
6814 AFTER is false to return the value before the operation (fetch_OP).
6815
6816 This function will *only* generate instructions if there is a direct
6817 optab. No compare and swap loops or libcalls will be generated. */
6818
6819 static rtx
expand_atomic_fetch_op_no_fallback(rtx target,rtx mem,rtx val,enum rtx_code code,enum memmodel model,bool after)6820 expand_atomic_fetch_op_no_fallback (rtx target, rtx mem, rtx val,
6821 enum rtx_code code, enum memmodel model,
6822 bool after)
6823 {
6824 machine_mode mode = GET_MODE (mem);
6825 struct atomic_op_functions optab;
6826 rtx result;
6827 bool unused_result = (target == const0_rtx);
6828
6829 get_atomic_op_for_code (&optab, code);
6830
6831 /* Check to see if there are any better instructions. */
6832 result = maybe_optimize_fetch_op (target, mem, val, code, model, after);
6833 if (result)
6834 return result;
6835
6836 /* Check for the case where the result isn't used and try those patterns. */
6837 if (unused_result)
6838 {
6839 /* Try the memory model variant first. */
6840 result = maybe_emit_op (&optab, target, mem, val, true, model, true);
6841 if (result)
6842 return result;
6843
6844 /* Next try the old style withuot a memory model. */
6845 result = maybe_emit_op (&optab, target, mem, val, false, model, true);
6846 if (result)
6847 return result;
6848
6849 /* There is no no-result pattern, so try patterns with a result. */
6850 target = NULL_RTX;
6851 }
6852
6853 /* Try the __atomic version. */
6854 result = maybe_emit_op (&optab, target, mem, val, true, model, after);
6855 if (result)
6856 return result;
6857
6858 /* Try the older __sync version. */
6859 result = maybe_emit_op (&optab, target, mem, val, false, model, after);
6860 if (result)
6861 return result;
6862
6863 /* If the fetch value can be calculated from the other variation of fetch,
6864 try that operation. */
6865 if (after || unused_result || optab.reverse_code != UNKNOWN)
6866 {
6867 /* Try the __atomic version, then the older __sync version. */
6868 result = maybe_emit_op (&optab, target, mem, val, true, model, !after);
6869 if (!result)
6870 result = maybe_emit_op (&optab, target, mem, val, false, model, !after);
6871
6872 if (result)
6873 {
6874 /* If the result isn't used, no need to do compensation code. */
6875 if (unused_result)
6876 return result;
6877
6878 /* Issue compensation code. Fetch_after == fetch_before OP val.
6879 Fetch_before == after REVERSE_OP val. */
6880 if (!after)
6881 code = optab.reverse_code;
6882 if (code == NOT)
6883 {
6884 result = expand_simple_binop (mode, AND, result, val, NULL_RTX,
6885 true, OPTAB_LIB_WIDEN);
6886 result = expand_simple_unop (mode, NOT, result, target, true);
6887 }
6888 else
6889 result = expand_simple_binop (mode, code, result, val, target,
6890 true, OPTAB_LIB_WIDEN);
6891 return result;
6892 }
6893 }
6894
6895 /* No direct opcode can be generated. */
6896 return NULL_RTX;
6897 }
6898
6899
6900
6901 /* This function expands an atomic fetch_OP or OP_fetch operation:
6902 TARGET is an option place to stick the return value. const0_rtx indicates
6903 the result is unused.
6904 atomically fetch MEM, perform the operation with VAL and return it to MEM.
6905 CODE is the operation being performed (OP)
6906 MEMMODEL is the memory model variant to use.
6907 AFTER is true to return the result of the operation (OP_fetch).
6908 AFTER is false to return the value before the operation (fetch_OP). */
6909 rtx
expand_atomic_fetch_op(rtx target,rtx mem,rtx val,enum rtx_code code,enum memmodel model,bool after)6910 expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
6911 enum memmodel model, bool after)
6912 {
6913 machine_mode mode = GET_MODE (mem);
6914 rtx result;
6915 bool unused_result = (target == const0_rtx);
6916
6917 /* If loads are not atomic for the required size and we are not called to
6918 provide a __sync builtin, do not do anything so that we stay consistent
6919 with atomic loads of the same size. */
6920 if (!can_atomic_load_p (mode) && !is_mm_sync (model))
6921 return NULL_RTX;
6922
6923 result = expand_atomic_fetch_op_no_fallback (target, mem, val, code, model,
6924 after);
6925
6926 if (result)
6927 return result;
6928
6929 /* Add/sub can be implemented by doing the reverse operation with -(val). */
6930 if (code == PLUS || code == MINUS)
6931 {
6932 rtx tmp;
6933 enum rtx_code reverse = (code == PLUS ? MINUS : PLUS);
6934
6935 start_sequence ();
6936 tmp = expand_simple_unop (mode, NEG, val, NULL_RTX, true);
6937 result = expand_atomic_fetch_op_no_fallback (target, mem, tmp, reverse,
6938 model, after);
6939 if (result)
6940 {
6941 /* PLUS worked so emit the insns and return. */
6942 tmp = get_insns ();
6943 end_sequence ();
6944 emit_insn (tmp);
6945 return result;
6946 }
6947
6948 /* PLUS did not work, so throw away the negation code and continue. */
6949 end_sequence ();
6950 }
6951
6952 /* Try the __sync libcalls only if we can't do compare-and-swap inline. */
6953 if (!can_compare_and_swap_p (mode, false))
6954 {
6955 rtx libfunc;
6956 bool fixup = false;
6957 enum rtx_code orig_code = code;
6958 struct atomic_op_functions optab;
6959
6960 get_atomic_op_for_code (&optab, code);
6961 libfunc = optab_libfunc (after ? optab.fetch_after
6962 : optab.fetch_before, mode);
6963 if (libfunc == NULL
6964 && (after || unused_result || optab.reverse_code != UNKNOWN))
6965 {
6966 fixup = true;
6967 if (!after)
6968 code = optab.reverse_code;
6969 libfunc = optab_libfunc (after ? optab.fetch_before
6970 : optab.fetch_after, mode);
6971 }
6972 if (libfunc != NULL)
6973 {
6974 rtx addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
6975 result = emit_library_call_value (libfunc, NULL, LCT_NORMAL, mode,
6976 addr, ptr_mode, val, mode);
6977
6978 if (!unused_result && fixup)
6979 result = expand_simple_binop (mode, code, result, val, target,
6980 true, OPTAB_LIB_WIDEN);
6981 return result;
6982 }
6983
6984 /* We need the original code for any further attempts. */
6985 code = orig_code;
6986 }
6987
6988 /* If nothing else has succeeded, default to a compare and swap loop. */
6989 if (can_compare_and_swap_p (mode, true))
6990 {
6991 rtx_insn *insn;
6992 rtx t0 = gen_reg_rtx (mode), t1;
6993
6994 start_sequence ();
6995
6996 /* If the result is used, get a register for it. */
6997 if (!unused_result)
6998 {
6999 if (!target || !register_operand (target, mode))
7000 target = gen_reg_rtx (mode);
7001 /* If fetch_before, copy the value now. */
7002 if (!after)
7003 emit_move_insn (target, t0);
7004 }
7005 else
7006 target = const0_rtx;
7007
7008 t1 = t0;
7009 if (code == NOT)
7010 {
7011 t1 = expand_simple_binop (mode, AND, t1, val, NULL_RTX,
7012 true, OPTAB_LIB_WIDEN);
7013 t1 = expand_simple_unop (mode, code, t1, NULL_RTX, true);
7014 }
7015 else
7016 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX, true,
7017 OPTAB_LIB_WIDEN);
7018
7019 /* For after, copy the value now. */
7020 if (!unused_result && after)
7021 emit_move_insn (target, t1);
7022 insn = get_insns ();
7023 end_sequence ();
7024
7025 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
7026 return target;
7027 }
7028
7029 return NULL_RTX;
7030 }
7031
7032 /* Return true if OPERAND is suitable for operand number OPNO of
7033 instruction ICODE. */
7034
7035 bool
insn_operand_matches(enum insn_code icode,unsigned int opno,rtx operand)7036 insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand)
7037 {
7038 return (!insn_data[(int) icode].operand[opno].predicate
7039 || (insn_data[(int) icode].operand[opno].predicate
7040 (operand, insn_data[(int) icode].operand[opno].mode)));
7041 }
7042
7043 /* TARGET is a target of a multiword operation that we are going to
7044 implement as a series of word-mode operations. Return true if
7045 TARGET is suitable for this purpose. */
7046
7047 bool
valid_multiword_target_p(rtx target)7048 valid_multiword_target_p (rtx target)
7049 {
7050 machine_mode mode;
7051 int i, size;
7052
7053 mode = GET_MODE (target);
7054 if (!GET_MODE_SIZE (mode).is_constant (&size))
7055 return false;
7056 for (i = 0; i < size; i += UNITS_PER_WORD)
7057 if (!validate_subreg (word_mode, mode, target, i))
7058 return false;
7059 return true;
7060 }
7061
7062 /* Make OP describe an input operand that has value INTVAL and that has
7063 no inherent mode. This function should only be used for operands that
7064 are always expand-time constants. The backend may request that INTVAL
7065 be copied into a different kind of rtx, but it must specify the mode
7066 of that rtx if so. */
7067
7068 void
create_integer_operand(struct expand_operand * op,poly_int64 intval)7069 create_integer_operand (struct expand_operand *op, poly_int64 intval)
7070 {
7071 create_expand_operand (op, EXPAND_INTEGER,
7072 gen_int_mode (intval, MAX_MODE_INT),
7073 VOIDmode, false, intval);
7074 }
7075
7076 /* Like maybe_legitimize_operand, but do not change the code of the
7077 current rtx value. */
7078
7079 static bool
maybe_legitimize_operand_same_code(enum insn_code icode,unsigned int opno,struct expand_operand * op)7080 maybe_legitimize_operand_same_code (enum insn_code icode, unsigned int opno,
7081 struct expand_operand *op)
7082 {
7083 /* See if the operand matches in its current form. */
7084 if (insn_operand_matches (icode, opno, op->value))
7085 return true;
7086
7087 /* If the operand is a memory whose address has no side effects,
7088 try forcing the address into a non-virtual pseudo register.
7089 The check for side effects is important because copy_to_mode_reg
7090 cannot handle things like auto-modified addresses. */
7091 if (insn_data[(int) icode].operand[opno].allows_mem && MEM_P (op->value))
7092 {
7093 rtx addr, mem;
7094
7095 mem = op->value;
7096 addr = XEXP (mem, 0);
7097 if (!(REG_P (addr) && REGNO (addr) > LAST_VIRTUAL_REGISTER)
7098 && !side_effects_p (addr))
7099 {
7100 rtx_insn *last;
7101 machine_mode mode;
7102
7103 last = get_last_insn ();
7104 mode = get_address_mode (mem);
7105 mem = replace_equiv_address (mem, copy_to_mode_reg (mode, addr));
7106 if (insn_operand_matches (icode, opno, mem))
7107 {
7108 op->value = mem;
7109 return true;
7110 }
7111 delete_insns_since (last);
7112 }
7113 }
7114
7115 return false;
7116 }
7117
7118 /* Try to make OP match operand OPNO of instruction ICODE. Return true
7119 on success, storing the new operand value back in OP. */
7120
7121 static bool
maybe_legitimize_operand(enum insn_code icode,unsigned int opno,struct expand_operand * op)7122 maybe_legitimize_operand (enum insn_code icode, unsigned int opno,
7123 struct expand_operand *op)
7124 {
7125 machine_mode mode, imode;
7126 bool old_volatile_ok, result;
7127
7128 mode = op->mode;
7129 switch (op->type)
7130 {
7131 case EXPAND_FIXED:
7132 old_volatile_ok = volatile_ok;
7133 volatile_ok = true;
7134 result = maybe_legitimize_operand_same_code (icode, opno, op);
7135 volatile_ok = old_volatile_ok;
7136 return result;
7137
7138 case EXPAND_OUTPUT:
7139 gcc_assert (mode != VOIDmode);
7140 if (op->value
7141 && op->value != const0_rtx
7142 && GET_MODE (op->value) == mode
7143 && maybe_legitimize_operand_same_code (icode, opno, op))
7144 return true;
7145
7146 op->value = gen_reg_rtx (mode);
7147 op->target = 0;
7148 break;
7149
7150 case EXPAND_INPUT:
7151 input:
7152 gcc_assert (mode != VOIDmode);
7153 gcc_assert (GET_MODE (op->value) == VOIDmode
7154 || GET_MODE (op->value) == mode);
7155 if (maybe_legitimize_operand_same_code (icode, opno, op))
7156 return true;
7157
7158 op->value = copy_to_mode_reg (mode, op->value);
7159 break;
7160
7161 case EXPAND_CONVERT_TO:
7162 gcc_assert (mode != VOIDmode);
7163 op->value = convert_to_mode (mode, op->value, op->unsigned_p);
7164 goto input;
7165
7166 case EXPAND_CONVERT_FROM:
7167 if (GET_MODE (op->value) != VOIDmode)
7168 mode = GET_MODE (op->value);
7169 else
7170 /* The caller must tell us what mode this value has. */
7171 gcc_assert (mode != VOIDmode);
7172
7173 imode = insn_data[(int) icode].operand[opno].mode;
7174 if (imode != VOIDmode && imode != mode)
7175 {
7176 op->value = convert_modes (imode, mode, op->value, op->unsigned_p);
7177 mode = imode;
7178 }
7179 goto input;
7180
7181 case EXPAND_ADDRESS:
7182 op->value = convert_memory_address (as_a <scalar_int_mode> (mode),
7183 op->value);
7184 goto input;
7185
7186 case EXPAND_INTEGER:
7187 mode = insn_data[(int) icode].operand[opno].mode;
7188 if (mode != VOIDmode
7189 && known_eq (trunc_int_for_mode (op->int_value, mode),
7190 op->int_value))
7191 {
7192 op->value = gen_int_mode (op->int_value, mode);
7193 goto input;
7194 }
7195 break;
7196 }
7197 return insn_operand_matches (icode, opno, op->value);
7198 }
7199
7200 /* Make OP describe an input operand that should have the same value
7201 as VALUE, after any mode conversion that the target might request.
7202 TYPE is the type of VALUE. */
7203
7204 void
create_convert_operand_from_type(struct expand_operand * op,rtx value,tree type)7205 create_convert_operand_from_type (struct expand_operand *op,
7206 rtx value, tree type)
7207 {
7208 create_convert_operand_from (op, value, TYPE_MODE (type),
7209 TYPE_UNSIGNED (type));
7210 }
7211
7212 /* Try to make operands [OPS, OPS + NOPS) match operands [OPNO, OPNO + NOPS)
7213 of instruction ICODE. Return true on success, leaving the new operand
7214 values in the OPS themselves. Emit no code on failure. */
7215
7216 bool
maybe_legitimize_operands(enum insn_code icode,unsigned int opno,unsigned int nops,struct expand_operand * ops)7217 maybe_legitimize_operands (enum insn_code icode, unsigned int opno,
7218 unsigned int nops, struct expand_operand *ops)
7219 {
7220 rtx_insn *last;
7221 unsigned int i;
7222
7223 last = get_last_insn ();
7224 for (i = 0; i < nops; i++)
7225 if (!maybe_legitimize_operand (icode, opno + i, &ops[i]))
7226 {
7227 delete_insns_since (last);
7228 return false;
7229 }
7230 return true;
7231 }
7232
7233 /* Try to generate instruction ICODE, using operands [OPS, OPS + NOPS)
7234 as its operands. Return the instruction pattern on success,
7235 and emit any necessary set-up code. Return null and emit no
7236 code on failure. */
7237
7238 rtx_insn *
maybe_gen_insn(enum insn_code icode,unsigned int nops,struct expand_operand * ops)7239 maybe_gen_insn (enum insn_code icode, unsigned int nops,
7240 struct expand_operand *ops)
7241 {
7242 gcc_assert (nops == (unsigned int) insn_data[(int) icode].n_generator_args);
7243 if (!maybe_legitimize_operands (icode, 0, nops, ops))
7244 return NULL;
7245
7246 switch (nops)
7247 {
7248 case 1:
7249 return GEN_FCN (icode) (ops[0].value);
7250 case 2:
7251 return GEN_FCN (icode) (ops[0].value, ops[1].value);
7252 case 3:
7253 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value);
7254 case 4:
7255 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
7256 ops[3].value);
7257 case 5:
7258 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
7259 ops[3].value, ops[4].value);
7260 case 6:
7261 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
7262 ops[3].value, ops[4].value, ops[5].value);
7263 case 7:
7264 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
7265 ops[3].value, ops[4].value, ops[5].value,
7266 ops[6].value);
7267 case 8:
7268 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
7269 ops[3].value, ops[4].value, ops[5].value,
7270 ops[6].value, ops[7].value);
7271 case 9:
7272 return GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value,
7273 ops[3].value, ops[4].value, ops[5].value,
7274 ops[6].value, ops[7].value, ops[8].value);
7275 }
7276 gcc_unreachable ();
7277 }
7278
7279 /* Try to emit instruction ICODE, using operands [OPS, OPS + NOPS)
7280 as its operands. Return true on success and emit no code on failure. */
7281
7282 bool
maybe_expand_insn(enum insn_code icode,unsigned int nops,struct expand_operand * ops)7283 maybe_expand_insn (enum insn_code icode, unsigned int nops,
7284 struct expand_operand *ops)
7285 {
7286 rtx_insn *pat = maybe_gen_insn (icode, nops, ops);
7287 if (pat)
7288 {
7289 emit_insn (pat);
7290 return true;
7291 }
7292 return false;
7293 }
7294
7295 /* Like maybe_expand_insn, but for jumps. */
7296
7297 bool
maybe_expand_jump_insn(enum insn_code icode,unsigned int nops,struct expand_operand * ops)7298 maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
7299 struct expand_operand *ops)
7300 {
7301 rtx_insn *pat = maybe_gen_insn (icode, nops, ops);
7302 if (pat)
7303 {
7304 emit_jump_insn (pat);
7305 return true;
7306 }
7307 return false;
7308 }
7309
7310 /* Emit instruction ICODE, using operands [OPS, OPS + NOPS)
7311 as its operands. */
7312
7313 void
expand_insn(enum insn_code icode,unsigned int nops,struct expand_operand * ops)7314 expand_insn (enum insn_code icode, unsigned int nops,
7315 struct expand_operand *ops)
7316 {
7317 if (!maybe_expand_insn (icode, nops, ops))
7318 gcc_unreachable ();
7319 }
7320
7321 /* Like expand_insn, but for jumps. */
7322
7323 void
expand_jump_insn(enum insn_code icode,unsigned int nops,struct expand_operand * ops)7324 expand_jump_insn (enum insn_code icode, unsigned int nops,
7325 struct expand_operand *ops)
7326 {
7327 if (!maybe_expand_jump_insn (icode, nops, ops))
7328 gcc_unreachable ();
7329 }
7330