1 /* Internal functions.
2    Copyright (C) 2011-2020 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 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "backend.h"
24 #include "target.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "predict.h"
29 #include "stringpool.h"
30 #include "tree-vrp.h"
31 #include "tree-ssanames.h"
32 #include "expmed.h"
33 #include "memmodel.h"
34 #include "optabs.h"
35 #include "emit-rtl.h"
36 #include "diagnostic-core.h"
37 #include "fold-const.h"
38 #include "internal-fn.h"
39 #include "stor-layout.h"
40 #include "dojump.h"
41 #include "expr.h"
42 #include "stringpool.h"
43 #include "attribs.h"
44 #include "asan.h"
45 #include "ubsan.h"
46 #include "recog.h"
47 #include "builtins.h"
48 #include "optabs-tree.h"
49 #include "gimple-ssa.h"
50 #include "tree-phinodes.h"
51 #include "ssa-iterators.h"
52 
53 /* The names of each internal function, indexed by function number.  */
54 const char *const internal_fn_name_array[] = {
55 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
56 #include "internal-fn.def"
57   "<invalid-fn>"
58 };
59 
60 /* The ECF_* flags of each internal function, indexed by function number.  */
61 const int internal_fn_flags_array[] = {
62 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
63 #include "internal-fn.def"
64   0
65 };
66 
67 /* Return the internal function called NAME, or IFN_LAST if there's
68    no such function.  */
69 
70 internal_fn
lookup_internal_fn(const char * name)71 lookup_internal_fn (const char *name)
72 {
73   typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
74   static name_to_fn_map_type *name_to_fn_map;
75 
76   if (!name_to_fn_map)
77     {
78       name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
79       for (unsigned int i = 0; i < IFN_LAST; ++i)
80 	name_to_fn_map->put (internal_fn_name (internal_fn (i)),
81 			     internal_fn (i));
82     }
83   internal_fn *entry = name_to_fn_map->get (name);
84   return entry ? *entry : IFN_LAST;
85 }
86 
87 /* Fnspec of each internal function, indexed by function number.  */
88 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
89 
90 void
init_internal_fns()91 init_internal_fns ()
92 {
93 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
94   if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
95     build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
96 #include "internal-fn.def"
97   internal_fn_fnspec_array[IFN_LAST] = 0;
98 }
99 
100 /* Create static initializers for the information returned by
101    direct_internal_fn.  */
102 #define not_direct { -2, -2, false }
103 #define mask_load_direct { -1, 2, false }
104 #define load_lanes_direct { -1, -1, false }
105 #define mask_load_lanes_direct { -1, -1, false }
106 #define gather_load_direct { 3, 1, false }
107 #define mask_store_direct { 3, 2, false }
108 #define store_lanes_direct { 0, 0, false }
109 #define mask_store_lanes_direct { 0, 0, false }
110 #define scatter_store_direct { 3, 1, false }
111 #define unary_direct { 0, 0, true }
112 #define binary_direct { 0, 0, true }
113 #define ternary_direct { 0, 0, true }
114 #define cond_unary_direct { 1, 1, true }
115 #define cond_binary_direct { 1, 1, true }
116 #define cond_ternary_direct { 1, 1, true }
117 #define while_direct { 0, 2, false }
118 #define fold_extract_direct { 2, 2, false }
119 #define fold_left_direct { 1, 1, false }
120 #define mask_fold_left_direct { 1, 1, false }
121 #define check_ptrs_direct { 0, 0, false }
122 
123 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
124 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
125 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
126 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
127 				     UNSIGNED_OPTAB, TYPE) TYPE##_direct,
128 #include "internal-fn.def"
129   not_direct
130 };
131 
132 /* ARRAY_TYPE is an array of vector modes.  Return the associated insn
133    for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none.  */
134 
135 static enum insn_code
get_multi_vector_move(tree array_type,convert_optab optab)136 get_multi_vector_move (tree array_type, convert_optab optab)
137 {
138   machine_mode imode;
139   machine_mode vmode;
140 
141   gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
142   imode = TYPE_MODE (array_type);
143   vmode = TYPE_MODE (TREE_TYPE (array_type));
144 
145   return convert_optab_handler (optab, imode, vmode);
146 }
147 
148 /* Expand LOAD_LANES call STMT using optab OPTAB.  */
149 
150 static void
expand_load_lanes_optab_fn(internal_fn,gcall * stmt,convert_optab optab)151 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
152 {
153   class expand_operand ops[2];
154   tree type, lhs, rhs;
155   rtx target, mem;
156 
157   lhs = gimple_call_lhs (stmt);
158   rhs = gimple_call_arg (stmt, 0);
159   type = TREE_TYPE (lhs);
160 
161   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
162   mem = expand_normal (rhs);
163 
164   gcc_assert (MEM_P (mem));
165   PUT_MODE (mem, TYPE_MODE (type));
166 
167   create_output_operand (&ops[0], target, TYPE_MODE (type));
168   create_fixed_operand (&ops[1], mem);
169   expand_insn (get_multi_vector_move (type, optab), 2, ops);
170   if (!rtx_equal_p (target, ops[0].value))
171     emit_move_insn (target, ops[0].value);
172 }
173 
174 /* Expand STORE_LANES call STMT using optab OPTAB.  */
175 
176 static void
expand_store_lanes_optab_fn(internal_fn,gcall * stmt,convert_optab optab)177 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
178 {
179   class expand_operand ops[2];
180   tree type, lhs, rhs;
181   rtx target, reg;
182 
183   lhs = gimple_call_lhs (stmt);
184   rhs = gimple_call_arg (stmt, 0);
185   type = TREE_TYPE (rhs);
186 
187   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
188   reg = expand_normal (rhs);
189 
190   gcc_assert (MEM_P (target));
191   PUT_MODE (target, TYPE_MODE (type));
192 
193   create_fixed_operand (&ops[0], target);
194   create_input_operand (&ops[1], reg, TYPE_MODE (type));
195   expand_insn (get_multi_vector_move (type, optab), 2, ops);
196 }
197 
198 static void
expand_ANNOTATE(internal_fn,gcall *)199 expand_ANNOTATE (internal_fn, gcall *)
200 {
201   gcc_unreachable ();
202 }
203 
204 /* This should get expanded in omp_device_lower pass.  */
205 
206 static void
expand_GOMP_USE_SIMT(internal_fn,gcall *)207 expand_GOMP_USE_SIMT (internal_fn, gcall *)
208 {
209   gcc_unreachable ();
210 }
211 
212 /* This should get expanded in omp_device_lower pass.  */
213 
214 static void
expand_GOMP_SIMT_ENTER(internal_fn,gcall *)215 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
216 {
217   gcc_unreachable ();
218 }
219 
220 /* Allocate per-lane storage and begin non-uniform execution region.  */
221 
222 static void
expand_GOMP_SIMT_ENTER_ALLOC(internal_fn,gcall * stmt)223 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
224 {
225   rtx target;
226   tree lhs = gimple_call_lhs (stmt);
227   if (lhs)
228     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
229   else
230     target = gen_reg_rtx (Pmode);
231   rtx size = expand_normal (gimple_call_arg (stmt, 0));
232   rtx align = expand_normal (gimple_call_arg (stmt, 1));
233   class expand_operand ops[3];
234   create_output_operand (&ops[0], target, Pmode);
235   create_input_operand (&ops[1], size, Pmode);
236   create_input_operand (&ops[2], align, Pmode);
237   gcc_assert (targetm.have_omp_simt_enter ());
238   expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
239 }
240 
241 /* Deallocate per-lane storage and leave non-uniform execution region.  */
242 
243 static void
expand_GOMP_SIMT_EXIT(internal_fn,gcall * stmt)244 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
245 {
246   gcc_checking_assert (!gimple_call_lhs (stmt));
247   rtx arg = expand_normal (gimple_call_arg (stmt, 0));
248   class expand_operand ops[1];
249   create_input_operand (&ops[0], arg, Pmode);
250   gcc_assert (targetm.have_omp_simt_exit ());
251   expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
252 }
253 
254 /* Lane index on SIMT targets: thread index in the warp on NVPTX.  On targets
255    without SIMT execution this should be expanded in omp_device_lower pass.  */
256 
257 static void
expand_GOMP_SIMT_LANE(internal_fn,gcall * stmt)258 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
259 {
260   tree lhs = gimple_call_lhs (stmt);
261   if (!lhs)
262     return;
263 
264   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
265   gcc_assert (targetm.have_omp_simt_lane ());
266   emit_insn (targetm.gen_omp_simt_lane (target));
267 }
268 
269 /* This should get expanded in omp_device_lower pass.  */
270 
271 static void
expand_GOMP_SIMT_VF(internal_fn,gcall *)272 expand_GOMP_SIMT_VF (internal_fn, gcall *)
273 {
274   gcc_unreachable ();
275 }
276 
277 /* Lane index of the first SIMT lane that supplies a non-zero argument.
278    This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
279    lane that executed the last iteration for handling OpenMP lastprivate.  */
280 
281 static void
expand_GOMP_SIMT_LAST_LANE(internal_fn,gcall * stmt)282 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
283 {
284   tree lhs = gimple_call_lhs (stmt);
285   if (!lhs)
286     return;
287 
288   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
289   rtx cond = expand_normal (gimple_call_arg (stmt, 0));
290   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
291   class expand_operand ops[2];
292   create_output_operand (&ops[0], target, mode);
293   create_input_operand (&ops[1], cond, mode);
294   gcc_assert (targetm.have_omp_simt_last_lane ());
295   expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
296 }
297 
298 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered".  */
299 
300 static void
expand_GOMP_SIMT_ORDERED_PRED(internal_fn,gcall * stmt)301 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
302 {
303   tree lhs = gimple_call_lhs (stmt);
304   if (!lhs)
305     return;
306 
307   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
308   rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
309   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
310   class expand_operand ops[2];
311   create_output_operand (&ops[0], target, mode);
312   create_input_operand (&ops[1], ctr, mode);
313   gcc_assert (targetm.have_omp_simt_ordered ());
314   expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
315 }
316 
317 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
318    any lane supplies a non-zero argument.  */
319 
320 static void
expand_GOMP_SIMT_VOTE_ANY(internal_fn,gcall * stmt)321 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
322 {
323   tree lhs = gimple_call_lhs (stmt);
324   if (!lhs)
325     return;
326 
327   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
328   rtx cond = expand_normal (gimple_call_arg (stmt, 0));
329   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
330   class expand_operand ops[2];
331   create_output_operand (&ops[0], target, mode);
332   create_input_operand (&ops[1], cond, mode);
333   gcc_assert (targetm.have_omp_simt_vote_any ());
334   expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
335 }
336 
337 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
338    is destination lane index XOR given offset.  */
339 
340 static void
expand_GOMP_SIMT_XCHG_BFLY(internal_fn,gcall * stmt)341 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
342 {
343   tree lhs = gimple_call_lhs (stmt);
344   if (!lhs)
345     return;
346 
347   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
348   rtx src = expand_normal (gimple_call_arg (stmt, 0));
349   rtx idx = expand_normal (gimple_call_arg (stmt, 1));
350   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
351   class expand_operand ops[3];
352   create_output_operand (&ops[0], target, mode);
353   create_input_operand (&ops[1], src, mode);
354   create_input_operand (&ops[2], idx, SImode);
355   gcc_assert (targetm.have_omp_simt_xchg_bfly ());
356   expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
357 }
358 
359 /* Exchange between SIMT lanes according to given source lane index.  */
360 
361 static void
expand_GOMP_SIMT_XCHG_IDX(internal_fn,gcall * stmt)362 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
363 {
364   tree lhs = gimple_call_lhs (stmt);
365   if (!lhs)
366     return;
367 
368   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
369   rtx src = expand_normal (gimple_call_arg (stmt, 0));
370   rtx idx = expand_normal (gimple_call_arg (stmt, 1));
371   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
372   class expand_operand ops[3];
373   create_output_operand (&ops[0], target, mode);
374   create_input_operand (&ops[1], src, mode);
375   create_input_operand (&ops[2], idx, SImode);
376   gcc_assert (targetm.have_omp_simt_xchg_idx ());
377   expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
378 }
379 
380 /* This should get expanded in adjust_simduid_builtins.  */
381 
382 static void
expand_GOMP_SIMD_LANE(internal_fn,gcall *)383 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
384 {
385   gcc_unreachable ();
386 }
387 
388 /* This should get expanded in adjust_simduid_builtins.  */
389 
390 static void
expand_GOMP_SIMD_VF(internal_fn,gcall *)391 expand_GOMP_SIMD_VF (internal_fn, gcall *)
392 {
393   gcc_unreachable ();
394 }
395 
396 /* This should get expanded in adjust_simduid_builtins.  */
397 
398 static void
expand_GOMP_SIMD_LAST_LANE(internal_fn,gcall *)399 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
400 {
401   gcc_unreachable ();
402 }
403 
404 /* This should get expanded in adjust_simduid_builtins.  */
405 
406 static void
expand_GOMP_SIMD_ORDERED_START(internal_fn,gcall *)407 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
408 {
409   gcc_unreachable ();
410 }
411 
412 /* This should get expanded in adjust_simduid_builtins.  */
413 
414 static void
expand_GOMP_SIMD_ORDERED_END(internal_fn,gcall *)415 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
416 {
417   gcc_unreachable ();
418 }
419 
420 /* This should get expanded in the sanopt pass.  */
421 
422 static void
expand_UBSAN_NULL(internal_fn,gcall *)423 expand_UBSAN_NULL (internal_fn, gcall *)
424 {
425   gcc_unreachable ();
426 }
427 
428 /* This should get expanded in the sanopt pass.  */
429 
430 static void
expand_UBSAN_BOUNDS(internal_fn,gcall *)431 expand_UBSAN_BOUNDS (internal_fn, gcall *)
432 {
433   gcc_unreachable ();
434 }
435 
436 /* This should get expanded in the sanopt pass.  */
437 
438 static void
expand_UBSAN_VPTR(internal_fn,gcall *)439 expand_UBSAN_VPTR (internal_fn, gcall *)
440 {
441   gcc_unreachable ();
442 }
443 
444 /* This should get expanded in the sanopt pass.  */
445 
446 static void
expand_UBSAN_PTR(internal_fn,gcall *)447 expand_UBSAN_PTR (internal_fn, gcall *)
448 {
449   gcc_unreachable ();
450 }
451 
452 /* This should get expanded in the sanopt pass.  */
453 
454 static void
expand_UBSAN_OBJECT_SIZE(internal_fn,gcall *)455 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
456 {
457   gcc_unreachable ();
458 }
459 
460 /* This should get expanded in the sanopt pass.  */
461 
462 static void
expand_ASAN_CHECK(internal_fn,gcall *)463 expand_ASAN_CHECK (internal_fn, gcall *)
464 {
465   gcc_unreachable ();
466 }
467 
468 /* This should get expanded in the sanopt pass.  */
469 
470 static void
expand_ASAN_MARK(internal_fn,gcall *)471 expand_ASAN_MARK (internal_fn, gcall *)
472 {
473   gcc_unreachable ();
474 }
475 
476 /* This should get expanded in the sanopt pass.  */
477 
478 static void
expand_ASAN_POISON(internal_fn,gcall *)479 expand_ASAN_POISON (internal_fn, gcall *)
480 {
481   gcc_unreachable ();
482 }
483 
484 /* This should get expanded in the sanopt pass.  */
485 
486 static void
expand_ASAN_POISON_USE(internal_fn,gcall *)487 expand_ASAN_POISON_USE (internal_fn, gcall *)
488 {
489   gcc_unreachable ();
490 }
491 
492 /* This should get expanded in the tsan pass.  */
493 
494 static void
expand_TSAN_FUNC_EXIT(internal_fn,gcall *)495 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
496 {
497   gcc_unreachable ();
498 }
499 
500 /* This should get expanded in the lower pass.  */
501 
502 static void
expand_FALLTHROUGH(internal_fn,gcall * call)503 expand_FALLTHROUGH (internal_fn, gcall *call)
504 {
505   error_at (gimple_location (call),
506 	    "invalid use of attribute %<fallthrough%>");
507 }
508 
509 /* Return minimum precision needed to represent all values
510    of ARG in SIGNed integral type.  */
511 
512 static int
get_min_precision(tree arg,signop sign)513 get_min_precision (tree arg, signop sign)
514 {
515   int prec = TYPE_PRECISION (TREE_TYPE (arg));
516   int cnt = 0;
517   signop orig_sign = sign;
518   if (TREE_CODE (arg) == INTEGER_CST)
519     {
520       int p;
521       if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
522 	{
523 	  widest_int w = wi::to_widest (arg);
524 	  w = wi::ext (w, prec, sign);
525 	  p = wi::min_precision (w, sign);
526 	}
527       else
528 	p = wi::min_precision (wi::to_wide (arg), sign);
529       return MIN (p, prec);
530     }
531   while (CONVERT_EXPR_P (arg)
532 	 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
533 	 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
534     {
535       arg = TREE_OPERAND (arg, 0);
536       if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
537 	{
538 	  if (TYPE_UNSIGNED (TREE_TYPE (arg)))
539 	    sign = UNSIGNED;
540 	  else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
541 	    return prec + (orig_sign != sign);
542 	  prec = TYPE_PRECISION (TREE_TYPE (arg));
543 	}
544       if (++cnt > 30)
545 	return prec + (orig_sign != sign);
546     }
547   if (TREE_CODE (arg) != SSA_NAME)
548     return prec + (orig_sign != sign);
549   wide_int arg_min, arg_max;
550   while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
551     {
552       gimple *g = SSA_NAME_DEF_STMT (arg);
553       if (is_gimple_assign (g)
554 	  && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
555 	{
556 	  tree t = gimple_assign_rhs1 (g);
557 	  if (INTEGRAL_TYPE_P (TREE_TYPE (t))
558 	      && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
559 	    {
560 	      arg = t;
561 	      if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
562 		{
563 		  if (TYPE_UNSIGNED (TREE_TYPE (arg)))
564 		    sign = UNSIGNED;
565 		  else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
566 		    return prec + (orig_sign != sign);
567 		  prec = TYPE_PRECISION (TREE_TYPE (arg));
568 		}
569 	      if (++cnt > 30)
570 		return prec + (orig_sign != sign);
571 	      continue;
572 	    }
573 	}
574       return prec + (orig_sign != sign);
575     }
576   if (sign == TYPE_SIGN (TREE_TYPE (arg)))
577     {
578       int p1 = wi::min_precision (arg_min, sign);
579       int p2 = wi::min_precision (arg_max, sign);
580       p1 = MAX (p1, p2);
581       prec = MIN (prec, p1);
582     }
583   else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
584     {
585       int p = wi::min_precision (arg_max, UNSIGNED);
586       prec = MIN (prec, p);
587     }
588   return prec + (orig_sign != sign);
589 }
590 
591 /* Helper for expand_*_overflow.  Set the __imag__ part to true
592    (1 except for signed:1 type, in which case store -1).  */
593 
594 static void
expand_arith_set_overflow(tree lhs,rtx target)595 expand_arith_set_overflow (tree lhs, rtx target)
596 {
597   if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
598       && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
599     write_complex_part (target, constm1_rtx, true);
600   else
601     write_complex_part (target, const1_rtx, true);
602 }
603 
604 /* Helper for expand_*_overflow.  Store RES into the __real__ part
605    of TARGET.  If RES has larger MODE than __real__ part of TARGET,
606    set the __imag__ part to 1 if RES doesn't fit into it.  Similarly
607    if LHS has smaller precision than its mode.  */
608 
609 static void
expand_arith_overflow_result_store(tree lhs,rtx target,scalar_int_mode mode,rtx res)610 expand_arith_overflow_result_store (tree lhs, rtx target,
611 				    scalar_int_mode mode, rtx res)
612 {
613   scalar_int_mode tgtmode
614     = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
615   rtx lres = res;
616   if (tgtmode != mode)
617     {
618       rtx_code_label *done_label = gen_label_rtx ();
619       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
620       lres = convert_modes (tgtmode, mode, res, uns);
621       gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
622       do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
623 			       EQ, true, mode, NULL_RTX, NULL, done_label,
624 			       profile_probability::very_likely ());
625       expand_arith_set_overflow (lhs, target);
626       emit_label (done_label);
627     }
628   int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
629   int tgtprec = GET_MODE_PRECISION (tgtmode);
630   if (prec < tgtprec)
631     {
632       rtx_code_label *done_label = gen_label_rtx ();
633       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
634       res = lres;
635       if (uns)
636 	{
637 	  rtx mask
638 	    = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
639 				    tgtmode);
640 	  lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
641 				      true, OPTAB_LIB_WIDEN);
642 	}
643       else
644 	{
645 	  lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
646 			       NULL_RTX, 1);
647 	  lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
648 			       NULL_RTX, 0);
649 	}
650       do_compare_rtx_and_jump (res, lres,
651 			       EQ, true, tgtmode, NULL_RTX, NULL, done_label,
652 			       profile_probability::very_likely ());
653       expand_arith_set_overflow (lhs, target);
654       emit_label (done_label);
655     }
656   write_complex_part (target, lres, false);
657 }
658 
659 /* Helper for expand_*_overflow.  Store RES into TARGET.  */
660 
661 static void
expand_ubsan_result_store(rtx target,rtx res)662 expand_ubsan_result_store (rtx target, rtx res)
663 {
664   if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
665     /* If this is a scalar in a register that is stored in a wider mode
666        than the declared mode, compute the result into its declared mode
667        and then convert to the wider mode.  Our value is the computed
668        expression.  */
669     convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
670   else
671     emit_move_insn (target, res);
672 }
673 
674 /* Add sub/add overflow checking to the statement STMT.
675    CODE says whether the operation is +, or -.  */
676 
677 static void
expand_addsub_overflow(location_t loc,tree_code code,tree lhs,tree arg0,tree arg1,bool unsr_p,bool uns0_p,bool uns1_p,bool is_ubsan,tree * datap)678 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
679 			tree arg0, tree arg1, bool unsr_p, bool uns0_p,
680 			bool uns1_p, bool is_ubsan, tree *datap)
681 {
682   rtx res, target = NULL_RTX;
683   tree fn;
684   rtx_code_label *done_label = gen_label_rtx ();
685   rtx_code_label *do_error = gen_label_rtx ();
686   do_pending_stack_adjust ();
687   rtx op0 = expand_normal (arg0);
688   rtx op1 = expand_normal (arg1);
689   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
690   int prec = GET_MODE_PRECISION (mode);
691   rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
692   bool do_xor = false;
693 
694   if (is_ubsan)
695     gcc_assert (!unsr_p && !uns0_p && !uns1_p);
696 
697   if (lhs)
698     {
699       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
700       if (!is_ubsan)
701 	write_complex_part (target, const0_rtx, true);
702     }
703 
704   /* We assume both operands and result have the same precision
705      here (GET_MODE_BITSIZE (mode)), S stands for signed type
706      with that precision, U for unsigned type with that precision,
707      sgn for unsigned most significant bit in that precision.
708      s1 is signed first operand, u1 is unsigned first operand,
709      s2 is signed second operand, u2 is unsigned second operand,
710      sr is signed result, ur is unsigned result and the following
711      rules say how to compute result (which is always result of
712      the operands as if both were unsigned, cast to the right
713      signedness) and how to compute whether operation overflowed.
714 
715      s1 + s2 -> sr
716 	res = (S) ((U) s1 + (U) s2)
717 	ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
718      s1 - s2 -> sr
719 	res = (S) ((U) s1 - (U) s2)
720 	ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
721      u1 + u2 -> ur
722 	res = u1 + u2
723 	ovf = res < u1 (or jump on carry, but RTL opts will handle it)
724      u1 - u2 -> ur
725 	res = u1 - u2
726 	ovf = res > u1 (or jump on carry, but RTL opts will handle it)
727      s1 + u2 -> sr
728 	res = (S) ((U) s1 + u2)
729 	ovf = ((U) res ^ sgn) < u2
730      s1 + u2 -> ur
731 	t1 = (S) (u2 ^ sgn)
732 	t2 = s1 + t1
733 	res = (U) t2 ^ sgn
734 	ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
735      s1 - u2 -> sr
736 	res = (S) ((U) s1 - u2)
737 	ovf = u2 > ((U) s1 ^ sgn)
738      s1 - u2 -> ur
739 	res = (U) s1 - u2
740 	ovf = s1 < 0 || u2 > (U) s1
741      u1 - s2 -> sr
742 	res = u1 - (U) s2
743  	ovf = u1 >= ((U) s2 ^ sgn)
744      u1 - s2 -> ur
745 	t1 = u1 ^ sgn
746 	t2 = t1 - (U) s2
747 	res = t2 ^ sgn
748 	ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
749      s1 + s2 -> ur
750 	res = (U) s1 + (U) s2
751 	ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
752      u1 + u2 -> sr
753 	res = (S) (u1 + u2)
754 	ovf = (U) res < u2 || res < 0
755      u1 - u2 -> sr
756 	res = (S) (u1 - u2)
757 	ovf = u1 >= u2 ? res < 0 : res >= 0
758      s1 - s2 -> ur
759 	res = (U) s1 - (U) s2
760 	ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0)  */
761 
762   if (code == PLUS_EXPR && uns0_p && !uns1_p)
763     {
764       /* PLUS_EXPR is commutative, if operand signedness differs,
765 	 canonicalize to the first operand being signed and second
766 	 unsigned to simplify following code.  */
767       std::swap (op0, op1);
768       std::swap (arg0, arg1);
769       uns0_p = false;
770       uns1_p = true;
771     }
772 
773   /* u1 +- u2 -> ur  */
774   if (uns0_p && uns1_p && unsr_p)
775     {
776       insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
777                                        : usubv4_optab, mode);
778       if (icode != CODE_FOR_nothing)
779 	{
780 	  class expand_operand ops[4];
781 	  rtx_insn *last = get_last_insn ();
782 
783 	  res = gen_reg_rtx (mode);
784 	  create_output_operand (&ops[0], res, mode);
785 	  create_input_operand (&ops[1], op0, mode);
786 	  create_input_operand (&ops[2], op1, mode);
787 	  create_fixed_operand (&ops[3], do_error);
788 	  if (maybe_expand_insn (icode, 4, ops))
789 	    {
790 	      last = get_last_insn ();
791 	      if (profile_status_for_fn (cfun) != PROFILE_ABSENT
792 		  && JUMP_P (last)
793 		  && any_condjump_p (last)
794 		  && !find_reg_note (last, REG_BR_PROB, 0))
795 		add_reg_br_prob_note (last,
796 				      profile_probability::very_unlikely ());
797 	      emit_jump (done_label);
798 	      goto do_error_label;
799 	    }
800 
801 	  delete_insns_since (last);
802 	}
803 
804       /* Compute the operation.  On RTL level, the addition is always
805 	 unsigned.  */
806       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
807 			  op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
808       rtx tem = op0;
809       /* For PLUS_EXPR, the operation is commutative, so we can pick
810 	 operand to compare against.  For prec <= BITS_PER_WORD, I think
811 	 preferring REG operand is better over CONST_INT, because
812 	 the CONST_INT might enlarge the instruction or CSE would need
813 	 to figure out we'd already loaded it into a register before.
814 	 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
815 	 as then the multi-word comparison can be perhaps simplified.  */
816       if (code == PLUS_EXPR
817 	  && (prec <= BITS_PER_WORD
818 	      ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
819 	      : CONST_SCALAR_INT_P (op1)))
820 	tem = op1;
821       do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
822 			       true, mode, NULL_RTX, NULL, done_label,
823 			       profile_probability::very_likely ());
824       goto do_error_label;
825     }
826 
827   /* s1 +- u2 -> sr  */
828   if (!uns0_p && uns1_p && !unsr_p)
829     {
830       /* Compute the operation.  On RTL level, the addition is always
831 	 unsigned.  */
832       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
833 			  op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
834       rtx tem = expand_binop (mode, add_optab,
835 			      code == PLUS_EXPR ? res : op0, sgn,
836 			      NULL_RTX, false, OPTAB_LIB_WIDEN);
837       do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
838 			       done_label, profile_probability::very_likely ());
839       goto do_error_label;
840     }
841 
842   /* s1 + u2 -> ur  */
843   if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
844     {
845       op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
846 			  OPTAB_LIB_WIDEN);
847       /* As we've changed op1, we have to avoid using the value range
848 	 for the original argument.  */
849       arg1 = error_mark_node;
850       do_xor = true;
851       goto do_signed;
852     }
853 
854   /* u1 - s2 -> ur  */
855   if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
856     {
857       op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
858 			  OPTAB_LIB_WIDEN);
859       /* As we've changed op0, we have to avoid using the value range
860 	 for the original argument.  */
861       arg0 = error_mark_node;
862       do_xor = true;
863       goto do_signed;
864     }
865 
866   /* s1 - u2 -> ur  */
867   if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
868     {
869       /* Compute the operation.  On RTL level, the addition is always
870 	 unsigned.  */
871       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
872 			  OPTAB_LIB_WIDEN);
873       int pos_neg = get_range_pos_neg (arg0);
874       if (pos_neg == 2)
875 	/* If ARG0 is known to be always negative, this is always overflow.  */
876 	emit_jump (do_error);
877       else if (pos_neg == 3)
878 	/* If ARG0 is not known to be always positive, check at runtime.  */
879 	do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
880 				 NULL, do_error, profile_probability::very_unlikely ());
881       do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
882 			       done_label, profile_probability::very_likely ());
883       goto do_error_label;
884     }
885 
886   /* u1 - s2 -> sr  */
887   if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
888     {
889       /* Compute the operation.  On RTL level, the addition is always
890 	 unsigned.  */
891       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
892 			  OPTAB_LIB_WIDEN);
893       rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
894 			      OPTAB_LIB_WIDEN);
895       do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
896 			       done_label, profile_probability::very_likely ());
897       goto do_error_label;
898     }
899 
900   /* u1 + u2 -> sr  */
901   if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
902     {
903       /* Compute the operation.  On RTL level, the addition is always
904 	 unsigned.  */
905       res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
906 			  OPTAB_LIB_WIDEN);
907       do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
908 			       NULL, do_error, profile_probability::very_unlikely ());
909       rtx tem = op1;
910       /* The operation is commutative, so we can pick operand to compare
911 	 against.  For prec <= BITS_PER_WORD, I think preferring REG operand
912 	 is better over CONST_INT, because the CONST_INT might enlarge the
913 	 instruction or CSE would need to figure out we'd already loaded it
914 	 into a register before.  For prec > BITS_PER_WORD, I think CONST_INT
915 	 might be more beneficial, as then the multi-word comparison can be
916 	 perhaps simplified.  */
917       if (prec <= BITS_PER_WORD
918 	  ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
919 	  : CONST_SCALAR_INT_P (op0))
920 	tem = op0;
921       do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
922 			       done_label, profile_probability::very_likely ());
923       goto do_error_label;
924     }
925 
926   /* s1 +- s2 -> ur  */
927   if (!uns0_p && !uns1_p && unsr_p)
928     {
929       /* Compute the operation.  On RTL level, the addition is always
930 	 unsigned.  */
931       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
932 			  op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
933       int pos_neg = get_range_pos_neg (arg1);
934       if (code == PLUS_EXPR)
935 	{
936 	  int pos_neg0 = get_range_pos_neg (arg0);
937 	  if (pos_neg0 != 3 && pos_neg == 3)
938 	    {
939 	      std::swap (op0, op1);
940 	      pos_neg = pos_neg0;
941 	    }
942 	}
943       rtx tem;
944       if (pos_neg != 3)
945 	{
946 	  tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
947 				    ? and_optab : ior_optab,
948 			      op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
949 	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
950 				   NULL, done_label, profile_probability::very_likely ());
951 	}
952       else
953 	{
954 	  rtx_code_label *do_ior_label = gen_label_rtx ();
955 	  do_compare_rtx_and_jump (op1, const0_rtx,
956 				   code == MINUS_EXPR ? GE : LT, false, mode,
957 				   NULL_RTX, NULL, do_ior_label,
958 				   profile_probability::even ());
959 	  tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
960 			      OPTAB_LIB_WIDEN);
961 	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
962 				   NULL, done_label, profile_probability::very_likely ());
963 	  emit_jump (do_error);
964 	  emit_label (do_ior_label);
965 	  tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
966 			      OPTAB_LIB_WIDEN);
967 	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
968 				   NULL, done_label, profile_probability::very_likely ());
969 	}
970       goto do_error_label;
971     }
972 
973   /* u1 - u2 -> sr  */
974   if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
975     {
976       /* Compute the operation.  On RTL level, the addition is always
977 	 unsigned.  */
978       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
979 			  OPTAB_LIB_WIDEN);
980       rtx_code_label *op0_geu_op1 = gen_label_rtx ();
981       do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
982 			       op0_geu_op1, profile_probability::even ());
983       do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
984 			       NULL, done_label, profile_probability::very_likely ());
985       emit_jump (do_error);
986       emit_label (op0_geu_op1);
987       do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
988 			       NULL, done_label, profile_probability::very_likely ());
989       goto do_error_label;
990     }
991 
992   gcc_assert (!uns0_p && !uns1_p && !unsr_p);
993 
994   /* s1 +- s2 -> sr  */
995  do_signed:
996   {
997     insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
998 				     : subv4_optab, mode);
999     if (icode != CODE_FOR_nothing)
1000       {
1001 	class expand_operand ops[4];
1002 	rtx_insn *last = get_last_insn ();
1003 
1004 	res = gen_reg_rtx (mode);
1005 	create_output_operand (&ops[0], res, mode);
1006 	create_input_operand (&ops[1], op0, mode);
1007 	create_input_operand (&ops[2], op1, mode);
1008 	create_fixed_operand (&ops[3], do_error);
1009 	if (maybe_expand_insn (icode, 4, ops))
1010 	  {
1011 	    last = get_last_insn ();
1012 	    if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1013 		&& JUMP_P (last)
1014 		&& any_condjump_p (last)
1015 		&& !find_reg_note (last, REG_BR_PROB, 0))
1016 	      add_reg_br_prob_note (last,
1017 				    profile_probability::very_unlikely ());
1018 	    emit_jump (done_label);
1019 	    goto do_error_label;
1020 	  }
1021 
1022 	delete_insns_since (last);
1023       }
1024 
1025     /* Compute the operation.  On RTL level, the addition is always
1026        unsigned.  */
1027     res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1028 			op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1029 
1030     /* If we can prove that one of the arguments (for MINUS_EXPR only
1031        the second operand, as subtraction is not commutative) is always
1032        non-negative or always negative, we can do just one comparison
1033        and conditional jump.  */
1034     int pos_neg = get_range_pos_neg (arg1);
1035     if (code == PLUS_EXPR)
1036       {
1037 	int pos_neg0 = get_range_pos_neg (arg0);
1038 	if (pos_neg0 != 3 && pos_neg == 3)
1039 	  {
1040 	    std::swap (op0, op1);
1041 	    pos_neg = pos_neg0;
1042 	  }
1043       }
1044 
1045     /* Addition overflows if and only if the two operands have the same sign,
1046        and the result has the opposite sign.  Subtraction overflows if and
1047        only if the two operands have opposite sign, and the subtrahend has
1048        the same sign as the result.  Here 0 is counted as positive.  */
1049     if (pos_neg == 3)
1050       {
1051 	/* Compute op0 ^ op1 (operands have opposite sign).  */
1052         rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1053 				   OPTAB_LIB_WIDEN);
1054 
1055 	/* Compute res ^ op1 (result and 2nd operand have opposite sign).  */
1056 	rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1057 				    OPTAB_LIB_WIDEN);
1058 
1059 	rtx tem;
1060 	if (code == PLUS_EXPR)
1061 	  {
1062 	    /* Compute (res ^ op1) & ~(op0 ^ op1).  */
1063 	    tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1064 	    tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1065 				OPTAB_LIB_WIDEN);
1066 	  }
1067 	else
1068 	  {
1069 	    /* Compute (op0 ^ op1) & ~(res ^ op1).  */
1070 	    tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1071 	    tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1072 				OPTAB_LIB_WIDEN);
1073 	  }
1074 
1075 	/* No overflow if the result has bit sign cleared.  */
1076 	do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1077 				 NULL, done_label, profile_probability::very_likely ());
1078       }
1079 
1080     /* Compare the result of the operation with the first operand.
1081        No overflow for addition if second operand is positive and result
1082        is larger or second operand is negative and result is smaller.
1083        Likewise for subtraction with sign of second operand flipped.  */
1084     else
1085       do_compare_rtx_and_jump (res, op0,
1086 			       (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1087 			       false, mode, NULL_RTX, NULL, done_label,
1088 			       profile_probability::very_likely ());
1089   }
1090 
1091  do_error_label:
1092   emit_label (do_error);
1093   if (is_ubsan)
1094     {
1095       /* Expand the ubsan builtin call.  */
1096       push_temp_slots ();
1097       fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1098 					 arg0, arg1, datap);
1099       expand_normal (fn);
1100       pop_temp_slots ();
1101       do_pending_stack_adjust ();
1102     }
1103   else if (lhs)
1104     expand_arith_set_overflow (lhs, target);
1105 
1106   /* We're done.  */
1107   emit_label (done_label);
1108 
1109   if (lhs)
1110     {
1111       if (is_ubsan)
1112 	expand_ubsan_result_store (target, res);
1113       else
1114 	{
1115 	  if (do_xor)
1116 	    res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1117 				OPTAB_LIB_WIDEN);
1118 
1119 	  expand_arith_overflow_result_store (lhs, target, mode, res);
1120 	}
1121     }
1122 }
1123 
1124 /* Add negate overflow checking to the statement STMT.  */
1125 
1126 static void
expand_neg_overflow(location_t loc,tree lhs,tree arg1,bool is_ubsan,tree * datap)1127 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1128 		     tree *datap)
1129 {
1130   rtx res, op1;
1131   tree fn;
1132   rtx_code_label *done_label, *do_error;
1133   rtx target = NULL_RTX;
1134 
1135   done_label = gen_label_rtx ();
1136   do_error = gen_label_rtx ();
1137 
1138   do_pending_stack_adjust ();
1139   op1 = expand_normal (arg1);
1140 
1141   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1142   if (lhs)
1143     {
1144       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1145       if (!is_ubsan)
1146 	write_complex_part (target, const0_rtx, true);
1147     }
1148 
1149   enum insn_code icode = optab_handler (negv3_optab, mode);
1150   if (icode != CODE_FOR_nothing)
1151     {
1152       class expand_operand ops[3];
1153       rtx_insn *last = get_last_insn ();
1154 
1155       res = gen_reg_rtx (mode);
1156       create_output_operand (&ops[0], res, mode);
1157       create_input_operand (&ops[1], op1, mode);
1158       create_fixed_operand (&ops[2], do_error);
1159       if (maybe_expand_insn (icode, 3, ops))
1160 	{
1161 	  last = get_last_insn ();
1162 	  if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1163 	      && JUMP_P (last)
1164 	      && any_condjump_p (last)
1165 	      && !find_reg_note (last, REG_BR_PROB, 0))
1166 	    add_reg_br_prob_note (last,
1167 				  profile_probability::very_unlikely ());
1168 	  emit_jump (done_label);
1169         }
1170       else
1171 	{
1172 	  delete_insns_since (last);
1173 	  icode = CODE_FOR_nothing;
1174 	}
1175     }
1176 
1177   if (icode == CODE_FOR_nothing)
1178     {
1179       /* Compute the operation.  On RTL level, the addition is always
1180 	 unsigned.  */
1181       res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1182 
1183       /* Compare the operand with the most negative value.  */
1184       rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1185       do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1186 			       done_label, profile_probability::very_likely ());
1187     }
1188 
1189   emit_label (do_error);
1190   if (is_ubsan)
1191     {
1192       /* Expand the ubsan builtin call.  */
1193       push_temp_slots ();
1194       fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1195 					 arg1, NULL_TREE, datap);
1196       expand_normal (fn);
1197       pop_temp_slots ();
1198       do_pending_stack_adjust ();
1199     }
1200   else if (lhs)
1201     expand_arith_set_overflow (lhs, target);
1202 
1203   /* We're done.  */
1204   emit_label (done_label);
1205 
1206   if (lhs)
1207     {
1208       if (is_ubsan)
1209 	expand_ubsan_result_store (target, res);
1210       else
1211 	expand_arith_overflow_result_store (lhs, target, mode, res);
1212     }
1213 }
1214 
1215 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1216    mode MODE can be expanded without using a libcall.  */
1217 
1218 static bool
can_widen_mult_without_libcall(scalar_int_mode wmode,scalar_int_mode mode,rtx op0,rtx op1,bool uns)1219 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1220 				rtx op0, rtx op1, bool uns)
1221 {
1222   if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1223       != CODE_FOR_nothing)
1224     return true;
1225 
1226   if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1227       != CODE_FOR_nothing)
1228     return true;
1229 
1230   rtx_insn *last = get_last_insn ();
1231   if (CONSTANT_P (op0))
1232     op0 = convert_modes (wmode, mode, op0, uns);
1233   else
1234     op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1235   if (CONSTANT_P (op1))
1236     op1 = convert_modes (wmode, mode, op1, uns);
1237   else
1238     op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1239   rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1240   delete_insns_since (last);
1241   return ret != NULL_RTX;
1242 }
1243 
1244 /* Add mul overflow checking to the statement STMT.  */
1245 
1246 static void
expand_mul_overflow(location_t loc,tree lhs,tree arg0,tree arg1,bool unsr_p,bool uns0_p,bool uns1_p,bool is_ubsan,tree * datap)1247 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1248 		     bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1249 		     tree *datap)
1250 {
1251   rtx res, op0, op1;
1252   tree fn, type;
1253   rtx_code_label *done_label, *do_error;
1254   rtx target = NULL_RTX;
1255   signop sign;
1256   enum insn_code icode;
1257 
1258   done_label = gen_label_rtx ();
1259   do_error = gen_label_rtx ();
1260 
1261   do_pending_stack_adjust ();
1262   op0 = expand_normal (arg0);
1263   op1 = expand_normal (arg1);
1264 
1265   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1266   bool uns = unsr_p;
1267   if (lhs)
1268     {
1269       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1270       if (!is_ubsan)
1271 	write_complex_part (target, const0_rtx, true);
1272     }
1273 
1274   if (is_ubsan)
1275     gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1276 
1277   /* We assume both operands and result have the same precision
1278      here (GET_MODE_BITSIZE (mode)), S stands for signed type
1279      with that precision, U for unsigned type with that precision,
1280      sgn for unsigned most significant bit in that precision.
1281      s1 is signed first operand, u1 is unsigned first operand,
1282      s2 is signed second operand, u2 is unsigned second operand,
1283      sr is signed result, ur is unsigned result and the following
1284      rules say how to compute result (which is always result of
1285      the operands as if both were unsigned, cast to the right
1286      signedness) and how to compute whether operation overflowed.
1287      main_ovf (false) stands for jump on signed multiplication
1288      overflow or the main algorithm with uns == false.
1289      main_ovf (true) stands for jump on unsigned multiplication
1290      overflow or the main algorithm with uns == true.
1291 
1292      s1 * s2 -> sr
1293 	res = (S) ((U) s1 * (U) s2)
1294 	ovf = main_ovf (false)
1295      u1 * u2 -> ur
1296 	res = u1 * u2
1297 	ovf = main_ovf (true)
1298      s1 * u2 -> ur
1299 	res = (U) s1 * u2
1300 	ovf = (s1 < 0 && u2) || main_ovf (true)
1301      u1 * u2 -> sr
1302 	res = (S) (u1 * u2)
1303 	ovf = res < 0 || main_ovf (true)
1304      s1 * u2 -> sr
1305 	res = (S) ((U) s1 * u2)
1306 	ovf = (S) u2 >= 0 ? main_ovf (false)
1307 			  : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1308      s1 * s2 -> ur
1309 	t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1310 	t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1311 	res = t1 * t2
1312 	ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true)  */
1313 
1314   if (uns0_p && !uns1_p)
1315     {
1316       /* Multiplication is commutative, if operand signedness differs,
1317 	 canonicalize to the first operand being signed and second
1318 	 unsigned to simplify following code.  */
1319       std::swap (op0, op1);
1320       std::swap (arg0, arg1);
1321       uns0_p = false;
1322       uns1_p = true;
1323     }
1324 
1325   int pos_neg0 = get_range_pos_neg (arg0);
1326   int pos_neg1 = get_range_pos_neg (arg1);
1327 
1328   /* s1 * u2 -> ur  */
1329   if (!uns0_p && uns1_p && unsr_p)
1330     {
1331       switch (pos_neg0)
1332 	{
1333 	case 1:
1334 	  /* If s1 is non-negative, just perform normal u1 * u2 -> ur.  */
1335 	  goto do_main;
1336 	case 2:
1337 	  /* If s1 is negative, avoid the main code, just multiply and
1338 	     signal overflow if op1 is not 0.  */
1339 	  struct separate_ops ops;
1340 	  ops.code = MULT_EXPR;
1341 	  ops.type = TREE_TYPE (arg1);
1342 	  ops.op0 = make_tree (ops.type, op0);
1343 	  ops.op1 = make_tree (ops.type, op1);
1344 	  ops.op2 = NULL_TREE;
1345 	  ops.location = loc;
1346 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1347 	  do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1348 				   NULL, done_label, profile_probability::very_likely ());
1349 	  goto do_error_label;
1350 	case 3:
1351 	  rtx_code_label *do_main_label;
1352 	  do_main_label = gen_label_rtx ();
1353 	  do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1354 				   NULL, do_main_label, profile_probability::very_likely ());
1355 	  do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1356 				   NULL, do_main_label, profile_probability::very_likely ());
1357 	  expand_arith_set_overflow (lhs, target);
1358 	  emit_label (do_main_label);
1359 	  goto do_main;
1360 	default:
1361 	  gcc_unreachable ();
1362 	}
1363     }
1364 
1365   /* u1 * u2 -> sr  */
1366   if (uns0_p && uns1_p && !unsr_p)
1367     {
1368       uns = true;
1369       /* Rest of handling of this case after res is computed.  */
1370       goto do_main;
1371     }
1372 
1373   /* s1 * u2 -> sr  */
1374   if (!uns0_p && uns1_p && !unsr_p)
1375     {
1376       switch (pos_neg1)
1377 	{
1378 	case 1:
1379 	  goto do_main;
1380 	case 2:
1381 	  /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1382 	     avoid the main code, just multiply and signal overflow
1383 	     unless 0 * u2 or -1 * ((U) Smin).  */
1384 	  struct separate_ops ops;
1385 	  ops.code = MULT_EXPR;
1386 	  ops.type = TREE_TYPE (arg1);
1387 	  ops.op0 = make_tree (ops.type, op0);
1388 	  ops.op1 = make_tree (ops.type, op1);
1389 	  ops.op2 = NULL_TREE;
1390 	  ops.location = loc;
1391 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1392 	  do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1393 				   NULL, done_label, profile_probability::very_likely ());
1394 	  do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1395 				   NULL, do_error, profile_probability::very_unlikely ());
1396 	  int prec;
1397 	  prec = GET_MODE_PRECISION (mode);
1398 	  rtx sgn;
1399 	  sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1400 	  do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1401 				   NULL, done_label, profile_probability::very_likely ());
1402 	  goto do_error_label;
1403 	case 3:
1404 	  /* Rest of handling of this case after res is computed.  */
1405 	  goto do_main;
1406 	default:
1407 	  gcc_unreachable ();
1408 	}
1409     }
1410 
1411   /* s1 * s2 -> ur  */
1412   if (!uns0_p && !uns1_p && unsr_p)
1413     {
1414       rtx tem;
1415       switch (pos_neg0 | pos_neg1)
1416 	{
1417 	case 1: /* Both operands known to be non-negative.  */
1418 	  goto do_main;
1419 	case 2: /* Both operands known to be negative.  */
1420 	  op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1421 	  op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1422 	  /* Avoid looking at arg0/arg1 ranges, as we've changed
1423 	     the arguments.  */
1424 	  arg0 = error_mark_node;
1425 	  arg1 = error_mark_node;
1426 	  goto do_main;
1427 	case 3:
1428 	  if ((pos_neg0 ^ pos_neg1) == 3)
1429 	    {
1430 	      /* If one operand is known to be negative and the other
1431 		 non-negative, this overflows always, unless the non-negative
1432 		 one is 0.  Just do normal multiply and set overflow
1433 		 unless one of the operands is 0.  */
1434 	      struct separate_ops ops;
1435 	      ops.code = MULT_EXPR;
1436 	      ops.type
1437 		= build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1438 						  1);
1439 	      ops.op0 = make_tree (ops.type, op0);
1440 	      ops.op1 = make_tree (ops.type, op1);
1441 	      ops.op2 = NULL_TREE;
1442 	      ops.location = loc;
1443 	      res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1444 	      do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1445 				       true, mode, NULL_RTX, NULL, done_label,
1446 				       profile_probability::very_likely ());
1447 	      goto do_error_label;
1448 	    }
1449 	  /* The general case, do all the needed comparisons at runtime.  */
1450 	  rtx_code_label *do_main_label, *after_negate_label;
1451 	  rtx rop0, rop1;
1452 	  rop0 = gen_reg_rtx (mode);
1453 	  rop1 = gen_reg_rtx (mode);
1454 	  emit_move_insn (rop0, op0);
1455 	  emit_move_insn (rop1, op1);
1456 	  op0 = rop0;
1457 	  op1 = rop1;
1458 	  do_main_label = gen_label_rtx ();
1459 	  after_negate_label = gen_label_rtx ();
1460 	  tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1461 			      OPTAB_LIB_WIDEN);
1462 	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1463 				   NULL, after_negate_label, profile_probability::very_likely ());
1464 	  /* Both arguments negative here, negate them and continue with
1465 	     normal unsigned overflow checking multiplication.  */
1466 	  emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1467 					    NULL_RTX, false));
1468 	  emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1469 					    NULL_RTX, false));
1470 	  /* Avoid looking at arg0/arg1 ranges, as we might have changed
1471 	     the arguments.  */
1472 	  arg0 = error_mark_node;
1473 	  arg1 = error_mark_node;
1474 	  emit_jump (do_main_label);
1475 	  emit_label (after_negate_label);
1476 	  tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1477 			      OPTAB_LIB_WIDEN);
1478 	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1479 				   NULL, do_main_label,
1480 				   profile_probability::very_likely ());
1481 	  /* One argument is negative here, the other positive.  This
1482 	     overflows always, unless one of the arguments is 0.  But
1483 	     if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1484 	     is, thus we can keep do_main code oring in overflow as is.  */
1485 	  if (pos_neg0 != 2)
1486 	    do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1487 				     NULL, do_main_label,
1488 				     profile_probability::very_unlikely ());
1489 	  if (pos_neg1 != 2)
1490 	    do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1491 				     NULL, do_main_label,
1492 				     profile_probability::very_unlikely ());
1493 	  expand_arith_set_overflow (lhs, target);
1494 	  emit_label (do_main_label);
1495 	  goto do_main;
1496 	default:
1497 	  gcc_unreachable ();
1498 	}
1499     }
1500 
1501  do_main:
1502   type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1503   sign = uns ? UNSIGNED : SIGNED;
1504   icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1505   if (uns
1506       && (integer_pow2p (arg0) || integer_pow2p (arg1))
1507       && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1508     {
1509       /* Optimize unsigned multiplication by power of 2 constant
1510 	 using 2 shifts, one for result, one to extract the shifted
1511 	 out bits to see if they are all zero.
1512 	 Don't do this if optimizing for size and we have umulv4_optab,
1513 	 in that case assume multiplication will be shorter.
1514 	 This is heuristics based on the single target that provides
1515 	 umulv4 right now (i?86/x86_64), if further targets add it, this
1516 	 might need to be revisited.
1517 	 Cases where both operands are constant should be folded already
1518 	 during GIMPLE, and cases where one operand is constant but not
1519 	 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1520 	 below can be done without multiplication, just by shifts and adds,
1521 	 or we'd need to divide the result (and hope it actually doesn't
1522 	 really divide nor multiply) and compare the result of the division
1523 	 with the original operand.  */
1524       rtx opn0 = op0;
1525       rtx opn1 = op1;
1526       tree argn0 = arg0;
1527       tree argn1 = arg1;
1528       if (integer_pow2p (arg0))
1529 	{
1530 	  std::swap (opn0, opn1);
1531 	  std::swap (argn0, argn1);
1532 	}
1533       int cnt = tree_log2 (argn1);
1534       if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1535 	{
1536 	  rtx upper = const0_rtx;
1537 	  res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1538 	  if (cnt != 0)
1539 	    upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1540 				  GET_MODE_PRECISION (mode) - cnt,
1541 				  NULL_RTX, uns);
1542 	  do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1543 				   NULL_RTX, NULL, done_label,
1544 				   profile_probability::very_likely ());
1545 	  goto do_error_label;
1546 	}
1547     }
1548   if (icode != CODE_FOR_nothing)
1549     {
1550       class expand_operand ops[4];
1551       rtx_insn *last = get_last_insn ();
1552 
1553       res = gen_reg_rtx (mode);
1554       create_output_operand (&ops[0], res, mode);
1555       create_input_operand (&ops[1], op0, mode);
1556       create_input_operand (&ops[2], op1, mode);
1557       create_fixed_operand (&ops[3], do_error);
1558       if (maybe_expand_insn (icode, 4, ops))
1559 	{
1560 	  last = get_last_insn ();
1561 	  if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1562 	      && JUMP_P (last)
1563 	      && any_condjump_p (last)
1564 	      && !find_reg_note (last, REG_BR_PROB, 0))
1565 	    add_reg_br_prob_note (last,
1566 				  profile_probability::very_unlikely ());
1567 	  emit_jump (done_label);
1568         }
1569       else
1570 	{
1571 	  delete_insns_since (last);
1572 	  icode = CODE_FOR_nothing;
1573 	}
1574     }
1575 
1576   if (icode == CODE_FOR_nothing)
1577     {
1578       struct separate_ops ops;
1579       int prec = GET_MODE_PRECISION (mode);
1580       scalar_int_mode hmode, wmode;
1581       ops.op0 = make_tree (type, op0);
1582       ops.op1 = make_tree (type, op1);
1583       ops.op2 = NULL_TREE;
1584       ops.location = loc;
1585 
1586       /* Optimize unsigned overflow check where we don't use the
1587 	 multiplication result, just whether overflow happened.
1588 	 If we can do MULT_HIGHPART_EXPR, that followed by
1589 	 comparison of the result against zero is cheapest.
1590 	 We'll still compute res, but it should be DCEd later.  */
1591       use_operand_p use;
1592       gimple *use_stmt;
1593       if (!is_ubsan
1594 	  && lhs
1595 	  && uns
1596 	  && !(uns0_p && uns1_p && !unsr_p)
1597 	  && can_mult_highpart_p (mode, uns) == 1
1598 	  && single_imm_use (lhs, &use, &use_stmt)
1599 	  && is_gimple_assign (use_stmt)
1600 	  && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1601 	goto highpart;
1602 
1603       if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1604 	  && targetm.scalar_mode_supported_p (wmode)
1605 	  && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1606 	{
1607 	twoxwider:
1608 	  ops.code = WIDEN_MULT_EXPR;
1609 	  ops.type
1610 	    = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1611 
1612 	  res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1613 	  rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1614 				     NULL_RTX, uns);
1615 	  hipart = convert_modes (mode, wmode, hipart, uns);
1616 	  res = convert_modes (mode, wmode, res, uns);
1617 	  if (uns)
1618 	    /* For the unsigned multiplication, there was overflow if
1619 	       HIPART is non-zero.  */
1620 	    do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1621 				     NULL_RTX, NULL, done_label,
1622 				     profile_probability::very_likely ());
1623 	  else
1624 	    {
1625 	      rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1626 					  NULL_RTX, 0);
1627 	      /* RES is low half of the double width result, HIPART
1628 		 the high half.  There was overflow if
1629 		 HIPART is different from RES < 0 ? -1 : 0.  */
1630 	      do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1631 				       NULL_RTX, NULL, done_label,
1632 				       profile_probability::very_likely ());
1633 	    }
1634 	}
1635       else if (can_mult_highpart_p (mode, uns) == 1)
1636 	{
1637 	highpart:
1638 	  ops.code = MULT_HIGHPART_EXPR;
1639 	  ops.type = type;
1640 
1641 	  rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1642 					   EXPAND_NORMAL);
1643 	  ops.code = MULT_EXPR;
1644 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1645 	  if (uns)
1646 	    /* For the unsigned multiplication, there was overflow if
1647 	       HIPART is non-zero.  */
1648 	    do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1649 				     NULL_RTX, NULL, done_label,
1650 				     profile_probability::very_likely ());
1651 	  else
1652 	    {
1653 	      rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1654 					  NULL_RTX, 0);
1655 	      /* RES is low half of the double width result, HIPART
1656 		 the high half.  There was overflow if
1657 		 HIPART is different from RES < 0 ? -1 : 0.  */
1658 	      do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1659 				       NULL_RTX, NULL, done_label,
1660 				       profile_probability::very_likely ());
1661 	    }
1662 
1663 	}
1664       else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
1665 	       && 2 * GET_MODE_PRECISION (hmode) == prec)
1666 	{
1667 	  rtx_code_label *large_op0 = gen_label_rtx ();
1668 	  rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1669 	  rtx_code_label *one_small_one_large = gen_label_rtx ();
1670 	  rtx_code_label *both_ops_large = gen_label_rtx ();
1671 	  rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1672 	  rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1673 	  rtx_code_label *do_overflow = gen_label_rtx ();
1674 	  rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1675 
1676 	  unsigned int hprec = GET_MODE_PRECISION (hmode);
1677 	  rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1678 				      NULL_RTX, uns);
1679 	  hipart0 = convert_modes (hmode, mode, hipart0, uns);
1680 	  rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1681 	  rtx signbit0 = const0_rtx;
1682 	  if (!uns)
1683 	    signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1684 				     NULL_RTX, 0);
1685 	  rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1686 				      NULL_RTX, uns);
1687 	  hipart1 = convert_modes (hmode, mode, hipart1, uns);
1688 	  rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1689 	  rtx signbit1 = const0_rtx;
1690 	  if (!uns)
1691 	    signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1692 				     NULL_RTX, 0);
1693 
1694 	  res = gen_reg_rtx (mode);
1695 
1696 	  /* True if op0 resp. op1 are known to be in the range of
1697 	     halfstype.  */
1698 	  bool op0_small_p = false;
1699 	  bool op1_small_p = false;
1700 	  /* True if op0 resp. op1 are known to have all zeros or all ones
1701 	     in the upper half of bits, but are not known to be
1702 	     op{0,1}_small_p.  */
1703 	  bool op0_medium_p = false;
1704 	  bool op1_medium_p = false;
1705 	  /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1706 	     nonnegative, 1 if unknown.  */
1707 	  int op0_sign = 1;
1708 	  int op1_sign = 1;
1709 
1710 	  if (pos_neg0 == 1)
1711 	    op0_sign = 0;
1712 	  else if (pos_neg0 == 2)
1713 	    op0_sign = -1;
1714 	  if (pos_neg1 == 1)
1715 	    op1_sign = 0;
1716 	  else if (pos_neg1 == 2)
1717 	    op1_sign = -1;
1718 
1719 	  unsigned int mprec0 = prec;
1720 	  if (arg0 != error_mark_node)
1721 	    mprec0 = get_min_precision (arg0, sign);
1722 	  if (mprec0 <= hprec)
1723 	    op0_small_p = true;
1724 	  else if (!uns && mprec0 <= hprec + 1)
1725 	    op0_medium_p = true;
1726 	  unsigned int mprec1 = prec;
1727 	  if (arg1 != error_mark_node)
1728 	    mprec1 = get_min_precision (arg1, sign);
1729 	  if (mprec1 <= hprec)
1730 	    op1_small_p = true;
1731 	  else if (!uns && mprec1 <= hprec + 1)
1732 	    op1_medium_p = true;
1733 
1734 	  int smaller_sign = 1;
1735 	  int larger_sign = 1;
1736 	  if (op0_small_p)
1737 	    {
1738 	      smaller_sign = op0_sign;
1739 	      larger_sign = op1_sign;
1740 	    }
1741 	  else if (op1_small_p)
1742 	    {
1743 	      smaller_sign = op1_sign;
1744 	      larger_sign = op0_sign;
1745 	    }
1746 	  else if (op0_sign == op1_sign)
1747 	    {
1748 	      smaller_sign = op0_sign;
1749 	      larger_sign = op0_sign;
1750 	    }
1751 
1752 	  if (!op0_small_p)
1753 	    do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1754 				     NULL_RTX, NULL, large_op0,
1755 				     profile_probability::unlikely ());
1756 
1757 	  if (!op1_small_p)
1758 	    do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1759 				     NULL_RTX, NULL, small_op0_large_op1,
1760 				     profile_probability::unlikely ());
1761 
1762 	  /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1763 	     hmode to mode, the multiplication will never overflow.  We can
1764 	     do just one hmode x hmode => mode widening multiplication.  */
1765 	  tree halfstype = build_nonstandard_integer_type (hprec, uns);
1766 	  ops.op0 = make_tree (halfstype, lopart0);
1767 	  ops.op1 = make_tree (halfstype, lopart1);
1768 	  ops.code = WIDEN_MULT_EXPR;
1769 	  ops.type = type;
1770 	  rtx thisres
1771 	    = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1772 	  emit_move_insn (res, thisres);
1773 	  emit_jump (done_label);
1774 
1775 	  emit_label (small_op0_large_op1);
1776 
1777 	  /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1778 	     but op1 is not, just swap the arguments and handle it as op1
1779 	     sign/zero extended, op0 not.  */
1780 	  rtx larger = gen_reg_rtx (mode);
1781 	  rtx hipart = gen_reg_rtx (hmode);
1782 	  rtx lopart = gen_reg_rtx (hmode);
1783 	  emit_move_insn (larger, op1);
1784 	  emit_move_insn (hipart, hipart1);
1785 	  emit_move_insn (lopart, lopart0);
1786 	  emit_jump (one_small_one_large);
1787 
1788 	  emit_label (large_op0);
1789 
1790 	  if (!op1_small_p)
1791 	    do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1792 				     NULL_RTX, NULL, both_ops_large,
1793 				     profile_probability::unlikely ());
1794 
1795 	  /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1796 	     but op0 is not, prepare larger, hipart and lopart pseudos and
1797 	     handle it together with small_op0_large_op1.  */
1798 	  emit_move_insn (larger, op0);
1799 	  emit_move_insn (hipart, hipart0);
1800 	  emit_move_insn (lopart, lopart1);
1801 
1802 	  emit_label (one_small_one_large);
1803 
1804 	  /* lopart is the low part of the operand that is sign extended
1805 	     to mode, larger is the other operand, hipart is the
1806 	     high part of larger and lopart0 and lopart1 are the low parts
1807 	     of both operands.
1808 	     We perform lopart0 * lopart1 and lopart * hipart widening
1809 	     multiplications.  */
1810 	  tree halfutype = build_nonstandard_integer_type (hprec, 1);
1811 	  ops.op0 = make_tree (halfutype, lopart0);
1812 	  ops.op1 = make_tree (halfutype, lopart1);
1813 	  rtx lo0xlo1
1814 	    = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1815 
1816 	  ops.op0 = make_tree (halfutype, lopart);
1817 	  ops.op1 = make_tree (halfutype, hipart);
1818 	  rtx loxhi = gen_reg_rtx (mode);
1819 	  rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1820 	  emit_move_insn (loxhi, tem);
1821 
1822 	  if (!uns)
1823 	    {
1824 	      /* if (hipart < 0) loxhi -= lopart << (bitsize / 2);  */
1825 	      if (larger_sign == 0)
1826 		emit_jump (after_hipart_neg);
1827 	      else if (larger_sign != -1)
1828 		do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1829 					 NULL_RTX, NULL, after_hipart_neg,
1830 					 profile_probability::even ());
1831 
1832 	      tem = convert_modes (mode, hmode, lopart, 1);
1833 	      tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1834 	      tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1835 					 1, OPTAB_WIDEN);
1836 	      emit_move_insn (loxhi, tem);
1837 
1838 	      emit_label (after_hipart_neg);
1839 
1840 	      /* if (lopart < 0) loxhi -= larger;  */
1841 	      if (smaller_sign == 0)
1842 		emit_jump (after_lopart_neg);
1843 	      else if (smaller_sign != -1)
1844 		do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1845 					 NULL_RTX, NULL, after_lopart_neg,
1846 					 profile_probability::even ());
1847 
1848 	      tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1849 					 1, OPTAB_WIDEN);
1850 	      emit_move_insn (loxhi, tem);
1851 
1852 	      emit_label (after_lopart_neg);
1853 	    }
1854 
1855 	  /* loxhi += (uns) lo0xlo1 >> (bitsize / 2);  */
1856 	  tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1857 	  tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1858 				     1, OPTAB_WIDEN);
1859 	  emit_move_insn (loxhi, tem);
1860 
1861 	  /* if (loxhi >> (bitsize / 2)
1862 		 == (hmode) loxhi >> (bitsize / 2 - 1))  (if !uns)
1863 	     if (loxhi >> (bitsize / 2) == 0		 (if uns).  */
1864 	  rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1865 					  NULL_RTX, 0);
1866 	  hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1867 	  rtx signbitloxhi = const0_rtx;
1868 	  if (!uns)
1869 	    signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1870 					 convert_modes (hmode, mode,
1871 							loxhi, 0),
1872 					 hprec - 1, NULL_RTX, 0);
1873 
1874 	  do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1875 				   NULL_RTX, NULL, do_overflow,
1876 				   profile_probability::very_unlikely ());
1877 
1878 	  /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1;  */
1879 	  rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1880 					   NULL_RTX, 1);
1881 	  tem = convert_modes (mode, hmode,
1882 			       convert_modes (hmode, mode, lo0xlo1, 1), 1);
1883 
1884 	  tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1885 				     1, OPTAB_WIDEN);
1886 	  if (tem != res)
1887 	    emit_move_insn (res, tem);
1888 	  emit_jump (done_label);
1889 
1890 	  emit_label (both_ops_large);
1891 
1892 	  /* If both operands are large (not sign (!uns) or zero (uns)
1893 	     extended from hmode), then perform the full multiplication
1894 	     which will be the result of the operation.
1895 	     The only cases which don't overflow are for signed multiplication
1896 	     some cases where both hipart0 and highpart1 are 0 or -1.
1897 	     For unsigned multiplication when high parts are both non-zero
1898 	     this overflows always.  */
1899 	  ops.code = MULT_EXPR;
1900 	  ops.op0 = make_tree (type, op0);
1901 	  ops.op1 = make_tree (type, op1);
1902 	  tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1903 	  emit_move_insn (res, tem);
1904 
1905 	  if (!uns)
1906 	    {
1907 	      if (!op0_medium_p)
1908 		{
1909 		  tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1910 					     NULL_RTX, 1, OPTAB_WIDEN);
1911 		  do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1912 					   NULL_RTX, NULL, do_error,
1913 					   profile_probability::very_unlikely ());
1914 		}
1915 
1916 	      if (!op1_medium_p)
1917 		{
1918 		  tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1919 					     NULL_RTX, 1, OPTAB_WIDEN);
1920 		  do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1921 					   NULL_RTX, NULL, do_error,
1922 					   profile_probability::very_unlikely ());
1923 		}
1924 
1925 	      /* At this point hipart{0,1} are both in [-1, 0].  If they are
1926 		 the same, overflow happened if res is non-positive, if they
1927 		 are different, overflow happened if res is positive.  */
1928 	      if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1929 		emit_jump (hipart_different);
1930 	      else if (op0_sign == 1 || op1_sign == 1)
1931 		do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1932 					 NULL_RTX, NULL, hipart_different,
1933 					 profile_probability::even ());
1934 
1935 	      do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
1936 				       NULL_RTX, NULL, do_error,
1937 				       profile_probability::very_unlikely ());
1938 	      emit_jump (done_label);
1939 
1940 	      emit_label (hipart_different);
1941 
1942 	      do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1943 				       NULL_RTX, NULL, do_error,
1944 				       profile_probability::very_unlikely ());
1945 	      emit_jump (done_label);
1946 	    }
1947 
1948 	  emit_label (do_overflow);
1949 
1950 	  /* Overflow, do full multiplication and fallthru into do_error.  */
1951 	  ops.op0 = make_tree (type, op0);
1952 	  ops.op1 = make_tree (type, op1);
1953 	  tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1954 	  emit_move_insn (res, tem);
1955 	}
1956       else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1957 	       && targetm.scalar_mode_supported_p (wmode))
1958 	/* Even emitting a libcall is better than not detecting overflow
1959 	   at all.  */
1960 	goto twoxwider;
1961       else
1962 	{
1963 	  gcc_assert (!is_ubsan);
1964 	  ops.code = MULT_EXPR;
1965 	  ops.type = type;
1966 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1967 	  emit_jump (done_label);
1968 	}
1969     }
1970 
1971  do_error_label:
1972   emit_label (do_error);
1973   if (is_ubsan)
1974     {
1975       /* Expand the ubsan builtin call.  */
1976       push_temp_slots ();
1977       fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1978 					 arg0, arg1, datap);
1979       expand_normal (fn);
1980       pop_temp_slots ();
1981       do_pending_stack_adjust ();
1982     }
1983   else if (lhs)
1984     expand_arith_set_overflow (lhs, target);
1985 
1986   /* We're done.  */
1987   emit_label (done_label);
1988 
1989   /* u1 * u2 -> sr  */
1990   if (uns0_p && uns1_p && !unsr_p)
1991     {
1992       rtx_code_label *all_done_label = gen_label_rtx ();
1993       do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1994 			       NULL, all_done_label, profile_probability::very_likely ());
1995       expand_arith_set_overflow (lhs, target);
1996       emit_label (all_done_label);
1997     }
1998 
1999   /* s1 * u2 -> sr  */
2000   if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2001     {
2002       rtx_code_label *all_done_label = gen_label_rtx ();
2003       rtx_code_label *set_noovf = gen_label_rtx ();
2004       do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2005 			       NULL, all_done_label, profile_probability::very_likely ());
2006       expand_arith_set_overflow (lhs, target);
2007       do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2008 			       NULL, set_noovf, profile_probability::very_likely ());
2009       do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2010 			       NULL, all_done_label, profile_probability::very_unlikely ());
2011       do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2012 			       all_done_label, profile_probability::very_unlikely ());
2013       emit_label (set_noovf);
2014       write_complex_part (target, const0_rtx, true);
2015       emit_label (all_done_label);
2016     }
2017 
2018   if (lhs)
2019     {
2020       if (is_ubsan)
2021 	expand_ubsan_result_store (target, res);
2022       else
2023 	expand_arith_overflow_result_store (lhs, target, mode, res);
2024     }
2025 }
2026 
2027 /* Expand UBSAN_CHECK_* internal function if it has vector operands.  */
2028 
2029 static void
expand_vector_ubsan_overflow(location_t loc,enum tree_code code,tree lhs,tree arg0,tree arg1)2030 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2031 			      tree arg0, tree arg1)
2032 {
2033   poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2034   rtx_code_label *loop_lab = NULL;
2035   rtx cntvar = NULL_RTX;
2036   tree cntv = NULL_TREE;
2037   tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2038   tree sz = TYPE_SIZE (eltype);
2039   tree data = NULL_TREE;
2040   tree resv = NULL_TREE;
2041   rtx lhsr = NULL_RTX;
2042   rtx resvr = NULL_RTX;
2043   unsigned HOST_WIDE_INT const_cnt = 0;
2044   bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2045 
2046   if (lhs)
2047     {
2048       optab op;
2049       lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2050       if (!VECTOR_MODE_P (GET_MODE (lhsr))
2051 	  || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2052 					optab_default)) == unknown_optab
2053 	  || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2054 	      == CODE_FOR_nothing))
2055 	{
2056 	  if (MEM_P (lhsr))
2057 	    resv = make_tree (TREE_TYPE (lhs), lhsr);
2058 	  else
2059 	    {
2060 	      resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2061 	      resv = make_tree (TREE_TYPE (lhs), resvr);
2062 	    }
2063 	}
2064     }
2065   if (use_loop_p)
2066     {
2067       do_pending_stack_adjust ();
2068       loop_lab = gen_label_rtx ();
2069       cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2070       cntv = make_tree (sizetype, cntvar);
2071       emit_move_insn (cntvar, const0_rtx);
2072       emit_label (loop_lab);
2073     }
2074   if (TREE_CODE (arg0) != VECTOR_CST)
2075     {
2076       rtx arg0r = expand_normal (arg0);
2077       arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2078     }
2079   if (TREE_CODE (arg1) != VECTOR_CST)
2080     {
2081       rtx arg1r = expand_normal (arg1);
2082       arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2083     }
2084   for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2085     {
2086       tree op0, op1, res = NULL_TREE;
2087       if (use_loop_p)
2088 	{
2089 	  tree atype = build_array_type_nelts (eltype, cnt);
2090 	  op0 = uniform_vector_p (arg0);
2091 	  if (op0 == NULL_TREE)
2092 	    {
2093 	      op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2094 	      op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2095 				NULL_TREE, NULL_TREE);
2096 	    }
2097 	  op1 = uniform_vector_p (arg1);
2098 	  if (op1 == NULL_TREE)
2099 	    {
2100 	      op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2101 	      op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2102 				NULL_TREE, NULL_TREE);
2103 	    }
2104 	  if (resv)
2105 	    {
2106 	      res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2107 	      res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2108 				NULL_TREE, NULL_TREE);
2109 	    }
2110 	}
2111       else
2112 	{
2113 	  tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2114 	  op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2115 	  op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2116 	  if (resv)
2117 	    res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2118 				   bitpos);
2119 	}
2120       switch (code)
2121 	{
2122 	case PLUS_EXPR:
2123 	  expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2124 				  false, false, false, true, &data);
2125 	  break;
2126 	case MINUS_EXPR:
2127 	  if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2128 	    expand_neg_overflow (loc, res, op1, true, &data);
2129 	  else
2130 	    expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2131 				    false, false, false, true, &data);
2132 	  break;
2133 	case MULT_EXPR:
2134 	  expand_mul_overflow (loc, res, op0, op1, false, false, false,
2135 			       true, &data);
2136 	  break;
2137 	default:
2138 	  gcc_unreachable ();
2139 	}
2140     }
2141   if (use_loop_p)
2142     {
2143       struct separate_ops ops;
2144       ops.code = PLUS_EXPR;
2145       ops.type = TREE_TYPE (cntv);
2146       ops.op0 = cntv;
2147       ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2148       ops.op2 = NULL_TREE;
2149       ops.location = loc;
2150       rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2151 				    EXPAND_NORMAL);
2152       if (ret != cntvar)
2153 	emit_move_insn (cntvar, ret);
2154       rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2155       do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2156 			       TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2157 			       profile_probability::very_likely ());
2158     }
2159   if (lhs && resv == NULL_TREE)
2160     {
2161       struct separate_ops ops;
2162       ops.code = code;
2163       ops.type = TREE_TYPE (arg0);
2164       ops.op0 = arg0;
2165       ops.op1 = arg1;
2166       ops.op2 = NULL_TREE;
2167       ops.location = loc;
2168       rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2169 				    EXPAND_NORMAL);
2170       if (ret != lhsr)
2171 	emit_move_insn (lhsr, ret);
2172     }
2173   else if (resvr)
2174     emit_move_insn (lhsr, resvr);
2175 }
2176 
2177 /* Expand UBSAN_CHECK_ADD call STMT.  */
2178 
2179 static void
expand_UBSAN_CHECK_ADD(internal_fn,gcall * stmt)2180 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2181 {
2182   location_t loc = gimple_location (stmt);
2183   tree lhs = gimple_call_lhs (stmt);
2184   tree arg0 = gimple_call_arg (stmt, 0);
2185   tree arg1 = gimple_call_arg (stmt, 1);
2186   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2187     expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2188   else
2189     expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2190 			    false, false, false, true, NULL);
2191 }
2192 
2193 /* Expand UBSAN_CHECK_SUB call STMT.  */
2194 
2195 static void
expand_UBSAN_CHECK_SUB(internal_fn,gcall * stmt)2196 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2197 {
2198   location_t loc = gimple_location (stmt);
2199   tree lhs = gimple_call_lhs (stmt);
2200   tree arg0 = gimple_call_arg (stmt, 0);
2201   tree arg1 = gimple_call_arg (stmt, 1);
2202   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2203     expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2204   else if (integer_zerop (arg0))
2205     expand_neg_overflow (loc, lhs, arg1, true, NULL);
2206   else
2207     expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2208 			    false, false, false, true, NULL);
2209 }
2210 
2211 /* Expand UBSAN_CHECK_MUL call STMT.  */
2212 
2213 static void
expand_UBSAN_CHECK_MUL(internal_fn,gcall * stmt)2214 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2215 {
2216   location_t loc = gimple_location (stmt);
2217   tree lhs = gimple_call_lhs (stmt);
2218   tree arg0 = gimple_call_arg (stmt, 0);
2219   tree arg1 = gimple_call_arg (stmt, 1);
2220   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2221     expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2222   else
2223     expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2224 			 NULL);
2225 }
2226 
2227 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion.  */
2228 
2229 static void
expand_arith_overflow(enum tree_code code,gimple * stmt)2230 expand_arith_overflow (enum tree_code code, gimple *stmt)
2231 {
2232   tree lhs = gimple_call_lhs (stmt);
2233   if (lhs == NULL_TREE)
2234     return;
2235   tree arg0 = gimple_call_arg (stmt, 0);
2236   tree arg1 = gimple_call_arg (stmt, 1);
2237   tree type = TREE_TYPE (TREE_TYPE (lhs));
2238   int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2239   int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2240   int unsr_p = TYPE_UNSIGNED (type);
2241   int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2242   int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2243   int precres = TYPE_PRECISION (type);
2244   location_t loc = gimple_location (stmt);
2245   if (!uns0_p && get_range_pos_neg (arg0) == 1)
2246     uns0_p = true;
2247   if (!uns1_p && get_range_pos_neg (arg1) == 1)
2248     uns1_p = true;
2249   int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2250   prec0 = MIN (prec0, pr);
2251   pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2252   prec1 = MIN (prec1, pr);
2253 
2254   /* If uns0_p && uns1_p, precop is minimum needed precision
2255      of unsigned type to hold the exact result, otherwise
2256      precop is minimum needed precision of signed type to
2257      hold the exact result.  */
2258   int precop;
2259   if (code == MULT_EXPR)
2260     precop = prec0 + prec1 + (uns0_p != uns1_p);
2261   else
2262     {
2263       if (uns0_p == uns1_p)
2264 	precop = MAX (prec0, prec1) + 1;
2265       else if (uns0_p)
2266 	precop = MAX (prec0 + 1, prec1) + 1;
2267       else
2268 	precop = MAX (prec0, prec1 + 1) + 1;
2269     }
2270   int orig_precres = precres;
2271 
2272   do
2273     {
2274       if ((uns0_p && uns1_p)
2275 	  ? ((precop + !unsr_p) <= precres
2276 	     /* u1 - u2 -> ur can overflow, no matter what precision
2277 		the result has.  */
2278 	     && (code != MINUS_EXPR || !unsr_p))
2279 	  : (!unsr_p && precop <= precres))
2280 	{
2281 	  /* The infinity precision result will always fit into result.  */
2282 	  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2283 	  write_complex_part (target, const0_rtx, true);
2284 	  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2285 	  struct separate_ops ops;
2286 	  ops.code = code;
2287 	  ops.type = type;
2288 	  ops.op0 = fold_convert_loc (loc, type, arg0);
2289 	  ops.op1 = fold_convert_loc (loc, type, arg1);
2290 	  ops.op2 = NULL_TREE;
2291 	  ops.location = loc;
2292 	  rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2293 	  expand_arith_overflow_result_store (lhs, target, mode, tem);
2294 	  return;
2295 	}
2296 
2297       /* For operations with low precision, if target doesn't have them, start
2298 	 with precres widening right away, otherwise do it only if the most
2299 	 simple cases can't be used.  */
2300       const int min_precision = targetm.min_arithmetic_precision ();
2301       if (orig_precres == precres && precres < min_precision)
2302 	;
2303       else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2304 		&& prec1 <= precres)
2305 	  || ((!uns0_p || !uns1_p) && !unsr_p
2306 	      && prec0 + uns0_p <= precres
2307 	      && prec1 + uns1_p <= precres))
2308 	{
2309 	  arg0 = fold_convert_loc (loc, type, arg0);
2310 	  arg1 = fold_convert_loc (loc, type, arg1);
2311 	  switch (code)
2312 	    {
2313 	    case MINUS_EXPR:
2314 	      if (integer_zerop (arg0) && !unsr_p)
2315 		{
2316 		  expand_neg_overflow (loc, lhs, arg1, false, NULL);
2317 		  return;
2318 		}
2319 	      /* FALLTHRU */
2320 	    case PLUS_EXPR:
2321 	      expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2322 				      unsr_p, unsr_p, false, NULL);
2323 	      return;
2324 	    case MULT_EXPR:
2325 	      expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2326 				   unsr_p, unsr_p, false, NULL);
2327 	      return;
2328 	    default:
2329 	      gcc_unreachable ();
2330 	    }
2331 	}
2332 
2333       /* For sub-word operations, retry with a wider type first.  */
2334       if (orig_precres == precres && precop <= BITS_PER_WORD)
2335 	{
2336 	  int p = MAX (min_precision, precop);
2337 	  scalar_int_mode m = smallest_int_mode_for_size (p);
2338 	  tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2339 							uns0_p && uns1_p
2340 							&& unsr_p);
2341 	  p = TYPE_PRECISION (optype);
2342 	  if (p > precres)
2343 	    {
2344 	      precres = p;
2345 	      unsr_p = TYPE_UNSIGNED (optype);
2346 	      type = optype;
2347 	      continue;
2348 	    }
2349 	}
2350 
2351       if (prec0 <= precres && prec1 <= precres)
2352 	{
2353 	  tree types[2];
2354 	  if (unsr_p)
2355 	    {
2356 	      types[0] = build_nonstandard_integer_type (precres, 0);
2357 	      types[1] = type;
2358 	    }
2359 	  else
2360 	    {
2361 	      types[0] = type;
2362 	      types[1] = build_nonstandard_integer_type (precres, 1);
2363 	    }
2364 	  arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2365 	  arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2366 	  if (code != MULT_EXPR)
2367 	    expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2368 				    uns0_p, uns1_p, false, NULL);
2369 	  else
2370 	    expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2371 				 uns0_p, uns1_p, false, NULL);
2372 	  return;
2373 	}
2374 
2375       /* Retry with a wider type.  */
2376       if (orig_precres == precres)
2377 	{
2378 	  int p = MAX (prec0, prec1);
2379 	  scalar_int_mode m = smallest_int_mode_for_size (p);
2380 	  tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2381 							uns0_p && uns1_p
2382 							&& unsr_p);
2383 	  p = TYPE_PRECISION (optype);
2384 	  if (p > precres)
2385 	    {
2386 	      precres = p;
2387 	      unsr_p = TYPE_UNSIGNED (optype);
2388 	      type = optype;
2389 	      continue;
2390 	    }
2391 	}
2392 
2393       gcc_unreachable ();
2394     }
2395   while (1);
2396 }
2397 
2398 /* Expand ADD_OVERFLOW STMT.  */
2399 
2400 static void
expand_ADD_OVERFLOW(internal_fn,gcall * stmt)2401 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2402 {
2403   expand_arith_overflow (PLUS_EXPR, stmt);
2404 }
2405 
2406 /* Expand SUB_OVERFLOW STMT.  */
2407 
2408 static void
expand_SUB_OVERFLOW(internal_fn,gcall * stmt)2409 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2410 {
2411   expand_arith_overflow (MINUS_EXPR, stmt);
2412 }
2413 
2414 /* Expand MUL_OVERFLOW STMT.  */
2415 
2416 static void
expand_MUL_OVERFLOW(internal_fn,gcall * stmt)2417 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2418 {
2419   expand_arith_overflow (MULT_EXPR, stmt);
2420 }
2421 
2422 /* This should get folded in tree-vectorizer.c.  */
2423 
2424 static void
expand_LOOP_VECTORIZED(internal_fn,gcall *)2425 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2426 {
2427   gcc_unreachable ();
2428 }
2429 
2430 /* This should get folded in tree-vectorizer.c.  */
2431 
2432 static void
expand_LOOP_DIST_ALIAS(internal_fn,gcall *)2433 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2434 {
2435   gcc_unreachable ();
2436 }
2437 
2438 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2439    Use argument INDEX + 1 to derive the second (TBAA) operand.  */
2440 
2441 static tree
expand_call_mem_ref(tree type,gcall * stmt,int index)2442 expand_call_mem_ref (tree type, gcall *stmt, int index)
2443 {
2444   tree addr = gimple_call_arg (stmt, index);
2445   tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2446   unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2447   if (TYPE_ALIGN (type) != align)
2448     type = build_aligned_type (type, align);
2449 
2450   tree tmp = addr;
2451   if (TREE_CODE (tmp) == SSA_NAME)
2452     {
2453       gimple *def = SSA_NAME_DEF_STMT (tmp);
2454       if (gimple_assign_single_p (def))
2455 	tmp = gimple_assign_rhs1 (def);
2456     }
2457 
2458   if (TREE_CODE (tmp) == ADDR_EXPR)
2459     {
2460       tree mem = TREE_OPERAND (tmp, 0);
2461       if (TREE_CODE (mem) == TARGET_MEM_REF
2462 	  && types_compatible_p (TREE_TYPE (mem), type))
2463 	{
2464 	  tree offset = TMR_OFFSET (mem);
2465 	  if (type != TREE_TYPE (mem)
2466 	      || alias_ptr_type != TREE_TYPE (offset)
2467 	      || !integer_zerop (offset))
2468 	    {
2469 	      mem = copy_node (mem);
2470 	      TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2471 						   wi::to_poly_wide (offset));
2472 	      TREE_TYPE (mem) = type;
2473 	    }
2474 	  return mem;
2475 	}
2476     }
2477 
2478   return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2479 }
2480 
2481 /* Expand MASK_LOAD{,_LANES} call STMT using optab OPTAB.  */
2482 
2483 static void
expand_mask_load_optab_fn(internal_fn,gcall * stmt,convert_optab optab)2484 expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2485 {
2486   class expand_operand ops[3];
2487   tree type, lhs, rhs, maskt;
2488   rtx mem, target, mask;
2489   insn_code icode;
2490 
2491   maskt = gimple_call_arg (stmt, 2);
2492   lhs = gimple_call_lhs (stmt);
2493   if (lhs == NULL_TREE)
2494     return;
2495   type = TREE_TYPE (lhs);
2496   rhs = expand_call_mem_ref (type, stmt, 0);
2497 
2498   if (optab == vec_mask_load_lanes_optab)
2499     icode = get_multi_vector_move (type, optab);
2500   else
2501     icode = convert_optab_handler (optab, TYPE_MODE (type),
2502 				   TYPE_MODE (TREE_TYPE (maskt)));
2503 
2504   mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2505   gcc_assert (MEM_P (mem));
2506   mask = expand_normal (maskt);
2507   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2508   create_output_operand (&ops[0], target, TYPE_MODE (type));
2509   create_fixed_operand (&ops[1], mem);
2510   create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2511   expand_insn (icode, 3, ops);
2512   if (!rtx_equal_p (target, ops[0].value))
2513     emit_move_insn (target, ops[0].value);
2514 }
2515 
2516 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2517 
2518 /* Expand MASK_STORE{,_LANES} call STMT using optab OPTAB.  */
2519 
2520 static void
expand_mask_store_optab_fn(internal_fn,gcall * stmt,convert_optab optab)2521 expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2522 {
2523   class expand_operand ops[3];
2524   tree type, lhs, rhs, maskt;
2525   rtx mem, reg, mask;
2526   insn_code icode;
2527 
2528   maskt = gimple_call_arg (stmt, 2);
2529   rhs = gimple_call_arg (stmt, 3);
2530   type = TREE_TYPE (rhs);
2531   lhs = expand_call_mem_ref (type, stmt, 0);
2532 
2533   if (optab == vec_mask_store_lanes_optab)
2534     icode = get_multi_vector_move (type, optab);
2535   else
2536     icode = convert_optab_handler (optab, TYPE_MODE (type),
2537 				   TYPE_MODE (TREE_TYPE (maskt)));
2538 
2539   mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2540   gcc_assert (MEM_P (mem));
2541   mask = expand_normal (maskt);
2542   reg = expand_normal (rhs);
2543   create_fixed_operand (&ops[0], mem);
2544   create_input_operand (&ops[1], reg, TYPE_MODE (type));
2545   create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2546   expand_insn (icode, 3, ops);
2547 }
2548 
2549 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2550 
2551 static void
expand_ABNORMAL_DISPATCHER(internal_fn,gcall *)2552 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
2553 {
2554 }
2555 
2556 static void
expand_BUILTIN_EXPECT(internal_fn,gcall * stmt)2557 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
2558 {
2559   /* When guessing was done, the hints should be already stripped away.  */
2560   gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2561 
2562   rtx target;
2563   tree lhs = gimple_call_lhs (stmt);
2564   if (lhs)
2565     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2566   else
2567     target = const0_rtx;
2568   rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2569   if (lhs && val != target)
2570     emit_move_insn (target, val);
2571 }
2572 
2573 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg.  So this dummy function
2574    should never be called.  */
2575 
2576 static void
expand_VA_ARG(internal_fn,gcall *)2577 expand_VA_ARG (internal_fn, gcall *)
2578 {
2579   gcc_unreachable ();
2580 }
2581 
2582 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector.  So this
2583    dummy function should never be called.  */
2584 
2585 static void
expand_VEC_CONVERT(internal_fn,gcall *)2586 expand_VEC_CONVERT (internal_fn, gcall *)
2587 {
2588   gcc_unreachable ();
2589 }
2590 
2591 /* Expand the IFN_UNIQUE function according to its first argument.  */
2592 
2593 static void
expand_UNIQUE(internal_fn,gcall * stmt)2594 expand_UNIQUE (internal_fn, gcall *stmt)
2595 {
2596   rtx pattern = NULL_RTX;
2597   enum ifn_unique_kind kind
2598     = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2599 
2600   switch (kind)
2601     {
2602     default:
2603       gcc_unreachable ();
2604 
2605     case IFN_UNIQUE_UNSPEC:
2606       if (targetm.have_unique ())
2607 	pattern = targetm.gen_unique ();
2608       break;
2609 
2610     case IFN_UNIQUE_OACC_FORK:
2611     case IFN_UNIQUE_OACC_JOIN:
2612       if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2613 	{
2614 	  tree lhs = gimple_call_lhs (stmt);
2615 	  rtx target = const0_rtx;
2616 
2617 	  if (lhs)
2618 	    target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2619 
2620 	  rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2621 	  rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2622 
2623 	  if (kind == IFN_UNIQUE_OACC_FORK)
2624 	    pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2625 	  else
2626 	    pattern = targetm.gen_oacc_join (target, data_dep, axis);
2627 	}
2628       else
2629 	gcc_unreachable ();
2630       break;
2631     }
2632 
2633   if (pattern)
2634     emit_insn (pattern);
2635 }
2636 
2637 /* The size of an OpenACC compute dimension.  */
2638 
2639 static void
expand_GOACC_DIM_SIZE(internal_fn,gcall * stmt)2640 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
2641 {
2642   tree lhs = gimple_call_lhs (stmt);
2643 
2644   if (!lhs)
2645     return;
2646 
2647   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2648   if (targetm.have_oacc_dim_size ())
2649     {
2650       rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2651 			     VOIDmode, EXPAND_NORMAL);
2652       emit_insn (targetm.gen_oacc_dim_size (target, dim));
2653     }
2654   else
2655     emit_move_insn (target, GEN_INT (1));
2656 }
2657 
2658 /* The position of an OpenACC execution engine along one compute axis.  */
2659 
2660 static void
expand_GOACC_DIM_POS(internal_fn,gcall * stmt)2661 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
2662 {
2663   tree lhs = gimple_call_lhs (stmt);
2664 
2665   if (!lhs)
2666     return;
2667 
2668   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2669   if (targetm.have_oacc_dim_pos ())
2670     {
2671       rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2672 			     VOIDmode, EXPAND_NORMAL);
2673       emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2674     }
2675   else
2676     emit_move_insn (target, const0_rtx);
2677 }
2678 
2679 /* This is expanded by oacc_device_lower pass.  */
2680 
2681 static void
expand_GOACC_LOOP(internal_fn,gcall *)2682 expand_GOACC_LOOP (internal_fn, gcall *)
2683 {
2684   gcc_unreachable ();
2685 }
2686 
2687 /* This is expanded by oacc_device_lower pass.  */
2688 
2689 static void
expand_GOACC_REDUCTION(internal_fn,gcall *)2690 expand_GOACC_REDUCTION (internal_fn, gcall *)
2691 {
2692   gcc_unreachable ();
2693 }
2694 
2695 /* This is expanded by oacc_device_lower pass.  */
2696 
2697 static void
expand_GOACC_TILE(internal_fn,gcall *)2698 expand_GOACC_TILE (internal_fn, gcall *)
2699 {
2700   gcc_unreachable ();
2701 }
2702 
2703 /* Set errno to EDOM.  */
2704 
2705 static void
expand_SET_EDOM(internal_fn,gcall *)2706 expand_SET_EDOM (internal_fn, gcall *)
2707 {
2708 #ifdef TARGET_EDOM
2709 #ifdef GEN_ERRNO_RTX
2710   rtx errno_rtx = GEN_ERRNO_RTX;
2711 #else
2712   rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2713 #endif
2714   emit_move_insn (errno_rtx,
2715 		  gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2716 #else
2717   gcc_unreachable ();
2718 #endif
2719 }
2720 
2721 /* Expand atomic bit test and set.  */
2722 
2723 static void
expand_ATOMIC_BIT_TEST_AND_SET(internal_fn,gcall * call)2724 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2725 {
2726   expand_ifn_atomic_bit_test_and (call);
2727 }
2728 
2729 /* Expand atomic bit test and complement.  */
2730 
2731 static void
expand_ATOMIC_BIT_TEST_AND_COMPLEMENT(internal_fn,gcall * call)2732 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2733 {
2734   expand_ifn_atomic_bit_test_and (call);
2735 }
2736 
2737 /* Expand atomic bit test and reset.  */
2738 
2739 static void
expand_ATOMIC_BIT_TEST_AND_RESET(internal_fn,gcall * call)2740 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2741 {
2742   expand_ifn_atomic_bit_test_and (call);
2743 }
2744 
2745 /* Expand atomic bit test and set.  */
2746 
2747 static void
expand_ATOMIC_COMPARE_EXCHANGE(internal_fn,gcall * call)2748 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2749 {
2750   expand_ifn_atomic_compare_exchange (call);
2751 }
2752 
2753 /* Expand LAUNDER to assignment, lhs = arg0.  */
2754 
2755 static void
expand_LAUNDER(internal_fn,gcall * call)2756 expand_LAUNDER (internal_fn, gcall *call)
2757 {
2758   tree lhs = gimple_call_lhs (call);
2759 
2760   if (!lhs)
2761     return;
2762 
2763   expand_assignment (lhs, gimple_call_arg (call, 0), false);
2764 }
2765 
2766 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB.  */
2767 
2768 static void
expand_scatter_store_optab_fn(internal_fn,gcall * stmt,direct_optab optab)2769 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2770 {
2771   internal_fn ifn = gimple_call_internal_fn (stmt);
2772   int rhs_index = internal_fn_stored_value_index (ifn);
2773   int mask_index = internal_fn_mask_index (ifn);
2774   tree base = gimple_call_arg (stmt, 0);
2775   tree offset = gimple_call_arg (stmt, 1);
2776   tree scale = gimple_call_arg (stmt, 2);
2777   tree rhs = gimple_call_arg (stmt, rhs_index);
2778 
2779   rtx base_rtx = expand_normal (base);
2780   rtx offset_rtx = expand_normal (offset);
2781   HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2782   rtx rhs_rtx = expand_normal (rhs);
2783 
2784   class expand_operand ops[6];
2785   int i = 0;
2786   create_address_operand (&ops[i++], base_rtx);
2787   create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2788   create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2789   create_integer_operand (&ops[i++], scale_int);
2790   create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
2791   if (mask_index >= 0)
2792     {
2793       tree mask = gimple_call_arg (stmt, mask_index);
2794       rtx mask_rtx = expand_normal (mask);
2795       create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2796     }
2797 
2798   insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
2799 					   TYPE_MODE (TREE_TYPE (offset)));
2800   expand_insn (icode, i, ops);
2801 }
2802 
2803 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB.  */
2804 
2805 static void
expand_gather_load_optab_fn(internal_fn,gcall * stmt,direct_optab optab)2806 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2807 {
2808   tree lhs = gimple_call_lhs (stmt);
2809   tree base = gimple_call_arg (stmt, 0);
2810   tree offset = gimple_call_arg (stmt, 1);
2811   tree scale = gimple_call_arg (stmt, 2);
2812 
2813   rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2814   rtx base_rtx = expand_normal (base);
2815   rtx offset_rtx = expand_normal (offset);
2816   HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2817 
2818   int i = 0;
2819   class expand_operand ops[6];
2820   create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
2821   create_address_operand (&ops[i++], base_rtx);
2822   create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2823   create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2824   create_integer_operand (&ops[i++], scale_int);
2825   if (optab == mask_gather_load_optab)
2826     {
2827       tree mask = gimple_call_arg (stmt, 4);
2828       rtx mask_rtx = expand_normal (mask);
2829       create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2830     }
2831   insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
2832 					   TYPE_MODE (TREE_TYPE (offset)));
2833   expand_insn (icode, i, ops);
2834   if (!rtx_equal_p (lhs_rtx, ops[0].value))
2835     emit_move_insn (lhs_rtx, ops[0].value);
2836 }
2837 
2838 /* Expand DIVMOD() using:
2839  a) optab handler for udivmod/sdivmod if it is available.
2840  b) If optab_handler doesn't exist, generate call to
2841     target-specific divmod libfunc.  */
2842 
2843 static void
expand_DIVMOD(internal_fn,gcall * call_stmt)2844 expand_DIVMOD (internal_fn, gcall *call_stmt)
2845 {
2846   tree lhs = gimple_call_lhs (call_stmt);
2847   tree arg0 = gimple_call_arg (call_stmt, 0);
2848   tree arg1 = gimple_call_arg (call_stmt, 1);
2849 
2850   gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
2851   tree type = TREE_TYPE (TREE_TYPE (lhs));
2852   machine_mode mode = TYPE_MODE (type);
2853   bool unsignedp = TYPE_UNSIGNED (type);
2854   optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
2855 
2856   rtx op0 = expand_normal (arg0);
2857   rtx op1 = expand_normal (arg1);
2858   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2859 
2860   rtx quotient, remainder, libfunc;
2861 
2862   /* Check if optab_handler exists for divmod_optab for given mode.  */
2863   if (optab_handler (tab, mode) != CODE_FOR_nothing)
2864     {
2865       quotient = gen_reg_rtx (mode);
2866       remainder = gen_reg_rtx (mode);
2867       expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
2868     }
2869 
2870   /* Generate call to divmod libfunc if it exists.  */
2871   else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
2872     targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
2873 				   &quotient, &remainder);
2874 
2875   else
2876     gcc_unreachable ();
2877 
2878   /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR.  */
2879   expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
2880 		       make_tree (TREE_TYPE (arg0), quotient),
2881 		       make_tree (TREE_TYPE (arg1), remainder)),
2882 	       target, VOIDmode, EXPAND_NORMAL);
2883 }
2884 
2885 /* Expand a NOP.  */
2886 
2887 static void
expand_NOP(internal_fn,gcall *)2888 expand_NOP (internal_fn, gcall *)
2889 {
2890   /* Nothing.  But it shouldn't really prevail.  */
2891 }
2892 
2893 /* Coroutines, all should have been processed at this stage.  */
2894 
2895 static void
expand_CO_FRAME(internal_fn,gcall *)2896 expand_CO_FRAME (internal_fn, gcall *)
2897 {
2898   gcc_unreachable ();
2899 }
2900 
2901 static void
expand_CO_YIELD(internal_fn,gcall *)2902 expand_CO_YIELD (internal_fn, gcall *)
2903 {
2904   gcc_unreachable ();
2905 }
2906 
2907 static void
expand_CO_SUSPN(internal_fn,gcall *)2908 expand_CO_SUSPN (internal_fn, gcall *)
2909 {
2910   gcc_unreachable ();
2911 }
2912 
2913 static void
expand_CO_ACTOR(internal_fn,gcall *)2914 expand_CO_ACTOR (internal_fn, gcall *)
2915 {
2916   gcc_unreachable ();
2917 }
2918 
2919 /* Expand a call to FN using the operands in STMT.  FN has a single
2920    output operand and NARGS input operands.  */
2921 
2922 static void
expand_direct_optab_fn(internal_fn fn,gcall * stmt,direct_optab optab,unsigned int nargs)2923 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2924 			unsigned int nargs)
2925 {
2926   expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2927 
2928   tree_pair types = direct_internal_fn_types (fn, stmt);
2929   insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2930   gcc_assert (icode != CODE_FOR_nothing);
2931 
2932   tree lhs = gimple_call_lhs (stmt);
2933   rtx lhs_rtx = NULL_RTX;
2934   if (lhs)
2935     lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2936 
2937   /* Do not assign directly to a promoted subreg, since there is no
2938      guarantee that the instruction will leave the upper bits of the
2939      register in the state required by SUBREG_PROMOTED_SIGN.  */
2940   rtx dest = lhs_rtx;
2941   if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
2942     dest = NULL_RTX;
2943 
2944   create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
2945 
2946   for (unsigned int i = 0; i < nargs; ++i)
2947     {
2948       tree rhs = gimple_call_arg (stmt, i);
2949       tree rhs_type = TREE_TYPE (rhs);
2950       rtx rhs_rtx = expand_normal (rhs);
2951       if (INTEGRAL_TYPE_P (rhs_type))
2952 	create_convert_operand_from (&ops[i + 1], rhs_rtx,
2953 				     TYPE_MODE (rhs_type),
2954 				     TYPE_UNSIGNED (rhs_type));
2955       else
2956 	create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2957     }
2958 
2959   expand_insn (icode, nargs + 1, ops);
2960   if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
2961     {
2962       /* If the return value has an integral type, convert the instruction
2963 	 result to that type.  This is useful for things that return an
2964 	 int regardless of the size of the input.  If the instruction result
2965 	 is smaller than required, assume that it is signed.
2966 
2967 	 If the return value has a nonintegral type, its mode must match
2968 	 the instruction result.  */
2969       if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2970 	{
2971 	  /* If this is a scalar in a register that is stored in a wider
2972 	     mode than the declared mode, compute the result into its
2973 	     declared mode and then convert to the wider mode.  */
2974 	  gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
2975 	  rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2976 	  convert_move (SUBREG_REG (lhs_rtx), tmp,
2977 			SUBREG_PROMOTED_SIGN (lhs_rtx));
2978 	}
2979       else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
2980 	emit_move_insn (lhs_rtx, ops[0].value);
2981       else
2982 	{
2983 	  gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
2984 	  convert_move (lhs_rtx, ops[0].value, 0);
2985 	}
2986     }
2987 }
2988 
2989 /* Expand WHILE_ULT call STMT using optab OPTAB.  */
2990 
2991 static void
expand_while_optab_fn(internal_fn,gcall * stmt,convert_optab optab)2992 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2993 {
2994   expand_operand ops[3];
2995   tree rhs_type[2];
2996 
2997   tree lhs = gimple_call_lhs (stmt);
2998   tree lhs_type = TREE_TYPE (lhs);
2999   rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3000   create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3001 
3002   for (unsigned int i = 0; i < 2; ++i)
3003     {
3004       tree rhs = gimple_call_arg (stmt, i);
3005       rhs_type[i] = TREE_TYPE (rhs);
3006       rtx rhs_rtx = expand_normal (rhs);
3007       create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3008     }
3009 
3010   insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3011 					   TYPE_MODE (lhs_type));
3012 
3013   expand_insn (icode, 3, ops);
3014   if (!rtx_equal_p (lhs_rtx, ops[0].value))
3015     emit_move_insn (lhs_rtx, ops[0].value);
3016 }
3017 
3018 /* Expanders for optabs that can use expand_direct_optab_fn.  */
3019 
3020 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3021   expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3022 
3023 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3024   expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3025 
3026 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3027   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3028 
3029 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3030   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3031 
3032 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3033   expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3034 
3035 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3036   expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3037 
3038 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3039   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3040 
3041 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3042   expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3043 
3044 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3045   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3046 
3047 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3048   expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3049 
3050 /* RETURN_TYPE and ARGS are a return type and argument list that are
3051    in principle compatible with FN (which satisfies direct_internal_fn_p).
3052    Return the types that should be used to determine whether the
3053    target supports FN.  */
3054 
3055 tree_pair
direct_internal_fn_types(internal_fn fn,tree return_type,tree * args)3056 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3057 {
3058   const direct_internal_fn_info &info = direct_internal_fn (fn);
3059   tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3060   tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3061   return tree_pair (type0, type1);
3062 }
3063 
3064 /* CALL is a call whose return type and arguments are in principle
3065    compatible with FN (which satisfies direct_internal_fn_p).  Return the
3066    types that should be used to determine whether the target supports FN.  */
3067 
3068 tree_pair
direct_internal_fn_types(internal_fn fn,gcall * call)3069 direct_internal_fn_types (internal_fn fn, gcall *call)
3070 {
3071   const direct_internal_fn_info &info = direct_internal_fn (fn);
3072   tree op0 = (info.type0 < 0
3073 	      ? gimple_call_lhs (call)
3074 	      : gimple_call_arg (call, info.type0));
3075   tree op1 = (info.type1 < 0
3076 	      ? gimple_call_lhs (call)
3077 	      : gimple_call_arg (call, info.type1));
3078   return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3079 }
3080 
3081 /* Return true if OPTAB is supported for TYPES (whose modes should be
3082    the same) when the optimization type is OPT_TYPE.  Used for simple
3083    direct optabs.  */
3084 
3085 static bool
direct_optab_supported_p(direct_optab optab,tree_pair types,optimization_type opt_type)3086 direct_optab_supported_p (direct_optab optab, tree_pair types,
3087 			  optimization_type opt_type)
3088 {
3089   machine_mode mode = TYPE_MODE (types.first);
3090   gcc_checking_assert (mode == TYPE_MODE (types.second));
3091   return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3092 }
3093 
3094 /* Return true if OPTAB is supported for TYPES, where the first type
3095    is the destination and the second type is the source.  Used for
3096    convert optabs.  */
3097 
3098 static bool
convert_optab_supported_p(convert_optab optab,tree_pair types,optimization_type opt_type)3099 convert_optab_supported_p (convert_optab optab, tree_pair types,
3100 			   optimization_type opt_type)
3101 {
3102   return (convert_optab_handler (optab, TYPE_MODE (types.first),
3103 				 TYPE_MODE (types.second), opt_type)
3104 	  != CODE_FOR_nothing);
3105 }
3106 
3107 /* Return true if load/store lanes optab OPTAB is supported for
3108    array type TYPES.first when the optimization type is OPT_TYPE.  */
3109 
3110 static bool
multi_vector_optab_supported_p(convert_optab optab,tree_pair types,optimization_type opt_type)3111 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3112 				optimization_type opt_type)
3113 {
3114   gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3115   machine_mode imode = TYPE_MODE (types.first);
3116   machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3117   return (convert_optab_handler (optab, imode, vmode, opt_type)
3118 	  != CODE_FOR_nothing);
3119 }
3120 
3121 #define direct_unary_optab_supported_p direct_optab_supported_p
3122 #define direct_binary_optab_supported_p direct_optab_supported_p
3123 #define direct_ternary_optab_supported_p direct_optab_supported_p
3124 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3125 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3126 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
3127 #define direct_mask_load_optab_supported_p direct_optab_supported_p
3128 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
3129 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
3130 #define direct_gather_load_optab_supported_p convert_optab_supported_p
3131 #define direct_mask_store_optab_supported_p direct_optab_supported_p
3132 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
3133 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
3134 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
3135 #define direct_while_optab_supported_p convert_optab_supported_p
3136 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
3137 #define direct_fold_left_optab_supported_p direct_optab_supported_p
3138 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
3139 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
3140 
3141 /* Return the optab used by internal function FN.  */
3142 
3143 static optab
direct_internal_fn_optab(internal_fn fn,tree_pair types)3144 direct_internal_fn_optab (internal_fn fn, tree_pair types)
3145 {
3146   switch (fn)
3147     {
3148 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3149     case IFN_##CODE: break;
3150 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3151     case IFN_##CODE: return OPTAB##_optab;
3152 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3153 				     UNSIGNED_OPTAB, TYPE)		\
3154     case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR)		\
3155 			     ? UNSIGNED_OPTAB ## _optab			\
3156 			     : SIGNED_OPTAB ## _optab);
3157 #include "internal-fn.def"
3158 
3159     case IFN_LAST:
3160       break;
3161     }
3162   gcc_unreachable ();
3163 }
3164 
3165 /* Return the optab used by internal function FN.  */
3166 
3167 static optab
direct_internal_fn_optab(internal_fn fn)3168 direct_internal_fn_optab (internal_fn fn)
3169 {
3170   switch (fn)
3171     {
3172 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3173     case IFN_##CODE: break;
3174 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3175     case IFN_##CODE: return OPTAB##_optab;
3176 #include "internal-fn.def"
3177 
3178     case IFN_LAST:
3179       break;
3180     }
3181   gcc_unreachable ();
3182 }
3183 
3184 /* Return true if FN is supported for the types in TYPES when the
3185    optimization type is OPT_TYPE.  The types are those associated with
3186    the "type0" and "type1" fields of FN's direct_internal_fn_info
3187    structure.  */
3188 
3189 bool
direct_internal_fn_supported_p(internal_fn fn,tree_pair types,optimization_type opt_type)3190 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
3191 				optimization_type opt_type)
3192 {
3193   switch (fn)
3194     {
3195 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3196     case IFN_##CODE: break;
3197 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3198     case IFN_##CODE: \
3199       return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
3200 						opt_type);
3201 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3202 				     UNSIGNED_OPTAB, TYPE)		\
3203     case IFN_##CODE:							\
3204       {									\
3205 	optab which_optab = (TYPE_UNSIGNED (types.SELECTOR)		\
3206 			     ? UNSIGNED_OPTAB ## _optab			\
3207 			     : SIGNED_OPTAB ## _optab);			\
3208 	return direct_##TYPE##_optab_supported_p (which_optab, types,	\
3209 						  opt_type);		\
3210       }
3211 #include "internal-fn.def"
3212 
3213     case IFN_LAST:
3214       break;
3215     }
3216   gcc_unreachable ();
3217 }
3218 
3219 /* Return true if FN is supported for type TYPE when the optimization
3220    type is OPT_TYPE.  The caller knows that the "type0" and "type1"
3221    fields of FN's direct_internal_fn_info structure are the same.  */
3222 
3223 bool
direct_internal_fn_supported_p(internal_fn fn,tree type,optimization_type opt_type)3224 direct_internal_fn_supported_p (internal_fn fn, tree type,
3225 				optimization_type opt_type)
3226 {
3227   const direct_internal_fn_info &info = direct_internal_fn (fn);
3228   gcc_checking_assert (info.type0 == info.type1);
3229   return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
3230 }
3231 
3232 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
3233    given that STMT is a call to a direct internal function.  */
3234 
3235 bool
direct_internal_fn_supported_p(gcall * stmt,optimization_type opt_type)3236 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
3237 {
3238   internal_fn fn = gimple_call_internal_fn (stmt);
3239   tree_pair types = direct_internal_fn_types (fn, stmt);
3240   return direct_internal_fn_supported_p (fn, types, opt_type);
3241 }
3242 
3243 /* If FN is commutative in two consecutive arguments, return the
3244    index of the first, otherwise return -1.  */
3245 
3246 int
first_commutative_argument(internal_fn fn)3247 first_commutative_argument (internal_fn fn)
3248 {
3249   switch (fn)
3250     {
3251     case IFN_FMA:
3252     case IFN_FMS:
3253     case IFN_FNMA:
3254     case IFN_FNMS:
3255     case IFN_AVG_FLOOR:
3256     case IFN_AVG_CEIL:
3257     case IFN_MULHS:
3258     case IFN_MULHRS:
3259     case IFN_FMIN:
3260     case IFN_FMAX:
3261       return 0;
3262 
3263     case IFN_COND_ADD:
3264     case IFN_COND_MUL:
3265     case IFN_COND_MIN:
3266     case IFN_COND_MAX:
3267     case IFN_COND_AND:
3268     case IFN_COND_IOR:
3269     case IFN_COND_XOR:
3270     case IFN_COND_FMA:
3271     case IFN_COND_FMS:
3272     case IFN_COND_FNMA:
3273     case IFN_COND_FNMS:
3274       return 1;
3275 
3276     default:
3277       return -1;
3278     }
3279 }
3280 
3281 /* Return true if IFN_SET_EDOM is supported.  */
3282 
3283 bool
set_edom_supported_p(void)3284 set_edom_supported_p (void)
3285 {
3286 #ifdef TARGET_EDOM
3287   return true;
3288 #else
3289   return false;
3290 #endif
3291 }
3292 
3293 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3294   static void						\
3295   expand_##CODE (internal_fn fn, gcall *stmt)		\
3296   {							\
3297     expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab);	\
3298   }
3299 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3300 				     UNSIGNED_OPTAB, TYPE)		\
3301   static void								\
3302   expand_##CODE (internal_fn fn, gcall *stmt)				\
3303   {									\
3304     tree_pair types = direct_internal_fn_types (fn, stmt);		\
3305     optab which_optab = direct_internal_fn_optab (fn, types);		\
3306     expand_##TYPE##_optab_fn (fn, stmt, which_optab);			\
3307   }
3308 #include "internal-fn.def"
3309 
3310 /* Routines to expand each internal function, indexed by function number.
3311    Each routine has the prototype:
3312 
3313        expand_<NAME> (gcall *stmt)
3314 
3315    where STMT is the statement that performs the call. */
3316 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
3317 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
3318 #include "internal-fn.def"
3319   0
3320 };
3321 
3322 /* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
3323    tree code CODE.  */
3324 #define FOR_EACH_CODE_MAPPING(T) \
3325   T (PLUS_EXPR, IFN_COND_ADD) \
3326   T (MINUS_EXPR, IFN_COND_SUB) \
3327   T (MULT_EXPR, IFN_COND_MUL) \
3328   T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
3329   T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
3330   T (RDIV_EXPR, IFN_COND_RDIV) \
3331   T (MIN_EXPR, IFN_COND_MIN) \
3332   T (MAX_EXPR, IFN_COND_MAX) \
3333   T (BIT_AND_EXPR, IFN_COND_AND) \
3334   T (BIT_IOR_EXPR, IFN_COND_IOR) \
3335   T (BIT_XOR_EXPR, IFN_COND_XOR) \
3336   T (LSHIFT_EXPR, IFN_COND_SHL) \
3337   T (RSHIFT_EXPR, IFN_COND_SHR)
3338 
3339 /* Return a function that only performs CODE when a certain condition is met
3340    and that uses a given fallback value otherwise.  For example, if CODE is
3341    a binary operation associated with conditional function FN:
3342 
3343      LHS = FN (COND, A, B, ELSE)
3344 
3345    is equivalent to the C expression:
3346 
3347      LHS = COND ? A CODE B : ELSE;
3348 
3349    operating elementwise if the operands are vectors.
3350 
3351    Return IFN_LAST if no such function exists.  */
3352 
3353 internal_fn
get_conditional_internal_fn(tree_code code)3354 get_conditional_internal_fn (tree_code code)
3355 {
3356   switch (code)
3357     {
3358 #define CASE(CODE, IFN) case CODE: return IFN;
3359       FOR_EACH_CODE_MAPPING(CASE)
3360 #undef CASE
3361     default:
3362       return IFN_LAST;
3363     }
3364 }
3365 
3366 /* If IFN implements the conditional form of a tree code, return that
3367    tree code, otherwise return ERROR_MARK.  */
3368 
3369 tree_code
conditional_internal_fn_code(internal_fn ifn)3370 conditional_internal_fn_code (internal_fn ifn)
3371 {
3372   switch (ifn)
3373     {
3374 #define CASE(CODE, IFN) case IFN: return CODE;
3375       FOR_EACH_CODE_MAPPING(CASE)
3376 #undef CASE
3377     default:
3378       return ERROR_MARK;
3379     }
3380 }
3381 
3382 /* Invoke T(IFN) for each internal function IFN that also has an
3383    IFN_COND_* form.  */
3384 #define FOR_EACH_COND_FN_PAIR(T) \
3385   T (FMA) \
3386   T (FMS) \
3387   T (FNMA) \
3388   T (FNMS)
3389 
3390 /* Return a function that only performs internal function FN when a
3391    certain condition is met and that uses a given fallback value otherwise.
3392    In other words, the returned function FN' is such that:
3393 
3394      LHS = FN' (COND, A1, ... An, ELSE)
3395 
3396    is equivalent to the C expression:
3397 
3398      LHS = COND ? FN (A1, ..., An) : ELSE;
3399 
3400    operating elementwise if the operands are vectors.
3401 
3402    Return IFN_LAST if no such function exists.  */
3403 
3404 internal_fn
get_conditional_internal_fn(internal_fn fn)3405 get_conditional_internal_fn (internal_fn fn)
3406 {
3407   switch (fn)
3408     {
3409 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
3410       FOR_EACH_COND_FN_PAIR(CASE)
3411 #undef CASE
3412     default:
3413       return IFN_LAST;
3414     }
3415 }
3416 
3417 /* If IFN implements the conditional form of an unconditional internal
3418    function, return that unconditional function, otherwise return IFN_LAST.  */
3419 
3420 internal_fn
get_unconditional_internal_fn(internal_fn ifn)3421 get_unconditional_internal_fn (internal_fn ifn)
3422 {
3423   switch (ifn)
3424     {
3425 #define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
3426       FOR_EACH_COND_FN_PAIR(CASE)
3427 #undef CASE
3428     default:
3429       return IFN_LAST;
3430     }
3431 }
3432 
3433 /* Return true if STMT can be interpreted as a conditional tree code
3434    operation of the form:
3435 
3436      LHS = COND ? OP (RHS1, ...) : ELSE;
3437 
3438    operating elementwise if the operands are vectors.  This includes
3439    the case of an all-true COND, so that the operation always happens.
3440 
3441    When returning true, set:
3442 
3443    - *COND_OUT to the condition COND, or to NULL_TREE if the condition
3444      is known to be all-true
3445    - *CODE_OUT to the tree code
3446    - OPS[I] to operand I of *CODE_OUT
3447    - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
3448      condition is known to be all true.  */
3449 
3450 bool
can_interpret_as_conditional_op_p(gimple * stmt,tree * cond_out,tree_code * code_out,tree (& ops)[3],tree * else_out)3451 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
3452 				   tree_code *code_out,
3453 				   tree (&ops)[3], tree *else_out)
3454 {
3455   if (gassign *assign = dyn_cast <gassign *> (stmt))
3456     {
3457       *cond_out = NULL_TREE;
3458       *code_out = gimple_assign_rhs_code (assign);
3459       ops[0] = gimple_assign_rhs1 (assign);
3460       ops[1] = gimple_assign_rhs2 (assign);
3461       ops[2] = gimple_assign_rhs3 (assign);
3462       *else_out = NULL_TREE;
3463       return true;
3464     }
3465   if (gcall *call = dyn_cast <gcall *> (stmt))
3466     if (gimple_call_internal_p (call))
3467       {
3468 	internal_fn ifn = gimple_call_internal_fn (call);
3469 	tree_code code = conditional_internal_fn_code (ifn);
3470 	if (code != ERROR_MARK)
3471 	  {
3472 	    *cond_out = gimple_call_arg (call, 0);
3473 	    *code_out = code;
3474 	    unsigned int nops = gimple_call_num_args (call) - 2;
3475 	    for (unsigned int i = 0; i < 3; ++i)
3476 	      ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
3477 	    *else_out = gimple_call_arg (call, nops + 1);
3478 	    if (integer_truep (*cond_out))
3479 	      {
3480 		*cond_out = NULL_TREE;
3481 		*else_out = NULL_TREE;
3482 	      }
3483 	    return true;
3484 	  }
3485       }
3486   return false;
3487 }
3488 
3489 /* Return true if IFN is some form of load from memory.  */
3490 
3491 bool
internal_load_fn_p(internal_fn fn)3492 internal_load_fn_p (internal_fn fn)
3493 {
3494   switch (fn)
3495     {
3496     case IFN_MASK_LOAD:
3497     case IFN_LOAD_LANES:
3498     case IFN_MASK_LOAD_LANES:
3499     case IFN_GATHER_LOAD:
3500     case IFN_MASK_GATHER_LOAD:
3501       return true;
3502 
3503     default:
3504       return false;
3505     }
3506 }
3507 
3508 /* Return true if IFN is some form of store to memory.  */
3509 
3510 bool
internal_store_fn_p(internal_fn fn)3511 internal_store_fn_p (internal_fn fn)
3512 {
3513   switch (fn)
3514     {
3515     case IFN_MASK_STORE:
3516     case IFN_STORE_LANES:
3517     case IFN_MASK_STORE_LANES:
3518     case IFN_SCATTER_STORE:
3519     case IFN_MASK_SCATTER_STORE:
3520       return true;
3521 
3522     default:
3523       return false;
3524     }
3525 }
3526 
3527 /* Return true if IFN is some form of gather load or scatter store.  */
3528 
3529 bool
internal_gather_scatter_fn_p(internal_fn fn)3530 internal_gather_scatter_fn_p (internal_fn fn)
3531 {
3532   switch (fn)
3533     {
3534     case IFN_GATHER_LOAD:
3535     case IFN_MASK_GATHER_LOAD:
3536     case IFN_SCATTER_STORE:
3537     case IFN_MASK_SCATTER_STORE:
3538       return true;
3539 
3540     default:
3541       return false;
3542     }
3543 }
3544 
3545 /* If FN takes a vector mask argument, return the index of that argument,
3546    otherwise return -1.  */
3547 
3548 int
internal_fn_mask_index(internal_fn fn)3549 internal_fn_mask_index (internal_fn fn)
3550 {
3551   switch (fn)
3552     {
3553     case IFN_MASK_LOAD:
3554     case IFN_MASK_LOAD_LANES:
3555     case IFN_MASK_STORE:
3556     case IFN_MASK_STORE_LANES:
3557       return 2;
3558 
3559     case IFN_MASK_GATHER_LOAD:
3560     case IFN_MASK_SCATTER_STORE:
3561       return 4;
3562 
3563     default:
3564       return (conditional_internal_fn_code (fn) != ERROR_MARK
3565 	      || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
3566     }
3567 }
3568 
3569 /* If FN takes a value that should be stored to memory, return the index
3570    of that argument, otherwise return -1.  */
3571 
3572 int
internal_fn_stored_value_index(internal_fn fn)3573 internal_fn_stored_value_index (internal_fn fn)
3574 {
3575   switch (fn)
3576     {
3577     case IFN_MASK_STORE:
3578     case IFN_SCATTER_STORE:
3579     case IFN_MASK_SCATTER_STORE:
3580       return 3;
3581 
3582     default:
3583       return -1;
3584     }
3585 }
3586 
3587 /* Return true if the target supports gather load or scatter store function
3588    IFN.  For loads, VECTOR_TYPE is the vector type of the load result,
3589    while for stores it is the vector type of the stored data argument.
3590    MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
3591    or stored.  OFFSET_VECTOR_TYPE is the vector type that holds the
3592    offset from the shared base address of each loaded or stored element.
3593    SCALE is the amount by which these offsets should be multiplied
3594    *after* they have been extended to address width.  */
3595 
3596 bool
internal_gather_scatter_fn_supported_p(internal_fn ifn,tree vector_type,tree memory_element_type,tree offset_vector_type,int scale)3597 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
3598 					tree memory_element_type,
3599 					tree offset_vector_type, int scale)
3600 {
3601   if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
3602 			   TYPE_SIZE (memory_element_type)))
3603     return false;
3604   if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
3605 		TYPE_VECTOR_SUBPARTS (offset_vector_type)))
3606     return false;
3607   optab optab = direct_internal_fn_optab (ifn);
3608   insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
3609 					   TYPE_MODE (offset_vector_type));
3610   int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
3611   bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
3612   return (icode != CODE_FOR_nothing
3613 	  && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
3614 	  && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
3615 }
3616 
3617 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
3618    for pointers of type TYPE when the accesses have LENGTH bytes and their
3619    common byte alignment is ALIGN.  */
3620 
3621 bool
internal_check_ptrs_fn_supported_p(internal_fn ifn,tree type,poly_uint64 length,unsigned int align)3622 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
3623 				    poly_uint64 length, unsigned int align)
3624 {
3625   machine_mode mode = TYPE_MODE (type);
3626   optab optab = direct_internal_fn_optab (ifn);
3627   insn_code icode = direct_optab_handler (optab, mode);
3628   if (icode == CODE_FOR_nothing)
3629     return false;
3630   rtx length_rtx = immed_wide_int_const (length, mode);
3631   return (insn_operand_matches (icode, 3, length_rtx)
3632 	  && insn_operand_matches (icode, 4, GEN_INT (align)));
3633 }
3634 
3635 /* Expand STMT as though it were a call to internal function FN.  */
3636 
3637 void
expand_internal_call(internal_fn fn,gcall * stmt)3638 expand_internal_call (internal_fn fn, gcall *stmt)
3639 {
3640   internal_fn_expanders[fn] (fn, stmt);
3641 }
3642 
3643 /* Expand STMT, which is a call to internal function FN.  */
3644 
3645 void
expand_internal_call(gcall * stmt)3646 expand_internal_call (gcall *stmt)
3647 {
3648   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
3649 }
3650 
3651 /* If TYPE is a vector type, return true if IFN is a direct internal
3652    function that is supported for that type.  If TYPE is a scalar type,
3653    return true if IFN is a direct internal function that is supported for
3654    the target's preferred vector version of TYPE.  */
3655 
3656 bool
vectorized_internal_fn_supported_p(internal_fn ifn,tree type)3657 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
3658 {
3659   scalar_mode smode;
3660   if (!VECTOR_TYPE_P (type) && is_a <scalar_mode> (TYPE_MODE (type), &smode))
3661     {
3662       machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
3663       if (VECTOR_MODE_P (vmode))
3664 	type = build_vector_type_for_mode (type, vmode);
3665     }
3666 
3667   return (VECTOR_MODE_P (TYPE_MODE (type))
3668 	  && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
3669 }
3670 
3671 void
expand_PHI(internal_fn,gcall *)3672 expand_PHI (internal_fn, gcall *)
3673 {
3674     gcc_unreachable ();
3675 }
3676