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