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