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