PR middle-end/79665
[official-gcc.git] / gcc / internal-fn.c
blobffe291d62cf5936af2acc81e0c2efd7103966198
1 /* Internal functions.
2 Copyright (C) 2011-2017 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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 "ubsan.h"
43 #include "recog.h"
44 #include "builtins.h"
45 #include "optabs-tree.h"
47 /* The names of each internal function, indexed by function number. */
48 const char *const internal_fn_name_array[] = {
49 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
50 #include "internal-fn.def"
51 "<invalid-fn>"
54 /* The ECF_* flags of each internal function, indexed by function number. */
55 const int internal_fn_flags_array[] = {
56 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
57 #include "internal-fn.def"
61 /* Fnspec of each internal function, indexed by function number. */
62 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
64 void
65 init_internal_fns ()
67 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
68 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
69 build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
70 #include "internal-fn.def"
71 internal_fn_fnspec_array[IFN_LAST] = 0;
74 /* Create static initializers for the information returned by
75 direct_internal_fn. */
76 #define not_direct { -2, -2, false }
77 #define mask_load_direct { -1, 2, false }
78 #define load_lanes_direct { -1, -1, false }
79 #define mask_store_direct { 3, 2, false }
80 #define store_lanes_direct { 0, 0, false }
81 #define unary_direct { 0, 0, true }
82 #define binary_direct { 0, 0, true }
84 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
85 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
86 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
87 #include "internal-fn.def"
88 not_direct
91 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
92 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
94 static enum insn_code
95 get_multi_vector_move (tree array_type, convert_optab optab)
97 machine_mode imode;
98 machine_mode vmode;
100 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
101 imode = TYPE_MODE (array_type);
102 vmode = TYPE_MODE (TREE_TYPE (array_type));
104 return convert_optab_handler (optab, imode, vmode);
107 /* Expand LOAD_LANES call STMT using optab OPTAB. */
109 static void
110 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
112 struct expand_operand ops[2];
113 tree type, lhs, rhs;
114 rtx target, mem;
116 lhs = gimple_call_lhs (stmt);
117 rhs = gimple_call_arg (stmt, 0);
118 type = TREE_TYPE (lhs);
120 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
121 mem = expand_normal (rhs);
123 gcc_assert (MEM_P (mem));
124 PUT_MODE (mem, TYPE_MODE (type));
126 create_output_operand (&ops[0], target, TYPE_MODE (type));
127 create_fixed_operand (&ops[1], mem);
128 expand_insn (get_multi_vector_move (type, optab), 2, ops);
131 /* Expand STORE_LANES call STMT using optab OPTAB. */
133 static void
134 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
136 struct expand_operand ops[2];
137 tree type, lhs, rhs;
138 rtx target, reg;
140 lhs = gimple_call_lhs (stmt);
141 rhs = gimple_call_arg (stmt, 0);
142 type = TREE_TYPE (rhs);
144 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
145 reg = expand_normal (rhs);
147 gcc_assert (MEM_P (target));
148 PUT_MODE (target, TYPE_MODE (type));
150 create_fixed_operand (&ops[0], target);
151 create_input_operand (&ops[1], reg, TYPE_MODE (type));
152 expand_insn (get_multi_vector_move (type, optab), 2, ops);
155 static void
156 expand_ANNOTATE (internal_fn, gcall *)
158 gcc_unreachable ();
161 /* This should get expanded in omp_device_lower pass. */
163 static void
164 expand_GOMP_USE_SIMT (internal_fn, gcall *)
166 gcc_unreachable ();
169 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
170 without SIMT execution this should be expanded in omp_device_lower pass. */
172 static void
173 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
175 tree lhs = gimple_call_lhs (stmt);
176 if (!lhs)
177 return;
179 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
180 gcc_assert (targetm.have_omp_simt_lane ());
181 emit_insn (targetm.gen_omp_simt_lane (target));
184 /* This should get expanded in omp_device_lower pass. */
186 static void
187 expand_GOMP_SIMT_VF (internal_fn, gcall *)
189 gcc_unreachable ();
192 /* Lane index of the first SIMT lane that supplies a non-zero argument.
193 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
194 lane that executed the last iteration for handling OpenMP lastprivate. */
196 static void
197 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
199 tree lhs = gimple_call_lhs (stmt);
200 if (!lhs)
201 return;
203 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
204 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
205 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
206 struct expand_operand ops[2];
207 create_output_operand (&ops[0], target, mode);
208 create_input_operand (&ops[1], cond, mode);
209 gcc_assert (targetm.have_omp_simt_last_lane ());
210 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
213 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
215 static void
216 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
218 tree lhs = gimple_call_lhs (stmt);
219 if (!lhs)
220 return;
222 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
223 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
224 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
225 struct expand_operand ops[2];
226 create_output_operand (&ops[0], target, mode);
227 create_input_operand (&ops[1], ctr, mode);
228 gcc_assert (targetm.have_omp_simt_ordered ());
229 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
232 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
233 any lane supplies a non-zero argument. */
235 static void
236 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
238 tree lhs = gimple_call_lhs (stmt);
239 if (!lhs)
240 return;
242 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
243 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
244 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
245 struct expand_operand ops[2];
246 create_output_operand (&ops[0], target, mode);
247 create_input_operand (&ops[1], cond, mode);
248 gcc_assert (targetm.have_omp_simt_vote_any ());
249 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
252 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
253 is destination lane index XOR given offset. */
255 static void
256 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
258 tree lhs = gimple_call_lhs (stmt);
259 if (!lhs)
260 return;
262 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
263 rtx src = expand_normal (gimple_call_arg (stmt, 0));
264 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
265 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
266 struct expand_operand ops[3];
267 create_output_operand (&ops[0], target, mode);
268 create_input_operand (&ops[1], src, mode);
269 create_input_operand (&ops[2], idx, SImode);
270 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
271 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
274 /* Exchange between SIMT lanes according to given source lane index. */
276 static void
277 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
279 tree lhs = gimple_call_lhs (stmt);
280 if (!lhs)
281 return;
283 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
284 rtx src = expand_normal (gimple_call_arg (stmt, 0));
285 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
286 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
287 struct expand_operand ops[3];
288 create_output_operand (&ops[0], target, mode);
289 create_input_operand (&ops[1], src, mode);
290 create_input_operand (&ops[2], idx, SImode);
291 gcc_assert (targetm.have_omp_simt_xchg_idx ());
292 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
295 /* This should get expanded in adjust_simduid_builtins. */
297 static void
298 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
300 gcc_unreachable ();
303 /* This should get expanded in adjust_simduid_builtins. */
305 static void
306 expand_GOMP_SIMD_VF (internal_fn, gcall *)
308 gcc_unreachable ();
311 /* This should get expanded in adjust_simduid_builtins. */
313 static void
314 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
316 gcc_unreachable ();
319 /* This should get expanded in adjust_simduid_builtins. */
321 static void
322 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
324 gcc_unreachable ();
327 /* This should get expanded in adjust_simduid_builtins. */
329 static void
330 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
332 gcc_unreachable ();
335 /* This should get expanded in the sanopt pass. */
337 static void
338 expand_UBSAN_NULL (internal_fn, gcall *)
340 gcc_unreachable ();
343 /* This should get expanded in the sanopt pass. */
345 static void
346 expand_UBSAN_BOUNDS (internal_fn, gcall *)
348 gcc_unreachable ();
351 /* This should get expanded in the sanopt pass. */
353 static void
354 expand_UBSAN_VPTR (internal_fn, gcall *)
356 gcc_unreachable ();
359 /* This should get expanded in the sanopt pass. */
361 static void
362 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
364 gcc_unreachable ();
367 /* This should get expanded in the sanopt pass. */
369 static void
370 expand_ASAN_CHECK (internal_fn, gcall *)
372 gcc_unreachable ();
375 /* This should get expanded in the sanopt pass. */
377 static void
378 expand_ASAN_MARK (internal_fn, gcall *)
380 gcc_unreachable ();
383 /* This should get expanded in the sanopt pass. */
385 static void
386 expand_ASAN_POISON (internal_fn, gcall *)
388 gcc_unreachable ();
391 /* This should get expanded in the sanopt pass. */
393 static void
394 expand_ASAN_POISON_USE (internal_fn, gcall *)
396 gcc_unreachable ();
399 /* This should get expanded in the tsan pass. */
401 static void
402 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
404 gcc_unreachable ();
407 /* This should get expanded in the lower pass. */
409 static void
410 expand_FALLTHROUGH (internal_fn, gcall *call)
412 error_at (gimple_location (call),
413 "invalid use of attribute %<fallthrough%>");
416 /* Return minimum precision needed to represent all values
417 of ARG in SIGNed integral type. */
419 static int
420 get_min_precision (tree arg, signop sign)
422 int prec = TYPE_PRECISION (TREE_TYPE (arg));
423 int cnt = 0;
424 signop orig_sign = sign;
425 if (TREE_CODE (arg) == INTEGER_CST)
427 int p;
428 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
430 widest_int w = wi::to_widest (arg);
431 w = wi::ext (w, prec, sign);
432 p = wi::min_precision (w, sign);
434 else
435 p = wi::min_precision (arg, sign);
436 return MIN (p, prec);
438 while (CONVERT_EXPR_P (arg)
439 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
440 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
442 arg = TREE_OPERAND (arg, 0);
443 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
445 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
446 sign = UNSIGNED;
447 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
448 return prec + (orig_sign != sign);
449 prec = TYPE_PRECISION (TREE_TYPE (arg));
451 if (++cnt > 30)
452 return prec + (orig_sign != sign);
454 if (TREE_CODE (arg) != SSA_NAME)
455 return prec + (orig_sign != sign);
456 wide_int arg_min, arg_max;
457 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
459 gimple *g = SSA_NAME_DEF_STMT (arg);
460 if (is_gimple_assign (g)
461 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
463 tree t = gimple_assign_rhs1 (g);
464 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
465 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
467 arg = t;
468 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
470 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
471 sign = UNSIGNED;
472 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
473 return prec + (orig_sign != sign);
474 prec = TYPE_PRECISION (TREE_TYPE (arg));
476 if (++cnt > 30)
477 return prec + (orig_sign != sign);
478 continue;
481 return prec + (orig_sign != sign);
483 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
485 int p1 = wi::min_precision (arg_min, sign);
486 int p2 = wi::min_precision (arg_max, sign);
487 p1 = MAX (p1, p2);
488 prec = MIN (prec, p1);
490 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
492 int p = wi::min_precision (arg_max, UNSIGNED);
493 prec = MIN (prec, p);
495 return prec + (orig_sign != sign);
498 /* Helper for expand_*_overflow. Set the __imag__ part to true
499 (1 except for signed:1 type, in which case store -1). */
501 static void
502 expand_arith_set_overflow (tree lhs, rtx target)
504 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
505 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
506 write_complex_part (target, constm1_rtx, true);
507 else
508 write_complex_part (target, const1_rtx, true);
511 /* Helper for expand_*_overflow. Store RES into the __real__ part
512 of TARGET. If RES has larger MODE than __real__ part of TARGET,
513 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
514 if LHS has smaller precision than its mode. */
516 static void
517 expand_arith_overflow_result_store (tree lhs, rtx target,
518 machine_mode mode, rtx res)
520 machine_mode tgtmode = GET_MODE_INNER (GET_MODE (target));
521 rtx lres = res;
522 if (tgtmode != mode)
524 rtx_code_label *done_label = gen_label_rtx ();
525 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
526 lres = convert_modes (tgtmode, mode, res, uns);
527 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
528 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
529 EQ, true, mode, NULL_RTX, NULL, done_label,
530 PROB_VERY_LIKELY);
531 expand_arith_set_overflow (lhs, target);
532 emit_label (done_label);
534 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
535 int tgtprec = GET_MODE_PRECISION (tgtmode);
536 if (prec < tgtprec)
538 rtx_code_label *done_label = gen_label_rtx ();
539 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
540 res = lres;
541 if (uns)
543 rtx mask
544 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
545 tgtmode);
546 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
547 true, OPTAB_LIB_WIDEN);
549 else
551 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
552 NULL_RTX, 1);
553 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
554 NULL_RTX, 0);
556 do_compare_rtx_and_jump (res, lres,
557 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
558 PROB_VERY_LIKELY);
559 expand_arith_set_overflow (lhs, target);
560 emit_label (done_label);
562 write_complex_part (target, lres, false);
565 /* Helper for expand_*_overflow. Store RES into TARGET. */
567 static void
568 expand_ubsan_result_store (rtx target, rtx res)
570 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
571 /* If this is a scalar in a register that is stored in a wider mode
572 than the declared mode, compute the result into its declared mode
573 and then convert to the wider mode. Our value is the computed
574 expression. */
575 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
576 else
577 emit_move_insn (target, res);
580 /* Add sub/add overflow checking to the statement STMT.
581 CODE says whether the operation is +, or -. */
583 static void
584 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
585 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
586 bool uns1_p, bool is_ubsan, tree *datap)
588 rtx res, target = NULL_RTX;
589 tree fn;
590 rtx_code_label *done_label = gen_label_rtx ();
591 rtx_code_label *do_error = gen_label_rtx ();
592 do_pending_stack_adjust ();
593 rtx op0 = expand_normal (arg0);
594 rtx op1 = expand_normal (arg1);
595 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
596 int prec = GET_MODE_PRECISION (mode);
597 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
598 bool do_xor = false;
600 if (is_ubsan)
601 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
603 if (lhs)
605 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
606 if (!is_ubsan)
607 write_complex_part (target, const0_rtx, true);
610 /* We assume both operands and result have the same precision
611 here (GET_MODE_BITSIZE (mode)), S stands for signed type
612 with that precision, U for unsigned type with that precision,
613 sgn for unsigned most significant bit in that precision.
614 s1 is signed first operand, u1 is unsigned first operand,
615 s2 is signed second operand, u2 is unsigned second operand,
616 sr is signed result, ur is unsigned result and the following
617 rules say how to compute result (which is always result of
618 the operands as if both were unsigned, cast to the right
619 signedness) and how to compute whether operation overflowed.
621 s1 + s2 -> sr
622 res = (S) ((U) s1 + (U) s2)
623 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
624 s1 - s2 -> sr
625 res = (S) ((U) s1 - (U) s2)
626 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
627 u1 + u2 -> ur
628 res = u1 + u2
629 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
630 u1 - u2 -> ur
631 res = u1 - u2
632 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
633 s1 + u2 -> sr
634 res = (S) ((U) s1 + u2)
635 ovf = ((U) res ^ sgn) < u2
636 s1 + u2 -> ur
637 t1 = (S) (u2 ^ sgn)
638 t2 = s1 + t1
639 res = (U) t2 ^ sgn
640 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
641 s1 - u2 -> sr
642 res = (S) ((U) s1 - u2)
643 ovf = u2 > ((U) s1 ^ sgn)
644 s1 - u2 -> ur
645 res = (U) s1 - u2
646 ovf = s1 < 0 || u2 > (U) s1
647 u1 - s2 -> sr
648 res = u1 - (U) s2
649 ovf = u1 >= ((U) s2 ^ sgn)
650 u1 - s2 -> ur
651 t1 = u1 ^ sgn
652 t2 = t1 - (U) s2
653 res = t2 ^ sgn
654 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
655 s1 + s2 -> ur
656 res = (U) s1 + (U) s2
657 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
658 u1 + u2 -> sr
659 res = (S) (u1 + u2)
660 ovf = (U) res < u2 || res < 0
661 u1 - u2 -> sr
662 res = (S) (u1 - u2)
663 ovf = u1 >= u2 ? res < 0 : res >= 0
664 s1 - s2 -> ur
665 res = (U) s1 - (U) s2
666 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
668 if (code == PLUS_EXPR && uns0_p && !uns1_p)
670 /* PLUS_EXPR is commutative, if operand signedness differs,
671 canonicalize to the first operand being signed and second
672 unsigned to simplify following code. */
673 std::swap (op0, op1);
674 std::swap (arg0, arg1);
675 uns0_p = false;
676 uns1_p = true;
679 /* u1 +- u2 -> ur */
680 if (uns0_p && uns1_p && unsr_p)
682 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
683 : usubv4_optab, mode);
684 if (icode != CODE_FOR_nothing)
686 struct expand_operand ops[4];
687 rtx_insn *last = get_last_insn ();
689 res = gen_reg_rtx (mode);
690 create_output_operand (&ops[0], res, mode);
691 create_input_operand (&ops[1], op0, mode);
692 create_input_operand (&ops[2], op1, mode);
693 create_fixed_operand (&ops[3], do_error);
694 if (maybe_expand_insn (icode, 4, ops))
696 last = get_last_insn ();
697 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
698 && JUMP_P (last)
699 && any_condjump_p (last)
700 && !find_reg_note (last, REG_BR_PROB, 0))
701 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
702 emit_jump (done_label);
703 goto do_error_label;
706 delete_insns_since (last);
709 /* Compute the operation. On RTL level, the addition is always
710 unsigned. */
711 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
712 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
713 rtx tem = op0;
714 /* For PLUS_EXPR, the operation is commutative, so we can pick
715 operand to compare against. For prec <= BITS_PER_WORD, I think
716 preferring REG operand is better over CONST_INT, because
717 the CONST_INT might enlarge the instruction or CSE would need
718 to figure out we'd already loaded it into a register before.
719 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
720 as then the multi-word comparison can be perhaps simplified. */
721 if (code == PLUS_EXPR
722 && (prec <= BITS_PER_WORD
723 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
724 : CONST_SCALAR_INT_P (op1)))
725 tem = op1;
726 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
727 true, mode, NULL_RTX, NULL, done_label,
728 PROB_VERY_LIKELY);
729 goto do_error_label;
732 /* s1 +- u2 -> sr */
733 if (!uns0_p && uns1_p && !unsr_p)
735 /* Compute the operation. On RTL level, the addition is always
736 unsigned. */
737 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
738 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
739 rtx tem = expand_binop (mode, add_optab,
740 code == PLUS_EXPR ? res : op0, sgn,
741 NULL_RTX, false, OPTAB_LIB_WIDEN);
742 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
743 done_label, PROB_VERY_LIKELY);
744 goto do_error_label;
747 /* s1 + u2 -> ur */
748 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
750 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
751 OPTAB_LIB_WIDEN);
752 /* As we've changed op1, we have to avoid using the value range
753 for the original argument. */
754 arg1 = error_mark_node;
755 do_xor = true;
756 goto do_signed;
759 /* u1 - s2 -> ur */
760 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
762 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
763 OPTAB_LIB_WIDEN);
764 /* As we've changed op0, we have to avoid using the value range
765 for the original argument. */
766 arg0 = error_mark_node;
767 do_xor = true;
768 goto do_signed;
771 /* s1 - u2 -> ur */
772 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
774 /* Compute the operation. On RTL level, the addition is always
775 unsigned. */
776 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
777 OPTAB_LIB_WIDEN);
778 int pos_neg = get_range_pos_neg (arg0);
779 if (pos_neg == 2)
780 /* If ARG0 is known to be always negative, this is always overflow. */
781 emit_jump (do_error);
782 else if (pos_neg == 3)
783 /* If ARG0 is not known to be always positive, check at runtime. */
784 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
785 NULL, do_error, PROB_VERY_UNLIKELY);
786 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
787 done_label, PROB_VERY_LIKELY);
788 goto do_error_label;
791 /* u1 - s2 -> sr */
792 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
794 /* Compute the operation. On RTL level, the addition is always
795 unsigned. */
796 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
797 OPTAB_LIB_WIDEN);
798 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
799 OPTAB_LIB_WIDEN);
800 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
801 done_label, PROB_VERY_LIKELY);
802 goto do_error_label;
805 /* u1 + u2 -> sr */
806 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
808 /* Compute the operation. On RTL level, the addition is always
809 unsigned. */
810 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
811 OPTAB_LIB_WIDEN);
812 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
813 NULL, do_error, PROB_VERY_UNLIKELY);
814 rtx tem = op1;
815 /* The operation is commutative, so we can pick operand to compare
816 against. For prec <= BITS_PER_WORD, I think preferring REG operand
817 is better over CONST_INT, because the CONST_INT might enlarge the
818 instruction or CSE would need to figure out we'd already loaded it
819 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
820 might be more beneficial, as then the multi-word comparison can be
821 perhaps simplified. */
822 if (prec <= BITS_PER_WORD
823 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
824 : CONST_SCALAR_INT_P (op0))
825 tem = op0;
826 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
827 done_label, PROB_VERY_LIKELY);
828 goto do_error_label;
831 /* s1 +- s2 -> ur */
832 if (!uns0_p && !uns1_p && unsr_p)
834 /* Compute the operation. On RTL level, the addition is always
835 unsigned. */
836 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
837 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
838 int pos_neg = get_range_pos_neg (arg1);
839 if (code == PLUS_EXPR)
841 int pos_neg0 = get_range_pos_neg (arg0);
842 if (pos_neg0 != 3 && pos_neg == 3)
844 std::swap (op0, op1);
845 pos_neg = pos_neg0;
848 rtx tem;
849 if (pos_neg != 3)
851 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
852 ? and_optab : ior_optab,
853 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
854 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
855 NULL, done_label, PROB_VERY_LIKELY);
857 else
859 rtx_code_label *do_ior_label = gen_label_rtx ();
860 do_compare_rtx_and_jump (op1, const0_rtx,
861 code == MINUS_EXPR ? GE : LT, false, mode,
862 NULL_RTX, NULL, do_ior_label,
863 PROB_EVEN);
864 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
865 OPTAB_LIB_WIDEN);
866 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
867 NULL, done_label, PROB_VERY_LIKELY);
868 emit_jump (do_error);
869 emit_label (do_ior_label);
870 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
871 OPTAB_LIB_WIDEN);
872 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
873 NULL, done_label, PROB_VERY_LIKELY);
875 goto do_error_label;
878 /* u1 - u2 -> sr */
879 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
881 /* Compute the operation. On RTL level, the addition is always
882 unsigned. */
883 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
884 OPTAB_LIB_WIDEN);
885 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
886 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
887 op0_geu_op1, PROB_EVEN);
888 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
889 NULL, done_label, PROB_VERY_LIKELY);
890 emit_jump (do_error);
891 emit_label (op0_geu_op1);
892 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
893 NULL, done_label, PROB_VERY_LIKELY);
894 goto do_error_label;
897 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
899 /* s1 +- s2 -> sr */
900 do_signed:
902 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
903 : subv4_optab, mode);
904 if (icode != CODE_FOR_nothing)
906 struct expand_operand ops[4];
907 rtx_insn *last = get_last_insn ();
909 res = gen_reg_rtx (mode);
910 create_output_operand (&ops[0], res, mode);
911 create_input_operand (&ops[1], op0, mode);
912 create_input_operand (&ops[2], op1, mode);
913 create_fixed_operand (&ops[3], do_error);
914 if (maybe_expand_insn (icode, 4, ops))
916 last = get_last_insn ();
917 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
918 && JUMP_P (last)
919 && any_condjump_p (last)
920 && !find_reg_note (last, REG_BR_PROB, 0))
921 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
922 emit_jump (done_label);
923 goto do_error_label;
926 delete_insns_since (last);
929 /* Compute the operation. On RTL level, the addition is always
930 unsigned. */
931 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
932 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
934 /* If we can prove that one of the arguments (for MINUS_EXPR only
935 the second operand, as subtraction is not commutative) is always
936 non-negative or always negative, we can do just one comparison
937 and conditional jump. */
938 int pos_neg = get_range_pos_neg (arg1);
939 if (code == PLUS_EXPR)
941 int pos_neg0 = get_range_pos_neg (arg0);
942 if (pos_neg0 != 3 && pos_neg == 3)
944 std::swap (op0, op1);
945 pos_neg = pos_neg0;
949 /* Addition overflows if and only if the two operands have the same sign,
950 and the result has the opposite sign. Subtraction overflows if and
951 only if the two operands have opposite sign, and the subtrahend has
952 the same sign as the result. Here 0 is counted as positive. */
953 if (pos_neg == 3)
955 /* Compute op0 ^ op1 (operands have opposite sign). */
956 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
957 OPTAB_LIB_WIDEN);
959 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
960 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
961 OPTAB_LIB_WIDEN);
963 rtx tem;
964 if (code == PLUS_EXPR)
966 /* Compute (res ^ op1) & ~(op0 ^ op1). */
967 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
968 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
969 OPTAB_LIB_WIDEN);
971 else
973 /* Compute (op0 ^ op1) & ~(res ^ op1). */
974 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
975 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
976 OPTAB_LIB_WIDEN);
979 /* No overflow if the result has bit sign cleared. */
980 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
981 NULL, done_label, PROB_VERY_LIKELY);
984 /* Compare the result of the operation with the first operand.
985 No overflow for addition if second operand is positive and result
986 is larger or second operand is negative and result is smaller.
987 Likewise for subtraction with sign of second operand flipped. */
988 else
989 do_compare_rtx_and_jump (res, op0,
990 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
991 false, mode, NULL_RTX, NULL, done_label,
992 PROB_VERY_LIKELY);
995 do_error_label:
996 emit_label (do_error);
997 if (is_ubsan)
999 /* Expand the ubsan builtin call. */
1000 push_temp_slots ();
1001 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1002 arg0, arg1, datap);
1003 expand_normal (fn);
1004 pop_temp_slots ();
1005 do_pending_stack_adjust ();
1007 else if (lhs)
1008 expand_arith_set_overflow (lhs, target);
1010 /* We're done. */
1011 emit_label (done_label);
1013 if (lhs)
1015 if (is_ubsan)
1016 expand_ubsan_result_store (target, res);
1017 else
1019 if (do_xor)
1020 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1021 OPTAB_LIB_WIDEN);
1023 expand_arith_overflow_result_store (lhs, target, mode, res);
1028 /* Add negate overflow checking to the statement STMT. */
1030 static void
1031 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1032 tree *datap)
1034 rtx res, op1;
1035 tree fn;
1036 rtx_code_label *done_label, *do_error;
1037 rtx target = NULL_RTX;
1039 done_label = gen_label_rtx ();
1040 do_error = gen_label_rtx ();
1042 do_pending_stack_adjust ();
1043 op1 = expand_normal (arg1);
1045 machine_mode mode = TYPE_MODE (TREE_TYPE (arg1));
1046 if (lhs)
1048 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1049 if (!is_ubsan)
1050 write_complex_part (target, const0_rtx, true);
1053 enum insn_code icode = optab_handler (negv3_optab, mode);
1054 if (icode != CODE_FOR_nothing)
1056 struct expand_operand ops[3];
1057 rtx_insn *last = get_last_insn ();
1059 res = gen_reg_rtx (mode);
1060 create_output_operand (&ops[0], res, mode);
1061 create_input_operand (&ops[1], op1, mode);
1062 create_fixed_operand (&ops[2], do_error);
1063 if (maybe_expand_insn (icode, 3, ops))
1065 last = get_last_insn ();
1066 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1067 && JUMP_P (last)
1068 && any_condjump_p (last)
1069 && !find_reg_note (last, REG_BR_PROB, 0))
1070 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
1071 emit_jump (done_label);
1073 else
1075 delete_insns_since (last);
1076 icode = CODE_FOR_nothing;
1080 if (icode == CODE_FOR_nothing)
1082 /* Compute the operation. On RTL level, the addition is always
1083 unsigned. */
1084 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1086 /* Compare the operand with the most negative value. */
1087 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1088 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1089 done_label, PROB_VERY_LIKELY);
1092 emit_label (do_error);
1093 if (is_ubsan)
1095 /* Expand the ubsan builtin call. */
1096 push_temp_slots ();
1097 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1098 arg1, NULL_TREE, datap);
1099 expand_normal (fn);
1100 pop_temp_slots ();
1101 do_pending_stack_adjust ();
1103 else if (lhs)
1104 expand_arith_set_overflow (lhs, target);
1106 /* We're done. */
1107 emit_label (done_label);
1109 if (lhs)
1111 if (is_ubsan)
1112 expand_ubsan_result_store (target, res);
1113 else
1114 expand_arith_overflow_result_store (lhs, target, mode, res);
1118 /* Add mul overflow checking to the statement STMT. */
1120 static void
1121 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1122 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1123 tree *datap)
1125 rtx res, op0, op1;
1126 tree fn, type;
1127 rtx_code_label *done_label, *do_error;
1128 rtx target = NULL_RTX;
1129 signop sign;
1130 enum insn_code icode;
1132 done_label = gen_label_rtx ();
1133 do_error = gen_label_rtx ();
1135 do_pending_stack_adjust ();
1136 op0 = expand_normal (arg0);
1137 op1 = expand_normal (arg1);
1139 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1140 bool uns = unsr_p;
1141 if (lhs)
1143 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1144 if (!is_ubsan)
1145 write_complex_part (target, const0_rtx, true);
1148 if (is_ubsan)
1149 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1151 /* We assume both operands and result have the same precision
1152 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1153 with that precision, U for unsigned type with that precision,
1154 sgn for unsigned most significant bit in that precision.
1155 s1 is signed first operand, u1 is unsigned first operand,
1156 s2 is signed second operand, u2 is unsigned second operand,
1157 sr is signed result, ur is unsigned result and the following
1158 rules say how to compute result (which is always result of
1159 the operands as if both were unsigned, cast to the right
1160 signedness) and how to compute whether operation overflowed.
1161 main_ovf (false) stands for jump on signed multiplication
1162 overflow or the main algorithm with uns == false.
1163 main_ovf (true) stands for jump on unsigned multiplication
1164 overflow or the main algorithm with uns == true.
1166 s1 * s2 -> sr
1167 res = (S) ((U) s1 * (U) s2)
1168 ovf = main_ovf (false)
1169 u1 * u2 -> ur
1170 res = u1 * u2
1171 ovf = main_ovf (true)
1172 s1 * u2 -> ur
1173 res = (U) s1 * u2
1174 ovf = (s1 < 0 && u2) || main_ovf (true)
1175 u1 * u2 -> sr
1176 res = (S) (u1 * u2)
1177 ovf = res < 0 || main_ovf (true)
1178 s1 * u2 -> sr
1179 res = (S) ((U) s1 * u2)
1180 ovf = (S) u2 >= 0 ? main_ovf (false)
1181 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1182 s1 * s2 -> ur
1183 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1184 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1185 res = t1 * t2
1186 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1188 if (uns0_p && !uns1_p)
1190 /* Multiplication is commutative, if operand signedness differs,
1191 canonicalize to the first operand being signed and second
1192 unsigned to simplify following code. */
1193 std::swap (op0, op1);
1194 std::swap (arg0, arg1);
1195 uns0_p = false;
1196 uns1_p = true;
1199 int pos_neg0 = get_range_pos_neg (arg0);
1200 int pos_neg1 = get_range_pos_neg (arg1);
1202 /* s1 * u2 -> ur */
1203 if (!uns0_p && uns1_p && unsr_p)
1205 switch (pos_neg0)
1207 case 1:
1208 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1209 goto do_main;
1210 case 2:
1211 /* If s1 is negative, avoid the main code, just multiply and
1212 signal overflow if op1 is not 0. */
1213 struct separate_ops ops;
1214 ops.code = MULT_EXPR;
1215 ops.type = TREE_TYPE (arg1);
1216 ops.op0 = make_tree (ops.type, op0);
1217 ops.op1 = make_tree (ops.type, op1);
1218 ops.op2 = NULL_TREE;
1219 ops.location = loc;
1220 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1221 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1222 NULL, done_label, PROB_VERY_LIKELY);
1223 goto do_error_label;
1224 case 3:
1225 rtx_code_label *do_main_label;
1226 do_main_label = gen_label_rtx ();
1227 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1228 NULL, do_main_label, PROB_VERY_LIKELY);
1229 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1230 NULL, do_main_label, PROB_VERY_LIKELY);
1231 expand_arith_set_overflow (lhs, target);
1232 emit_label (do_main_label);
1233 goto do_main;
1234 default:
1235 gcc_unreachable ();
1239 /* u1 * u2 -> sr */
1240 if (uns0_p && uns1_p && !unsr_p)
1242 uns = true;
1243 /* Rest of handling of this case after res is computed. */
1244 goto do_main;
1247 /* s1 * u2 -> sr */
1248 if (!uns0_p && uns1_p && !unsr_p)
1250 switch (pos_neg1)
1252 case 1:
1253 goto do_main;
1254 case 2:
1255 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1256 avoid the main code, just multiply and signal overflow
1257 unless 0 * u2 or -1 * ((U) Smin). */
1258 struct separate_ops ops;
1259 ops.code = MULT_EXPR;
1260 ops.type = TREE_TYPE (arg1);
1261 ops.op0 = make_tree (ops.type, op0);
1262 ops.op1 = make_tree (ops.type, op1);
1263 ops.op2 = NULL_TREE;
1264 ops.location = loc;
1265 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1266 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1267 NULL, done_label, PROB_VERY_LIKELY);
1268 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1269 NULL, do_error, PROB_VERY_UNLIKELY);
1270 int prec;
1271 prec = GET_MODE_PRECISION (mode);
1272 rtx sgn;
1273 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1274 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1275 NULL, done_label, PROB_VERY_LIKELY);
1276 goto do_error_label;
1277 case 3:
1278 /* Rest of handling of this case after res is computed. */
1279 goto do_main;
1280 default:
1281 gcc_unreachable ();
1285 /* s1 * s2 -> ur */
1286 if (!uns0_p && !uns1_p && unsr_p)
1288 rtx tem, tem2;
1289 switch (pos_neg0 | pos_neg1)
1291 case 1: /* Both operands known to be non-negative. */
1292 goto do_main;
1293 case 2: /* Both operands known to be negative. */
1294 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1295 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1296 /* Avoid looking at arg0/arg1 ranges, as we've changed
1297 the arguments. */
1298 arg0 = error_mark_node;
1299 arg1 = error_mark_node;
1300 goto do_main;
1301 case 3:
1302 if ((pos_neg0 ^ pos_neg1) == 3)
1304 /* If one operand is known to be negative and the other
1305 non-negative, this overflows always, unless the non-negative
1306 one is 0. Just do normal multiply and set overflow
1307 unless one of the operands is 0. */
1308 struct separate_ops ops;
1309 ops.code = MULT_EXPR;
1310 ops.type
1311 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1313 ops.op0 = make_tree (ops.type, op0);
1314 ops.op1 = make_tree (ops.type, op1);
1315 ops.op2 = NULL_TREE;
1316 ops.location = loc;
1317 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1318 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1319 OPTAB_LIB_WIDEN);
1320 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1321 NULL_RTX, NULL, done_label,
1322 PROB_VERY_LIKELY);
1323 goto do_error_label;
1325 /* The general case, do all the needed comparisons at runtime. */
1326 rtx_code_label *do_main_label, *after_negate_label;
1327 rtx rop0, rop1;
1328 rop0 = gen_reg_rtx (mode);
1329 rop1 = gen_reg_rtx (mode);
1330 emit_move_insn (rop0, op0);
1331 emit_move_insn (rop1, op1);
1332 op0 = rop0;
1333 op1 = rop1;
1334 do_main_label = gen_label_rtx ();
1335 after_negate_label = gen_label_rtx ();
1336 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1337 OPTAB_LIB_WIDEN);
1338 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1339 NULL, after_negate_label, PROB_VERY_LIKELY);
1340 /* Both arguments negative here, negate them and continue with
1341 normal unsigned overflow checking multiplication. */
1342 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1343 NULL_RTX, false));
1344 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1345 NULL_RTX, false));
1346 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1347 the arguments. */
1348 arg0 = error_mark_node;
1349 arg1 = error_mark_node;
1350 emit_jump (do_main_label);
1351 emit_label (after_negate_label);
1352 tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1353 OPTAB_LIB_WIDEN);
1354 do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1355 NULL, do_main_label, PROB_VERY_LIKELY);
1356 /* One argument is negative here, the other positive. This
1357 overflows always, unless one of the arguments is 0. But
1358 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1359 is, thus we can keep do_main code oring in overflow as is. */
1360 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1361 NULL, do_main_label, PROB_VERY_LIKELY);
1362 expand_arith_set_overflow (lhs, target);
1363 emit_label (do_main_label);
1364 goto do_main;
1365 default:
1366 gcc_unreachable ();
1370 do_main:
1371 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1372 sign = uns ? UNSIGNED : SIGNED;
1373 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1374 if (icode != CODE_FOR_nothing)
1376 struct expand_operand ops[4];
1377 rtx_insn *last = get_last_insn ();
1379 res = gen_reg_rtx (mode);
1380 create_output_operand (&ops[0], res, mode);
1381 create_input_operand (&ops[1], op0, mode);
1382 create_input_operand (&ops[2], op1, mode);
1383 create_fixed_operand (&ops[3], do_error);
1384 if (maybe_expand_insn (icode, 4, ops))
1386 last = get_last_insn ();
1387 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1388 && JUMP_P (last)
1389 && any_condjump_p (last)
1390 && !find_reg_note (last, REG_BR_PROB, 0))
1391 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
1392 emit_jump (done_label);
1394 else
1396 delete_insns_since (last);
1397 icode = CODE_FOR_nothing;
1401 if (icode == CODE_FOR_nothing)
1403 struct separate_ops ops;
1404 int prec = GET_MODE_PRECISION (mode);
1405 machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
1406 ops.op0 = make_tree (type, op0);
1407 ops.op1 = make_tree (type, op1);
1408 ops.op2 = NULL_TREE;
1409 ops.location = loc;
1410 if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode
1411 && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode)))
1413 machine_mode wmode = GET_MODE_2XWIDER_MODE (mode);
1414 ops.code = WIDEN_MULT_EXPR;
1415 ops.type
1416 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1418 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1419 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1420 NULL_RTX, uns);
1421 hipart = convert_modes (mode, wmode, hipart, uns);
1422 res = convert_modes (mode, wmode, res, uns);
1423 if (uns)
1424 /* For the unsigned multiplication, there was overflow if
1425 HIPART is non-zero. */
1426 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1427 NULL_RTX, NULL, done_label,
1428 PROB_VERY_LIKELY);
1429 else
1431 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1432 NULL_RTX, 0);
1433 /* RES is low half of the double width result, HIPART
1434 the high half. There was overflow if
1435 HIPART is different from RES < 0 ? -1 : 0. */
1436 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1437 NULL_RTX, NULL, done_label,
1438 PROB_VERY_LIKELY);
1441 else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
1443 rtx_code_label *large_op0 = gen_label_rtx ();
1444 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1445 rtx_code_label *one_small_one_large = gen_label_rtx ();
1446 rtx_code_label *both_ops_large = gen_label_rtx ();
1447 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1448 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1449 rtx_code_label *do_overflow = gen_label_rtx ();
1450 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1452 unsigned int hprec = GET_MODE_PRECISION (hmode);
1453 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1454 NULL_RTX, uns);
1455 hipart0 = convert_modes (hmode, mode, hipart0, uns);
1456 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1457 rtx signbit0 = const0_rtx;
1458 if (!uns)
1459 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1460 NULL_RTX, 0);
1461 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1462 NULL_RTX, uns);
1463 hipart1 = convert_modes (hmode, mode, hipart1, uns);
1464 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1465 rtx signbit1 = const0_rtx;
1466 if (!uns)
1467 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1468 NULL_RTX, 0);
1470 res = gen_reg_rtx (mode);
1472 /* True if op0 resp. op1 are known to be in the range of
1473 halfstype. */
1474 bool op0_small_p = false;
1475 bool op1_small_p = false;
1476 /* True if op0 resp. op1 are known to have all zeros or all ones
1477 in the upper half of bits, but are not known to be
1478 op{0,1}_small_p. */
1479 bool op0_medium_p = false;
1480 bool op1_medium_p = false;
1481 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1482 nonnegative, 1 if unknown. */
1483 int op0_sign = 1;
1484 int op1_sign = 1;
1486 if (pos_neg0 == 1)
1487 op0_sign = 0;
1488 else if (pos_neg0 == 2)
1489 op0_sign = -1;
1490 if (pos_neg1 == 1)
1491 op1_sign = 0;
1492 else if (pos_neg1 == 2)
1493 op1_sign = -1;
1495 unsigned int mprec0 = prec;
1496 if (arg0 != error_mark_node)
1497 mprec0 = get_min_precision (arg0, sign);
1498 if (mprec0 <= hprec)
1499 op0_small_p = true;
1500 else if (!uns && mprec0 <= hprec + 1)
1501 op0_medium_p = true;
1502 unsigned int mprec1 = prec;
1503 if (arg1 != error_mark_node)
1504 mprec1 = get_min_precision (arg1, sign);
1505 if (mprec1 <= hprec)
1506 op1_small_p = true;
1507 else if (!uns && mprec1 <= hprec + 1)
1508 op1_medium_p = true;
1510 int smaller_sign = 1;
1511 int larger_sign = 1;
1512 if (op0_small_p)
1514 smaller_sign = op0_sign;
1515 larger_sign = op1_sign;
1517 else if (op1_small_p)
1519 smaller_sign = op1_sign;
1520 larger_sign = op0_sign;
1522 else if (op0_sign == op1_sign)
1524 smaller_sign = op0_sign;
1525 larger_sign = op0_sign;
1528 if (!op0_small_p)
1529 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1530 NULL_RTX, NULL, large_op0,
1531 PROB_UNLIKELY);
1533 if (!op1_small_p)
1534 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1535 NULL_RTX, NULL, small_op0_large_op1,
1536 PROB_UNLIKELY);
1538 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1539 hmode to mode, the multiplication will never overflow. We can
1540 do just one hmode x hmode => mode widening multiplication. */
1541 rtx lopart0s = lopart0, lopart1s = lopart1;
1542 if (GET_CODE (lopart0) == SUBREG)
1544 lopart0s = shallow_copy_rtx (lopart0);
1545 SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1546 SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1548 if (GET_CODE (lopart1) == SUBREG)
1550 lopart1s = shallow_copy_rtx (lopart1);
1551 SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1552 SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1554 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1555 ops.op0 = make_tree (halfstype, lopart0s);
1556 ops.op1 = make_tree (halfstype, lopart1s);
1557 ops.code = WIDEN_MULT_EXPR;
1558 ops.type = type;
1559 rtx thisres
1560 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1561 emit_move_insn (res, thisres);
1562 emit_jump (done_label);
1564 emit_label (small_op0_large_op1);
1566 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1567 but op1 is not, just swap the arguments and handle it as op1
1568 sign/zero extended, op0 not. */
1569 rtx larger = gen_reg_rtx (mode);
1570 rtx hipart = gen_reg_rtx (hmode);
1571 rtx lopart = gen_reg_rtx (hmode);
1572 emit_move_insn (larger, op1);
1573 emit_move_insn (hipart, hipart1);
1574 emit_move_insn (lopart, lopart0);
1575 emit_jump (one_small_one_large);
1577 emit_label (large_op0);
1579 if (!op1_small_p)
1580 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1581 NULL_RTX, NULL, both_ops_large,
1582 PROB_UNLIKELY);
1584 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1585 but op0 is not, prepare larger, hipart and lopart pseudos and
1586 handle it together with small_op0_large_op1. */
1587 emit_move_insn (larger, op0);
1588 emit_move_insn (hipart, hipart0);
1589 emit_move_insn (lopart, lopart1);
1591 emit_label (one_small_one_large);
1593 /* lopart is the low part of the operand that is sign extended
1594 to mode, larger is the other operand, hipart is the
1595 high part of larger and lopart0 and lopart1 are the low parts
1596 of both operands.
1597 We perform lopart0 * lopart1 and lopart * hipart widening
1598 multiplications. */
1599 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1600 ops.op0 = make_tree (halfutype, lopart0);
1601 ops.op1 = make_tree (halfutype, lopart1);
1602 rtx lo0xlo1
1603 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1605 ops.op0 = make_tree (halfutype, lopart);
1606 ops.op1 = make_tree (halfutype, hipart);
1607 rtx loxhi = gen_reg_rtx (mode);
1608 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1609 emit_move_insn (loxhi, tem);
1611 if (!uns)
1613 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1614 if (larger_sign == 0)
1615 emit_jump (after_hipart_neg);
1616 else if (larger_sign != -1)
1617 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1618 NULL_RTX, NULL, after_hipart_neg,
1619 PROB_EVEN);
1621 tem = convert_modes (mode, hmode, lopart, 1);
1622 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1623 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1624 1, OPTAB_DIRECT);
1625 emit_move_insn (loxhi, tem);
1627 emit_label (after_hipart_neg);
1629 /* if (lopart < 0) loxhi -= larger; */
1630 if (smaller_sign == 0)
1631 emit_jump (after_lopart_neg);
1632 else if (smaller_sign != -1)
1633 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1634 NULL_RTX, NULL, after_lopart_neg,
1635 PROB_EVEN);
1637 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1638 1, OPTAB_DIRECT);
1639 emit_move_insn (loxhi, tem);
1641 emit_label (after_lopart_neg);
1644 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1645 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1646 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1647 1, OPTAB_DIRECT);
1648 emit_move_insn (loxhi, tem);
1650 /* if (loxhi >> (bitsize / 2)
1651 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1652 if (loxhi >> (bitsize / 2) == 0 (if uns). */
1653 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1654 NULL_RTX, 0);
1655 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1656 rtx signbitloxhi = const0_rtx;
1657 if (!uns)
1658 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1659 convert_modes (hmode, mode,
1660 loxhi, 0),
1661 hprec - 1, NULL_RTX, 0);
1663 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1664 NULL_RTX, NULL, do_overflow,
1665 PROB_VERY_UNLIKELY);
1667 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1668 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1669 NULL_RTX, 1);
1670 tem = convert_modes (mode, hmode,
1671 convert_modes (hmode, mode, lo0xlo1, 1), 1);
1673 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1674 1, OPTAB_DIRECT);
1675 if (tem != res)
1676 emit_move_insn (res, tem);
1677 emit_jump (done_label);
1679 emit_label (both_ops_large);
1681 /* If both operands are large (not sign (!uns) or zero (uns)
1682 extended from hmode), then perform the full multiplication
1683 which will be the result of the operation.
1684 The only cases which don't overflow are for signed multiplication
1685 some cases where both hipart0 and highpart1 are 0 or -1.
1686 For unsigned multiplication when high parts are both non-zero
1687 this overflows always. */
1688 ops.code = MULT_EXPR;
1689 ops.op0 = make_tree (type, op0);
1690 ops.op1 = make_tree (type, op1);
1691 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1692 emit_move_insn (res, tem);
1694 if (!uns)
1696 if (!op0_medium_p)
1698 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1699 NULL_RTX, 1, OPTAB_DIRECT);
1700 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1701 NULL_RTX, NULL, do_error,
1702 PROB_VERY_UNLIKELY);
1705 if (!op1_medium_p)
1707 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1708 NULL_RTX, 1, OPTAB_DIRECT);
1709 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1710 NULL_RTX, NULL, do_error,
1711 PROB_VERY_UNLIKELY);
1714 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1715 the same, overflow happened if res is negative, if they are
1716 different, overflow happened if res is positive. */
1717 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1718 emit_jump (hipart_different);
1719 else if (op0_sign == 1 || op1_sign == 1)
1720 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1721 NULL_RTX, NULL, hipart_different,
1722 PROB_EVEN);
1724 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
1725 NULL_RTX, NULL, do_error,
1726 PROB_VERY_UNLIKELY);
1727 emit_jump (done_label);
1729 emit_label (hipart_different);
1731 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1732 NULL_RTX, NULL, do_error,
1733 PROB_VERY_UNLIKELY);
1734 emit_jump (done_label);
1737 emit_label (do_overflow);
1739 /* Overflow, do full multiplication and fallthru into do_error. */
1740 ops.op0 = make_tree (type, op0);
1741 ops.op1 = make_tree (type, op1);
1742 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1743 emit_move_insn (res, tem);
1745 else
1747 gcc_assert (!is_ubsan);
1748 ops.code = MULT_EXPR;
1749 ops.type = type;
1750 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1751 emit_jump (done_label);
1755 do_error_label:
1756 emit_label (do_error);
1757 if (is_ubsan)
1759 /* Expand the ubsan builtin call. */
1760 push_temp_slots ();
1761 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1762 arg0, arg1, datap);
1763 expand_normal (fn);
1764 pop_temp_slots ();
1765 do_pending_stack_adjust ();
1767 else if (lhs)
1768 expand_arith_set_overflow (lhs, target);
1770 /* We're done. */
1771 emit_label (done_label);
1773 /* u1 * u2 -> sr */
1774 if (uns0_p && uns1_p && !unsr_p)
1776 rtx_code_label *all_done_label = gen_label_rtx ();
1777 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1778 NULL, all_done_label, PROB_VERY_LIKELY);
1779 expand_arith_set_overflow (lhs, target);
1780 emit_label (all_done_label);
1783 /* s1 * u2 -> sr */
1784 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
1786 rtx_code_label *all_done_label = gen_label_rtx ();
1787 rtx_code_label *set_noovf = gen_label_rtx ();
1788 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
1789 NULL, all_done_label, PROB_VERY_LIKELY);
1790 expand_arith_set_overflow (lhs, target);
1791 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1792 NULL, set_noovf, PROB_VERY_LIKELY);
1793 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1794 NULL, all_done_label, PROB_VERY_UNLIKELY);
1795 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
1796 all_done_label, PROB_VERY_UNLIKELY);
1797 emit_label (set_noovf);
1798 write_complex_part (target, const0_rtx, true);
1799 emit_label (all_done_label);
1802 if (lhs)
1804 if (is_ubsan)
1805 expand_ubsan_result_store (target, res);
1806 else
1807 expand_arith_overflow_result_store (lhs, target, mode, res);
1811 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
1813 static void
1814 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
1815 tree arg0, tree arg1)
1817 int cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
1818 rtx_code_label *loop_lab = NULL;
1819 rtx cntvar = NULL_RTX;
1820 tree cntv = NULL_TREE;
1821 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
1822 tree sz = TYPE_SIZE (eltype);
1823 tree data = NULL_TREE;
1824 tree resv = NULL_TREE;
1825 rtx lhsr = NULL_RTX;
1826 rtx resvr = NULL_RTX;
1828 if (lhs)
1830 optab op;
1831 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1832 if (!VECTOR_MODE_P (GET_MODE (lhsr))
1833 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
1834 optab_default)) == unknown_optab
1835 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
1836 == CODE_FOR_nothing))
1838 if (MEM_P (lhsr))
1839 resv = make_tree (TREE_TYPE (lhs), lhsr);
1840 else
1842 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
1843 resv = make_tree (TREE_TYPE (lhs), resvr);
1847 if (cnt > 4)
1849 do_pending_stack_adjust ();
1850 loop_lab = gen_label_rtx ();
1851 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
1852 cntv = make_tree (sizetype, cntvar);
1853 emit_move_insn (cntvar, const0_rtx);
1854 emit_label (loop_lab);
1856 if (TREE_CODE (arg0) != VECTOR_CST)
1858 rtx arg0r = expand_normal (arg0);
1859 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
1861 if (TREE_CODE (arg1) != VECTOR_CST)
1863 rtx arg1r = expand_normal (arg1);
1864 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
1866 for (int i = 0; i < (cnt > 4 ? 1 : cnt); i++)
1868 tree op0, op1, res = NULL_TREE;
1869 if (cnt > 4)
1871 tree atype = build_array_type_nelts (eltype, cnt);
1872 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
1873 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
1874 NULL_TREE, NULL_TREE);
1875 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
1876 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
1877 NULL_TREE, NULL_TREE);
1878 if (resv)
1880 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
1881 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
1882 NULL_TREE, NULL_TREE);
1885 else
1887 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
1888 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
1889 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
1890 if (resv)
1891 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
1892 bitpos);
1894 switch (code)
1896 case PLUS_EXPR:
1897 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
1898 false, false, false, true, &data);
1899 break;
1900 case MINUS_EXPR:
1901 if (cnt > 4 ? integer_zerop (arg0) : integer_zerop (op0))
1902 expand_neg_overflow (loc, res, op1, true, &data);
1903 else
1904 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
1905 false, false, false, true, &data);
1906 break;
1907 case MULT_EXPR:
1908 expand_mul_overflow (loc, res, op0, op1, false, false, false,
1909 true, &data);
1910 break;
1911 default:
1912 gcc_unreachable ();
1915 if (cnt > 4)
1917 struct separate_ops ops;
1918 ops.code = PLUS_EXPR;
1919 ops.type = TREE_TYPE (cntv);
1920 ops.op0 = cntv;
1921 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
1922 ops.op2 = NULL_TREE;
1923 ops.location = loc;
1924 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
1925 EXPAND_NORMAL);
1926 if (ret != cntvar)
1927 emit_move_insn (cntvar, ret);
1928 do_compare_rtx_and_jump (cntvar, GEN_INT (cnt), NE, false,
1929 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
1930 PROB_VERY_LIKELY);
1932 if (lhs && resv == NULL_TREE)
1934 struct separate_ops ops;
1935 ops.code = code;
1936 ops.type = TREE_TYPE (arg0);
1937 ops.op0 = arg0;
1938 ops.op1 = arg1;
1939 ops.op2 = NULL_TREE;
1940 ops.location = loc;
1941 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
1942 EXPAND_NORMAL);
1943 if (ret != lhsr)
1944 emit_move_insn (lhsr, ret);
1946 else if (resvr)
1947 emit_move_insn (lhsr, resvr);
1950 /* Expand UBSAN_CHECK_ADD call STMT. */
1952 static void
1953 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
1955 location_t loc = gimple_location (stmt);
1956 tree lhs = gimple_call_lhs (stmt);
1957 tree arg0 = gimple_call_arg (stmt, 0);
1958 tree arg1 = gimple_call_arg (stmt, 1);
1959 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
1960 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
1961 else
1962 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
1963 false, false, false, true, NULL);
1966 /* Expand UBSAN_CHECK_SUB call STMT. */
1968 static void
1969 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
1971 location_t loc = gimple_location (stmt);
1972 tree lhs = gimple_call_lhs (stmt);
1973 tree arg0 = gimple_call_arg (stmt, 0);
1974 tree arg1 = gimple_call_arg (stmt, 1);
1975 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
1976 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
1977 else if (integer_zerop (arg0))
1978 expand_neg_overflow (loc, lhs, arg1, true, NULL);
1979 else
1980 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
1981 false, false, false, true, NULL);
1984 /* Expand UBSAN_CHECK_MUL call STMT. */
1986 static void
1987 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
1989 location_t loc = gimple_location (stmt);
1990 tree lhs = gimple_call_lhs (stmt);
1991 tree arg0 = gimple_call_arg (stmt, 0);
1992 tree arg1 = gimple_call_arg (stmt, 1);
1993 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
1994 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
1995 else
1996 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
1997 NULL);
2000 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2002 static void
2003 expand_arith_overflow (enum tree_code code, gimple *stmt)
2005 tree lhs = gimple_call_lhs (stmt);
2006 if (lhs == NULL_TREE)
2007 return;
2008 tree arg0 = gimple_call_arg (stmt, 0);
2009 tree arg1 = gimple_call_arg (stmt, 1);
2010 tree type = TREE_TYPE (TREE_TYPE (lhs));
2011 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2012 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2013 int unsr_p = TYPE_UNSIGNED (type);
2014 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2015 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2016 int precres = TYPE_PRECISION (type);
2017 location_t loc = gimple_location (stmt);
2018 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2019 uns0_p = true;
2020 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2021 uns1_p = true;
2022 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2023 prec0 = MIN (prec0, pr);
2024 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2025 prec1 = MIN (prec1, pr);
2027 /* If uns0_p && uns1_p, precop is minimum needed precision
2028 of unsigned type to hold the exact result, otherwise
2029 precop is minimum needed precision of signed type to
2030 hold the exact result. */
2031 int precop;
2032 if (code == MULT_EXPR)
2033 precop = prec0 + prec1 + (uns0_p != uns1_p);
2034 else
2036 if (uns0_p == uns1_p)
2037 precop = MAX (prec0, prec1) + 1;
2038 else if (uns0_p)
2039 precop = MAX (prec0 + 1, prec1) + 1;
2040 else
2041 precop = MAX (prec0, prec1 + 1) + 1;
2043 int orig_precres = precres;
2047 if ((uns0_p && uns1_p)
2048 ? ((precop + !unsr_p) <= precres
2049 /* u1 - u2 -> ur can overflow, no matter what precision
2050 the result has. */
2051 && (code != MINUS_EXPR || !unsr_p))
2052 : (!unsr_p && precop <= precres))
2054 /* The infinity precision result will always fit into result. */
2055 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2056 write_complex_part (target, const0_rtx, true);
2057 enum machine_mode mode = TYPE_MODE (type);
2058 struct separate_ops ops;
2059 ops.code = code;
2060 ops.type = type;
2061 ops.op0 = fold_convert_loc (loc, type, arg0);
2062 ops.op1 = fold_convert_loc (loc, type, arg1);
2063 ops.op2 = NULL_TREE;
2064 ops.location = loc;
2065 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2066 expand_arith_overflow_result_store (lhs, target, mode, tem);
2067 return;
2070 /* For operations with low precision, if target doesn't have them, start
2071 with precres widening right away, otherwise do it only if the most
2072 simple cases can't be used. */
2073 const int min_precision = targetm.min_arithmetic_precision ();
2074 if (orig_precres == precres && precres < min_precision)
2076 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2077 && prec1 <= precres)
2078 || ((!uns0_p || !uns1_p) && !unsr_p
2079 && prec0 + uns0_p <= precres
2080 && prec1 + uns1_p <= precres))
2082 arg0 = fold_convert_loc (loc, type, arg0);
2083 arg1 = fold_convert_loc (loc, type, arg1);
2084 switch (code)
2086 case MINUS_EXPR:
2087 if (integer_zerop (arg0) && !unsr_p)
2089 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2090 return;
2092 /* FALLTHRU */
2093 case PLUS_EXPR:
2094 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2095 unsr_p, unsr_p, false, NULL);
2096 return;
2097 case MULT_EXPR:
2098 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2099 unsr_p, unsr_p, false, NULL);
2100 return;
2101 default:
2102 gcc_unreachable ();
2106 /* For sub-word operations, retry with a wider type first. */
2107 if (orig_precres == precres && precop <= BITS_PER_WORD)
2109 int p = MAX (min_precision, precop);
2110 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
2111 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2112 uns0_p && uns1_p
2113 && unsr_p);
2114 p = TYPE_PRECISION (optype);
2115 if (p > precres)
2117 precres = p;
2118 unsr_p = TYPE_UNSIGNED (optype);
2119 type = optype;
2120 continue;
2124 if (prec0 <= precres && prec1 <= precres)
2126 tree types[2];
2127 if (unsr_p)
2129 types[0] = build_nonstandard_integer_type (precres, 0);
2130 types[1] = type;
2132 else
2134 types[0] = type;
2135 types[1] = build_nonstandard_integer_type (precres, 1);
2137 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2138 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2139 if (code != MULT_EXPR)
2140 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2141 uns0_p, uns1_p, false, NULL);
2142 else
2143 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2144 uns0_p, uns1_p, false, NULL);
2145 return;
2148 /* Retry with a wider type. */
2149 if (orig_precres == precres)
2151 int p = MAX (prec0, prec1);
2152 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
2153 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2154 uns0_p && uns1_p
2155 && unsr_p);
2156 p = TYPE_PRECISION (optype);
2157 if (p > precres)
2159 precres = p;
2160 unsr_p = TYPE_UNSIGNED (optype);
2161 type = optype;
2162 continue;
2166 gcc_unreachable ();
2168 while (1);
2171 /* Expand ADD_OVERFLOW STMT. */
2173 static void
2174 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2176 expand_arith_overflow (PLUS_EXPR, stmt);
2179 /* Expand SUB_OVERFLOW STMT. */
2181 static void
2182 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2184 expand_arith_overflow (MINUS_EXPR, stmt);
2187 /* Expand MUL_OVERFLOW STMT. */
2189 static void
2190 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2192 expand_arith_overflow (MULT_EXPR, stmt);
2195 /* This should get folded in tree-vectorizer.c. */
2197 static void
2198 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2200 gcc_unreachable ();
2203 /* Expand MASK_LOAD call STMT using optab OPTAB. */
2205 static void
2206 expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2208 struct expand_operand ops[3];
2209 tree type, lhs, rhs, maskt, ptr;
2210 rtx mem, target, mask;
2211 unsigned align;
2213 maskt = gimple_call_arg (stmt, 2);
2214 lhs = gimple_call_lhs (stmt);
2215 if (lhs == NULL_TREE)
2216 return;
2217 type = TREE_TYPE (lhs);
2218 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
2219 align = tree_to_shwi (gimple_call_arg (stmt, 1));
2220 if (TYPE_ALIGN (type) != align)
2221 type = build_aligned_type (type, align);
2222 rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
2224 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2225 gcc_assert (MEM_P (mem));
2226 mask = expand_normal (maskt);
2227 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2228 create_output_operand (&ops[0], target, TYPE_MODE (type));
2229 create_fixed_operand (&ops[1], mem);
2230 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2231 expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
2232 TYPE_MODE (TREE_TYPE (maskt))),
2233 3, ops);
2236 /* Expand MASK_STORE call STMT using optab OPTAB. */
2238 static void
2239 expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2241 struct expand_operand ops[3];
2242 tree type, lhs, rhs, maskt, ptr;
2243 rtx mem, reg, mask;
2244 unsigned align;
2246 maskt = gimple_call_arg (stmt, 2);
2247 rhs = gimple_call_arg (stmt, 3);
2248 type = TREE_TYPE (rhs);
2249 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
2250 align = tree_to_shwi (gimple_call_arg (stmt, 1));
2251 if (TYPE_ALIGN (type) != align)
2252 type = build_aligned_type (type, align);
2253 lhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
2255 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2256 gcc_assert (MEM_P (mem));
2257 mask = expand_normal (maskt);
2258 reg = expand_normal (rhs);
2259 create_fixed_operand (&ops[0], mem);
2260 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2261 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2262 expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
2263 TYPE_MODE (TREE_TYPE (maskt))),
2264 3, ops);
2267 static void
2268 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
2272 static void
2273 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
2275 /* When guessing was done, the hints should be already stripped away. */
2276 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2278 rtx target;
2279 tree lhs = gimple_call_lhs (stmt);
2280 if (lhs)
2281 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2282 else
2283 target = const0_rtx;
2284 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2285 if (lhs && val != target)
2286 emit_move_insn (target, val);
2289 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
2290 should never be called. */
2292 static void
2293 expand_VA_ARG (internal_fn, gcall *)
2295 gcc_unreachable ();
2298 /* Expand the IFN_UNIQUE function according to its first argument. */
2300 static void
2301 expand_UNIQUE (internal_fn, gcall *stmt)
2303 rtx pattern = NULL_RTX;
2304 enum ifn_unique_kind kind
2305 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2307 switch (kind)
2309 default:
2310 gcc_unreachable ();
2312 case IFN_UNIQUE_UNSPEC:
2313 if (targetm.have_unique ())
2314 pattern = targetm.gen_unique ();
2315 break;
2317 case IFN_UNIQUE_OACC_FORK:
2318 case IFN_UNIQUE_OACC_JOIN:
2319 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2321 tree lhs = gimple_call_lhs (stmt);
2322 rtx target = const0_rtx;
2324 if (lhs)
2325 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2327 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2328 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2330 if (kind == IFN_UNIQUE_OACC_FORK)
2331 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2332 else
2333 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2335 else
2336 gcc_unreachable ();
2337 break;
2340 if (pattern)
2341 emit_insn (pattern);
2344 /* The size of an OpenACC compute dimension. */
2346 static void
2347 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
2349 tree lhs = gimple_call_lhs (stmt);
2351 if (!lhs)
2352 return;
2354 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2355 if (targetm.have_oacc_dim_size ())
2357 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2358 VOIDmode, EXPAND_NORMAL);
2359 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2361 else
2362 emit_move_insn (target, GEN_INT (1));
2365 /* The position of an OpenACC execution engine along one compute axis. */
2367 static void
2368 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
2370 tree lhs = gimple_call_lhs (stmt);
2372 if (!lhs)
2373 return;
2375 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2376 if (targetm.have_oacc_dim_pos ())
2378 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2379 VOIDmode, EXPAND_NORMAL);
2380 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2382 else
2383 emit_move_insn (target, const0_rtx);
2386 /* This is expanded by oacc_device_lower pass. */
2388 static void
2389 expand_GOACC_LOOP (internal_fn, gcall *)
2391 gcc_unreachable ();
2394 /* This is expanded by oacc_device_lower pass. */
2396 static void
2397 expand_GOACC_REDUCTION (internal_fn, gcall *)
2399 gcc_unreachable ();
2402 /* This is expanded by oacc_device_lower pass. */
2404 static void
2405 expand_GOACC_TILE (internal_fn, gcall *)
2407 gcc_unreachable ();
2410 /* Set errno to EDOM. */
2412 static void
2413 expand_SET_EDOM (internal_fn, gcall *)
2415 #ifdef TARGET_EDOM
2416 #ifdef GEN_ERRNO_RTX
2417 rtx errno_rtx = GEN_ERRNO_RTX;
2418 #else
2419 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2420 #endif
2421 emit_move_insn (errno_rtx,
2422 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2423 #else
2424 gcc_unreachable ();
2425 #endif
2428 /* Expand atomic bit test and set. */
2430 static void
2431 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2433 expand_ifn_atomic_bit_test_and (call);
2436 /* Expand atomic bit test and complement. */
2438 static void
2439 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2441 expand_ifn_atomic_bit_test_and (call);
2444 /* Expand atomic bit test and reset. */
2446 static void
2447 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2449 expand_ifn_atomic_bit_test_and (call);
2452 /* Expand atomic bit test and set. */
2454 static void
2455 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2457 expand_ifn_atomic_compare_exchange (call);
2460 /* Expand LAUNDER to assignment, lhs = arg0. */
2462 static void
2463 expand_LAUNDER (internal_fn, gcall *call)
2465 tree lhs = gimple_call_lhs (call);
2467 if (!lhs)
2468 return;
2470 expand_assignment (lhs, gimple_call_arg (call, 0), false);
2473 /* Expand DIVMOD() using:
2474 a) optab handler for udivmod/sdivmod if it is available.
2475 b) If optab_handler doesn't exist, generate call to
2476 target-specific divmod libfunc. */
2478 static void
2479 expand_DIVMOD (internal_fn, gcall *call_stmt)
2481 tree lhs = gimple_call_lhs (call_stmt);
2482 tree arg0 = gimple_call_arg (call_stmt, 0);
2483 tree arg1 = gimple_call_arg (call_stmt, 1);
2485 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
2486 tree type = TREE_TYPE (TREE_TYPE (lhs));
2487 machine_mode mode = TYPE_MODE (type);
2488 bool unsignedp = TYPE_UNSIGNED (type);
2489 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
2491 rtx op0 = expand_normal (arg0);
2492 rtx op1 = expand_normal (arg1);
2493 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2495 rtx quotient, remainder, libfunc;
2497 /* Check if optab_handler exists for divmod_optab for given mode. */
2498 if (optab_handler (tab, mode) != CODE_FOR_nothing)
2500 quotient = gen_reg_rtx (mode);
2501 remainder = gen_reg_rtx (mode);
2502 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
2505 /* Generate call to divmod libfunc if it exists. */
2506 else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
2507 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
2508 &quotient, &remainder);
2510 else
2511 gcc_unreachable ();
2513 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
2514 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
2515 make_tree (TREE_TYPE (arg0), quotient),
2516 make_tree (TREE_TYPE (arg1), remainder)),
2517 target, VOIDmode, EXPAND_NORMAL);
2520 /* Expand a call to FN using the operands in STMT. FN has a single
2521 output operand and NARGS input operands. */
2523 static void
2524 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2525 unsigned int nargs)
2527 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2529 tree_pair types = direct_internal_fn_types (fn, stmt);
2530 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2532 tree lhs = gimple_call_lhs (stmt);
2533 tree lhs_type = TREE_TYPE (lhs);
2534 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2535 create_output_operand (&ops[0], lhs_rtx, insn_data[icode].operand[0].mode);
2537 for (unsigned int i = 0; i < nargs; ++i)
2539 tree rhs = gimple_call_arg (stmt, i);
2540 tree rhs_type = TREE_TYPE (rhs);
2541 rtx rhs_rtx = expand_normal (rhs);
2542 if (INTEGRAL_TYPE_P (rhs_type))
2543 create_convert_operand_from (&ops[i + 1], rhs_rtx,
2544 TYPE_MODE (rhs_type),
2545 TYPE_UNSIGNED (rhs_type));
2546 else
2547 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2550 expand_insn (icode, nargs + 1, ops);
2551 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2553 /* If the return value has an integral type, convert the instruction
2554 result to that type. This is useful for things that return an
2555 int regardless of the size of the input. If the instruction result
2556 is smaller than required, assume that it is signed.
2558 If the return value has a nonintegral type, its mode must match
2559 the instruction result. */
2560 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2562 /* If this is a scalar in a register that is stored in a wider
2563 mode than the declared mode, compute the result into its
2564 declared mode and then convert to the wider mode. */
2565 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2566 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2567 convert_move (SUBREG_REG (lhs_rtx), tmp,
2568 SUBREG_PROMOTED_SIGN (lhs_rtx));
2570 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
2571 emit_move_insn (lhs_rtx, ops[0].value);
2572 else
2574 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2575 convert_move (lhs_rtx, ops[0].value, 0);
2580 /* Expanders for optabs that can use expand_direct_optab_fn. */
2582 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
2583 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
2585 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
2586 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
2588 /* RETURN_TYPE and ARGS are a return type and argument list that are
2589 in principle compatible with FN (which satisfies direct_internal_fn_p).
2590 Return the types that should be used to determine whether the
2591 target supports FN. */
2593 tree_pair
2594 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
2596 const direct_internal_fn_info &info = direct_internal_fn (fn);
2597 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
2598 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
2599 return tree_pair (type0, type1);
2602 /* CALL is a call whose return type and arguments are in principle
2603 compatible with FN (which satisfies direct_internal_fn_p). Return the
2604 types that should be used to determine whether the target supports FN. */
2606 tree_pair
2607 direct_internal_fn_types (internal_fn fn, gcall *call)
2609 const direct_internal_fn_info &info = direct_internal_fn (fn);
2610 tree op0 = (info.type0 < 0
2611 ? gimple_call_lhs (call)
2612 : gimple_call_arg (call, info.type0));
2613 tree op1 = (info.type1 < 0
2614 ? gimple_call_lhs (call)
2615 : gimple_call_arg (call, info.type1));
2616 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
2619 /* Return true if OPTAB is supported for TYPES (whose modes should be
2620 the same) when the optimization type is OPT_TYPE. Used for simple
2621 direct optabs. */
2623 static bool
2624 direct_optab_supported_p (direct_optab optab, tree_pair types,
2625 optimization_type opt_type)
2627 machine_mode mode = TYPE_MODE (types.first);
2628 gcc_checking_assert (mode == TYPE_MODE (types.second));
2629 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
2632 /* Return true if load/store lanes optab OPTAB is supported for
2633 array type TYPES.first when the optimization type is OPT_TYPE. */
2635 static bool
2636 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
2637 optimization_type opt_type)
2639 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
2640 machine_mode imode = TYPE_MODE (types.first);
2641 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
2642 return (convert_optab_handler (optab, imode, vmode, opt_type)
2643 != CODE_FOR_nothing);
2646 #define direct_unary_optab_supported_p direct_optab_supported_p
2647 #define direct_binary_optab_supported_p direct_optab_supported_p
2648 #define direct_mask_load_optab_supported_p direct_optab_supported_p
2649 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
2650 #define direct_mask_store_optab_supported_p direct_optab_supported_p
2651 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
2653 /* Return true if FN is supported for the types in TYPES when the
2654 optimization type is OPT_TYPE. The types are those associated with
2655 the "type0" and "type1" fields of FN's direct_internal_fn_info
2656 structure. */
2658 bool
2659 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
2660 optimization_type opt_type)
2662 switch (fn)
2664 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
2665 case IFN_##CODE: break;
2666 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2667 case IFN_##CODE: \
2668 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
2669 opt_type);
2670 #include "internal-fn.def"
2672 case IFN_LAST:
2673 break;
2675 gcc_unreachable ();
2678 /* Return true if FN is supported for type TYPE when the optimization
2679 type is OPT_TYPE. The caller knows that the "type0" and "type1"
2680 fields of FN's direct_internal_fn_info structure are the same. */
2682 bool
2683 direct_internal_fn_supported_p (internal_fn fn, tree type,
2684 optimization_type opt_type)
2686 const direct_internal_fn_info &info = direct_internal_fn (fn);
2687 gcc_checking_assert (info.type0 == info.type1);
2688 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
2691 /* Return true if IFN_SET_EDOM is supported. */
2693 bool
2694 set_edom_supported_p (void)
2696 #ifdef TARGET_EDOM
2697 return true;
2698 #else
2699 return false;
2700 #endif
2703 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2704 static void \
2705 expand_##CODE (internal_fn fn, gcall *stmt) \
2707 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
2709 #include "internal-fn.def"
2711 /* Routines to expand each internal function, indexed by function number.
2712 Each routine has the prototype:
2714 expand_<NAME> (gcall *stmt)
2716 where STMT is the statement that performs the call. */
2717 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
2718 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
2719 #include "internal-fn.def"
2723 /* Expand STMT as though it were a call to internal function FN. */
2725 void
2726 expand_internal_call (internal_fn fn, gcall *stmt)
2728 internal_fn_expanders[fn] (fn, stmt);
2731 /* Expand STMT, which is a call to internal function FN. */
2733 void
2734 expand_internal_call (gcall *stmt)
2736 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
2739 void
2740 expand_PHI (internal_fn, gcall *)
2742 gcc_unreachable ();