Replace REDUC_*_EXPRs with internal functions.
[platform/upstream/gcc.git] / gcc / internal-fn.c
1 /* Internal functions.
2    Copyright (C) 2011-2017 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 /* Fnspec of each internal function, indexed by function number.  */
68 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
69
70 void
71 init_internal_fns ()
72 {
73 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
74   if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
75     build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
76 #include "internal-fn.def"
77   internal_fn_fnspec_array[IFN_LAST] = 0;
78 }
79
80 /* Create static initializers for the information returned by
81    direct_internal_fn.  */
82 #define not_direct { -2, -2, false }
83 #define mask_load_direct { -1, 2, false }
84 #define load_lanes_direct { -1, -1, false }
85 #define mask_store_direct { 3, 2, false }
86 #define store_lanes_direct { 0, 0, false }
87 #define unary_direct { 0, 0, true }
88 #define binary_direct { 0, 0, true }
89
90 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
91 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
92 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
93 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
94                                      UNSIGNED_OPTAB, TYPE) TYPE##_direct,
95 #include "internal-fn.def"
96   not_direct
97 };
98
99 /* ARRAY_TYPE is an array of vector modes.  Return the associated insn
100    for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none.  */
101
102 static enum insn_code
103 get_multi_vector_move (tree array_type, convert_optab optab)
104 {
105   machine_mode imode;
106   machine_mode vmode;
107
108   gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
109   imode = TYPE_MODE (array_type);
110   vmode = TYPE_MODE (TREE_TYPE (array_type));
111
112   return convert_optab_handler (optab, imode, vmode);
113 }
114
115 /* Expand LOAD_LANES call STMT using optab OPTAB.  */
116
117 static void
118 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
119 {
120   struct expand_operand ops[2];
121   tree type, lhs, rhs;
122   rtx target, mem;
123
124   lhs = gimple_call_lhs (stmt);
125   rhs = gimple_call_arg (stmt, 0);
126   type = TREE_TYPE (lhs);
127
128   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
129   mem = expand_normal (rhs);
130
131   gcc_assert (MEM_P (mem));
132   PUT_MODE (mem, TYPE_MODE (type));
133
134   create_output_operand (&ops[0], target, TYPE_MODE (type));
135   create_fixed_operand (&ops[1], mem);
136   expand_insn (get_multi_vector_move (type, optab), 2, ops);
137 }
138
139 /* Expand STORE_LANES call STMT using optab OPTAB.  */
140
141 static void
142 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
143 {
144   struct expand_operand ops[2];
145   tree type, lhs, rhs;
146   rtx target, reg;
147
148   lhs = gimple_call_lhs (stmt);
149   rhs = gimple_call_arg (stmt, 0);
150   type = TREE_TYPE (rhs);
151
152   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
153   reg = expand_normal (rhs);
154
155   gcc_assert (MEM_P (target));
156   PUT_MODE (target, TYPE_MODE (type));
157
158   create_fixed_operand (&ops[0], target);
159   create_input_operand (&ops[1], reg, TYPE_MODE (type));
160   expand_insn (get_multi_vector_move (type, optab), 2, ops);
161 }
162
163 static void
164 expand_ANNOTATE (internal_fn, gcall *)
165 {
166   gcc_unreachable ();
167 }
168
169 /* This should get expanded in omp_device_lower pass.  */
170
171 static void
172 expand_GOMP_USE_SIMT (internal_fn, gcall *)
173 {
174   gcc_unreachable ();
175 }
176
177 /* This should get expanded in omp_device_lower pass.  */
178
179 static void
180 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
181 {
182   gcc_unreachable ();
183 }
184
185 /* Allocate per-lane storage and begin non-uniform execution region.  */
186
187 static void
188 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
189 {
190   rtx target;
191   tree lhs = gimple_call_lhs (stmt);
192   if (lhs)
193     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
194   else
195     target = gen_reg_rtx (Pmode);
196   rtx size = expand_normal (gimple_call_arg (stmt, 0));
197   rtx align = expand_normal (gimple_call_arg (stmt, 1));
198   struct expand_operand ops[3];
199   create_output_operand (&ops[0], target, Pmode);
200   create_input_operand (&ops[1], size, Pmode);
201   create_input_operand (&ops[2], align, Pmode);
202   gcc_assert (targetm.have_omp_simt_enter ());
203   expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
204 }
205
206 /* Deallocate per-lane storage and leave non-uniform execution region.  */
207
208 static void
209 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
210 {
211   gcc_checking_assert (!gimple_call_lhs (stmt));
212   rtx arg = expand_normal (gimple_call_arg (stmt, 0));
213   struct expand_operand ops[1];
214   create_input_operand (&ops[0], arg, Pmode);
215   gcc_assert (targetm.have_omp_simt_exit ());
216   expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
217 }
218
219 /* Lane index on SIMT targets: thread index in the warp on NVPTX.  On targets
220    without SIMT execution this should be expanded in omp_device_lower pass.  */
221
222 static void
223 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
224 {
225   tree lhs = gimple_call_lhs (stmt);
226   if (!lhs)
227     return;
228
229   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
230   gcc_assert (targetm.have_omp_simt_lane ());
231   emit_insn (targetm.gen_omp_simt_lane (target));
232 }
233
234 /* This should get expanded in omp_device_lower pass.  */
235
236 static void
237 expand_GOMP_SIMT_VF (internal_fn, gcall *)
238 {
239   gcc_unreachable ();
240 }
241
242 /* Lane index of the first SIMT lane that supplies a non-zero argument.
243    This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
244    lane that executed the last iteration for handling OpenMP lastprivate.  */
245
246 static void
247 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
248 {
249   tree lhs = gimple_call_lhs (stmt);
250   if (!lhs)
251     return;
252
253   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
254   rtx cond = expand_normal (gimple_call_arg (stmt, 0));
255   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
256   struct expand_operand ops[2];
257   create_output_operand (&ops[0], target, mode);
258   create_input_operand (&ops[1], cond, mode);
259   gcc_assert (targetm.have_omp_simt_last_lane ());
260   expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
261 }
262
263 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered".  */
264
265 static void
266 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
267 {
268   tree lhs = gimple_call_lhs (stmt);
269   if (!lhs)
270     return;
271
272   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
273   rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
274   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
275   struct expand_operand ops[2];
276   create_output_operand (&ops[0], target, mode);
277   create_input_operand (&ops[1], ctr, mode);
278   gcc_assert (targetm.have_omp_simt_ordered ());
279   expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
280 }
281
282 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
283    any lane supplies a non-zero argument.  */
284
285 static void
286 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
287 {
288   tree lhs = gimple_call_lhs (stmt);
289   if (!lhs)
290     return;
291
292   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
293   rtx cond = expand_normal (gimple_call_arg (stmt, 0));
294   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
295   struct expand_operand ops[2];
296   create_output_operand (&ops[0], target, mode);
297   create_input_operand (&ops[1], cond, mode);
298   gcc_assert (targetm.have_omp_simt_vote_any ());
299   expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
300 }
301
302 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
303    is destination lane index XOR given offset.  */
304
305 static void
306 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
307 {
308   tree lhs = gimple_call_lhs (stmt);
309   if (!lhs)
310     return;
311
312   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
313   rtx src = expand_normal (gimple_call_arg (stmt, 0));
314   rtx idx = expand_normal (gimple_call_arg (stmt, 1));
315   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
316   struct expand_operand ops[3];
317   create_output_operand (&ops[0], target, mode);
318   create_input_operand (&ops[1], src, mode);
319   create_input_operand (&ops[2], idx, SImode);
320   gcc_assert (targetm.have_omp_simt_xchg_bfly ());
321   expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
322 }
323
324 /* Exchange between SIMT lanes according to given source lane index.  */
325
326 static void
327 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
328 {
329   tree lhs = gimple_call_lhs (stmt);
330   if (!lhs)
331     return;
332
333   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
334   rtx src = expand_normal (gimple_call_arg (stmt, 0));
335   rtx idx = expand_normal (gimple_call_arg (stmt, 1));
336   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
337   struct expand_operand ops[3];
338   create_output_operand (&ops[0], target, mode);
339   create_input_operand (&ops[1], src, mode);
340   create_input_operand (&ops[2], idx, SImode);
341   gcc_assert (targetm.have_omp_simt_xchg_idx ());
342   expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
343 }
344
345 /* This should get expanded in adjust_simduid_builtins.  */
346
347 static void
348 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
349 {
350   gcc_unreachable ();
351 }
352
353 /* This should get expanded in adjust_simduid_builtins.  */
354
355 static void
356 expand_GOMP_SIMD_VF (internal_fn, gcall *)
357 {
358   gcc_unreachable ();
359 }
360
361 /* This should get expanded in adjust_simduid_builtins.  */
362
363 static void
364 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
365 {
366   gcc_unreachable ();
367 }
368
369 /* This should get expanded in adjust_simduid_builtins.  */
370
371 static void
372 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
373 {
374   gcc_unreachable ();
375 }
376
377 /* This should get expanded in adjust_simduid_builtins.  */
378
379 static void
380 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
381 {
382   gcc_unreachable ();
383 }
384
385 /* This should get expanded in the sanopt pass.  */
386
387 static void
388 expand_UBSAN_NULL (internal_fn, gcall *)
389 {
390   gcc_unreachable ();
391 }
392
393 /* This should get expanded in the sanopt pass.  */
394
395 static void
396 expand_UBSAN_BOUNDS (internal_fn, gcall *)
397 {
398   gcc_unreachable ();
399 }
400
401 /* This should get expanded in the sanopt pass.  */
402
403 static void
404 expand_UBSAN_VPTR (internal_fn, gcall *)
405 {
406   gcc_unreachable ();
407 }
408
409 /* This should get expanded in the sanopt pass.  */
410
411 static void
412 expand_UBSAN_PTR (internal_fn, gcall *)
413 {
414   gcc_unreachable ();
415 }
416
417 /* This should get expanded in the sanopt pass.  */
418
419 static void
420 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
421 {
422   gcc_unreachable ();
423 }
424
425 /* This should get expanded in the sanopt pass.  */
426
427 static void
428 expand_ASAN_CHECK (internal_fn, gcall *)
429 {
430   gcc_unreachable ();
431 }
432
433 /* This should get expanded in the sanopt pass.  */
434
435 static void
436 expand_ASAN_MARK (internal_fn, gcall *)
437 {
438   gcc_unreachable ();
439 }
440
441 /* This should get expanded in the sanopt pass.  */
442
443 static void
444 expand_ASAN_POISON (internal_fn, gcall *)
445 {
446   gcc_unreachable ();
447 }
448
449 /* This should get expanded in the sanopt pass.  */
450
451 static void
452 expand_ASAN_POISON_USE (internal_fn, gcall *)
453 {
454   gcc_unreachable ();
455 }
456
457 /* This should get expanded in the tsan pass.  */
458
459 static void
460 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
461 {
462   gcc_unreachable ();
463 }
464
465 /* This should get expanded in the lower pass.  */
466
467 static void
468 expand_FALLTHROUGH (internal_fn, gcall *call)
469 {
470   error_at (gimple_location (call),
471             "invalid use of attribute %<fallthrough%>");
472 }
473
474 /* Return minimum precision needed to represent all values
475    of ARG in SIGNed integral type.  */
476
477 static int
478 get_min_precision (tree arg, signop sign)
479 {
480   int prec = TYPE_PRECISION (TREE_TYPE (arg));
481   int cnt = 0;
482   signop orig_sign = sign;
483   if (TREE_CODE (arg) == INTEGER_CST)
484     {
485       int p;
486       if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
487         {
488           widest_int w = wi::to_widest (arg);
489           w = wi::ext (w, prec, sign);
490           p = wi::min_precision (w, sign);
491         }
492       else
493         p = wi::min_precision (wi::to_wide (arg), sign);
494       return MIN (p, prec);
495     }
496   while (CONVERT_EXPR_P (arg)
497          && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
498          && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
499     {
500       arg = TREE_OPERAND (arg, 0);
501       if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
502         {
503           if (TYPE_UNSIGNED (TREE_TYPE (arg)))
504             sign = UNSIGNED;
505           else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
506             return prec + (orig_sign != sign);
507           prec = TYPE_PRECISION (TREE_TYPE (arg));
508         }
509       if (++cnt > 30)
510         return prec + (orig_sign != sign);
511     }
512   if (TREE_CODE (arg) != SSA_NAME)
513     return prec + (orig_sign != sign);
514   wide_int arg_min, arg_max;
515   while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
516     {
517       gimple *g = SSA_NAME_DEF_STMT (arg);
518       if (is_gimple_assign (g)
519           && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
520         {
521           tree t = gimple_assign_rhs1 (g);
522           if (INTEGRAL_TYPE_P (TREE_TYPE (t))
523               && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
524             {
525               arg = t;
526               if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
527                 {
528                   if (TYPE_UNSIGNED (TREE_TYPE (arg)))
529                     sign = UNSIGNED;
530                   else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
531                     return prec + (orig_sign != sign);
532                   prec = TYPE_PRECISION (TREE_TYPE (arg));
533                 }
534               if (++cnt > 30)
535                 return prec + (orig_sign != sign);
536               continue;
537             }
538         }
539       return prec + (orig_sign != sign);
540     }
541   if (sign == TYPE_SIGN (TREE_TYPE (arg)))
542     {
543       int p1 = wi::min_precision (arg_min, sign);
544       int p2 = wi::min_precision (arg_max, sign);
545       p1 = MAX (p1, p2);
546       prec = MIN (prec, p1);
547     }
548   else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
549     {
550       int p = wi::min_precision (arg_max, UNSIGNED);
551       prec = MIN (prec, p);
552     }
553   return prec + (orig_sign != sign);
554 }
555
556 /* Helper for expand_*_overflow.  Set the __imag__ part to true
557    (1 except for signed:1 type, in which case store -1).  */
558
559 static void
560 expand_arith_set_overflow (tree lhs, rtx target)
561 {
562   if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
563       && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
564     write_complex_part (target, constm1_rtx, true);
565   else
566     write_complex_part (target, const1_rtx, true);
567 }
568
569 /* Helper for expand_*_overflow.  Store RES into the __real__ part
570    of TARGET.  If RES has larger MODE than __real__ part of TARGET,
571    set the __imag__ part to 1 if RES doesn't fit into it.  Similarly
572    if LHS has smaller precision than its mode.  */
573
574 static void
575 expand_arith_overflow_result_store (tree lhs, rtx target,
576                                     scalar_int_mode mode, rtx res)
577 {
578   scalar_int_mode tgtmode
579     = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
580   rtx lres = res;
581   if (tgtmode != mode)
582     {
583       rtx_code_label *done_label = gen_label_rtx ();
584       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
585       lres = convert_modes (tgtmode, mode, res, uns);
586       gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
587       do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
588                                EQ, true, mode, NULL_RTX, NULL, done_label,
589                                profile_probability::very_likely ());
590       expand_arith_set_overflow (lhs, target);
591       emit_label (done_label);
592     }
593   int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
594   int tgtprec = GET_MODE_PRECISION (tgtmode);
595   if (prec < tgtprec)
596     {
597       rtx_code_label *done_label = gen_label_rtx ();
598       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
599       res = lres;
600       if (uns)
601         {
602           rtx mask
603             = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
604                                     tgtmode);
605           lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
606                                       true, OPTAB_LIB_WIDEN);
607         }
608       else
609         {
610           lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
611                                NULL_RTX, 1);
612           lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
613                                NULL_RTX, 0);
614         }
615       do_compare_rtx_and_jump (res, lres,
616                                EQ, true, tgtmode, NULL_RTX, NULL, done_label,
617                                profile_probability::very_likely ());
618       expand_arith_set_overflow (lhs, target);
619       emit_label (done_label);
620     }
621   write_complex_part (target, lres, false);
622 }
623
624 /* Helper for expand_*_overflow.  Store RES into TARGET.  */
625
626 static void
627 expand_ubsan_result_store (rtx target, rtx res)
628 {
629   if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
630     /* If this is a scalar in a register that is stored in a wider mode   
631        than the declared mode, compute the result into its declared mode
632        and then convert to the wider mode.  Our value is the computed
633        expression.  */
634     convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
635   else
636     emit_move_insn (target, res);
637 }
638
639 /* Add sub/add overflow checking to the statement STMT.
640    CODE says whether the operation is +, or -.  */
641
642 static void
643 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
644                         tree arg0, tree arg1, bool unsr_p, bool uns0_p,
645                         bool uns1_p, bool is_ubsan, tree *datap)
646 {
647   rtx res, target = NULL_RTX;
648   tree fn;
649   rtx_code_label *done_label = gen_label_rtx ();
650   rtx_code_label *do_error = gen_label_rtx ();
651   do_pending_stack_adjust ();
652   rtx op0 = expand_normal (arg0);
653   rtx op1 = expand_normal (arg1);
654   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
655   int prec = GET_MODE_PRECISION (mode);
656   rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
657   bool do_xor = false;
658
659   if (is_ubsan)
660     gcc_assert (!unsr_p && !uns0_p && !uns1_p);
661
662   if (lhs)
663     {
664       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
665       if (!is_ubsan)
666         write_complex_part (target, const0_rtx, true);
667     }
668
669   /* We assume both operands and result have the same precision
670      here (GET_MODE_BITSIZE (mode)), S stands for signed type
671      with that precision, U for unsigned type with that precision,
672      sgn for unsigned most significant bit in that precision.
673      s1 is signed first operand, u1 is unsigned first operand,
674      s2 is signed second operand, u2 is unsigned second operand,
675      sr is signed result, ur is unsigned result and the following
676      rules say how to compute result (which is always result of
677      the operands as if both were unsigned, cast to the right
678      signedness) and how to compute whether operation overflowed.
679
680      s1 + s2 -> sr
681         res = (S) ((U) s1 + (U) s2)
682         ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
683      s1 - s2 -> sr
684         res = (S) ((U) s1 - (U) s2)
685         ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
686      u1 + u2 -> ur
687         res = u1 + u2
688         ovf = res < u1 (or jump on carry, but RTL opts will handle it)
689      u1 - u2 -> ur
690         res = u1 - u2
691         ovf = res > u1 (or jump on carry, but RTL opts will handle it)
692      s1 + u2 -> sr
693         res = (S) ((U) s1 + u2)
694         ovf = ((U) res ^ sgn) < u2
695      s1 + u2 -> ur
696         t1 = (S) (u2 ^ sgn)
697         t2 = s1 + t1
698         res = (U) t2 ^ sgn
699         ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
700      s1 - u2 -> sr
701         res = (S) ((U) s1 - u2)
702         ovf = u2 > ((U) s1 ^ sgn)
703      s1 - u2 -> ur
704         res = (U) s1 - u2
705         ovf = s1 < 0 || u2 > (U) s1
706      u1 - s2 -> sr
707         res = u1 - (U) s2
708         ovf = u1 >= ((U) s2 ^ sgn)
709      u1 - s2 -> ur
710         t1 = u1 ^ sgn
711         t2 = t1 - (U) s2
712         res = t2 ^ sgn
713         ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
714      s1 + s2 -> ur
715         res = (U) s1 + (U) s2
716         ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
717      u1 + u2 -> sr
718         res = (S) (u1 + u2)
719         ovf = (U) res < u2 || res < 0
720      u1 - u2 -> sr
721         res = (S) (u1 - u2)
722         ovf = u1 >= u2 ? res < 0 : res >= 0
723      s1 - s2 -> ur
724         res = (U) s1 - (U) s2
725         ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0)  */
726
727   if (code == PLUS_EXPR && uns0_p && !uns1_p)
728     {
729       /* PLUS_EXPR is commutative, if operand signedness differs,
730          canonicalize to the first operand being signed and second
731          unsigned to simplify following code.  */
732       std::swap (op0, op1);
733       std::swap (arg0, arg1);
734       uns0_p = false;
735       uns1_p = true;
736     }
737
738   /* u1 +- u2 -> ur  */
739   if (uns0_p && uns1_p && unsr_p)
740     {
741       insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
742                                        : usubv4_optab, mode);
743       if (icode != CODE_FOR_nothing)
744         {
745           struct expand_operand ops[4];
746           rtx_insn *last = get_last_insn ();
747
748           res = gen_reg_rtx (mode);
749           create_output_operand (&ops[0], res, mode);
750           create_input_operand (&ops[1], op0, mode);
751           create_input_operand (&ops[2], op1, mode);
752           create_fixed_operand (&ops[3], do_error);
753           if (maybe_expand_insn (icode, 4, ops))
754             {
755               last = get_last_insn ();
756               if (profile_status_for_fn (cfun) != PROFILE_ABSENT
757                   && JUMP_P (last)
758                   && any_condjump_p (last)
759                   && !find_reg_note (last, REG_BR_PROB, 0))
760                 add_reg_br_prob_note (last,
761                                       profile_probability::very_unlikely ());
762               emit_jump (done_label);
763               goto do_error_label;
764             }
765
766           delete_insns_since (last);
767         }
768
769       /* Compute the operation.  On RTL level, the addition is always
770          unsigned.  */
771       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
772                           op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
773       rtx tem = op0;
774       /* For PLUS_EXPR, the operation is commutative, so we can pick
775          operand to compare against.  For prec <= BITS_PER_WORD, I think
776          preferring REG operand is better over CONST_INT, because
777          the CONST_INT might enlarge the instruction or CSE would need
778          to figure out we'd already loaded it into a register before.
779          For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
780          as then the multi-word comparison can be perhaps simplified.  */
781       if (code == PLUS_EXPR
782           && (prec <= BITS_PER_WORD
783               ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
784               : CONST_SCALAR_INT_P (op1)))
785         tem = op1;
786       do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
787                                true, mode, NULL_RTX, NULL, done_label,
788                                profile_probability::very_likely ());
789       goto do_error_label;
790     }
791
792   /* s1 +- u2 -> sr  */
793   if (!uns0_p && uns1_p && !unsr_p)
794     {
795       /* Compute the operation.  On RTL level, the addition is always
796          unsigned.  */
797       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
798                           op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
799       rtx tem = expand_binop (mode, add_optab,
800                               code == PLUS_EXPR ? res : op0, sgn,
801                               NULL_RTX, false, OPTAB_LIB_WIDEN);
802       do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
803                                done_label, profile_probability::very_likely ());
804       goto do_error_label;
805     }
806
807   /* s1 + u2 -> ur  */
808   if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
809     {
810       op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
811                           OPTAB_LIB_WIDEN);
812       /* As we've changed op1, we have to avoid using the value range
813          for the original argument.  */
814       arg1 = error_mark_node;
815       do_xor = true;
816       goto do_signed;
817     }
818
819   /* u1 - s2 -> ur  */
820   if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
821     {
822       op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
823                           OPTAB_LIB_WIDEN);
824       /* As we've changed op0, we have to avoid using the value range
825          for the original argument.  */
826       arg0 = error_mark_node;
827       do_xor = true;
828       goto do_signed;
829     }
830
831   /* s1 - u2 -> ur  */
832   if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
833     {
834       /* Compute the operation.  On RTL level, the addition is always
835          unsigned.  */
836       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
837                           OPTAB_LIB_WIDEN);
838       int pos_neg = get_range_pos_neg (arg0);
839       if (pos_neg == 2)
840         /* If ARG0 is known to be always negative, this is always overflow.  */
841         emit_jump (do_error);
842       else if (pos_neg == 3)
843         /* If ARG0 is not known to be always positive, check at runtime.  */
844         do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
845                                  NULL, do_error, profile_probability::very_unlikely ());
846       do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
847                                done_label, profile_probability::very_likely ());
848       goto do_error_label;
849     }
850
851   /* u1 - s2 -> sr  */
852   if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
853     {
854       /* Compute the operation.  On RTL level, the addition is always
855          unsigned.  */
856       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
857                           OPTAB_LIB_WIDEN);
858       rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
859                               OPTAB_LIB_WIDEN);
860       do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
861                                done_label, profile_probability::very_likely ());
862       goto do_error_label;
863     }
864
865   /* u1 + u2 -> sr  */
866   if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
867     {
868       /* Compute the operation.  On RTL level, the addition is always
869          unsigned.  */
870       res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
871                           OPTAB_LIB_WIDEN);
872       do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
873                                NULL, do_error, profile_probability::very_unlikely ());
874       rtx tem = op1;
875       /* The operation is commutative, so we can pick operand to compare
876          against.  For prec <= BITS_PER_WORD, I think preferring REG operand
877          is better over CONST_INT, because the CONST_INT might enlarge the
878          instruction or CSE would need to figure out we'd already loaded it
879          into a register before.  For prec > BITS_PER_WORD, I think CONST_INT
880          might be more beneficial, as then the multi-word comparison can be
881          perhaps simplified.  */
882       if (prec <= BITS_PER_WORD
883           ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
884           : CONST_SCALAR_INT_P (op0))
885         tem = op0;
886       do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
887                                done_label, profile_probability::very_likely ());
888       goto do_error_label;
889     }
890
891   /* s1 +- s2 -> ur  */
892   if (!uns0_p && !uns1_p && unsr_p)
893     {
894       /* Compute the operation.  On RTL level, the addition is always
895          unsigned.  */
896       res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
897                           op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
898       int pos_neg = get_range_pos_neg (arg1);
899       if (code == PLUS_EXPR)
900         {
901           int pos_neg0 = get_range_pos_neg (arg0);
902           if (pos_neg0 != 3 && pos_neg == 3)
903             {
904               std::swap (op0, op1);
905               pos_neg = pos_neg0;
906             }
907         }
908       rtx tem;
909       if (pos_neg != 3)
910         {
911           tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
912                                     ? and_optab : ior_optab,
913                               op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
914           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
915                                    NULL, done_label, profile_probability::very_likely ());
916         }
917       else
918         {
919           rtx_code_label *do_ior_label = gen_label_rtx ();
920           do_compare_rtx_and_jump (op1, const0_rtx,
921                                    code == MINUS_EXPR ? GE : LT, false, mode,
922                                    NULL_RTX, NULL, do_ior_label,
923                                    profile_probability::even ());
924           tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
925                               OPTAB_LIB_WIDEN);
926           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
927                                    NULL, done_label, profile_probability::very_likely ());
928           emit_jump (do_error);
929           emit_label (do_ior_label);
930           tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
931                               OPTAB_LIB_WIDEN);
932           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
933                                    NULL, done_label, profile_probability::very_likely ());
934         }
935       goto do_error_label;
936     }
937
938   /* u1 - u2 -> sr  */
939   if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
940     {
941       /* Compute the operation.  On RTL level, the addition is always
942          unsigned.  */
943       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
944                           OPTAB_LIB_WIDEN);
945       rtx_code_label *op0_geu_op1 = gen_label_rtx ();
946       do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
947                                op0_geu_op1, profile_probability::even ());
948       do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
949                                NULL, done_label, profile_probability::very_likely ());
950       emit_jump (do_error);
951       emit_label (op0_geu_op1);
952       do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
953                                NULL, done_label, profile_probability::very_likely ());
954       goto do_error_label;
955     }
956
957   gcc_assert (!uns0_p && !uns1_p && !unsr_p);
958
959   /* s1 +- s2 -> sr  */
960  do_signed:
961   {
962     insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
963                                      : subv4_optab, mode);
964     if (icode != CODE_FOR_nothing)
965       {
966         struct expand_operand ops[4];
967         rtx_insn *last = get_last_insn ();
968
969         res = gen_reg_rtx (mode);
970         create_output_operand (&ops[0], res, mode);
971         create_input_operand (&ops[1], op0, mode);
972         create_input_operand (&ops[2], op1, mode);
973         create_fixed_operand (&ops[3], do_error);
974         if (maybe_expand_insn (icode, 4, ops))
975           {
976             last = get_last_insn ();
977             if (profile_status_for_fn (cfun) != PROFILE_ABSENT
978                 && JUMP_P (last)
979                 && any_condjump_p (last)
980                 && !find_reg_note (last, REG_BR_PROB, 0))
981               add_reg_br_prob_note (last, 
982                                     profile_probability::very_unlikely ());
983             emit_jump (done_label);
984             goto do_error_label;
985           }
986
987         delete_insns_since (last);
988       }
989
990     /* Compute the operation.  On RTL level, the addition is always
991        unsigned.  */
992     res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
993                         op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
994
995     /* If we can prove that one of the arguments (for MINUS_EXPR only
996        the second operand, as subtraction is not commutative) is always
997        non-negative or always negative, we can do just one comparison
998        and conditional jump.  */
999     int pos_neg = get_range_pos_neg (arg1);
1000     if (code == PLUS_EXPR)
1001       {
1002         int pos_neg0 = get_range_pos_neg (arg0);
1003         if (pos_neg0 != 3 && pos_neg == 3)
1004           {
1005             std::swap (op0, op1);
1006             pos_neg = pos_neg0;
1007           }
1008       }
1009
1010     /* Addition overflows if and only if the two operands have the same sign,
1011        and the result has the opposite sign.  Subtraction overflows if and
1012        only if the two operands have opposite sign, and the subtrahend has
1013        the same sign as the result.  Here 0 is counted as positive.  */
1014     if (pos_neg == 3)
1015       {
1016         /* Compute op0 ^ op1 (operands have opposite sign).  */
1017         rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1018                                    OPTAB_LIB_WIDEN);
1019
1020         /* Compute res ^ op1 (result and 2nd operand have opposite sign).  */
1021         rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1022                                     OPTAB_LIB_WIDEN);
1023
1024         rtx tem;
1025         if (code == PLUS_EXPR)
1026           {
1027             /* Compute (res ^ op1) & ~(op0 ^ op1).  */
1028             tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1029             tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1030                                 OPTAB_LIB_WIDEN);
1031           }
1032         else
1033           {
1034             /* Compute (op0 ^ op1) & ~(res ^ op1).  */
1035             tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1036             tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1037                                 OPTAB_LIB_WIDEN);
1038           }
1039
1040         /* No overflow if the result has bit sign cleared.  */
1041         do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1042                                  NULL, done_label, profile_probability::very_likely ());
1043       }
1044
1045     /* Compare the result of the operation with the first operand.
1046        No overflow for addition if second operand is positive and result
1047        is larger or second operand is negative and result is smaller.
1048        Likewise for subtraction with sign of second operand flipped.  */
1049     else
1050       do_compare_rtx_and_jump (res, op0,
1051                                (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1052                                false, mode, NULL_RTX, NULL, done_label,
1053                                profile_probability::very_likely ());
1054   }
1055
1056  do_error_label:
1057   emit_label (do_error);
1058   if (is_ubsan)
1059     {
1060       /* Expand the ubsan builtin call.  */
1061       push_temp_slots ();
1062       fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1063                                          arg0, arg1, datap);
1064       expand_normal (fn);
1065       pop_temp_slots ();
1066       do_pending_stack_adjust ();
1067     }
1068   else if (lhs)
1069     expand_arith_set_overflow (lhs, target);
1070
1071   /* We're done.  */
1072   emit_label (done_label);
1073
1074   if (lhs)
1075     {
1076       if (is_ubsan)
1077         expand_ubsan_result_store (target, res);
1078       else
1079         {
1080           if (do_xor)
1081             res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1082                                 OPTAB_LIB_WIDEN);
1083
1084           expand_arith_overflow_result_store (lhs, target, mode, res);
1085         }
1086     }
1087 }
1088
1089 /* Add negate overflow checking to the statement STMT.  */
1090
1091 static void
1092 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1093                      tree *datap)
1094 {
1095   rtx res, op1;
1096   tree fn;
1097   rtx_code_label *done_label, *do_error;
1098   rtx target = NULL_RTX;
1099
1100   done_label = gen_label_rtx ();
1101   do_error = gen_label_rtx ();
1102
1103   do_pending_stack_adjust ();
1104   op1 = expand_normal (arg1);
1105
1106   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1107   if (lhs)
1108     {
1109       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1110       if (!is_ubsan)
1111         write_complex_part (target, const0_rtx, true);
1112     }
1113
1114   enum insn_code icode = optab_handler (negv3_optab, mode);
1115   if (icode != CODE_FOR_nothing)
1116     {
1117       struct expand_operand ops[3];
1118       rtx_insn *last = get_last_insn ();
1119
1120       res = gen_reg_rtx (mode);
1121       create_output_operand (&ops[0], res, mode);
1122       create_input_operand (&ops[1], op1, mode);
1123       create_fixed_operand (&ops[2], do_error);
1124       if (maybe_expand_insn (icode, 3, ops))
1125         {
1126           last = get_last_insn ();
1127           if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1128               && JUMP_P (last)
1129               && any_condjump_p (last)
1130               && !find_reg_note (last, REG_BR_PROB, 0))
1131             add_reg_br_prob_note (last, 
1132                                   profile_probability::very_unlikely ());
1133           emit_jump (done_label);
1134         }
1135       else
1136         {
1137           delete_insns_since (last);
1138           icode = CODE_FOR_nothing;
1139         }
1140     }
1141
1142   if (icode == CODE_FOR_nothing)
1143     {
1144       /* Compute the operation.  On RTL level, the addition is always
1145          unsigned.  */
1146       res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1147
1148       /* Compare the operand with the most negative value.  */
1149       rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1150       do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1151                                done_label, profile_probability::very_likely ());
1152     }
1153
1154   emit_label (do_error);
1155   if (is_ubsan)
1156     {
1157       /* Expand the ubsan builtin call.  */
1158       push_temp_slots ();
1159       fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1160                                          arg1, NULL_TREE, datap);
1161       expand_normal (fn);
1162       pop_temp_slots ();
1163       do_pending_stack_adjust ();
1164     }
1165   else if (lhs)
1166     expand_arith_set_overflow (lhs, target);
1167
1168   /* We're done.  */
1169   emit_label (done_label);
1170
1171   if (lhs)
1172     {
1173       if (is_ubsan)
1174         expand_ubsan_result_store (target, res);
1175       else
1176         expand_arith_overflow_result_store (lhs, target, mode, res);
1177     }
1178 }
1179
1180 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1181    mode MODE can be expanded without using a libcall.  */
1182
1183 static bool
1184 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1185                                 rtx op0, rtx op1, bool uns)
1186 {
1187   if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1188       != CODE_FOR_nothing)
1189     return true;
1190     
1191   if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1192       != CODE_FOR_nothing)
1193     return true;
1194
1195   rtx_insn *last = get_last_insn ();
1196   if (CONSTANT_P (op0))
1197     op0 = convert_modes (wmode, mode, op0, uns);
1198   else
1199     op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1200   if (CONSTANT_P (op1))
1201     op1 = convert_modes (wmode, mode, op1, uns);
1202   else
1203     op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1204   rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1205   delete_insns_since (last);
1206   return ret != NULL_RTX;
1207
1208
1209 /* Add mul overflow checking to the statement STMT.  */
1210
1211 static void
1212 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1213                      bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1214                      tree *datap)
1215 {
1216   rtx res, op0, op1;
1217   tree fn, type;
1218   rtx_code_label *done_label, *do_error;
1219   rtx target = NULL_RTX;
1220   signop sign;
1221   enum insn_code icode;
1222
1223   done_label = gen_label_rtx ();
1224   do_error = gen_label_rtx ();
1225
1226   do_pending_stack_adjust ();
1227   op0 = expand_normal (arg0);
1228   op1 = expand_normal (arg1);
1229
1230   scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1231   bool uns = unsr_p;
1232   if (lhs)
1233     {
1234       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1235       if (!is_ubsan)
1236         write_complex_part (target, const0_rtx, true);
1237     }
1238
1239   if (is_ubsan)
1240     gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1241
1242   /* We assume both operands and result have the same precision
1243      here (GET_MODE_BITSIZE (mode)), S stands for signed type
1244      with that precision, U for unsigned type with that precision,
1245      sgn for unsigned most significant bit in that precision.
1246      s1 is signed first operand, u1 is unsigned first operand,
1247      s2 is signed second operand, u2 is unsigned second operand,
1248      sr is signed result, ur is unsigned result and the following
1249      rules say how to compute result (which is always result of
1250      the operands as if both were unsigned, cast to the right
1251      signedness) and how to compute whether operation overflowed.
1252      main_ovf (false) stands for jump on signed multiplication
1253      overflow or the main algorithm with uns == false.
1254      main_ovf (true) stands for jump on unsigned multiplication
1255      overflow or the main algorithm with uns == true.
1256
1257      s1 * s2 -> sr
1258         res = (S) ((U) s1 * (U) s2)
1259         ovf = main_ovf (false)
1260      u1 * u2 -> ur
1261         res = u1 * u2
1262         ovf = main_ovf (true)
1263      s1 * u2 -> ur
1264         res = (U) s1 * u2
1265         ovf = (s1 < 0 && u2) || main_ovf (true)
1266      u1 * u2 -> sr
1267         res = (S) (u1 * u2)
1268         ovf = res < 0 || main_ovf (true)
1269      s1 * u2 -> sr
1270         res = (S) ((U) s1 * u2)
1271         ovf = (S) u2 >= 0 ? main_ovf (false)
1272                           : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1273      s1 * s2 -> ur
1274         t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1275         t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1276         res = t1 * t2
1277         ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true)  */
1278
1279   if (uns0_p && !uns1_p)
1280     {
1281       /* Multiplication is commutative, if operand signedness differs,
1282          canonicalize to the first operand being signed and second
1283          unsigned to simplify following code.  */
1284       std::swap (op0, op1);
1285       std::swap (arg0, arg1);
1286       uns0_p = false;
1287       uns1_p = true;
1288     }
1289
1290   int pos_neg0 = get_range_pos_neg (arg0);
1291   int pos_neg1 = get_range_pos_neg (arg1);
1292
1293   /* s1 * u2 -> ur  */
1294   if (!uns0_p && uns1_p && unsr_p)
1295     {
1296       switch (pos_neg0)
1297         {
1298         case 1:
1299           /* If s1 is non-negative, just perform normal u1 * u2 -> ur.  */
1300           goto do_main;
1301         case 2:
1302           /* If s1 is negative, avoid the main code, just multiply and
1303              signal overflow if op1 is not 0.  */
1304           struct separate_ops ops;
1305           ops.code = MULT_EXPR;
1306           ops.type = TREE_TYPE (arg1);
1307           ops.op0 = make_tree (ops.type, op0);
1308           ops.op1 = make_tree (ops.type, op1);
1309           ops.op2 = NULL_TREE;
1310           ops.location = loc;
1311           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1312           do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1313                                    NULL, done_label, profile_probability::very_likely ());
1314           goto do_error_label;
1315         case 3:
1316           rtx_code_label *do_main_label;
1317           do_main_label = gen_label_rtx ();
1318           do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1319                                    NULL, do_main_label, profile_probability::very_likely ());
1320           do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1321                                    NULL, do_main_label, profile_probability::very_likely ());
1322           expand_arith_set_overflow (lhs, target);
1323           emit_label (do_main_label);
1324           goto do_main;
1325         default:
1326           gcc_unreachable ();
1327         }
1328     }
1329
1330   /* u1 * u2 -> sr  */
1331   if (uns0_p && uns1_p && !unsr_p)
1332     {
1333       uns = true;
1334       /* Rest of handling of this case after res is computed.  */
1335       goto do_main;
1336     }
1337
1338   /* s1 * u2 -> sr  */
1339   if (!uns0_p && uns1_p && !unsr_p)
1340     {
1341       switch (pos_neg1)
1342         {
1343         case 1:
1344           goto do_main;
1345         case 2:
1346           /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1347              avoid the main code, just multiply and signal overflow
1348              unless 0 * u2 or -1 * ((U) Smin).  */
1349           struct separate_ops ops;
1350           ops.code = MULT_EXPR;
1351           ops.type = TREE_TYPE (arg1);
1352           ops.op0 = make_tree (ops.type, op0);
1353           ops.op1 = make_tree (ops.type, op1);
1354           ops.op2 = NULL_TREE;
1355           ops.location = loc;
1356           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1357           do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1358                                    NULL, done_label, profile_probability::very_likely ());
1359           do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1360                                    NULL, do_error, profile_probability::very_unlikely ());
1361           int prec;
1362           prec = GET_MODE_PRECISION (mode);
1363           rtx sgn;
1364           sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1365           do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1366                                    NULL, done_label, profile_probability::very_likely ());
1367           goto do_error_label;
1368         case 3:
1369           /* Rest of handling of this case after res is computed.  */
1370           goto do_main;
1371         default:
1372           gcc_unreachable ();
1373         }
1374     }
1375
1376   /* s1 * s2 -> ur  */
1377   if (!uns0_p && !uns1_p && unsr_p)
1378     {
1379       rtx tem, tem2;
1380       switch (pos_neg0 | pos_neg1)
1381         {
1382         case 1: /* Both operands known to be non-negative.  */
1383           goto do_main;
1384         case 2: /* Both operands known to be negative.  */
1385           op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1386           op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1387           /* Avoid looking at arg0/arg1 ranges, as we've changed
1388              the arguments.  */
1389           arg0 = error_mark_node;
1390           arg1 = error_mark_node;
1391           goto do_main;
1392         case 3:
1393           if ((pos_neg0 ^ pos_neg1) == 3)
1394             {
1395               /* If one operand is known to be negative and the other
1396                  non-negative, this overflows always, unless the non-negative
1397                  one is 0.  Just do normal multiply and set overflow
1398                  unless one of the operands is 0.  */
1399               struct separate_ops ops;
1400               ops.code = MULT_EXPR;
1401               ops.type
1402                 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1403                                                   1);
1404               ops.op0 = make_tree (ops.type, op0);
1405               ops.op1 = make_tree (ops.type, op1);
1406               ops.op2 = NULL_TREE;
1407               ops.location = loc;
1408               res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1409               tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1410                                   OPTAB_LIB_WIDEN);
1411               do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1412                                        NULL_RTX, NULL, done_label,
1413                                        profile_probability::very_likely ());
1414               goto do_error_label;
1415             }
1416           /* The general case, do all the needed comparisons at runtime.  */
1417           rtx_code_label *do_main_label, *after_negate_label;
1418           rtx rop0, rop1;
1419           rop0 = gen_reg_rtx (mode);
1420           rop1 = gen_reg_rtx (mode);
1421           emit_move_insn (rop0, op0);
1422           emit_move_insn (rop1, op1);
1423           op0 = rop0;
1424           op1 = rop1;
1425           do_main_label = gen_label_rtx ();
1426           after_negate_label = gen_label_rtx ();
1427           tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1428                               OPTAB_LIB_WIDEN);
1429           do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1430                                    NULL, after_negate_label, profile_probability::very_likely ());
1431           /* Both arguments negative here, negate them and continue with
1432              normal unsigned overflow checking multiplication.  */
1433           emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1434                                             NULL_RTX, false));
1435           emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1436                                             NULL_RTX, false));
1437           /* Avoid looking at arg0/arg1 ranges, as we might have changed
1438              the arguments.  */
1439           arg0 = error_mark_node;
1440           arg1 = error_mark_node;
1441           emit_jump (do_main_label);
1442           emit_label (after_negate_label);
1443           tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1444                                OPTAB_LIB_WIDEN);
1445           do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1446                                    NULL, do_main_label, profile_probability::very_likely ());
1447           /* One argument is negative here, the other positive.  This
1448              overflows always, unless one of the arguments is 0.  But
1449              if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1450              is, thus we can keep do_main code oring in overflow as is.  */
1451           do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1452                                    NULL, do_main_label, profile_probability::very_likely ());
1453           expand_arith_set_overflow (lhs, target);
1454           emit_label (do_main_label);
1455           goto do_main;
1456         default:
1457           gcc_unreachable ();
1458         }
1459     }
1460
1461  do_main:
1462   type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1463   sign = uns ? UNSIGNED : SIGNED;
1464   icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1465   if (icode != CODE_FOR_nothing)
1466     {
1467       struct expand_operand ops[4];
1468       rtx_insn *last = get_last_insn ();
1469
1470       res = gen_reg_rtx (mode);
1471       create_output_operand (&ops[0], res, mode);
1472       create_input_operand (&ops[1], op0, mode);
1473       create_input_operand (&ops[2], op1, mode);
1474       create_fixed_operand (&ops[3], do_error);
1475       if (maybe_expand_insn (icode, 4, ops))
1476         {
1477           last = get_last_insn ();
1478           if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1479               && JUMP_P (last)
1480               && any_condjump_p (last)
1481               && !find_reg_note (last, REG_BR_PROB, 0))
1482             add_reg_br_prob_note (last, 
1483                                   profile_probability::very_unlikely ());
1484           emit_jump (done_label);
1485         }
1486       else
1487         {
1488           delete_insns_since (last);
1489           icode = CODE_FOR_nothing;
1490         }
1491     }
1492
1493   if (icode == CODE_FOR_nothing)
1494     {
1495       struct separate_ops ops;
1496       int prec = GET_MODE_PRECISION (mode);
1497       scalar_int_mode hmode, wmode;
1498       ops.op0 = make_tree (type, op0);
1499       ops.op1 = make_tree (type, op1);
1500       ops.op2 = NULL_TREE;
1501       ops.location = loc;
1502
1503       /* Optimize unsigned overflow check where we don't use the
1504          multiplication result, just whether overflow happened.
1505          If we can do MULT_HIGHPART_EXPR, that followed by
1506          comparison of the result against zero is cheapest.
1507          We'll still compute res, but it should be DCEd later.  */
1508       use_operand_p use;
1509       gimple *use_stmt;
1510       if (!is_ubsan
1511           && lhs
1512           && uns
1513           && !(uns0_p && uns1_p && !unsr_p)
1514           && can_mult_highpart_p (mode, uns) == 1
1515           && single_imm_use (lhs, &use, &use_stmt)
1516           && is_gimple_assign (use_stmt)
1517           && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1518         goto highpart;
1519
1520       if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1521           && targetm.scalar_mode_supported_p (wmode)
1522           && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1523         {
1524         twoxwider:
1525           ops.code = WIDEN_MULT_EXPR;
1526           ops.type
1527             = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1528
1529           res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1530           rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1531                                      NULL_RTX, uns);
1532           hipart = convert_modes (mode, wmode, hipart, uns);
1533           res = convert_modes (mode, wmode, res, uns);
1534           if (uns)
1535             /* For the unsigned multiplication, there was overflow if
1536                HIPART is non-zero.  */
1537             do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1538                                      NULL_RTX, NULL, done_label,
1539                                      profile_probability::very_likely ());
1540           else
1541             {
1542               rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1543                                           NULL_RTX, 0);
1544               /* RES is low half of the double width result, HIPART
1545                  the high half.  There was overflow if
1546                  HIPART is different from RES < 0 ? -1 : 0.  */
1547               do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1548                                        NULL_RTX, NULL, done_label,
1549                                        profile_probability::very_likely ());
1550             }
1551         }
1552       else if (can_mult_highpart_p (mode, uns) == 1)
1553         {
1554         highpart:
1555           ops.code = MULT_HIGHPART_EXPR;
1556           ops.type = type;
1557
1558           rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1559                                            EXPAND_NORMAL);
1560           ops.code = MULT_EXPR;
1561           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1562           if (uns)
1563             /* For the unsigned multiplication, there was overflow if
1564                HIPART is non-zero.  */
1565             do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1566                                      NULL_RTX, NULL, done_label,
1567                                      profile_probability::very_likely ());
1568           else
1569             {
1570               rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1571                                           NULL_RTX, 0);
1572               /* RES is low half of the double width result, HIPART
1573                  the high half.  There was overflow if
1574                  HIPART is different from RES < 0 ? -1 : 0.  */
1575               do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1576                                        NULL_RTX, NULL, done_label,
1577                                        profile_probability::very_likely ());
1578             }
1579           
1580         }
1581       else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
1582                && 2 * GET_MODE_PRECISION (hmode) == prec)
1583         {
1584           rtx_code_label *large_op0 = gen_label_rtx ();
1585           rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1586           rtx_code_label *one_small_one_large = gen_label_rtx ();
1587           rtx_code_label *both_ops_large = gen_label_rtx ();
1588           rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1589           rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1590           rtx_code_label *do_overflow = gen_label_rtx ();
1591           rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1592
1593           unsigned int hprec = GET_MODE_PRECISION (hmode);
1594           rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1595                                       NULL_RTX, uns);
1596           hipart0 = convert_modes (hmode, mode, hipart0, uns);
1597           rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1598           rtx signbit0 = const0_rtx;
1599           if (!uns)
1600             signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1601                                      NULL_RTX, 0);
1602           rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1603                                       NULL_RTX, uns);
1604           hipart1 = convert_modes (hmode, mode, hipart1, uns);
1605           rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1606           rtx signbit1 = const0_rtx;
1607           if (!uns)
1608             signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1609                                      NULL_RTX, 0);
1610
1611           res = gen_reg_rtx (mode);
1612
1613           /* True if op0 resp. op1 are known to be in the range of
1614              halfstype.  */
1615           bool op0_small_p = false;
1616           bool op1_small_p = false;
1617           /* True if op0 resp. op1 are known to have all zeros or all ones
1618              in the upper half of bits, but are not known to be
1619              op{0,1}_small_p.  */
1620           bool op0_medium_p = false;
1621           bool op1_medium_p = false;
1622           /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1623              nonnegative, 1 if unknown.  */
1624           int op0_sign = 1;
1625           int op1_sign = 1;
1626
1627           if (pos_neg0 == 1)
1628             op0_sign = 0;
1629           else if (pos_neg0 == 2)
1630             op0_sign = -1;
1631           if (pos_neg1 == 1)
1632             op1_sign = 0;
1633           else if (pos_neg1 == 2)
1634             op1_sign = -1;
1635
1636           unsigned int mprec0 = prec;
1637           if (arg0 != error_mark_node)
1638             mprec0 = get_min_precision (arg0, sign);
1639           if (mprec0 <= hprec)
1640             op0_small_p = true;
1641           else if (!uns && mprec0 <= hprec + 1)
1642             op0_medium_p = true;
1643           unsigned int mprec1 = prec;
1644           if (arg1 != error_mark_node)
1645             mprec1 = get_min_precision (arg1, sign);
1646           if (mprec1 <= hprec)
1647             op1_small_p = true;
1648           else if (!uns && mprec1 <= hprec + 1)
1649             op1_medium_p = true;
1650
1651           int smaller_sign = 1;
1652           int larger_sign = 1;
1653           if (op0_small_p)
1654             {
1655               smaller_sign = op0_sign;
1656               larger_sign = op1_sign;
1657             }
1658           else if (op1_small_p)
1659             {
1660               smaller_sign = op1_sign;
1661               larger_sign = op0_sign;
1662             }
1663           else if (op0_sign == op1_sign)
1664             {
1665               smaller_sign = op0_sign;
1666               larger_sign = op0_sign;
1667             }
1668
1669           if (!op0_small_p)
1670             do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1671                                      NULL_RTX, NULL, large_op0,
1672                                      profile_probability::unlikely ());
1673
1674           if (!op1_small_p)
1675             do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1676                                      NULL_RTX, NULL, small_op0_large_op1,
1677                                      profile_probability::unlikely ());
1678
1679           /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1680              hmode to mode, the multiplication will never overflow.  We can
1681              do just one hmode x hmode => mode widening multiplication.  */
1682           rtx lopart0s = lopart0, lopart1s = lopart1;
1683           if (GET_CODE (lopart0) == SUBREG)
1684             {
1685               lopart0s = shallow_copy_rtx (lopart0);
1686               SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1687               SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1688             }
1689           if (GET_CODE (lopart1) == SUBREG)
1690             {
1691               lopart1s = shallow_copy_rtx (lopart1);
1692               SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1693               SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1694             }
1695           tree halfstype = build_nonstandard_integer_type (hprec, uns);
1696           ops.op0 = make_tree (halfstype, lopart0s);
1697           ops.op1 = make_tree (halfstype, lopart1s);
1698           ops.code = WIDEN_MULT_EXPR;
1699           ops.type = type;
1700           rtx thisres
1701             = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1702           emit_move_insn (res, thisres);
1703           emit_jump (done_label);
1704
1705           emit_label (small_op0_large_op1);
1706
1707           /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1708              but op1 is not, just swap the arguments and handle it as op1
1709              sign/zero extended, op0 not.  */
1710           rtx larger = gen_reg_rtx (mode);
1711           rtx hipart = gen_reg_rtx (hmode);
1712           rtx lopart = gen_reg_rtx (hmode);
1713           emit_move_insn (larger, op1);
1714           emit_move_insn (hipart, hipart1);
1715           emit_move_insn (lopart, lopart0);
1716           emit_jump (one_small_one_large);
1717
1718           emit_label (large_op0);
1719
1720           if (!op1_small_p)
1721             do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1722                                      NULL_RTX, NULL, both_ops_large,
1723                                      profile_probability::unlikely ());
1724
1725           /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1726              but op0 is not, prepare larger, hipart and lopart pseudos and
1727              handle it together with small_op0_large_op1.  */
1728           emit_move_insn (larger, op0);
1729           emit_move_insn (hipart, hipart0);
1730           emit_move_insn (lopart, lopart1);
1731
1732           emit_label (one_small_one_large);
1733
1734           /* lopart is the low part of the operand that is sign extended
1735              to mode, larger is the other operand, hipart is the
1736              high part of larger and lopart0 and lopart1 are the low parts
1737              of both operands.
1738              We perform lopart0 * lopart1 and lopart * hipart widening
1739              multiplications.  */
1740           tree halfutype = build_nonstandard_integer_type (hprec, 1);
1741           ops.op0 = make_tree (halfutype, lopart0);
1742           ops.op1 = make_tree (halfutype, lopart1);
1743           rtx lo0xlo1
1744             = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1745
1746           ops.op0 = make_tree (halfutype, lopart);
1747           ops.op1 = make_tree (halfutype, hipart);
1748           rtx loxhi = gen_reg_rtx (mode);
1749           rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1750           emit_move_insn (loxhi, tem);
1751
1752           if (!uns)
1753             {
1754               /* if (hipart < 0) loxhi -= lopart << (bitsize / 2);  */
1755               if (larger_sign == 0)
1756                 emit_jump (after_hipart_neg);
1757               else if (larger_sign != -1)
1758                 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1759                                          NULL_RTX, NULL, after_hipart_neg,
1760                                          profile_probability::even ());
1761
1762               tem = convert_modes (mode, hmode, lopart, 1);
1763               tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1764               tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1765                                          1, OPTAB_WIDEN);
1766               emit_move_insn (loxhi, tem);
1767
1768               emit_label (after_hipart_neg);
1769
1770               /* if (lopart < 0) loxhi -= larger;  */
1771               if (smaller_sign == 0)
1772                 emit_jump (after_lopart_neg);
1773               else if (smaller_sign != -1)
1774                 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1775                                          NULL_RTX, NULL, after_lopart_neg,
1776                                          profile_probability::even ());
1777
1778               tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1779                                          1, OPTAB_WIDEN);
1780               emit_move_insn (loxhi, tem);
1781
1782               emit_label (after_lopart_neg);
1783             }
1784
1785           /* loxhi += (uns) lo0xlo1 >> (bitsize / 2);  */
1786           tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1787           tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1788                                      1, OPTAB_WIDEN);
1789           emit_move_insn (loxhi, tem);
1790
1791           /* if (loxhi >> (bitsize / 2)
1792                  == (hmode) loxhi >> (bitsize / 2 - 1))  (if !uns)
1793              if (loxhi >> (bitsize / 2) == 0             (if uns).  */
1794           rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1795                                           NULL_RTX, 0);
1796           hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1797           rtx signbitloxhi = const0_rtx;
1798           if (!uns)
1799             signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1800                                          convert_modes (hmode, mode,
1801                                                         loxhi, 0),
1802                                          hprec - 1, NULL_RTX, 0);
1803
1804           do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1805                                    NULL_RTX, NULL, do_overflow,
1806                                    profile_probability::very_unlikely ());
1807
1808           /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1;  */
1809           rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1810                                            NULL_RTX, 1);
1811           tem = convert_modes (mode, hmode,
1812                                convert_modes (hmode, mode, lo0xlo1, 1), 1);
1813
1814           tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1815                                      1, OPTAB_WIDEN);
1816           if (tem != res)
1817             emit_move_insn (res, tem);
1818           emit_jump (done_label);
1819
1820           emit_label (both_ops_large);
1821
1822           /* If both operands are large (not sign (!uns) or zero (uns)
1823              extended from hmode), then perform the full multiplication
1824              which will be the result of the operation.
1825              The only cases which don't overflow are for signed multiplication
1826              some cases where both hipart0 and highpart1 are 0 or -1.
1827              For unsigned multiplication when high parts are both non-zero
1828              this overflows always.  */
1829           ops.code = MULT_EXPR;
1830           ops.op0 = make_tree (type, op0);
1831           ops.op1 = make_tree (type, op1);
1832           tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1833           emit_move_insn (res, tem);
1834
1835           if (!uns)
1836             {
1837               if (!op0_medium_p)
1838                 {
1839                   tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1840                                              NULL_RTX, 1, OPTAB_WIDEN);
1841                   do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1842                                            NULL_RTX, NULL, do_error,
1843                                            profile_probability::very_unlikely ());
1844                 }
1845
1846               if (!op1_medium_p)
1847                 {
1848                   tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1849                                              NULL_RTX, 1, OPTAB_WIDEN);
1850                   do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1851                                            NULL_RTX, NULL, do_error,
1852                                            profile_probability::very_unlikely ());
1853                 }
1854
1855               /* At this point hipart{0,1} are both in [-1, 0].  If they are
1856                  the same, overflow happened if res is non-positive, if they
1857                  are different, overflow happened if res is positive.  */
1858               if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1859                 emit_jump (hipart_different);
1860               else if (op0_sign == 1 || op1_sign == 1)
1861                 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1862                                          NULL_RTX, NULL, hipart_different,
1863                                          profile_probability::even ());
1864
1865               do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
1866                                        NULL_RTX, NULL, do_error,
1867                                        profile_probability::very_unlikely ());
1868               emit_jump (done_label);
1869
1870               emit_label (hipart_different);
1871
1872               do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1873                                        NULL_RTX, NULL, do_error,
1874                                        profile_probability::very_unlikely ());
1875               emit_jump (done_label);
1876             }
1877
1878           emit_label (do_overflow);
1879
1880           /* Overflow, do full multiplication and fallthru into do_error.  */
1881           ops.op0 = make_tree (type, op0);
1882           ops.op1 = make_tree (type, op1);
1883           tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1884           emit_move_insn (res, tem);
1885         }
1886       else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1887                && targetm.scalar_mode_supported_p (wmode))
1888         /* Even emitting a libcall is better than not detecting overflow
1889            at all.  */
1890         goto twoxwider;
1891       else
1892         {
1893           gcc_assert (!is_ubsan);
1894           ops.code = MULT_EXPR;
1895           ops.type = type;
1896           res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1897           emit_jump (done_label);
1898         }
1899     }
1900
1901  do_error_label:
1902   emit_label (do_error);
1903   if (is_ubsan)
1904     {
1905       /* Expand the ubsan builtin call.  */
1906       push_temp_slots ();
1907       fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1908                                          arg0, arg1, datap);
1909       expand_normal (fn);
1910       pop_temp_slots ();
1911       do_pending_stack_adjust ();
1912     }
1913   else if (lhs)
1914     expand_arith_set_overflow (lhs, target);
1915
1916   /* We're done.  */
1917   emit_label (done_label);
1918
1919   /* u1 * u2 -> sr  */
1920   if (uns0_p && uns1_p && !unsr_p)
1921     {
1922       rtx_code_label *all_done_label = gen_label_rtx ();
1923       do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1924                                NULL, all_done_label, profile_probability::very_likely ());
1925       expand_arith_set_overflow (lhs, target);
1926       emit_label (all_done_label);
1927     }
1928
1929   /* s1 * u2 -> sr  */
1930   if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
1931     {
1932       rtx_code_label *all_done_label = gen_label_rtx ();
1933       rtx_code_label *set_noovf = gen_label_rtx ();
1934       do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
1935                                NULL, all_done_label, profile_probability::very_likely ());
1936       expand_arith_set_overflow (lhs, target);
1937       do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1938                                NULL, set_noovf, profile_probability::very_likely ());
1939       do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1940                                NULL, all_done_label, profile_probability::very_unlikely ());
1941       do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
1942                                all_done_label, profile_probability::very_unlikely ());
1943       emit_label (set_noovf);
1944       write_complex_part (target, const0_rtx, true);
1945       emit_label (all_done_label);
1946     }
1947
1948   if (lhs)
1949     {
1950       if (is_ubsan)
1951         expand_ubsan_result_store (target, res);
1952       else
1953         expand_arith_overflow_result_store (lhs, target, mode, res);
1954     }
1955 }
1956
1957 /* Expand UBSAN_CHECK_* internal function if it has vector operands.  */
1958
1959 static void
1960 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
1961                               tree arg0, tree arg1)
1962 {
1963   int cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
1964   rtx_code_label *loop_lab = NULL;
1965   rtx cntvar = NULL_RTX;
1966   tree cntv = NULL_TREE;
1967   tree eltype = TREE_TYPE (TREE_TYPE (arg0));
1968   tree sz = TYPE_SIZE (eltype);
1969   tree data = NULL_TREE;
1970   tree resv = NULL_TREE;
1971   rtx lhsr = NULL_RTX;
1972   rtx resvr = NULL_RTX;
1973
1974   if (lhs)
1975     {
1976       optab op;
1977       lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1978       if (!VECTOR_MODE_P (GET_MODE (lhsr))
1979           || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
1980                                         optab_default)) == unknown_optab
1981           || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
1982               == CODE_FOR_nothing))
1983         {
1984           if (MEM_P (lhsr))
1985             resv = make_tree (TREE_TYPE (lhs), lhsr);
1986           else
1987             {
1988               resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
1989               resv = make_tree (TREE_TYPE (lhs), resvr);
1990             }
1991         }
1992     }
1993   if (cnt > 4)
1994     {
1995       do_pending_stack_adjust ();
1996       loop_lab = gen_label_rtx ();
1997       cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
1998       cntv = make_tree (sizetype, cntvar);
1999       emit_move_insn (cntvar, const0_rtx);
2000       emit_label (loop_lab);
2001     }
2002   if (TREE_CODE (arg0) != VECTOR_CST)
2003     {
2004       rtx arg0r = expand_normal (arg0);
2005       arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2006     }
2007   if (TREE_CODE (arg1) != VECTOR_CST)
2008     {
2009       rtx arg1r = expand_normal (arg1);
2010       arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2011     }
2012   for (int i = 0; i < (cnt > 4 ? 1 : cnt); i++)
2013     {
2014       tree op0, op1, res = NULL_TREE;
2015       if (cnt > 4)
2016         {
2017           tree atype = build_array_type_nelts (eltype, cnt);
2018           op0 = uniform_vector_p (arg0);
2019           if (op0 == NULL_TREE)
2020             {
2021               op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2022               op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2023                                 NULL_TREE, NULL_TREE);
2024             }
2025           op1 = uniform_vector_p (arg1);
2026           if (op1 == NULL_TREE)
2027             {
2028               op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2029               op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2030                                 NULL_TREE, NULL_TREE);
2031             }
2032           if (resv)
2033             {
2034               res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2035               res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2036                                 NULL_TREE, NULL_TREE);
2037             }
2038         }
2039       else
2040         {
2041           tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2042           op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2043           op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2044           if (resv)
2045             res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2046                                    bitpos);
2047         }
2048       switch (code)
2049         {
2050         case PLUS_EXPR:
2051           expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2052                                   false, false, false, true, &data);
2053           break;
2054         case MINUS_EXPR:
2055           if (cnt > 4 ? integer_zerop (arg0) : integer_zerop (op0))
2056             expand_neg_overflow (loc, res, op1, true, &data);
2057           else
2058             expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2059                                     false, false, false, true, &data);
2060           break;
2061         case MULT_EXPR:
2062           expand_mul_overflow (loc, res, op0, op1, false, false, false,
2063                                true, &data);
2064           break;
2065         default:
2066           gcc_unreachable ();
2067         }
2068     }
2069   if (cnt > 4)
2070     {
2071       struct separate_ops ops;
2072       ops.code = PLUS_EXPR;
2073       ops.type = TREE_TYPE (cntv);
2074       ops.op0 = cntv;
2075       ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2076       ops.op2 = NULL_TREE;
2077       ops.location = loc;
2078       rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2079                                     EXPAND_NORMAL);
2080       if (ret != cntvar)
2081         emit_move_insn (cntvar, ret);
2082       do_compare_rtx_and_jump (cntvar, GEN_INT (cnt), NE, false,
2083                                TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2084                                profile_probability::very_likely ());
2085     }
2086   if (lhs && resv == NULL_TREE)
2087     {
2088       struct separate_ops ops;
2089       ops.code = code;
2090       ops.type = TREE_TYPE (arg0);
2091       ops.op0 = arg0;
2092       ops.op1 = arg1;
2093       ops.op2 = NULL_TREE;
2094       ops.location = loc;
2095       rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2096                                     EXPAND_NORMAL);
2097       if (ret != lhsr)
2098         emit_move_insn (lhsr, ret);
2099     }
2100   else if (resvr)
2101     emit_move_insn (lhsr, resvr);
2102 }
2103
2104 /* Expand UBSAN_CHECK_ADD call STMT.  */
2105
2106 static void
2107 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2108 {
2109   location_t loc = gimple_location (stmt);
2110   tree lhs = gimple_call_lhs (stmt);
2111   tree arg0 = gimple_call_arg (stmt, 0);
2112   tree arg1 = gimple_call_arg (stmt, 1);
2113   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2114     expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2115   else
2116     expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2117                             false, false, false, true, NULL);
2118 }
2119
2120 /* Expand UBSAN_CHECK_SUB call STMT.  */
2121
2122 static void
2123 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2124 {
2125   location_t loc = gimple_location (stmt);
2126   tree lhs = gimple_call_lhs (stmt);
2127   tree arg0 = gimple_call_arg (stmt, 0);
2128   tree arg1 = gimple_call_arg (stmt, 1);
2129   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2130     expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2131   else if (integer_zerop (arg0))
2132     expand_neg_overflow (loc, lhs, arg1, true, NULL);
2133   else
2134     expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2135                             false, false, false, true, NULL);
2136 }
2137
2138 /* Expand UBSAN_CHECK_MUL call STMT.  */
2139
2140 static void
2141 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2142 {
2143   location_t loc = gimple_location (stmt);
2144   tree lhs = gimple_call_lhs (stmt);
2145   tree arg0 = gimple_call_arg (stmt, 0);
2146   tree arg1 = gimple_call_arg (stmt, 1);
2147   if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2148     expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2149   else
2150     expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2151                          NULL);
2152 }
2153
2154 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion.  */
2155
2156 static void
2157 expand_arith_overflow (enum tree_code code, gimple *stmt)
2158 {
2159   tree lhs = gimple_call_lhs (stmt);
2160   if (lhs == NULL_TREE)
2161     return;
2162   tree arg0 = gimple_call_arg (stmt, 0);
2163   tree arg1 = gimple_call_arg (stmt, 1);
2164   tree type = TREE_TYPE (TREE_TYPE (lhs));
2165   int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2166   int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2167   int unsr_p = TYPE_UNSIGNED (type);
2168   int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2169   int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2170   int precres = TYPE_PRECISION (type);
2171   location_t loc = gimple_location (stmt);
2172   if (!uns0_p && get_range_pos_neg (arg0) == 1)
2173     uns0_p = true;
2174   if (!uns1_p && get_range_pos_neg (arg1) == 1)
2175     uns1_p = true;
2176   int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2177   prec0 = MIN (prec0, pr);
2178   pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2179   prec1 = MIN (prec1, pr);
2180
2181   /* If uns0_p && uns1_p, precop is minimum needed precision
2182      of unsigned type to hold the exact result, otherwise
2183      precop is minimum needed precision of signed type to
2184      hold the exact result.  */
2185   int precop;
2186   if (code == MULT_EXPR)
2187     precop = prec0 + prec1 + (uns0_p != uns1_p);
2188   else
2189     {
2190       if (uns0_p == uns1_p)
2191         precop = MAX (prec0, prec1) + 1;
2192       else if (uns0_p)
2193         precop = MAX (prec0 + 1, prec1) + 1;
2194       else
2195         precop = MAX (prec0, prec1 + 1) + 1;
2196     }
2197   int orig_precres = precres;
2198
2199   do
2200     {
2201       if ((uns0_p && uns1_p)
2202           ? ((precop + !unsr_p) <= precres
2203              /* u1 - u2 -> ur can overflow, no matter what precision
2204                 the result has.  */
2205              && (code != MINUS_EXPR || !unsr_p))
2206           : (!unsr_p && precop <= precres))
2207         {
2208           /* The infinity precision result will always fit into result.  */
2209           rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2210           write_complex_part (target, const0_rtx, true);
2211           scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2212           struct separate_ops ops;
2213           ops.code = code;
2214           ops.type = type;
2215           ops.op0 = fold_convert_loc (loc, type, arg0);
2216           ops.op1 = fold_convert_loc (loc, type, arg1);
2217           ops.op2 = NULL_TREE;
2218           ops.location = loc;
2219           rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2220           expand_arith_overflow_result_store (lhs, target, mode, tem);
2221           return;
2222         }
2223
2224       /* For operations with low precision, if target doesn't have them, start
2225          with precres widening right away, otherwise do it only if the most
2226          simple cases can't be used.  */
2227       const int min_precision = targetm.min_arithmetic_precision ();
2228       if (orig_precres == precres && precres < min_precision)
2229         ;
2230       else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2231                 && prec1 <= precres)
2232           || ((!uns0_p || !uns1_p) && !unsr_p
2233               && prec0 + uns0_p <= precres
2234               && prec1 + uns1_p <= precres))
2235         {
2236           arg0 = fold_convert_loc (loc, type, arg0);
2237           arg1 = fold_convert_loc (loc, type, arg1);
2238           switch (code)
2239             {
2240             case MINUS_EXPR:
2241               if (integer_zerop (arg0) && !unsr_p)
2242                 {
2243                   expand_neg_overflow (loc, lhs, arg1, false, NULL);
2244                   return;
2245                 }
2246               /* FALLTHRU */
2247             case PLUS_EXPR:
2248               expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2249                                       unsr_p, unsr_p, false, NULL);
2250               return;
2251             case MULT_EXPR:
2252               expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2253                                    unsr_p, unsr_p, false, NULL);
2254               return;
2255             default:
2256               gcc_unreachable ();
2257             }
2258         }
2259
2260       /* For sub-word operations, retry with a wider type first.  */
2261       if (orig_precres == precres && precop <= BITS_PER_WORD)
2262         {
2263           int p = MAX (min_precision, precop);
2264           scalar_int_mode m = smallest_int_mode_for_size (p);
2265           tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2266                                                         uns0_p && uns1_p
2267                                                         && unsr_p);
2268           p = TYPE_PRECISION (optype);
2269           if (p > precres)
2270             {
2271               precres = p;
2272               unsr_p = TYPE_UNSIGNED (optype);
2273               type = optype;
2274               continue;
2275             }
2276         }
2277
2278       if (prec0 <= precres && prec1 <= precres)
2279         {
2280           tree types[2];
2281           if (unsr_p)
2282             {
2283               types[0] = build_nonstandard_integer_type (precres, 0);
2284               types[1] = type;
2285             }
2286           else
2287             {
2288               types[0] = type;
2289               types[1] = build_nonstandard_integer_type (precres, 1);
2290             }
2291           arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2292           arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2293           if (code != MULT_EXPR)
2294             expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2295                                     uns0_p, uns1_p, false, NULL);
2296           else
2297             expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2298                                  uns0_p, uns1_p, false, NULL);
2299           return;
2300         }
2301
2302       /* Retry with a wider type.  */
2303       if (orig_precres == precres)
2304         {
2305           int p = MAX (prec0, prec1);
2306           scalar_int_mode m = smallest_int_mode_for_size (p);
2307           tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2308                                                         uns0_p && uns1_p
2309                                                         && unsr_p);
2310           p = TYPE_PRECISION (optype);
2311           if (p > precres)
2312             {
2313               precres = p;
2314               unsr_p = TYPE_UNSIGNED (optype);
2315               type = optype;
2316               continue;
2317             }
2318         }
2319
2320       gcc_unreachable ();
2321     }
2322   while (1);
2323 }
2324
2325 /* Expand ADD_OVERFLOW STMT.  */
2326
2327 static void
2328 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2329 {
2330   expand_arith_overflow (PLUS_EXPR, stmt);
2331 }
2332
2333 /* Expand SUB_OVERFLOW STMT.  */
2334
2335 static void
2336 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2337 {
2338   expand_arith_overflow (MINUS_EXPR, stmt);
2339 }
2340
2341 /* Expand MUL_OVERFLOW STMT.  */
2342
2343 static void
2344 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2345 {
2346   expand_arith_overflow (MULT_EXPR, stmt);
2347 }
2348
2349 /* This should get folded in tree-vectorizer.c.  */
2350
2351 static void
2352 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2353 {
2354   gcc_unreachable ();
2355 }
2356
2357 /* This should get folded in tree-vectorizer.c.  */
2358
2359 static void
2360 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2361 {
2362   gcc_unreachable ();
2363 }
2364
2365 /* Expand MASK_LOAD call STMT using optab OPTAB.  */
2366
2367 static void
2368 expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2369 {
2370   struct expand_operand ops[3];
2371   tree type, lhs, rhs, maskt, ptr;
2372   rtx mem, target, mask;
2373   unsigned align;
2374
2375   maskt = gimple_call_arg (stmt, 2);
2376   lhs = gimple_call_lhs (stmt);
2377   if (lhs == NULL_TREE)
2378     return;
2379   type = TREE_TYPE (lhs);
2380   ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
2381   align = tree_to_shwi (gimple_call_arg (stmt, 1));
2382   if (TYPE_ALIGN (type) != align)
2383     type = build_aligned_type (type, align);
2384   rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
2385
2386   mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2387   gcc_assert (MEM_P (mem));
2388   mask = expand_normal (maskt);
2389   target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2390   create_output_operand (&ops[0], target, TYPE_MODE (type));
2391   create_fixed_operand (&ops[1], mem);
2392   create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2393   expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
2394                                       TYPE_MODE (TREE_TYPE (maskt))),
2395                3, ops);
2396 }
2397
2398 /* Expand MASK_STORE call STMT using optab OPTAB.  */
2399
2400 static void
2401 expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2402 {
2403   struct expand_operand ops[3];
2404   tree type, lhs, rhs, maskt, ptr;
2405   rtx mem, reg, mask;
2406   unsigned align;
2407
2408   maskt = gimple_call_arg (stmt, 2);
2409   rhs = gimple_call_arg (stmt, 3);
2410   type = TREE_TYPE (rhs);
2411   ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
2412   align = tree_to_shwi (gimple_call_arg (stmt, 1));
2413   if (TYPE_ALIGN (type) != align)
2414     type = build_aligned_type (type, align);
2415   lhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
2416
2417   mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2418   gcc_assert (MEM_P (mem));
2419   mask = expand_normal (maskt);
2420   reg = expand_normal (rhs);
2421   create_fixed_operand (&ops[0], mem);
2422   create_input_operand (&ops[1], reg, TYPE_MODE (type));
2423   create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2424   expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
2425                                       TYPE_MODE (TREE_TYPE (maskt))),
2426                3, ops);
2427 }
2428
2429 static void
2430 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
2431 {
2432 }
2433
2434 static void
2435 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
2436 {
2437   /* When guessing was done, the hints should be already stripped away.  */
2438   gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2439
2440   rtx target;
2441   tree lhs = gimple_call_lhs (stmt);
2442   if (lhs)
2443     target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2444   else
2445     target = const0_rtx;
2446   rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2447   if (lhs && val != target)
2448     emit_move_insn (target, val);
2449 }
2450
2451 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg.  So this dummy function
2452    should never be called.  */
2453
2454 static void
2455 expand_VA_ARG (internal_fn, gcall *)
2456 {
2457   gcc_unreachable ();
2458 }
2459
2460 /* Expand the IFN_UNIQUE function according to its first argument.  */
2461
2462 static void
2463 expand_UNIQUE (internal_fn, gcall *stmt)
2464 {
2465   rtx pattern = NULL_RTX;
2466   enum ifn_unique_kind kind
2467     = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2468
2469   switch (kind)
2470     {
2471     default:
2472       gcc_unreachable ();
2473
2474     case IFN_UNIQUE_UNSPEC:
2475       if (targetm.have_unique ())
2476         pattern = targetm.gen_unique ();
2477       break;
2478
2479     case IFN_UNIQUE_OACC_FORK:
2480     case IFN_UNIQUE_OACC_JOIN:
2481       if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2482         {
2483           tree lhs = gimple_call_lhs (stmt);
2484           rtx target = const0_rtx;
2485
2486           if (lhs)
2487             target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2488
2489           rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2490           rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2491
2492           if (kind == IFN_UNIQUE_OACC_FORK)
2493             pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2494           else
2495             pattern = targetm.gen_oacc_join (target, data_dep, axis);
2496         }
2497       else
2498         gcc_unreachable ();
2499       break;
2500     }
2501
2502   if (pattern)
2503     emit_insn (pattern);
2504 }
2505
2506 /* The size of an OpenACC compute dimension.  */
2507
2508 static void
2509 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
2510 {
2511   tree lhs = gimple_call_lhs (stmt);
2512
2513   if (!lhs)
2514     return;
2515
2516   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2517   if (targetm.have_oacc_dim_size ())
2518     {
2519       rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2520                              VOIDmode, EXPAND_NORMAL);
2521       emit_insn (targetm.gen_oacc_dim_size (target, dim));
2522     }
2523   else
2524     emit_move_insn (target, GEN_INT (1));
2525 }
2526
2527 /* The position of an OpenACC execution engine along one compute axis.  */
2528
2529 static void
2530 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
2531 {
2532   tree lhs = gimple_call_lhs (stmt);
2533
2534   if (!lhs)
2535     return;
2536
2537   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2538   if (targetm.have_oacc_dim_pos ())
2539     {
2540       rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2541                              VOIDmode, EXPAND_NORMAL);
2542       emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2543     }
2544   else
2545     emit_move_insn (target, const0_rtx);
2546 }
2547
2548 /* This is expanded by oacc_device_lower pass.  */
2549
2550 static void
2551 expand_GOACC_LOOP (internal_fn, gcall *)
2552 {
2553   gcc_unreachable ();
2554 }
2555
2556 /* This is expanded by oacc_device_lower pass.  */
2557
2558 static void
2559 expand_GOACC_REDUCTION (internal_fn, gcall *)
2560 {
2561   gcc_unreachable ();
2562 }
2563
2564 /* This is expanded by oacc_device_lower pass.  */
2565
2566 static void
2567 expand_GOACC_TILE (internal_fn, gcall *)
2568 {
2569   gcc_unreachable ();
2570 }
2571
2572 /* Set errno to EDOM.  */
2573
2574 static void
2575 expand_SET_EDOM (internal_fn, gcall *)
2576 {
2577 #ifdef TARGET_EDOM
2578 #ifdef GEN_ERRNO_RTX
2579   rtx errno_rtx = GEN_ERRNO_RTX;
2580 #else
2581   rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2582 #endif
2583   emit_move_insn (errno_rtx,
2584                   gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2585 #else
2586   gcc_unreachable ();
2587 #endif
2588 }
2589
2590 /* Expand atomic bit test and set.  */
2591
2592 static void
2593 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2594 {
2595   expand_ifn_atomic_bit_test_and (call);
2596 }
2597
2598 /* Expand atomic bit test and complement.  */
2599
2600 static void
2601 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2602 {
2603   expand_ifn_atomic_bit_test_and (call);
2604 }
2605
2606 /* Expand atomic bit test and reset.  */
2607
2608 static void
2609 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2610 {
2611   expand_ifn_atomic_bit_test_and (call);
2612 }
2613
2614 /* Expand atomic bit test and set.  */
2615
2616 static void
2617 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2618 {
2619   expand_ifn_atomic_compare_exchange (call);
2620 }
2621
2622 /* Expand LAUNDER to assignment, lhs = arg0.  */
2623
2624 static void
2625 expand_LAUNDER (internal_fn, gcall *call)
2626 {
2627   tree lhs = gimple_call_lhs (call);
2628
2629   if (!lhs)
2630     return;
2631
2632   expand_assignment (lhs, gimple_call_arg (call, 0), false);
2633 }
2634
2635 /* Expand DIVMOD() using:
2636  a) optab handler for udivmod/sdivmod if it is available.
2637  b) If optab_handler doesn't exist, generate call to
2638     target-specific divmod libfunc.  */
2639
2640 static void
2641 expand_DIVMOD (internal_fn, gcall *call_stmt)
2642 {
2643   tree lhs = gimple_call_lhs (call_stmt);
2644   tree arg0 = gimple_call_arg (call_stmt, 0);
2645   tree arg1 = gimple_call_arg (call_stmt, 1);
2646
2647   gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
2648   tree type = TREE_TYPE (TREE_TYPE (lhs));
2649   machine_mode mode = TYPE_MODE (type);
2650   bool unsignedp = TYPE_UNSIGNED (type);
2651   optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
2652
2653   rtx op0 = expand_normal (arg0);
2654   rtx op1 = expand_normal (arg1);
2655   rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2656
2657   rtx quotient, remainder, libfunc;
2658
2659   /* Check if optab_handler exists for divmod_optab for given mode.  */
2660   if (optab_handler (tab, mode) != CODE_FOR_nothing)
2661     {
2662       quotient = gen_reg_rtx (mode);
2663       remainder = gen_reg_rtx (mode);
2664       expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
2665     }
2666
2667   /* Generate call to divmod libfunc if it exists.  */
2668   else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
2669     targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
2670                                    &quotient, &remainder);
2671
2672   else
2673     gcc_unreachable ();
2674
2675   /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR.  */
2676   expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
2677                        make_tree (TREE_TYPE (arg0), quotient),
2678                        make_tree (TREE_TYPE (arg1), remainder)),
2679                target, VOIDmode, EXPAND_NORMAL);
2680 }
2681
2682 /* Expand a call to FN using the operands in STMT.  FN has a single
2683    output operand and NARGS input operands.  */
2684
2685 static void
2686 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2687                         unsigned int nargs)
2688 {
2689   expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2690
2691   tree_pair types = direct_internal_fn_types (fn, stmt);
2692   insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2693
2694   tree lhs = gimple_call_lhs (stmt);
2695   tree lhs_type = TREE_TYPE (lhs);
2696   rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2697
2698   /* Do not assign directly to a promoted subreg, since there is no
2699      guarantee that the instruction will leave the upper bits of the
2700      register in the state required by SUBREG_PROMOTED_SIGN.  */
2701   rtx dest = lhs_rtx;
2702   if (GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
2703     dest = NULL_RTX;
2704
2705   create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
2706
2707   for (unsigned int i = 0; i < nargs; ++i)
2708     {
2709       tree rhs = gimple_call_arg (stmt, i);
2710       tree rhs_type = TREE_TYPE (rhs);
2711       rtx rhs_rtx = expand_normal (rhs);
2712       if (INTEGRAL_TYPE_P (rhs_type))
2713         create_convert_operand_from (&ops[i + 1], rhs_rtx,
2714                                      TYPE_MODE (rhs_type),
2715                                      TYPE_UNSIGNED (rhs_type));
2716       else
2717         create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2718     }
2719
2720   expand_insn (icode, nargs + 1, ops);
2721   if (!rtx_equal_p (lhs_rtx, ops[0].value))
2722     {
2723       /* If the return value has an integral type, convert the instruction
2724          result to that type.  This is useful for things that return an
2725          int regardless of the size of the input.  If the instruction result
2726          is smaller than required, assume that it is signed.
2727
2728          If the return value has a nonintegral type, its mode must match
2729          the instruction result.  */
2730       if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2731         {
2732           /* If this is a scalar in a register that is stored in a wider
2733              mode than the declared mode, compute the result into its
2734              declared mode and then convert to the wider mode.  */
2735           gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2736           rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2737           convert_move (SUBREG_REG (lhs_rtx), tmp,
2738                         SUBREG_PROMOTED_SIGN (lhs_rtx));
2739         }
2740       else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
2741         emit_move_insn (lhs_rtx, ops[0].value);
2742       else
2743         {
2744           gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2745           convert_move (lhs_rtx, ops[0].value, 0);
2746         }
2747     }
2748 }
2749
2750 /* Expanders for optabs that can use expand_direct_optab_fn.  */
2751
2752 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
2753   expand_direct_optab_fn (FN, STMT, OPTAB, 1)
2754
2755 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
2756   expand_direct_optab_fn (FN, STMT, OPTAB, 2)
2757
2758 /* RETURN_TYPE and ARGS are a return type and argument list that are
2759    in principle compatible with FN (which satisfies direct_internal_fn_p).
2760    Return the types that should be used to determine whether the
2761    target supports FN.  */
2762
2763 tree_pair
2764 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
2765 {
2766   const direct_internal_fn_info &info = direct_internal_fn (fn);
2767   tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
2768   tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
2769   return tree_pair (type0, type1);
2770 }
2771
2772 /* CALL is a call whose return type and arguments are in principle
2773    compatible with FN (which satisfies direct_internal_fn_p).  Return the
2774    types that should be used to determine whether the target supports FN.  */
2775
2776 tree_pair
2777 direct_internal_fn_types (internal_fn fn, gcall *call)
2778 {
2779   const direct_internal_fn_info &info = direct_internal_fn (fn);
2780   tree op0 = (info.type0 < 0
2781               ? gimple_call_lhs (call)
2782               : gimple_call_arg (call, info.type0));
2783   tree op1 = (info.type1 < 0
2784               ? gimple_call_lhs (call)
2785               : gimple_call_arg (call, info.type1));
2786   return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
2787 }
2788
2789 /* Return true if OPTAB is supported for TYPES (whose modes should be
2790    the same) when the optimization type is OPT_TYPE.  Used for simple
2791    direct optabs.  */
2792
2793 static bool
2794 direct_optab_supported_p (direct_optab optab, tree_pair types,
2795                           optimization_type opt_type)
2796 {
2797   machine_mode mode = TYPE_MODE (types.first);
2798   gcc_checking_assert (mode == TYPE_MODE (types.second));
2799   return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
2800 }
2801
2802 /* Return true if load/store lanes optab OPTAB is supported for
2803    array type TYPES.first when the optimization type is OPT_TYPE.  */
2804
2805 static bool
2806 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
2807                                 optimization_type opt_type)
2808 {
2809   gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
2810   machine_mode imode = TYPE_MODE (types.first);
2811   machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
2812   return (convert_optab_handler (optab, imode, vmode, opt_type)
2813           != CODE_FOR_nothing);
2814 }
2815
2816 #define direct_unary_optab_supported_p direct_optab_supported_p
2817 #define direct_binary_optab_supported_p direct_optab_supported_p
2818 #define direct_mask_load_optab_supported_p direct_optab_supported_p
2819 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
2820 #define direct_mask_store_optab_supported_p direct_optab_supported_p
2821 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
2822
2823 /* Return the optab used by internal function FN.  */
2824
2825 static optab
2826 direct_internal_fn_optab (internal_fn fn, tree_pair types)
2827 {
2828   switch (fn)
2829     {
2830 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
2831     case IFN_##CODE: break;
2832 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2833     case IFN_##CODE: return OPTAB##_optab;
2834 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
2835                                      UNSIGNED_OPTAB, TYPE)              \
2836     case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR)             \
2837                              ? UNSIGNED_OPTAB ## _optab                 \
2838                              : SIGNED_OPTAB ## _optab);
2839 #include "internal-fn.def"
2840
2841     case IFN_LAST:
2842       break;
2843     }
2844   gcc_unreachable ();
2845 }
2846
2847 /* Return true if FN is supported for the types in TYPES when the
2848    optimization type is OPT_TYPE.  The types are those associated with
2849    the "type0" and "type1" fields of FN's direct_internal_fn_info
2850    structure.  */
2851
2852 bool
2853 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
2854                                 optimization_type opt_type)
2855 {
2856   switch (fn)
2857     {
2858 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
2859     case IFN_##CODE: break;
2860 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2861     case IFN_##CODE: \
2862       return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
2863                                                 opt_type);
2864 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
2865                                      UNSIGNED_OPTAB, TYPE)              \
2866     case IFN_##CODE:                                                    \
2867       {                                                                 \
2868         optab which_optab = (TYPE_UNSIGNED (types.SELECTOR)             \
2869                              ? UNSIGNED_OPTAB ## _optab                 \
2870                              : SIGNED_OPTAB ## _optab);                 \
2871         return direct_##TYPE##_optab_supported_p (which_optab, types,   \
2872                                                   opt_type);            \
2873       }
2874 #include "internal-fn.def"
2875
2876     case IFN_LAST:
2877       break;
2878     }
2879   gcc_unreachable ();
2880 }
2881
2882 /* Return true if FN is supported for type TYPE when the optimization
2883    type is OPT_TYPE.  The caller knows that the "type0" and "type1"
2884    fields of FN's direct_internal_fn_info structure are the same.  */
2885
2886 bool
2887 direct_internal_fn_supported_p (internal_fn fn, tree type,
2888                                 optimization_type opt_type)
2889 {
2890   const direct_internal_fn_info &info = direct_internal_fn (fn);
2891   gcc_checking_assert (info.type0 == info.type1);
2892   return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
2893 }
2894
2895 /* Return true if IFN_SET_EDOM is supported.  */
2896
2897 bool
2898 set_edom_supported_p (void)
2899 {
2900 #ifdef TARGET_EDOM
2901   return true;
2902 #else
2903   return false;
2904 #endif
2905 }
2906
2907 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2908   static void                                           \
2909   expand_##CODE (internal_fn fn, gcall *stmt)           \
2910   {                                                     \
2911     expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
2912   }
2913 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
2914                                      UNSIGNED_OPTAB, TYPE)              \
2915   static void                                                           \
2916   expand_##CODE (internal_fn fn, gcall *stmt)                           \
2917   {                                                                     \
2918     tree_pair types = direct_internal_fn_types (fn, stmt);              \
2919     optab which_optab = direct_internal_fn_optab (fn, types);           \
2920     expand_##TYPE##_optab_fn (fn, stmt, which_optab);                   \
2921   }
2922 #include "internal-fn.def"
2923
2924 /* Routines to expand each internal function, indexed by function number.
2925    Each routine has the prototype:
2926
2927        expand_<NAME> (gcall *stmt)
2928
2929    where STMT is the statement that performs the call. */
2930 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
2931 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
2932 #include "internal-fn.def"
2933   0
2934 };
2935
2936 /* Expand STMT as though it were a call to internal function FN.  */
2937
2938 void
2939 expand_internal_call (internal_fn fn, gcall *stmt)
2940 {
2941   internal_fn_expanders[fn] (fn, stmt);
2942 }
2943
2944 /* Expand STMT, which is a call to internal function FN.  */
2945
2946 void
2947 expand_internal_call (gcall *stmt)
2948 {
2949   expand_internal_call (gimple_call_internal_fn (stmt), stmt);
2950 }
2951
2952 void
2953 expand_PHI (internal_fn, gcall *)
2954 {
2955     gcc_unreachable ();
2956 }