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