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