Use gather loads for strided accesses
[official-gcc.git] / gcc / internal-fn.c
blob8cf5b79c0289c1741ff5a5c9a40b0cb12e4cf96d
1 /* Internal functions.
2 Copyright (C) 2011-2018 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 "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"
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>"
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"
67 /* Fnspec of each internal function, indexed by function number. */
68 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
70 void
71 init_internal_fns ()
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;
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_load_lanes_direct { -1, -1, false }
86 #define gather_load_direct { -1, -1, false }
87 #define mask_store_direct { 3, 2, false }
88 #define store_lanes_direct { 0, 0, false }
89 #define mask_store_lanes_direct { 0, 0, false }
90 #define unary_direct { 0, 0, true }
91 #define binary_direct { 0, 0, true }
92 #define cond_unary_direct { 1, 1, true }
93 #define cond_binary_direct { 1, 1, true }
94 #define while_direct { 0, 2, false }
95 #define fold_extract_direct { 2, 2, false }
96 #define fold_left_direct { 1, 1, false }
98 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
99 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
100 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
101 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
102 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
103 #include "internal-fn.def"
104 not_direct
107 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
108 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
110 static enum insn_code
111 get_multi_vector_move (tree array_type, convert_optab optab)
113 machine_mode imode;
114 machine_mode vmode;
116 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
117 imode = TYPE_MODE (array_type);
118 vmode = TYPE_MODE (TREE_TYPE (array_type));
120 return convert_optab_handler (optab, imode, vmode);
123 /* Expand LOAD_LANES call STMT using optab OPTAB. */
125 static void
126 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
128 struct expand_operand ops[2];
129 tree type, lhs, rhs;
130 rtx target, mem;
132 lhs = gimple_call_lhs (stmt);
133 rhs = gimple_call_arg (stmt, 0);
134 type = TREE_TYPE (lhs);
136 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
137 mem = expand_normal (rhs);
139 gcc_assert (MEM_P (mem));
140 PUT_MODE (mem, TYPE_MODE (type));
142 create_output_operand (&ops[0], target, TYPE_MODE (type));
143 create_fixed_operand (&ops[1], mem);
144 expand_insn (get_multi_vector_move (type, optab), 2, ops);
147 /* Expand STORE_LANES call STMT using optab OPTAB. */
149 static void
150 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
152 struct expand_operand ops[2];
153 tree type, lhs, rhs;
154 rtx target, reg;
156 lhs = gimple_call_lhs (stmt);
157 rhs = gimple_call_arg (stmt, 0);
158 type = TREE_TYPE (rhs);
160 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
161 reg = expand_normal (rhs);
163 gcc_assert (MEM_P (target));
164 PUT_MODE (target, TYPE_MODE (type));
166 create_fixed_operand (&ops[0], target);
167 create_input_operand (&ops[1], reg, TYPE_MODE (type));
168 expand_insn (get_multi_vector_move (type, optab), 2, ops);
171 static void
172 expand_ANNOTATE (internal_fn, gcall *)
174 gcc_unreachable ();
177 /* This should get expanded in omp_device_lower pass. */
179 static void
180 expand_GOMP_USE_SIMT (internal_fn, gcall *)
182 gcc_unreachable ();
185 /* This should get expanded in omp_device_lower pass. */
187 static void
188 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
190 gcc_unreachable ();
193 /* Allocate per-lane storage and begin non-uniform execution region. */
195 static void
196 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
198 rtx target;
199 tree lhs = gimple_call_lhs (stmt);
200 if (lhs)
201 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
202 else
203 target = gen_reg_rtx (Pmode);
204 rtx size = expand_normal (gimple_call_arg (stmt, 0));
205 rtx align = expand_normal (gimple_call_arg (stmt, 1));
206 struct expand_operand ops[3];
207 create_output_operand (&ops[0], target, Pmode);
208 create_input_operand (&ops[1], size, Pmode);
209 create_input_operand (&ops[2], align, Pmode);
210 gcc_assert (targetm.have_omp_simt_enter ());
211 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
214 /* Deallocate per-lane storage and leave non-uniform execution region. */
216 static void
217 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
219 gcc_checking_assert (!gimple_call_lhs (stmt));
220 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
221 struct expand_operand ops[1];
222 create_input_operand (&ops[0], arg, Pmode);
223 gcc_assert (targetm.have_omp_simt_exit ());
224 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
227 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
228 without SIMT execution this should be expanded in omp_device_lower pass. */
230 static void
231 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
233 tree lhs = gimple_call_lhs (stmt);
234 if (!lhs)
235 return;
237 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
238 gcc_assert (targetm.have_omp_simt_lane ());
239 emit_insn (targetm.gen_omp_simt_lane (target));
242 /* This should get expanded in omp_device_lower pass. */
244 static void
245 expand_GOMP_SIMT_VF (internal_fn, gcall *)
247 gcc_unreachable ();
250 /* Lane index of the first SIMT lane that supplies a non-zero argument.
251 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
252 lane that executed the last iteration for handling OpenMP lastprivate. */
254 static void
255 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
257 tree lhs = gimple_call_lhs (stmt);
258 if (!lhs)
259 return;
261 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
262 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
263 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
264 struct expand_operand ops[2];
265 create_output_operand (&ops[0], target, mode);
266 create_input_operand (&ops[1], cond, mode);
267 gcc_assert (targetm.have_omp_simt_last_lane ());
268 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
271 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
273 static void
274 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
276 tree lhs = gimple_call_lhs (stmt);
277 if (!lhs)
278 return;
280 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
281 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
282 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
283 struct expand_operand ops[2];
284 create_output_operand (&ops[0], target, mode);
285 create_input_operand (&ops[1], ctr, mode);
286 gcc_assert (targetm.have_omp_simt_ordered ());
287 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
290 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
291 any lane supplies a non-zero argument. */
293 static void
294 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
296 tree lhs = gimple_call_lhs (stmt);
297 if (!lhs)
298 return;
300 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
301 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
302 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
303 struct expand_operand ops[2];
304 create_output_operand (&ops[0], target, mode);
305 create_input_operand (&ops[1], cond, mode);
306 gcc_assert (targetm.have_omp_simt_vote_any ());
307 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
310 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
311 is destination lane index XOR given offset. */
313 static void
314 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
316 tree lhs = gimple_call_lhs (stmt);
317 if (!lhs)
318 return;
320 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
321 rtx src = expand_normal (gimple_call_arg (stmt, 0));
322 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
323 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
324 struct expand_operand ops[3];
325 create_output_operand (&ops[0], target, mode);
326 create_input_operand (&ops[1], src, mode);
327 create_input_operand (&ops[2], idx, SImode);
328 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
329 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
332 /* Exchange between SIMT lanes according to given source lane index. */
334 static void
335 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
337 tree lhs = gimple_call_lhs (stmt);
338 if (!lhs)
339 return;
341 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
342 rtx src = expand_normal (gimple_call_arg (stmt, 0));
343 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
344 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
345 struct expand_operand ops[3];
346 create_output_operand (&ops[0], target, mode);
347 create_input_operand (&ops[1], src, mode);
348 create_input_operand (&ops[2], idx, SImode);
349 gcc_assert (targetm.have_omp_simt_xchg_idx ());
350 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
353 /* This should get expanded in adjust_simduid_builtins. */
355 static void
356 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
358 gcc_unreachable ();
361 /* This should get expanded in adjust_simduid_builtins. */
363 static void
364 expand_GOMP_SIMD_VF (internal_fn, gcall *)
366 gcc_unreachable ();
369 /* This should get expanded in adjust_simduid_builtins. */
371 static void
372 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
374 gcc_unreachable ();
377 /* This should get expanded in adjust_simduid_builtins. */
379 static void
380 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
382 gcc_unreachable ();
385 /* This should get expanded in adjust_simduid_builtins. */
387 static void
388 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
390 gcc_unreachable ();
393 /* This should get expanded in the sanopt pass. */
395 static void
396 expand_UBSAN_NULL (internal_fn, gcall *)
398 gcc_unreachable ();
401 /* This should get expanded in the sanopt pass. */
403 static void
404 expand_UBSAN_BOUNDS (internal_fn, gcall *)
406 gcc_unreachable ();
409 /* This should get expanded in the sanopt pass. */
411 static void
412 expand_UBSAN_VPTR (internal_fn, gcall *)
414 gcc_unreachable ();
417 /* This should get expanded in the sanopt pass. */
419 static void
420 expand_UBSAN_PTR (internal_fn, gcall *)
422 gcc_unreachable ();
425 /* This should get expanded in the sanopt pass. */
427 static void
428 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
430 gcc_unreachable ();
433 /* This should get expanded in the sanopt pass. */
435 static void
436 expand_ASAN_CHECK (internal_fn, gcall *)
438 gcc_unreachable ();
441 /* This should get expanded in the sanopt pass. */
443 static void
444 expand_ASAN_MARK (internal_fn, gcall *)
446 gcc_unreachable ();
449 /* This should get expanded in the sanopt pass. */
451 static void
452 expand_ASAN_POISON (internal_fn, gcall *)
454 gcc_unreachable ();
457 /* This should get expanded in the sanopt pass. */
459 static void
460 expand_ASAN_POISON_USE (internal_fn, gcall *)
462 gcc_unreachable ();
465 /* This should get expanded in the tsan pass. */
467 static void
468 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
470 gcc_unreachable ();
473 /* This should get expanded in the lower pass. */
475 static void
476 expand_FALLTHROUGH (internal_fn, gcall *call)
478 error_at (gimple_location (call),
479 "invalid use of attribute %<fallthrough%>");
482 /* Return minimum precision needed to represent all values
483 of ARG in SIGNed integral type. */
485 static int
486 get_min_precision (tree arg, signop sign)
488 int prec = TYPE_PRECISION (TREE_TYPE (arg));
489 int cnt = 0;
490 signop orig_sign = sign;
491 if (TREE_CODE (arg) == INTEGER_CST)
493 int p;
494 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
496 widest_int w = wi::to_widest (arg);
497 w = wi::ext (w, prec, sign);
498 p = wi::min_precision (w, sign);
500 else
501 p = wi::min_precision (wi::to_wide (arg), sign);
502 return MIN (p, prec);
504 while (CONVERT_EXPR_P (arg)
505 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
506 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
508 arg = TREE_OPERAND (arg, 0);
509 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
511 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
512 sign = UNSIGNED;
513 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
514 return prec + (orig_sign != sign);
515 prec = TYPE_PRECISION (TREE_TYPE (arg));
517 if (++cnt > 30)
518 return prec + (orig_sign != sign);
520 if (TREE_CODE (arg) != SSA_NAME)
521 return prec + (orig_sign != sign);
522 wide_int arg_min, arg_max;
523 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
525 gimple *g = SSA_NAME_DEF_STMT (arg);
526 if (is_gimple_assign (g)
527 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
529 tree t = gimple_assign_rhs1 (g);
530 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
531 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
533 arg = t;
534 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
536 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
537 sign = UNSIGNED;
538 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
539 return prec + (orig_sign != sign);
540 prec = TYPE_PRECISION (TREE_TYPE (arg));
542 if (++cnt > 30)
543 return prec + (orig_sign != sign);
544 continue;
547 return prec + (orig_sign != sign);
549 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
551 int p1 = wi::min_precision (arg_min, sign);
552 int p2 = wi::min_precision (arg_max, sign);
553 p1 = MAX (p1, p2);
554 prec = MIN (prec, p1);
556 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
558 int p = wi::min_precision (arg_max, UNSIGNED);
559 prec = MIN (prec, p);
561 return prec + (orig_sign != sign);
564 /* Helper for expand_*_overflow. Set the __imag__ part to true
565 (1 except for signed:1 type, in which case store -1). */
567 static void
568 expand_arith_set_overflow (tree lhs, rtx target)
570 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
571 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
572 write_complex_part (target, constm1_rtx, true);
573 else
574 write_complex_part (target, const1_rtx, true);
577 /* Helper for expand_*_overflow. Store RES into the __real__ part
578 of TARGET. If RES has larger MODE than __real__ part of TARGET,
579 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
580 if LHS has smaller precision than its mode. */
582 static void
583 expand_arith_overflow_result_store (tree lhs, rtx target,
584 scalar_int_mode mode, rtx res)
586 scalar_int_mode tgtmode
587 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
588 rtx lres = res;
589 if (tgtmode != mode)
591 rtx_code_label *done_label = gen_label_rtx ();
592 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
593 lres = convert_modes (tgtmode, mode, res, uns);
594 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
595 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
596 EQ, true, mode, NULL_RTX, NULL, done_label,
597 profile_probability::very_likely ());
598 expand_arith_set_overflow (lhs, target);
599 emit_label (done_label);
601 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
602 int tgtprec = GET_MODE_PRECISION (tgtmode);
603 if (prec < tgtprec)
605 rtx_code_label *done_label = gen_label_rtx ();
606 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
607 res = lres;
608 if (uns)
610 rtx mask
611 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
612 tgtmode);
613 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
614 true, OPTAB_LIB_WIDEN);
616 else
618 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
619 NULL_RTX, 1);
620 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
621 NULL_RTX, 0);
623 do_compare_rtx_and_jump (res, lres,
624 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
625 profile_probability::very_likely ());
626 expand_arith_set_overflow (lhs, target);
627 emit_label (done_label);
629 write_complex_part (target, lres, false);
632 /* Helper for expand_*_overflow. Store RES into TARGET. */
634 static void
635 expand_ubsan_result_store (rtx target, rtx res)
637 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
638 /* If this is a scalar in a register that is stored in a wider mode
639 than the declared mode, compute the result into its declared mode
640 and then convert to the wider mode. Our value is the computed
641 expression. */
642 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
643 else
644 emit_move_insn (target, res);
647 /* Add sub/add overflow checking to the statement STMT.
648 CODE says whether the operation is +, or -. */
650 static void
651 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
652 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
653 bool uns1_p, bool is_ubsan, tree *datap)
655 rtx res, target = NULL_RTX;
656 tree fn;
657 rtx_code_label *done_label = gen_label_rtx ();
658 rtx_code_label *do_error = gen_label_rtx ();
659 do_pending_stack_adjust ();
660 rtx op0 = expand_normal (arg0);
661 rtx op1 = expand_normal (arg1);
662 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
663 int prec = GET_MODE_PRECISION (mode);
664 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
665 bool do_xor = false;
667 if (is_ubsan)
668 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
670 if (lhs)
672 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
673 if (!is_ubsan)
674 write_complex_part (target, const0_rtx, true);
677 /* We assume both operands and result have the same precision
678 here (GET_MODE_BITSIZE (mode)), S stands for signed type
679 with that precision, U for unsigned type with that precision,
680 sgn for unsigned most significant bit in that precision.
681 s1 is signed first operand, u1 is unsigned first operand,
682 s2 is signed second operand, u2 is unsigned second operand,
683 sr is signed result, ur is unsigned result and the following
684 rules say how to compute result (which is always result of
685 the operands as if both were unsigned, cast to the right
686 signedness) and how to compute whether operation overflowed.
688 s1 + s2 -> sr
689 res = (S) ((U) s1 + (U) s2)
690 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
691 s1 - s2 -> sr
692 res = (S) ((U) s1 - (U) s2)
693 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
694 u1 + u2 -> ur
695 res = u1 + u2
696 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
697 u1 - u2 -> ur
698 res = u1 - u2
699 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
700 s1 + u2 -> sr
701 res = (S) ((U) s1 + u2)
702 ovf = ((U) res ^ sgn) < u2
703 s1 + u2 -> ur
704 t1 = (S) (u2 ^ sgn)
705 t2 = s1 + t1
706 res = (U) t2 ^ sgn
707 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
708 s1 - u2 -> sr
709 res = (S) ((U) s1 - u2)
710 ovf = u2 > ((U) s1 ^ sgn)
711 s1 - u2 -> ur
712 res = (U) s1 - u2
713 ovf = s1 < 0 || u2 > (U) s1
714 u1 - s2 -> sr
715 res = u1 - (U) s2
716 ovf = u1 >= ((U) s2 ^ sgn)
717 u1 - s2 -> ur
718 t1 = u1 ^ sgn
719 t2 = t1 - (U) s2
720 res = t2 ^ sgn
721 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
722 s1 + s2 -> ur
723 res = (U) s1 + (U) s2
724 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
725 u1 + u2 -> sr
726 res = (S) (u1 + u2)
727 ovf = (U) res < u2 || res < 0
728 u1 - u2 -> sr
729 res = (S) (u1 - u2)
730 ovf = u1 >= u2 ? res < 0 : res >= 0
731 s1 - s2 -> ur
732 res = (U) s1 - (U) s2
733 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
735 if (code == PLUS_EXPR && uns0_p && !uns1_p)
737 /* PLUS_EXPR is commutative, if operand signedness differs,
738 canonicalize to the first operand being signed and second
739 unsigned to simplify following code. */
740 std::swap (op0, op1);
741 std::swap (arg0, arg1);
742 uns0_p = false;
743 uns1_p = true;
746 /* u1 +- u2 -> ur */
747 if (uns0_p && uns1_p && unsr_p)
749 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
750 : usubv4_optab, mode);
751 if (icode != CODE_FOR_nothing)
753 struct expand_operand ops[4];
754 rtx_insn *last = get_last_insn ();
756 res = gen_reg_rtx (mode);
757 create_output_operand (&ops[0], res, mode);
758 create_input_operand (&ops[1], op0, mode);
759 create_input_operand (&ops[2], op1, mode);
760 create_fixed_operand (&ops[3], do_error);
761 if (maybe_expand_insn (icode, 4, ops))
763 last = get_last_insn ();
764 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
765 && JUMP_P (last)
766 && any_condjump_p (last)
767 && !find_reg_note (last, REG_BR_PROB, 0))
768 add_reg_br_prob_note (last,
769 profile_probability::very_unlikely ());
770 emit_jump (done_label);
771 goto do_error_label;
774 delete_insns_since (last);
777 /* Compute the operation. On RTL level, the addition is always
778 unsigned. */
779 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
780 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
781 rtx tem = op0;
782 /* For PLUS_EXPR, the operation is commutative, so we can pick
783 operand to compare against. For prec <= BITS_PER_WORD, I think
784 preferring REG operand is better over CONST_INT, because
785 the CONST_INT might enlarge the instruction or CSE would need
786 to figure out we'd already loaded it into a register before.
787 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
788 as then the multi-word comparison can be perhaps simplified. */
789 if (code == PLUS_EXPR
790 && (prec <= BITS_PER_WORD
791 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
792 : CONST_SCALAR_INT_P (op1)))
793 tem = op1;
794 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
795 true, mode, NULL_RTX, NULL, done_label,
796 profile_probability::very_likely ());
797 goto do_error_label;
800 /* s1 +- u2 -> sr */
801 if (!uns0_p && uns1_p && !unsr_p)
803 /* Compute the operation. On RTL level, the addition is always
804 unsigned. */
805 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
806 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
807 rtx tem = expand_binop (mode, add_optab,
808 code == PLUS_EXPR ? res : op0, sgn,
809 NULL_RTX, false, OPTAB_LIB_WIDEN);
810 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
811 done_label, profile_probability::very_likely ());
812 goto do_error_label;
815 /* s1 + u2 -> ur */
816 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
818 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
819 OPTAB_LIB_WIDEN);
820 /* As we've changed op1, we have to avoid using the value range
821 for the original argument. */
822 arg1 = error_mark_node;
823 do_xor = true;
824 goto do_signed;
827 /* u1 - s2 -> ur */
828 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
830 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
831 OPTAB_LIB_WIDEN);
832 /* As we've changed op0, we have to avoid using the value range
833 for the original argument. */
834 arg0 = error_mark_node;
835 do_xor = true;
836 goto do_signed;
839 /* s1 - u2 -> ur */
840 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
842 /* Compute the operation. On RTL level, the addition is always
843 unsigned. */
844 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
845 OPTAB_LIB_WIDEN);
846 int pos_neg = get_range_pos_neg (arg0);
847 if (pos_neg == 2)
848 /* If ARG0 is known to be always negative, this is always overflow. */
849 emit_jump (do_error);
850 else if (pos_neg == 3)
851 /* If ARG0 is not known to be always positive, check at runtime. */
852 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
853 NULL, do_error, profile_probability::very_unlikely ());
854 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
855 done_label, profile_probability::very_likely ());
856 goto do_error_label;
859 /* u1 - s2 -> sr */
860 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
862 /* Compute the operation. On RTL level, the addition is always
863 unsigned. */
864 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
865 OPTAB_LIB_WIDEN);
866 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
867 OPTAB_LIB_WIDEN);
868 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
869 done_label, profile_probability::very_likely ());
870 goto do_error_label;
873 /* u1 + u2 -> sr */
874 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
876 /* Compute the operation. On RTL level, the addition is always
877 unsigned. */
878 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
879 OPTAB_LIB_WIDEN);
880 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
881 NULL, do_error, profile_probability::very_unlikely ());
882 rtx tem = op1;
883 /* The operation is commutative, so we can pick operand to compare
884 against. For prec <= BITS_PER_WORD, I think preferring REG operand
885 is better over CONST_INT, because the CONST_INT might enlarge the
886 instruction or CSE would need to figure out we'd already loaded it
887 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
888 might be more beneficial, as then the multi-word comparison can be
889 perhaps simplified. */
890 if (prec <= BITS_PER_WORD
891 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
892 : CONST_SCALAR_INT_P (op0))
893 tem = op0;
894 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
895 done_label, profile_probability::very_likely ());
896 goto do_error_label;
899 /* s1 +- s2 -> ur */
900 if (!uns0_p && !uns1_p && unsr_p)
902 /* Compute the operation. On RTL level, the addition is always
903 unsigned. */
904 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
905 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
906 int pos_neg = get_range_pos_neg (arg1);
907 if (code == PLUS_EXPR)
909 int pos_neg0 = get_range_pos_neg (arg0);
910 if (pos_neg0 != 3 && pos_neg == 3)
912 std::swap (op0, op1);
913 pos_neg = pos_neg0;
916 rtx tem;
917 if (pos_neg != 3)
919 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
920 ? and_optab : ior_optab,
921 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
922 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
923 NULL, done_label, profile_probability::very_likely ());
925 else
927 rtx_code_label *do_ior_label = gen_label_rtx ();
928 do_compare_rtx_and_jump (op1, const0_rtx,
929 code == MINUS_EXPR ? GE : LT, false, mode,
930 NULL_RTX, NULL, do_ior_label,
931 profile_probability::even ());
932 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
933 OPTAB_LIB_WIDEN);
934 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
935 NULL, done_label, profile_probability::very_likely ());
936 emit_jump (do_error);
937 emit_label (do_ior_label);
938 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
939 OPTAB_LIB_WIDEN);
940 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
941 NULL, done_label, profile_probability::very_likely ());
943 goto do_error_label;
946 /* u1 - u2 -> sr */
947 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
949 /* Compute the operation. On RTL level, the addition is always
950 unsigned. */
951 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
952 OPTAB_LIB_WIDEN);
953 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
954 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
955 op0_geu_op1, profile_probability::even ());
956 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
957 NULL, done_label, profile_probability::very_likely ());
958 emit_jump (do_error);
959 emit_label (op0_geu_op1);
960 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
961 NULL, done_label, profile_probability::very_likely ());
962 goto do_error_label;
965 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
967 /* s1 +- s2 -> sr */
968 do_signed:
970 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
971 : subv4_optab, mode);
972 if (icode != CODE_FOR_nothing)
974 struct expand_operand ops[4];
975 rtx_insn *last = get_last_insn ();
977 res = gen_reg_rtx (mode);
978 create_output_operand (&ops[0], res, mode);
979 create_input_operand (&ops[1], op0, mode);
980 create_input_operand (&ops[2], op1, mode);
981 create_fixed_operand (&ops[3], do_error);
982 if (maybe_expand_insn (icode, 4, ops))
984 last = get_last_insn ();
985 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
986 && JUMP_P (last)
987 && any_condjump_p (last)
988 && !find_reg_note (last, REG_BR_PROB, 0))
989 add_reg_br_prob_note (last,
990 profile_probability::very_unlikely ());
991 emit_jump (done_label);
992 goto do_error_label;
995 delete_insns_since (last);
998 /* Compute the operation. On RTL level, the addition is always
999 unsigned. */
1000 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1001 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1003 /* If we can prove that one of the arguments (for MINUS_EXPR only
1004 the second operand, as subtraction is not commutative) is always
1005 non-negative or always negative, we can do just one comparison
1006 and conditional jump. */
1007 int pos_neg = get_range_pos_neg (arg1);
1008 if (code == PLUS_EXPR)
1010 int pos_neg0 = get_range_pos_neg (arg0);
1011 if (pos_neg0 != 3 && pos_neg == 3)
1013 std::swap (op0, op1);
1014 pos_neg = pos_neg0;
1018 /* Addition overflows if and only if the two operands have the same sign,
1019 and the result has the opposite sign. Subtraction overflows if and
1020 only if the two operands have opposite sign, and the subtrahend has
1021 the same sign as the result. Here 0 is counted as positive. */
1022 if (pos_neg == 3)
1024 /* Compute op0 ^ op1 (operands have opposite sign). */
1025 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1026 OPTAB_LIB_WIDEN);
1028 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1029 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1030 OPTAB_LIB_WIDEN);
1032 rtx tem;
1033 if (code == PLUS_EXPR)
1035 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1036 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1037 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1038 OPTAB_LIB_WIDEN);
1040 else
1042 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1043 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1044 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1045 OPTAB_LIB_WIDEN);
1048 /* No overflow if the result has bit sign cleared. */
1049 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1050 NULL, done_label, profile_probability::very_likely ());
1053 /* Compare the result of the operation with the first operand.
1054 No overflow for addition if second operand is positive and result
1055 is larger or second operand is negative and result is smaller.
1056 Likewise for subtraction with sign of second operand flipped. */
1057 else
1058 do_compare_rtx_and_jump (res, op0,
1059 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1060 false, mode, NULL_RTX, NULL, done_label,
1061 profile_probability::very_likely ());
1064 do_error_label:
1065 emit_label (do_error);
1066 if (is_ubsan)
1068 /* Expand the ubsan builtin call. */
1069 push_temp_slots ();
1070 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1071 arg0, arg1, datap);
1072 expand_normal (fn);
1073 pop_temp_slots ();
1074 do_pending_stack_adjust ();
1076 else if (lhs)
1077 expand_arith_set_overflow (lhs, target);
1079 /* We're done. */
1080 emit_label (done_label);
1082 if (lhs)
1084 if (is_ubsan)
1085 expand_ubsan_result_store (target, res);
1086 else
1088 if (do_xor)
1089 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1090 OPTAB_LIB_WIDEN);
1092 expand_arith_overflow_result_store (lhs, target, mode, res);
1097 /* Add negate overflow checking to the statement STMT. */
1099 static void
1100 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1101 tree *datap)
1103 rtx res, op1;
1104 tree fn;
1105 rtx_code_label *done_label, *do_error;
1106 rtx target = NULL_RTX;
1108 done_label = gen_label_rtx ();
1109 do_error = gen_label_rtx ();
1111 do_pending_stack_adjust ();
1112 op1 = expand_normal (arg1);
1114 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1115 if (lhs)
1117 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1118 if (!is_ubsan)
1119 write_complex_part (target, const0_rtx, true);
1122 enum insn_code icode = optab_handler (negv3_optab, mode);
1123 if (icode != CODE_FOR_nothing)
1125 struct expand_operand ops[3];
1126 rtx_insn *last = get_last_insn ();
1128 res = gen_reg_rtx (mode);
1129 create_output_operand (&ops[0], res, mode);
1130 create_input_operand (&ops[1], op1, mode);
1131 create_fixed_operand (&ops[2], do_error);
1132 if (maybe_expand_insn (icode, 3, ops))
1134 last = get_last_insn ();
1135 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1136 && JUMP_P (last)
1137 && any_condjump_p (last)
1138 && !find_reg_note (last, REG_BR_PROB, 0))
1139 add_reg_br_prob_note (last,
1140 profile_probability::very_unlikely ());
1141 emit_jump (done_label);
1143 else
1145 delete_insns_since (last);
1146 icode = CODE_FOR_nothing;
1150 if (icode == CODE_FOR_nothing)
1152 /* Compute the operation. On RTL level, the addition is always
1153 unsigned. */
1154 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1156 /* Compare the operand with the most negative value. */
1157 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1158 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1159 done_label, profile_probability::very_likely ());
1162 emit_label (do_error);
1163 if (is_ubsan)
1165 /* Expand the ubsan builtin call. */
1166 push_temp_slots ();
1167 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1168 arg1, NULL_TREE, datap);
1169 expand_normal (fn);
1170 pop_temp_slots ();
1171 do_pending_stack_adjust ();
1173 else if (lhs)
1174 expand_arith_set_overflow (lhs, target);
1176 /* We're done. */
1177 emit_label (done_label);
1179 if (lhs)
1181 if (is_ubsan)
1182 expand_ubsan_result_store (target, res);
1183 else
1184 expand_arith_overflow_result_store (lhs, target, mode, res);
1188 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1189 mode MODE can be expanded without using a libcall. */
1191 static bool
1192 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1193 rtx op0, rtx op1, bool uns)
1195 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1196 != CODE_FOR_nothing)
1197 return true;
1199 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1200 != CODE_FOR_nothing)
1201 return true;
1203 rtx_insn *last = get_last_insn ();
1204 if (CONSTANT_P (op0))
1205 op0 = convert_modes (wmode, mode, op0, uns);
1206 else
1207 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1208 if (CONSTANT_P (op1))
1209 op1 = convert_modes (wmode, mode, op1, uns);
1210 else
1211 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1212 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1213 delete_insns_since (last);
1214 return ret != NULL_RTX;
1217 /* Add mul overflow checking to the statement STMT. */
1219 static void
1220 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1221 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1222 tree *datap)
1224 rtx res, op0, op1;
1225 tree fn, type;
1226 rtx_code_label *done_label, *do_error;
1227 rtx target = NULL_RTX;
1228 signop sign;
1229 enum insn_code icode;
1231 done_label = gen_label_rtx ();
1232 do_error = gen_label_rtx ();
1234 do_pending_stack_adjust ();
1235 op0 = expand_normal (arg0);
1236 op1 = expand_normal (arg1);
1238 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1239 bool uns = unsr_p;
1240 if (lhs)
1242 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1243 if (!is_ubsan)
1244 write_complex_part (target, const0_rtx, true);
1247 if (is_ubsan)
1248 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1250 /* We assume both operands and result have the same precision
1251 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1252 with that precision, U for unsigned type with that precision,
1253 sgn for unsigned most significant bit in that precision.
1254 s1 is signed first operand, u1 is unsigned first operand,
1255 s2 is signed second operand, u2 is unsigned second operand,
1256 sr is signed result, ur is unsigned result and the following
1257 rules say how to compute result (which is always result of
1258 the operands as if both were unsigned, cast to the right
1259 signedness) and how to compute whether operation overflowed.
1260 main_ovf (false) stands for jump on signed multiplication
1261 overflow or the main algorithm with uns == false.
1262 main_ovf (true) stands for jump on unsigned multiplication
1263 overflow or the main algorithm with uns == true.
1265 s1 * s2 -> sr
1266 res = (S) ((U) s1 * (U) s2)
1267 ovf = main_ovf (false)
1268 u1 * u2 -> ur
1269 res = u1 * u2
1270 ovf = main_ovf (true)
1271 s1 * u2 -> ur
1272 res = (U) s1 * u2
1273 ovf = (s1 < 0 && u2) || main_ovf (true)
1274 u1 * u2 -> sr
1275 res = (S) (u1 * u2)
1276 ovf = res < 0 || main_ovf (true)
1277 s1 * u2 -> sr
1278 res = (S) ((U) s1 * u2)
1279 ovf = (S) u2 >= 0 ? main_ovf (false)
1280 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1281 s1 * s2 -> ur
1282 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1283 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1284 res = t1 * t2
1285 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1287 if (uns0_p && !uns1_p)
1289 /* Multiplication is commutative, if operand signedness differs,
1290 canonicalize to the first operand being signed and second
1291 unsigned to simplify following code. */
1292 std::swap (op0, op1);
1293 std::swap (arg0, arg1);
1294 uns0_p = false;
1295 uns1_p = true;
1298 int pos_neg0 = get_range_pos_neg (arg0);
1299 int pos_neg1 = get_range_pos_neg (arg1);
1301 /* s1 * u2 -> ur */
1302 if (!uns0_p && uns1_p && unsr_p)
1304 switch (pos_neg0)
1306 case 1:
1307 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1308 goto do_main;
1309 case 2:
1310 /* If s1 is negative, avoid the main code, just multiply and
1311 signal overflow if op1 is not 0. */
1312 struct separate_ops ops;
1313 ops.code = MULT_EXPR;
1314 ops.type = TREE_TYPE (arg1);
1315 ops.op0 = make_tree (ops.type, op0);
1316 ops.op1 = make_tree (ops.type, op1);
1317 ops.op2 = NULL_TREE;
1318 ops.location = loc;
1319 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1320 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1321 NULL, done_label, profile_probability::very_likely ());
1322 goto do_error_label;
1323 case 3:
1324 rtx_code_label *do_main_label;
1325 do_main_label = gen_label_rtx ();
1326 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1327 NULL, do_main_label, profile_probability::very_likely ());
1328 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1329 NULL, do_main_label, profile_probability::very_likely ());
1330 expand_arith_set_overflow (lhs, target);
1331 emit_label (do_main_label);
1332 goto do_main;
1333 default:
1334 gcc_unreachable ();
1338 /* u1 * u2 -> sr */
1339 if (uns0_p && uns1_p && !unsr_p)
1341 uns = true;
1342 /* Rest of handling of this case after res is computed. */
1343 goto do_main;
1346 /* s1 * u2 -> sr */
1347 if (!uns0_p && uns1_p && !unsr_p)
1349 switch (pos_neg1)
1351 case 1:
1352 goto do_main;
1353 case 2:
1354 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1355 avoid the main code, just multiply and signal overflow
1356 unless 0 * u2 or -1 * ((U) Smin). */
1357 struct separate_ops ops;
1358 ops.code = MULT_EXPR;
1359 ops.type = TREE_TYPE (arg1);
1360 ops.op0 = make_tree (ops.type, op0);
1361 ops.op1 = make_tree (ops.type, op1);
1362 ops.op2 = NULL_TREE;
1363 ops.location = loc;
1364 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1365 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1366 NULL, done_label, profile_probability::very_likely ());
1367 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1368 NULL, do_error, profile_probability::very_unlikely ());
1369 int prec;
1370 prec = GET_MODE_PRECISION (mode);
1371 rtx sgn;
1372 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1373 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1374 NULL, done_label, profile_probability::very_likely ());
1375 goto do_error_label;
1376 case 3:
1377 /* Rest of handling of this case after res is computed. */
1378 goto do_main;
1379 default:
1380 gcc_unreachable ();
1384 /* s1 * s2 -> ur */
1385 if (!uns0_p && !uns1_p && unsr_p)
1387 rtx tem, tem2;
1388 switch (pos_neg0 | pos_neg1)
1390 case 1: /* Both operands known to be non-negative. */
1391 goto do_main;
1392 case 2: /* Both operands known to be negative. */
1393 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1394 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1395 /* Avoid looking at arg0/arg1 ranges, as we've changed
1396 the arguments. */
1397 arg0 = error_mark_node;
1398 arg1 = error_mark_node;
1399 goto do_main;
1400 case 3:
1401 if ((pos_neg0 ^ pos_neg1) == 3)
1403 /* If one operand is known to be negative and the other
1404 non-negative, this overflows always, unless the non-negative
1405 one is 0. Just do normal multiply and set overflow
1406 unless one of the operands is 0. */
1407 struct separate_ops ops;
1408 ops.code = MULT_EXPR;
1409 ops.type
1410 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1412 ops.op0 = make_tree (ops.type, op0);
1413 ops.op1 = make_tree (ops.type, op1);
1414 ops.op2 = NULL_TREE;
1415 ops.location = loc;
1416 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1417 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1418 OPTAB_LIB_WIDEN);
1419 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1420 NULL_RTX, NULL, done_label,
1421 profile_probability::very_likely ());
1422 goto do_error_label;
1424 /* The general case, do all the needed comparisons at runtime. */
1425 rtx_code_label *do_main_label, *after_negate_label;
1426 rtx rop0, rop1;
1427 rop0 = gen_reg_rtx (mode);
1428 rop1 = gen_reg_rtx (mode);
1429 emit_move_insn (rop0, op0);
1430 emit_move_insn (rop1, op1);
1431 op0 = rop0;
1432 op1 = rop1;
1433 do_main_label = gen_label_rtx ();
1434 after_negate_label = gen_label_rtx ();
1435 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1436 OPTAB_LIB_WIDEN);
1437 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1438 NULL, after_negate_label, profile_probability::very_likely ());
1439 /* Both arguments negative here, negate them and continue with
1440 normal unsigned overflow checking multiplication. */
1441 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1442 NULL_RTX, false));
1443 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1444 NULL_RTX, false));
1445 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1446 the arguments. */
1447 arg0 = error_mark_node;
1448 arg1 = error_mark_node;
1449 emit_jump (do_main_label);
1450 emit_label (after_negate_label);
1451 tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1452 OPTAB_LIB_WIDEN);
1453 do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1454 NULL, do_main_label, profile_probability::very_likely ());
1455 /* One argument is negative here, the other positive. This
1456 overflows always, unless one of the arguments is 0. But
1457 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1458 is, thus we can keep do_main code oring in overflow as is. */
1459 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1460 NULL, do_main_label, profile_probability::very_likely ());
1461 expand_arith_set_overflow (lhs, target);
1462 emit_label (do_main_label);
1463 goto do_main;
1464 default:
1465 gcc_unreachable ();
1469 do_main:
1470 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1471 sign = uns ? UNSIGNED : SIGNED;
1472 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1473 if (uns
1474 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1475 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1477 /* Optimize unsigned multiplication by power of 2 constant
1478 using 2 shifts, one for result, one to extract the shifted
1479 out bits to see if they are all zero.
1480 Don't do this if optimizing for size and we have umulv4_optab,
1481 in that case assume multiplication will be shorter.
1482 This is heuristics based on the single target that provides
1483 umulv4 right now (i?86/x86_64), if further targets add it, this
1484 might need to be revisited.
1485 Cases where both operands are constant should be folded already
1486 during GIMPLE, and cases where one operand is constant but not
1487 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1488 below can be done without multiplication, just by shifts and adds,
1489 or we'd need to divide the result (and hope it actually doesn't
1490 really divide nor multiply) and compare the result of the division
1491 with the original operand. */
1492 rtx opn0 = op0;
1493 rtx opn1 = op1;
1494 tree argn0 = arg0;
1495 tree argn1 = arg1;
1496 if (integer_pow2p (arg0))
1498 std::swap (opn0, opn1);
1499 std::swap (argn0, argn1);
1501 int cnt = tree_log2 (argn1);
1502 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1504 rtx upper = const0_rtx;
1505 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1506 if (cnt != 0)
1507 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1508 GET_MODE_PRECISION (mode) - cnt,
1509 NULL_RTX, uns);
1510 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1511 NULL_RTX, NULL, done_label,
1512 profile_probability::very_likely ());
1513 goto do_error_label;
1516 if (icode != CODE_FOR_nothing)
1518 struct expand_operand ops[4];
1519 rtx_insn *last = get_last_insn ();
1521 res = gen_reg_rtx (mode);
1522 create_output_operand (&ops[0], res, mode);
1523 create_input_operand (&ops[1], op0, mode);
1524 create_input_operand (&ops[2], op1, mode);
1525 create_fixed_operand (&ops[3], do_error);
1526 if (maybe_expand_insn (icode, 4, ops))
1528 last = get_last_insn ();
1529 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1530 && JUMP_P (last)
1531 && any_condjump_p (last)
1532 && !find_reg_note (last, REG_BR_PROB, 0))
1533 add_reg_br_prob_note (last,
1534 profile_probability::very_unlikely ());
1535 emit_jump (done_label);
1537 else
1539 delete_insns_since (last);
1540 icode = CODE_FOR_nothing;
1544 if (icode == CODE_FOR_nothing)
1546 struct separate_ops ops;
1547 int prec = GET_MODE_PRECISION (mode);
1548 scalar_int_mode hmode, wmode;
1549 ops.op0 = make_tree (type, op0);
1550 ops.op1 = make_tree (type, op1);
1551 ops.op2 = NULL_TREE;
1552 ops.location = loc;
1554 /* Optimize unsigned overflow check where we don't use the
1555 multiplication result, just whether overflow happened.
1556 If we can do MULT_HIGHPART_EXPR, that followed by
1557 comparison of the result against zero is cheapest.
1558 We'll still compute res, but it should be DCEd later. */
1559 use_operand_p use;
1560 gimple *use_stmt;
1561 if (!is_ubsan
1562 && lhs
1563 && uns
1564 && !(uns0_p && uns1_p && !unsr_p)
1565 && can_mult_highpart_p (mode, uns) == 1
1566 && single_imm_use (lhs, &use, &use_stmt)
1567 && is_gimple_assign (use_stmt)
1568 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1569 goto highpart;
1571 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1572 && targetm.scalar_mode_supported_p (wmode)
1573 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1575 twoxwider:
1576 ops.code = WIDEN_MULT_EXPR;
1577 ops.type
1578 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1580 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1581 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1582 NULL_RTX, uns);
1583 hipart = convert_modes (mode, wmode, hipart, uns);
1584 res = convert_modes (mode, wmode, res, uns);
1585 if (uns)
1586 /* For the unsigned multiplication, there was overflow if
1587 HIPART is non-zero. */
1588 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1589 NULL_RTX, NULL, done_label,
1590 profile_probability::very_likely ());
1591 else
1593 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1594 NULL_RTX, 0);
1595 /* RES is low half of the double width result, HIPART
1596 the high half. There was overflow if
1597 HIPART is different from RES < 0 ? -1 : 0. */
1598 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1599 NULL_RTX, NULL, done_label,
1600 profile_probability::very_likely ());
1603 else if (can_mult_highpart_p (mode, uns) == 1)
1605 highpart:
1606 ops.code = MULT_HIGHPART_EXPR;
1607 ops.type = type;
1609 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1610 EXPAND_NORMAL);
1611 ops.code = MULT_EXPR;
1612 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1613 if (uns)
1614 /* For the unsigned multiplication, there was overflow if
1615 HIPART is non-zero. */
1616 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1617 NULL_RTX, NULL, done_label,
1618 profile_probability::very_likely ());
1619 else
1621 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1622 NULL_RTX, 0);
1623 /* RES is low half of the double width result, HIPART
1624 the high half. There was overflow if
1625 HIPART is different from RES < 0 ? -1 : 0. */
1626 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1627 NULL_RTX, NULL, done_label,
1628 profile_probability::very_likely ());
1632 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
1633 && 2 * GET_MODE_PRECISION (hmode) == prec)
1635 rtx_code_label *large_op0 = gen_label_rtx ();
1636 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1637 rtx_code_label *one_small_one_large = gen_label_rtx ();
1638 rtx_code_label *both_ops_large = gen_label_rtx ();
1639 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1640 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1641 rtx_code_label *do_overflow = gen_label_rtx ();
1642 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1644 unsigned int hprec = GET_MODE_PRECISION (hmode);
1645 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1646 NULL_RTX, uns);
1647 hipart0 = convert_modes (hmode, mode, hipart0, uns);
1648 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1649 rtx signbit0 = const0_rtx;
1650 if (!uns)
1651 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1652 NULL_RTX, 0);
1653 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1654 NULL_RTX, uns);
1655 hipart1 = convert_modes (hmode, mode, hipart1, uns);
1656 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1657 rtx signbit1 = const0_rtx;
1658 if (!uns)
1659 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1660 NULL_RTX, 0);
1662 res = gen_reg_rtx (mode);
1664 /* True if op0 resp. op1 are known to be in the range of
1665 halfstype. */
1666 bool op0_small_p = false;
1667 bool op1_small_p = false;
1668 /* True if op0 resp. op1 are known to have all zeros or all ones
1669 in the upper half of bits, but are not known to be
1670 op{0,1}_small_p. */
1671 bool op0_medium_p = false;
1672 bool op1_medium_p = false;
1673 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1674 nonnegative, 1 if unknown. */
1675 int op0_sign = 1;
1676 int op1_sign = 1;
1678 if (pos_neg0 == 1)
1679 op0_sign = 0;
1680 else if (pos_neg0 == 2)
1681 op0_sign = -1;
1682 if (pos_neg1 == 1)
1683 op1_sign = 0;
1684 else if (pos_neg1 == 2)
1685 op1_sign = -1;
1687 unsigned int mprec0 = prec;
1688 if (arg0 != error_mark_node)
1689 mprec0 = get_min_precision (arg0, sign);
1690 if (mprec0 <= hprec)
1691 op0_small_p = true;
1692 else if (!uns && mprec0 <= hprec + 1)
1693 op0_medium_p = true;
1694 unsigned int mprec1 = prec;
1695 if (arg1 != error_mark_node)
1696 mprec1 = get_min_precision (arg1, sign);
1697 if (mprec1 <= hprec)
1698 op1_small_p = true;
1699 else if (!uns && mprec1 <= hprec + 1)
1700 op1_medium_p = true;
1702 int smaller_sign = 1;
1703 int larger_sign = 1;
1704 if (op0_small_p)
1706 smaller_sign = op0_sign;
1707 larger_sign = op1_sign;
1709 else if (op1_small_p)
1711 smaller_sign = op1_sign;
1712 larger_sign = op0_sign;
1714 else if (op0_sign == op1_sign)
1716 smaller_sign = op0_sign;
1717 larger_sign = op0_sign;
1720 if (!op0_small_p)
1721 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1722 NULL_RTX, NULL, large_op0,
1723 profile_probability::unlikely ());
1725 if (!op1_small_p)
1726 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1727 NULL_RTX, NULL, small_op0_large_op1,
1728 profile_probability::unlikely ());
1730 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1731 hmode to mode, the multiplication will never overflow. We can
1732 do just one hmode x hmode => mode widening multiplication. */
1733 rtx lopart0s = lopart0, lopart1s = lopart1;
1734 if (GET_CODE (lopart0) == SUBREG)
1736 lopart0s = shallow_copy_rtx (lopart0);
1737 SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1738 SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1740 if (GET_CODE (lopart1) == SUBREG)
1742 lopart1s = shallow_copy_rtx (lopart1);
1743 SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1744 SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
1746 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1747 ops.op0 = make_tree (halfstype, lopart0s);
1748 ops.op1 = make_tree (halfstype, lopart1s);
1749 ops.code = WIDEN_MULT_EXPR;
1750 ops.type = type;
1751 rtx thisres
1752 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1753 emit_move_insn (res, thisres);
1754 emit_jump (done_label);
1756 emit_label (small_op0_large_op1);
1758 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1759 but op1 is not, just swap the arguments and handle it as op1
1760 sign/zero extended, op0 not. */
1761 rtx larger = gen_reg_rtx (mode);
1762 rtx hipart = gen_reg_rtx (hmode);
1763 rtx lopart = gen_reg_rtx (hmode);
1764 emit_move_insn (larger, op1);
1765 emit_move_insn (hipart, hipart1);
1766 emit_move_insn (lopart, lopart0);
1767 emit_jump (one_small_one_large);
1769 emit_label (large_op0);
1771 if (!op1_small_p)
1772 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1773 NULL_RTX, NULL, both_ops_large,
1774 profile_probability::unlikely ());
1776 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1777 but op0 is not, prepare larger, hipart and lopart pseudos and
1778 handle it together with small_op0_large_op1. */
1779 emit_move_insn (larger, op0);
1780 emit_move_insn (hipart, hipart0);
1781 emit_move_insn (lopart, lopart1);
1783 emit_label (one_small_one_large);
1785 /* lopart is the low part of the operand that is sign extended
1786 to mode, larger is the other operand, hipart is the
1787 high part of larger and lopart0 and lopart1 are the low parts
1788 of both operands.
1789 We perform lopart0 * lopart1 and lopart * hipart widening
1790 multiplications. */
1791 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1792 ops.op0 = make_tree (halfutype, lopart0);
1793 ops.op1 = make_tree (halfutype, lopart1);
1794 rtx lo0xlo1
1795 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1797 ops.op0 = make_tree (halfutype, lopart);
1798 ops.op1 = make_tree (halfutype, hipart);
1799 rtx loxhi = gen_reg_rtx (mode);
1800 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1801 emit_move_insn (loxhi, tem);
1803 if (!uns)
1805 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1806 if (larger_sign == 0)
1807 emit_jump (after_hipart_neg);
1808 else if (larger_sign != -1)
1809 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1810 NULL_RTX, NULL, after_hipart_neg,
1811 profile_probability::even ());
1813 tem = convert_modes (mode, hmode, lopart, 1);
1814 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1815 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1816 1, OPTAB_WIDEN);
1817 emit_move_insn (loxhi, tem);
1819 emit_label (after_hipart_neg);
1821 /* if (lopart < 0) loxhi -= larger; */
1822 if (smaller_sign == 0)
1823 emit_jump (after_lopart_neg);
1824 else if (smaller_sign != -1)
1825 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1826 NULL_RTX, NULL, after_lopart_neg,
1827 profile_probability::even ());
1829 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1830 1, OPTAB_WIDEN);
1831 emit_move_insn (loxhi, tem);
1833 emit_label (after_lopart_neg);
1836 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1837 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1838 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1839 1, OPTAB_WIDEN);
1840 emit_move_insn (loxhi, tem);
1842 /* if (loxhi >> (bitsize / 2)
1843 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1844 if (loxhi >> (bitsize / 2) == 0 (if uns). */
1845 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1846 NULL_RTX, 0);
1847 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1848 rtx signbitloxhi = const0_rtx;
1849 if (!uns)
1850 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1851 convert_modes (hmode, mode,
1852 loxhi, 0),
1853 hprec - 1, NULL_RTX, 0);
1855 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1856 NULL_RTX, NULL, do_overflow,
1857 profile_probability::very_unlikely ());
1859 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1860 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1861 NULL_RTX, 1);
1862 tem = convert_modes (mode, hmode,
1863 convert_modes (hmode, mode, lo0xlo1, 1), 1);
1865 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1866 1, OPTAB_WIDEN);
1867 if (tem != res)
1868 emit_move_insn (res, tem);
1869 emit_jump (done_label);
1871 emit_label (both_ops_large);
1873 /* If both operands are large (not sign (!uns) or zero (uns)
1874 extended from hmode), then perform the full multiplication
1875 which will be the result of the operation.
1876 The only cases which don't overflow are for signed multiplication
1877 some cases where both hipart0 and highpart1 are 0 or -1.
1878 For unsigned multiplication when high parts are both non-zero
1879 this overflows always. */
1880 ops.code = MULT_EXPR;
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);
1886 if (!uns)
1888 if (!op0_medium_p)
1890 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1891 NULL_RTX, 1, OPTAB_WIDEN);
1892 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1893 NULL_RTX, NULL, do_error,
1894 profile_probability::very_unlikely ());
1897 if (!op1_medium_p)
1899 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1900 NULL_RTX, 1, OPTAB_WIDEN);
1901 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1902 NULL_RTX, NULL, do_error,
1903 profile_probability::very_unlikely ());
1906 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1907 the same, overflow happened if res is non-positive, if they
1908 are different, overflow happened if res is positive. */
1909 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1910 emit_jump (hipart_different);
1911 else if (op0_sign == 1 || op1_sign == 1)
1912 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1913 NULL_RTX, NULL, hipart_different,
1914 profile_probability::even ());
1916 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
1917 NULL_RTX, NULL, do_error,
1918 profile_probability::very_unlikely ());
1919 emit_jump (done_label);
1921 emit_label (hipart_different);
1923 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1924 NULL_RTX, NULL, do_error,
1925 profile_probability::very_unlikely ());
1926 emit_jump (done_label);
1929 emit_label (do_overflow);
1931 /* Overflow, do full multiplication and fallthru into do_error. */
1932 ops.op0 = make_tree (type, op0);
1933 ops.op1 = make_tree (type, op1);
1934 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1935 emit_move_insn (res, tem);
1937 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1938 && targetm.scalar_mode_supported_p (wmode))
1939 /* Even emitting a libcall is better than not detecting overflow
1940 at all. */
1941 goto twoxwider;
1942 else
1944 gcc_assert (!is_ubsan);
1945 ops.code = MULT_EXPR;
1946 ops.type = type;
1947 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1948 emit_jump (done_label);
1952 do_error_label:
1953 emit_label (do_error);
1954 if (is_ubsan)
1956 /* Expand the ubsan builtin call. */
1957 push_temp_slots ();
1958 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1959 arg0, arg1, datap);
1960 expand_normal (fn);
1961 pop_temp_slots ();
1962 do_pending_stack_adjust ();
1964 else if (lhs)
1965 expand_arith_set_overflow (lhs, target);
1967 /* We're done. */
1968 emit_label (done_label);
1970 /* u1 * u2 -> sr */
1971 if (uns0_p && uns1_p && !unsr_p)
1973 rtx_code_label *all_done_label = gen_label_rtx ();
1974 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1975 NULL, all_done_label, profile_probability::very_likely ());
1976 expand_arith_set_overflow (lhs, target);
1977 emit_label (all_done_label);
1980 /* s1 * u2 -> sr */
1981 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
1983 rtx_code_label *all_done_label = gen_label_rtx ();
1984 rtx_code_label *set_noovf = gen_label_rtx ();
1985 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
1986 NULL, all_done_label, profile_probability::very_likely ());
1987 expand_arith_set_overflow (lhs, target);
1988 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1989 NULL, set_noovf, profile_probability::very_likely ());
1990 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1991 NULL, all_done_label, profile_probability::very_unlikely ());
1992 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
1993 all_done_label, profile_probability::very_unlikely ());
1994 emit_label (set_noovf);
1995 write_complex_part (target, const0_rtx, true);
1996 emit_label (all_done_label);
1999 if (lhs)
2001 if (is_ubsan)
2002 expand_ubsan_result_store (target, res);
2003 else
2004 expand_arith_overflow_result_store (lhs, target, mode, res);
2008 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2010 static void
2011 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2012 tree arg0, tree arg1)
2014 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2015 rtx_code_label *loop_lab = NULL;
2016 rtx cntvar = NULL_RTX;
2017 tree cntv = NULL_TREE;
2018 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2019 tree sz = TYPE_SIZE (eltype);
2020 tree data = NULL_TREE;
2021 tree resv = NULL_TREE;
2022 rtx lhsr = NULL_RTX;
2023 rtx resvr = NULL_RTX;
2024 unsigned HOST_WIDE_INT const_cnt = 0;
2025 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2027 if (lhs)
2029 optab op;
2030 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2031 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2032 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2033 optab_default)) == unknown_optab
2034 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2035 == CODE_FOR_nothing))
2037 if (MEM_P (lhsr))
2038 resv = make_tree (TREE_TYPE (lhs), lhsr);
2039 else
2041 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2042 resv = make_tree (TREE_TYPE (lhs), resvr);
2046 if (use_loop_p)
2048 do_pending_stack_adjust ();
2049 loop_lab = gen_label_rtx ();
2050 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2051 cntv = make_tree (sizetype, cntvar);
2052 emit_move_insn (cntvar, const0_rtx);
2053 emit_label (loop_lab);
2055 if (TREE_CODE (arg0) != VECTOR_CST)
2057 rtx arg0r = expand_normal (arg0);
2058 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2060 if (TREE_CODE (arg1) != VECTOR_CST)
2062 rtx arg1r = expand_normal (arg1);
2063 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2065 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2067 tree op0, op1, res = NULL_TREE;
2068 if (use_loop_p)
2070 tree atype = build_array_type_nelts (eltype, cnt);
2071 op0 = uniform_vector_p (arg0);
2072 if (op0 == NULL_TREE)
2074 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2075 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2076 NULL_TREE, NULL_TREE);
2078 op1 = uniform_vector_p (arg1);
2079 if (op1 == NULL_TREE)
2081 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2082 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2083 NULL_TREE, NULL_TREE);
2085 if (resv)
2087 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2088 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2089 NULL_TREE, NULL_TREE);
2092 else
2094 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2095 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2096 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2097 if (resv)
2098 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2099 bitpos);
2101 switch (code)
2103 case PLUS_EXPR:
2104 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2105 false, false, false, true, &data);
2106 break;
2107 case MINUS_EXPR:
2108 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2109 expand_neg_overflow (loc, res, op1, true, &data);
2110 else
2111 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2112 false, false, false, true, &data);
2113 break;
2114 case MULT_EXPR:
2115 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2116 true, &data);
2117 break;
2118 default:
2119 gcc_unreachable ();
2122 if (use_loop_p)
2124 struct separate_ops ops;
2125 ops.code = PLUS_EXPR;
2126 ops.type = TREE_TYPE (cntv);
2127 ops.op0 = cntv;
2128 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2129 ops.op2 = NULL_TREE;
2130 ops.location = loc;
2131 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2132 EXPAND_NORMAL);
2133 if (ret != cntvar)
2134 emit_move_insn (cntvar, ret);
2135 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2136 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2137 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2138 profile_probability::very_likely ());
2140 if (lhs && resv == NULL_TREE)
2142 struct separate_ops ops;
2143 ops.code = code;
2144 ops.type = TREE_TYPE (arg0);
2145 ops.op0 = arg0;
2146 ops.op1 = arg1;
2147 ops.op2 = NULL_TREE;
2148 ops.location = loc;
2149 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2150 EXPAND_NORMAL);
2151 if (ret != lhsr)
2152 emit_move_insn (lhsr, ret);
2154 else if (resvr)
2155 emit_move_insn (lhsr, resvr);
2158 /* Expand UBSAN_CHECK_ADD call STMT. */
2160 static void
2161 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2163 location_t loc = gimple_location (stmt);
2164 tree lhs = gimple_call_lhs (stmt);
2165 tree arg0 = gimple_call_arg (stmt, 0);
2166 tree arg1 = gimple_call_arg (stmt, 1);
2167 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2168 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2169 else
2170 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2171 false, false, false, true, NULL);
2174 /* Expand UBSAN_CHECK_SUB call STMT. */
2176 static void
2177 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2179 location_t loc = gimple_location (stmt);
2180 tree lhs = gimple_call_lhs (stmt);
2181 tree arg0 = gimple_call_arg (stmt, 0);
2182 tree arg1 = gimple_call_arg (stmt, 1);
2183 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2184 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2185 else if (integer_zerop (arg0))
2186 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2187 else
2188 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2189 false, false, false, true, NULL);
2192 /* Expand UBSAN_CHECK_MUL call STMT. */
2194 static void
2195 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2197 location_t loc = gimple_location (stmt);
2198 tree lhs = gimple_call_lhs (stmt);
2199 tree arg0 = gimple_call_arg (stmt, 0);
2200 tree arg1 = gimple_call_arg (stmt, 1);
2201 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2202 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2203 else
2204 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2205 NULL);
2208 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2210 static void
2211 expand_arith_overflow (enum tree_code code, gimple *stmt)
2213 tree lhs = gimple_call_lhs (stmt);
2214 if (lhs == NULL_TREE)
2215 return;
2216 tree arg0 = gimple_call_arg (stmt, 0);
2217 tree arg1 = gimple_call_arg (stmt, 1);
2218 tree type = TREE_TYPE (TREE_TYPE (lhs));
2219 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2220 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2221 int unsr_p = TYPE_UNSIGNED (type);
2222 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2223 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2224 int precres = TYPE_PRECISION (type);
2225 location_t loc = gimple_location (stmt);
2226 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2227 uns0_p = true;
2228 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2229 uns1_p = true;
2230 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2231 prec0 = MIN (prec0, pr);
2232 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2233 prec1 = MIN (prec1, pr);
2235 /* If uns0_p && uns1_p, precop is minimum needed precision
2236 of unsigned type to hold the exact result, otherwise
2237 precop is minimum needed precision of signed type to
2238 hold the exact result. */
2239 int precop;
2240 if (code == MULT_EXPR)
2241 precop = prec0 + prec1 + (uns0_p != uns1_p);
2242 else
2244 if (uns0_p == uns1_p)
2245 precop = MAX (prec0, prec1) + 1;
2246 else if (uns0_p)
2247 precop = MAX (prec0 + 1, prec1) + 1;
2248 else
2249 precop = MAX (prec0, prec1 + 1) + 1;
2251 int orig_precres = precres;
2255 if ((uns0_p && uns1_p)
2256 ? ((precop + !unsr_p) <= precres
2257 /* u1 - u2 -> ur can overflow, no matter what precision
2258 the result has. */
2259 && (code != MINUS_EXPR || !unsr_p))
2260 : (!unsr_p && precop <= precres))
2262 /* The infinity precision result will always fit into result. */
2263 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2264 write_complex_part (target, const0_rtx, true);
2265 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2266 struct separate_ops ops;
2267 ops.code = code;
2268 ops.type = type;
2269 ops.op0 = fold_convert_loc (loc, type, arg0);
2270 ops.op1 = fold_convert_loc (loc, type, arg1);
2271 ops.op2 = NULL_TREE;
2272 ops.location = loc;
2273 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2274 expand_arith_overflow_result_store (lhs, target, mode, tem);
2275 return;
2278 /* For operations with low precision, if target doesn't have them, start
2279 with precres widening right away, otherwise do it only if the most
2280 simple cases can't be used. */
2281 const int min_precision = targetm.min_arithmetic_precision ();
2282 if (orig_precres == precres && precres < min_precision)
2284 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2285 && prec1 <= precres)
2286 || ((!uns0_p || !uns1_p) && !unsr_p
2287 && prec0 + uns0_p <= precres
2288 && prec1 + uns1_p <= precres))
2290 arg0 = fold_convert_loc (loc, type, arg0);
2291 arg1 = fold_convert_loc (loc, type, arg1);
2292 switch (code)
2294 case MINUS_EXPR:
2295 if (integer_zerop (arg0) && !unsr_p)
2297 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2298 return;
2300 /* FALLTHRU */
2301 case PLUS_EXPR:
2302 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2303 unsr_p, unsr_p, false, NULL);
2304 return;
2305 case MULT_EXPR:
2306 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2307 unsr_p, unsr_p, false, NULL);
2308 return;
2309 default:
2310 gcc_unreachable ();
2314 /* For sub-word operations, retry with a wider type first. */
2315 if (orig_precres == precres && precop <= BITS_PER_WORD)
2317 int p = MAX (min_precision, precop);
2318 scalar_int_mode m = smallest_int_mode_for_size (p);
2319 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2320 uns0_p && uns1_p
2321 && unsr_p);
2322 p = TYPE_PRECISION (optype);
2323 if (p > precres)
2325 precres = p;
2326 unsr_p = TYPE_UNSIGNED (optype);
2327 type = optype;
2328 continue;
2332 if (prec0 <= precres && prec1 <= precres)
2334 tree types[2];
2335 if (unsr_p)
2337 types[0] = build_nonstandard_integer_type (precres, 0);
2338 types[1] = type;
2340 else
2342 types[0] = type;
2343 types[1] = build_nonstandard_integer_type (precres, 1);
2345 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2346 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2347 if (code != MULT_EXPR)
2348 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2349 uns0_p, uns1_p, false, NULL);
2350 else
2351 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2352 uns0_p, uns1_p, false, NULL);
2353 return;
2356 /* Retry with a wider type. */
2357 if (orig_precres == precres)
2359 int p = MAX (prec0, prec1);
2360 scalar_int_mode m = smallest_int_mode_for_size (p);
2361 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2362 uns0_p && uns1_p
2363 && unsr_p);
2364 p = TYPE_PRECISION (optype);
2365 if (p > precres)
2367 precres = p;
2368 unsr_p = TYPE_UNSIGNED (optype);
2369 type = optype;
2370 continue;
2374 gcc_unreachable ();
2376 while (1);
2379 /* Expand ADD_OVERFLOW STMT. */
2381 static void
2382 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2384 expand_arith_overflow (PLUS_EXPR, stmt);
2387 /* Expand SUB_OVERFLOW STMT. */
2389 static void
2390 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2392 expand_arith_overflow (MINUS_EXPR, stmt);
2395 /* Expand MUL_OVERFLOW STMT. */
2397 static void
2398 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2400 expand_arith_overflow (MULT_EXPR, stmt);
2403 /* This should get folded in tree-vectorizer.c. */
2405 static void
2406 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2408 gcc_unreachable ();
2411 /* This should get folded in tree-vectorizer.c. */
2413 static void
2414 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2416 gcc_unreachable ();
2419 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2420 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2422 static tree
2423 expand_call_mem_ref (tree type, gcall *stmt, int index)
2425 tree addr = gimple_call_arg (stmt, index);
2426 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2427 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2428 if (TYPE_ALIGN (type) != align)
2429 type = build_aligned_type (type, align);
2431 tree tmp = addr;
2432 if (TREE_CODE (tmp) == SSA_NAME)
2434 gimple *def = SSA_NAME_DEF_STMT (tmp);
2435 if (gimple_assign_single_p (def))
2436 tmp = gimple_assign_rhs1 (def);
2439 if (TREE_CODE (tmp) == ADDR_EXPR)
2441 tree mem = TREE_OPERAND (tmp, 0);
2442 if (TREE_CODE (mem) == TARGET_MEM_REF
2443 && types_compatible_p (TREE_TYPE (mem), type))
2445 tree offset = TMR_OFFSET (mem);
2446 if (alias_ptr_type != TREE_TYPE (offset) || !integer_zerop (offset))
2448 mem = copy_node (mem);
2449 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2450 wi::to_poly_wide (offset));
2452 return mem;
2456 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2459 /* Expand MASK_LOAD{,_LANES} call STMT using optab OPTAB. */
2461 static void
2462 expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2464 struct expand_operand ops[3];
2465 tree type, lhs, rhs, maskt;
2466 rtx mem, target, mask;
2467 insn_code icode;
2469 maskt = gimple_call_arg (stmt, 2);
2470 lhs = gimple_call_lhs (stmt);
2471 if (lhs == NULL_TREE)
2472 return;
2473 type = TREE_TYPE (lhs);
2474 rhs = expand_call_mem_ref (type, stmt, 0);
2476 if (optab == vec_mask_load_lanes_optab)
2477 icode = get_multi_vector_move (type, optab);
2478 else
2479 icode = convert_optab_handler (optab, TYPE_MODE (type),
2480 TYPE_MODE (TREE_TYPE (maskt)));
2482 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2483 gcc_assert (MEM_P (mem));
2484 mask = expand_normal (maskt);
2485 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2486 create_output_operand (&ops[0], target, TYPE_MODE (type));
2487 create_fixed_operand (&ops[1], mem);
2488 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2489 expand_insn (icode, 3, ops);
2492 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2494 /* Expand MASK_STORE{,_LANES} call STMT using optab OPTAB. */
2496 static void
2497 expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2499 struct expand_operand ops[3];
2500 tree type, lhs, rhs, maskt;
2501 rtx mem, reg, mask;
2502 insn_code icode;
2504 maskt = gimple_call_arg (stmt, 2);
2505 rhs = gimple_call_arg (stmt, 3);
2506 type = TREE_TYPE (rhs);
2507 lhs = expand_call_mem_ref (type, stmt, 0);
2509 if (optab == vec_mask_store_lanes_optab)
2510 icode = get_multi_vector_move (type, optab);
2511 else
2512 icode = convert_optab_handler (optab, TYPE_MODE (type),
2513 TYPE_MODE (TREE_TYPE (maskt)));
2515 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2516 gcc_assert (MEM_P (mem));
2517 mask = expand_normal (maskt);
2518 reg = expand_normal (rhs);
2519 create_fixed_operand (&ops[0], mem);
2520 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2521 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2522 expand_insn (icode, 3, ops);
2525 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2527 static void
2528 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
2532 static void
2533 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
2535 /* When guessing was done, the hints should be already stripped away. */
2536 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2538 rtx target;
2539 tree lhs = gimple_call_lhs (stmt);
2540 if (lhs)
2541 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2542 else
2543 target = const0_rtx;
2544 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2545 if (lhs && val != target)
2546 emit_move_insn (target, val);
2549 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
2550 should never be called. */
2552 static void
2553 expand_VA_ARG (internal_fn, gcall *)
2555 gcc_unreachable ();
2558 /* Expand the IFN_UNIQUE function according to its first argument. */
2560 static void
2561 expand_UNIQUE (internal_fn, gcall *stmt)
2563 rtx pattern = NULL_RTX;
2564 enum ifn_unique_kind kind
2565 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2567 switch (kind)
2569 default:
2570 gcc_unreachable ();
2572 case IFN_UNIQUE_UNSPEC:
2573 if (targetm.have_unique ())
2574 pattern = targetm.gen_unique ();
2575 break;
2577 case IFN_UNIQUE_OACC_FORK:
2578 case IFN_UNIQUE_OACC_JOIN:
2579 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2581 tree lhs = gimple_call_lhs (stmt);
2582 rtx target = const0_rtx;
2584 if (lhs)
2585 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2587 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2588 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2590 if (kind == IFN_UNIQUE_OACC_FORK)
2591 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2592 else
2593 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2595 else
2596 gcc_unreachable ();
2597 break;
2600 if (pattern)
2601 emit_insn (pattern);
2604 /* The size of an OpenACC compute dimension. */
2606 static void
2607 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
2609 tree lhs = gimple_call_lhs (stmt);
2611 if (!lhs)
2612 return;
2614 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2615 if (targetm.have_oacc_dim_size ())
2617 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2618 VOIDmode, EXPAND_NORMAL);
2619 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2621 else
2622 emit_move_insn (target, GEN_INT (1));
2625 /* The position of an OpenACC execution engine along one compute axis. */
2627 static void
2628 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
2630 tree lhs = gimple_call_lhs (stmt);
2632 if (!lhs)
2633 return;
2635 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2636 if (targetm.have_oacc_dim_pos ())
2638 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2639 VOIDmode, EXPAND_NORMAL);
2640 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2642 else
2643 emit_move_insn (target, const0_rtx);
2646 /* This is expanded by oacc_device_lower pass. */
2648 static void
2649 expand_GOACC_LOOP (internal_fn, gcall *)
2651 gcc_unreachable ();
2654 /* This is expanded by oacc_device_lower pass. */
2656 static void
2657 expand_GOACC_REDUCTION (internal_fn, gcall *)
2659 gcc_unreachable ();
2662 /* This is expanded by oacc_device_lower pass. */
2664 static void
2665 expand_GOACC_TILE (internal_fn, gcall *)
2667 gcc_unreachable ();
2670 /* Set errno to EDOM. */
2672 static void
2673 expand_SET_EDOM (internal_fn, gcall *)
2675 #ifdef TARGET_EDOM
2676 #ifdef GEN_ERRNO_RTX
2677 rtx errno_rtx = GEN_ERRNO_RTX;
2678 #else
2679 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2680 #endif
2681 emit_move_insn (errno_rtx,
2682 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2683 #else
2684 gcc_unreachable ();
2685 #endif
2688 /* Expand atomic bit test and set. */
2690 static void
2691 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2693 expand_ifn_atomic_bit_test_and (call);
2696 /* Expand atomic bit test and complement. */
2698 static void
2699 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2701 expand_ifn_atomic_bit_test_and (call);
2704 /* Expand atomic bit test and reset. */
2706 static void
2707 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2709 expand_ifn_atomic_bit_test_and (call);
2712 /* Expand atomic bit test and set. */
2714 static void
2715 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2717 expand_ifn_atomic_compare_exchange (call);
2720 /* Expand LAUNDER to assignment, lhs = arg0. */
2722 static void
2723 expand_LAUNDER (internal_fn, gcall *call)
2725 tree lhs = gimple_call_lhs (call);
2727 if (!lhs)
2728 return;
2730 expand_assignment (lhs, gimple_call_arg (call, 0), false);
2733 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
2735 static void
2736 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2738 tree lhs = gimple_call_lhs (stmt);
2739 tree base = gimple_call_arg (stmt, 0);
2740 tree offset = gimple_call_arg (stmt, 1);
2741 tree scale = gimple_call_arg (stmt, 2);
2743 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2744 rtx base_rtx = expand_normal (base);
2745 rtx offset_rtx = expand_normal (offset);
2746 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2748 int i = 0;
2749 struct expand_operand ops[6];
2750 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
2751 create_address_operand (&ops[i++], base_rtx);
2752 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2753 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2754 create_integer_operand (&ops[i++], scale_int);
2755 if (optab == mask_gather_load_optab)
2757 tree mask = gimple_call_arg (stmt, 3);
2758 rtx mask_rtx = expand_normal (mask);
2759 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2761 insn_code icode = direct_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)));
2762 expand_insn (icode, i, ops);
2765 /* Expand DIVMOD() using:
2766 a) optab handler for udivmod/sdivmod if it is available.
2767 b) If optab_handler doesn't exist, generate call to
2768 target-specific divmod libfunc. */
2770 static void
2771 expand_DIVMOD (internal_fn, gcall *call_stmt)
2773 tree lhs = gimple_call_lhs (call_stmt);
2774 tree arg0 = gimple_call_arg (call_stmt, 0);
2775 tree arg1 = gimple_call_arg (call_stmt, 1);
2777 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
2778 tree type = TREE_TYPE (TREE_TYPE (lhs));
2779 machine_mode mode = TYPE_MODE (type);
2780 bool unsignedp = TYPE_UNSIGNED (type);
2781 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
2783 rtx op0 = expand_normal (arg0);
2784 rtx op1 = expand_normal (arg1);
2785 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2787 rtx quotient, remainder, libfunc;
2789 /* Check if optab_handler exists for divmod_optab for given mode. */
2790 if (optab_handler (tab, mode) != CODE_FOR_nothing)
2792 quotient = gen_reg_rtx (mode);
2793 remainder = gen_reg_rtx (mode);
2794 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
2797 /* Generate call to divmod libfunc if it exists. */
2798 else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
2799 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
2800 &quotient, &remainder);
2802 else
2803 gcc_unreachable ();
2805 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
2806 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
2807 make_tree (TREE_TYPE (arg0), quotient),
2808 make_tree (TREE_TYPE (arg1), remainder)),
2809 target, VOIDmode, EXPAND_NORMAL);
2812 /* Expand a NOP. */
2814 static void
2815 expand_NOP (internal_fn, gcall *)
2817 /* Nothing. But it shouldn't really prevail. */
2820 /* Expand a call to FN using the operands in STMT. FN has a single
2821 output operand and NARGS input operands. */
2823 static void
2824 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2825 unsigned int nargs)
2827 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2829 tree_pair types = direct_internal_fn_types (fn, stmt);
2830 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2832 tree lhs = gimple_call_lhs (stmt);
2833 tree lhs_type = TREE_TYPE (lhs);
2834 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2836 /* Do not assign directly to a promoted subreg, since there is no
2837 guarantee that the instruction will leave the upper bits of the
2838 register in the state required by SUBREG_PROMOTED_SIGN. */
2839 rtx dest = lhs_rtx;
2840 if (GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
2841 dest = NULL_RTX;
2843 create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
2845 for (unsigned int i = 0; i < nargs; ++i)
2847 tree rhs = gimple_call_arg (stmt, i);
2848 tree rhs_type = TREE_TYPE (rhs);
2849 rtx rhs_rtx = expand_normal (rhs);
2850 if (INTEGRAL_TYPE_P (rhs_type))
2851 create_convert_operand_from (&ops[i + 1], rhs_rtx,
2852 TYPE_MODE (rhs_type),
2853 TYPE_UNSIGNED (rhs_type));
2854 else
2855 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2858 expand_insn (icode, nargs + 1, ops);
2859 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2861 /* If the return value has an integral type, convert the instruction
2862 result to that type. This is useful for things that return an
2863 int regardless of the size of the input. If the instruction result
2864 is smaller than required, assume that it is signed.
2866 If the return value has a nonintegral type, its mode must match
2867 the instruction result. */
2868 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2870 /* If this is a scalar in a register that is stored in a wider
2871 mode than the declared mode, compute the result into its
2872 declared mode and then convert to the wider mode. */
2873 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2874 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2875 convert_move (SUBREG_REG (lhs_rtx), tmp,
2876 SUBREG_PROMOTED_SIGN (lhs_rtx));
2878 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
2879 emit_move_insn (lhs_rtx, ops[0].value);
2880 else
2882 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2883 convert_move (lhs_rtx, ops[0].value, 0);
2888 /* Expand WHILE_ULT call STMT using optab OPTAB. */
2890 static void
2891 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2893 expand_operand ops[3];
2894 tree rhs_type[2];
2896 tree lhs = gimple_call_lhs (stmt);
2897 tree lhs_type = TREE_TYPE (lhs);
2898 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2899 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
2901 for (unsigned int i = 0; i < 2; ++i)
2903 tree rhs = gimple_call_arg (stmt, i);
2904 rhs_type[i] = TREE_TYPE (rhs);
2905 rtx rhs_rtx = expand_normal (rhs);
2906 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
2909 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
2910 TYPE_MODE (lhs_type));
2912 expand_insn (icode, 3, ops);
2913 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2914 emit_move_insn (lhs_rtx, ops[0].value);
2917 /* Expanders for optabs that can use expand_direct_optab_fn. */
2919 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
2920 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
2922 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
2923 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
2925 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
2926 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
2928 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
2929 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
2931 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
2932 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
2934 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
2935 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
2937 /* RETURN_TYPE and ARGS are a return type and argument list that are
2938 in principle compatible with FN (which satisfies direct_internal_fn_p).
2939 Return the types that should be used to determine whether the
2940 target supports FN. */
2942 tree_pair
2943 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
2945 const direct_internal_fn_info &info = direct_internal_fn (fn);
2946 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
2947 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
2948 return tree_pair (type0, type1);
2951 /* CALL is a call whose return type and arguments are in principle
2952 compatible with FN (which satisfies direct_internal_fn_p). Return the
2953 types that should be used to determine whether the target supports FN. */
2955 tree_pair
2956 direct_internal_fn_types (internal_fn fn, gcall *call)
2958 const direct_internal_fn_info &info = direct_internal_fn (fn);
2959 tree op0 = (info.type0 < 0
2960 ? gimple_call_lhs (call)
2961 : gimple_call_arg (call, info.type0));
2962 tree op1 = (info.type1 < 0
2963 ? gimple_call_lhs (call)
2964 : gimple_call_arg (call, info.type1));
2965 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
2968 /* Return true if OPTAB is supported for TYPES (whose modes should be
2969 the same) when the optimization type is OPT_TYPE. Used for simple
2970 direct optabs. */
2972 static bool
2973 direct_optab_supported_p (direct_optab optab, tree_pair types,
2974 optimization_type opt_type)
2976 machine_mode mode = TYPE_MODE (types.first);
2977 gcc_checking_assert (mode == TYPE_MODE (types.second));
2978 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
2981 /* Return true if OPTAB is supported for TYPES, where the first type
2982 is the destination and the second type is the source. Used for
2983 convert optabs. */
2985 static bool
2986 convert_optab_supported_p (convert_optab optab, tree_pair types,
2987 optimization_type opt_type)
2989 return (convert_optab_handler (optab, TYPE_MODE (types.first),
2990 TYPE_MODE (types.second), opt_type)
2991 != CODE_FOR_nothing);
2994 /* Return true if load/store lanes optab OPTAB is supported for
2995 array type TYPES.first when the optimization type is OPT_TYPE. */
2997 static bool
2998 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
2999 optimization_type opt_type)
3001 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3002 machine_mode imode = TYPE_MODE (types.first);
3003 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3004 return (convert_optab_handler (optab, imode, vmode, opt_type)
3005 != CODE_FOR_nothing);
3008 #define direct_unary_optab_supported_p direct_optab_supported_p
3009 #define direct_binary_optab_supported_p direct_optab_supported_p
3010 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3011 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3012 #define direct_mask_load_optab_supported_p direct_optab_supported_p
3013 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
3014 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
3015 #define direct_gather_load_optab_supported_p direct_optab_supported_p
3016 #define direct_mask_store_optab_supported_p direct_optab_supported_p
3017 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
3018 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
3019 #define direct_while_optab_supported_p convert_optab_supported_p
3020 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
3021 #define direct_fold_left_optab_supported_p direct_optab_supported_p
3023 /* Return the optab used by internal function FN. */
3025 static optab
3026 direct_internal_fn_optab (internal_fn fn, tree_pair types)
3028 switch (fn)
3030 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3031 case IFN_##CODE: break;
3032 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3033 case IFN_##CODE: return OPTAB##_optab;
3034 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3035 UNSIGNED_OPTAB, TYPE) \
3036 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
3037 ? UNSIGNED_OPTAB ## _optab \
3038 : SIGNED_OPTAB ## _optab);
3039 #include "internal-fn.def"
3041 case IFN_LAST:
3042 break;
3044 gcc_unreachable ();
3047 /* Return the optab used by internal function FN. */
3049 static optab
3050 direct_internal_fn_optab (internal_fn fn)
3052 switch (fn)
3054 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3055 case IFN_##CODE: break;
3056 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3057 case IFN_##CODE: return OPTAB##_optab;
3058 #include "internal-fn.def"
3060 case IFN_LAST:
3061 break;
3063 gcc_unreachable ();
3066 /* Return true if FN is supported for the types in TYPES when the
3067 optimization type is OPT_TYPE. The types are those associated with
3068 the "type0" and "type1" fields of FN's direct_internal_fn_info
3069 structure. */
3071 bool
3072 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
3073 optimization_type opt_type)
3075 switch (fn)
3077 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3078 case IFN_##CODE: break;
3079 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3080 case IFN_##CODE: \
3081 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
3082 opt_type);
3083 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3084 UNSIGNED_OPTAB, TYPE) \
3085 case IFN_##CODE: \
3087 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
3088 ? UNSIGNED_OPTAB ## _optab \
3089 : SIGNED_OPTAB ## _optab); \
3090 return direct_##TYPE##_optab_supported_p (which_optab, types, \
3091 opt_type); \
3093 #include "internal-fn.def"
3095 case IFN_LAST:
3096 break;
3098 gcc_unreachable ();
3101 /* Return true if FN is supported for type TYPE when the optimization
3102 type is OPT_TYPE. The caller knows that the "type0" and "type1"
3103 fields of FN's direct_internal_fn_info structure are the same. */
3105 bool
3106 direct_internal_fn_supported_p (internal_fn fn, tree type,
3107 optimization_type opt_type)
3109 const direct_internal_fn_info &info = direct_internal_fn (fn);
3110 gcc_checking_assert (info.type0 == info.type1);
3111 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
3114 /* Return true if IFN_SET_EDOM is supported. */
3116 bool
3117 set_edom_supported_p (void)
3119 #ifdef TARGET_EDOM
3120 return true;
3121 #else
3122 return false;
3123 #endif
3126 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3127 static void \
3128 expand_##CODE (internal_fn fn, gcall *stmt) \
3130 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
3132 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3133 UNSIGNED_OPTAB, TYPE) \
3134 static void \
3135 expand_##CODE (internal_fn fn, gcall *stmt) \
3137 tree_pair types = direct_internal_fn_types (fn, stmt); \
3138 optab which_optab = direct_internal_fn_optab (fn, types); \
3139 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
3141 #include "internal-fn.def"
3143 /* Routines to expand each internal function, indexed by function number.
3144 Each routine has the prototype:
3146 expand_<NAME> (gcall *stmt)
3148 where STMT is the statement that performs the call. */
3149 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
3150 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
3151 #include "internal-fn.def"
3155 /* Return a function that performs the conditional form of CODE, i.e.:
3157 LHS = RHS1 ? RHS2 CODE RHS3 : RHS2
3159 (operating elementwise if the operands are vectors). Return IFN_LAST
3160 if no such function exists. */
3162 internal_fn
3163 get_conditional_internal_fn (tree_code code)
3165 switch (code)
3167 case PLUS_EXPR:
3168 return IFN_COND_ADD;
3169 case MINUS_EXPR:
3170 return IFN_COND_SUB;
3171 case MIN_EXPR:
3172 return IFN_COND_MIN;
3173 case MAX_EXPR:
3174 return IFN_COND_MAX;
3175 case BIT_AND_EXPR:
3176 return IFN_COND_AND;
3177 case BIT_IOR_EXPR:
3178 return IFN_COND_IOR;
3179 case BIT_XOR_EXPR:
3180 return IFN_COND_XOR;
3181 default:
3182 return IFN_LAST;
3186 /* Return true if IFN is some form of load from memory. */
3188 bool
3189 internal_load_fn_p (internal_fn fn)
3191 switch (fn)
3193 case IFN_MASK_LOAD:
3194 case IFN_LOAD_LANES:
3195 case IFN_MASK_LOAD_LANES:
3196 case IFN_GATHER_LOAD:
3197 case IFN_MASK_GATHER_LOAD:
3198 return true;
3200 default:
3201 return false;
3205 /* Return true if IFN is some form of gather load or scatter store. */
3207 bool
3208 internal_gather_scatter_fn_p (internal_fn fn)
3210 switch (fn)
3212 case IFN_GATHER_LOAD:
3213 case IFN_MASK_GATHER_LOAD:
3214 return true;
3216 default:
3217 return false;
3221 /* If FN takes a vector mask argument, return the index of that argument,
3222 otherwise return -1. */
3225 internal_fn_mask_index (internal_fn fn)
3227 switch (fn)
3229 case IFN_MASK_LOAD:
3230 case IFN_MASK_LOAD_LANES:
3231 case IFN_MASK_STORE:
3232 case IFN_MASK_STORE_LANES:
3233 return 2;
3235 case IFN_MASK_GATHER_LOAD:
3236 return 3;
3238 default:
3239 return -1;
3243 /* Return true if the target supports gather load or scatter store function
3244 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
3245 while for stores it is the vector type of the stored data argument.
3246 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
3247 or stored. OFFSET_SIGN is the sign of the offset argument, which is
3248 only relevant when the offset is narrower than an address. SCALE is
3249 the amount by which the offset should be multiplied *after* it has
3250 been extended to address width. */
3252 bool
3253 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
3254 tree memory_element_type,
3255 signop offset_sign, int scale)
3257 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
3258 TYPE_SIZE (memory_element_type)))
3259 return false;
3260 optab optab = direct_internal_fn_optab (ifn);
3261 insn_code icode = direct_optab_handler (optab, TYPE_MODE (vector_type));
3262 return (icode != CODE_FOR_nothing
3263 && insn_operand_matches (icode, 3, GEN_INT (offset_sign == UNSIGNED))
3264 && insn_operand_matches (icode, 4, GEN_INT (scale)));
3267 /* Expand STMT as though it were a call to internal function FN. */
3269 void
3270 expand_internal_call (internal_fn fn, gcall *stmt)
3272 internal_fn_expanders[fn] (fn, stmt);
3275 /* Expand STMT, which is a call to internal function FN. */
3277 void
3278 expand_internal_call (gcall *stmt)
3280 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
3283 void
3284 expand_PHI (internal_fn, gcall *)
3286 gcc_unreachable ();