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