aix: Fix _STDC_FORMAT_MACROS in inttypes.h [PR97044]
[official-gcc.git] / gcc / internal-fn.c
blob6cf2687fe6beddfb9ca7e08f7f3797508325fdca
1 /* Internal functions.
2 Copyright (C) 2011-2020 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"
52 #include "explow.h"
54 /* The names of each internal function, indexed by function number. */
55 const char *const internal_fn_name_array[] = {
56 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
57 #include "internal-fn.def"
58 "<invalid-fn>"
61 /* The ECF_* flags of each internal function, indexed by function number. */
62 const int internal_fn_flags_array[] = {
63 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
64 #include "internal-fn.def"
68 /* Return the internal function called NAME, or IFN_LAST if there's
69 no such function. */
71 internal_fn
72 lookup_internal_fn (const char *name)
74 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
75 static name_to_fn_map_type *name_to_fn_map;
77 if (!name_to_fn_map)
79 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
80 for (unsigned int i = 0; i < IFN_LAST; ++i)
81 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
82 internal_fn (i));
84 internal_fn *entry = name_to_fn_map->get (name);
85 return entry ? *entry : IFN_LAST;
88 /* Fnspec of each internal function, indexed by function number. */
89 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
91 void
92 init_internal_fns ()
94 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
95 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
96 build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
97 #include "internal-fn.def"
98 internal_fn_fnspec_array[IFN_LAST] = 0;
101 /* Create static initializers for the information returned by
102 direct_internal_fn. */
103 #define not_direct { -2, -2, false }
104 #define mask_load_direct { -1, 2, false }
105 #define load_lanes_direct { -1, -1, false }
106 #define mask_load_lanes_direct { -1, -1, false }
107 #define gather_load_direct { 3, 1, false }
108 #define len_load_direct { -1, -1, false }
109 #define mask_store_direct { 3, 2, false }
110 #define store_lanes_direct { 0, 0, false }
111 #define mask_store_lanes_direct { 0, 0, false }
112 #define vec_cond_mask_direct { 0, 0, false }
113 #define vec_cond_direct { 0, 0, false }
114 #define vec_condu_direct { 0, 0, false }
115 #define vec_condeq_direct { 0, 0, false }
116 #define scatter_store_direct { 3, 1, false }
117 #define len_store_direct { 3, 3, false }
118 #define unary_direct { 0, 0, true }
119 #define binary_direct { 0, 0, true }
120 #define ternary_direct { 0, 0, true }
121 #define cond_unary_direct { 1, 1, true }
122 #define cond_binary_direct { 1, 1, true }
123 #define cond_ternary_direct { 1, 1, true }
124 #define while_direct { 0, 2, false }
125 #define fold_extract_direct { 2, 2, false }
126 #define fold_left_direct { 1, 1, false }
127 #define mask_fold_left_direct { 1, 1, false }
128 #define check_ptrs_direct { 0, 0, false }
130 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
131 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
132 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
133 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
134 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
135 #include "internal-fn.def"
136 not_direct
139 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
140 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
142 static enum insn_code
143 get_multi_vector_move (tree array_type, convert_optab optab)
145 machine_mode imode;
146 machine_mode vmode;
148 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
149 imode = TYPE_MODE (array_type);
150 vmode = TYPE_MODE (TREE_TYPE (array_type));
152 return convert_optab_handler (optab, imode, vmode);
155 /* Expand LOAD_LANES call STMT using optab OPTAB. */
157 static void
158 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
160 class expand_operand ops[2];
161 tree type, lhs, rhs;
162 rtx target, mem;
164 lhs = gimple_call_lhs (stmt);
165 rhs = gimple_call_arg (stmt, 0);
166 type = TREE_TYPE (lhs);
168 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
169 mem = expand_normal (rhs);
171 gcc_assert (MEM_P (mem));
172 PUT_MODE (mem, TYPE_MODE (type));
174 create_output_operand (&ops[0], target, TYPE_MODE (type));
175 create_fixed_operand (&ops[1], mem);
176 expand_insn (get_multi_vector_move (type, optab), 2, ops);
177 if (!rtx_equal_p (target, ops[0].value))
178 emit_move_insn (target, ops[0].value);
181 /* Expand STORE_LANES call STMT using optab OPTAB. */
183 static void
184 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
186 class expand_operand ops[2];
187 tree type, lhs, rhs;
188 rtx target, reg;
190 lhs = gimple_call_lhs (stmt);
191 rhs = gimple_call_arg (stmt, 0);
192 type = TREE_TYPE (rhs);
194 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
195 reg = expand_normal (rhs);
197 gcc_assert (MEM_P (target));
198 PUT_MODE (target, TYPE_MODE (type));
200 create_fixed_operand (&ops[0], target);
201 create_input_operand (&ops[1], reg, TYPE_MODE (type));
202 expand_insn (get_multi_vector_move (type, optab), 2, ops);
205 static void
206 expand_ANNOTATE (internal_fn, gcall *)
208 gcc_unreachable ();
211 /* This should get expanded in omp_device_lower pass. */
213 static void
214 expand_GOMP_USE_SIMT (internal_fn, gcall *)
216 gcc_unreachable ();
219 /* This should get expanded in omp_device_lower pass. */
221 static void
222 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
224 gcc_unreachable ();
227 /* Allocate per-lane storage and begin non-uniform execution region. */
229 static void
230 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
232 rtx target;
233 tree lhs = gimple_call_lhs (stmt);
234 if (lhs)
235 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
236 else
237 target = gen_reg_rtx (Pmode);
238 rtx size = expand_normal (gimple_call_arg (stmt, 0));
239 rtx align = expand_normal (gimple_call_arg (stmt, 1));
240 class expand_operand ops[3];
241 create_output_operand (&ops[0], target, Pmode);
242 create_input_operand (&ops[1], size, Pmode);
243 create_input_operand (&ops[2], align, Pmode);
244 gcc_assert (targetm.have_omp_simt_enter ());
245 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
248 /* Deallocate per-lane storage and leave non-uniform execution region. */
250 static void
251 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
253 gcc_checking_assert (!gimple_call_lhs (stmt));
254 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
255 class expand_operand ops[1];
256 create_input_operand (&ops[0], arg, Pmode);
257 gcc_assert (targetm.have_omp_simt_exit ());
258 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
261 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
262 without SIMT execution this should be expanded in omp_device_lower pass. */
264 static void
265 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
267 tree lhs = gimple_call_lhs (stmt);
268 if (!lhs)
269 return;
271 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
272 gcc_assert (targetm.have_omp_simt_lane ());
273 emit_insn (targetm.gen_omp_simt_lane (target));
276 /* This should get expanded in omp_device_lower pass. */
278 static void
279 expand_GOMP_SIMT_VF (internal_fn, gcall *)
281 gcc_unreachable ();
284 /* Lane index of the first SIMT lane that supplies a non-zero argument.
285 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
286 lane that executed the last iteration for handling OpenMP lastprivate. */
288 static void
289 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
291 tree lhs = gimple_call_lhs (stmt);
292 if (!lhs)
293 return;
295 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
296 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
297 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
298 class expand_operand ops[2];
299 create_output_operand (&ops[0], target, mode);
300 create_input_operand (&ops[1], cond, mode);
301 gcc_assert (targetm.have_omp_simt_last_lane ());
302 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
305 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
307 static void
308 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
310 tree lhs = gimple_call_lhs (stmt);
311 if (!lhs)
312 return;
314 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
315 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
316 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
317 class expand_operand ops[2];
318 create_output_operand (&ops[0], target, mode);
319 create_input_operand (&ops[1], ctr, mode);
320 gcc_assert (targetm.have_omp_simt_ordered ());
321 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
324 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
325 any lane supplies a non-zero argument. */
327 static void
328 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
330 tree lhs = gimple_call_lhs (stmt);
331 if (!lhs)
332 return;
334 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
335 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
336 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
337 class expand_operand ops[2];
338 create_output_operand (&ops[0], target, mode);
339 create_input_operand (&ops[1], cond, mode);
340 gcc_assert (targetm.have_omp_simt_vote_any ());
341 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
344 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
345 is destination lane index XOR given offset. */
347 static void
348 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
350 tree lhs = gimple_call_lhs (stmt);
351 if (!lhs)
352 return;
354 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
355 rtx src = expand_normal (gimple_call_arg (stmt, 0));
356 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
357 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
358 class expand_operand ops[3];
359 create_output_operand (&ops[0], target, mode);
360 create_input_operand (&ops[1], src, mode);
361 create_input_operand (&ops[2], idx, SImode);
362 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
363 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
366 /* Exchange between SIMT lanes according to given source lane index. */
368 static void
369 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
371 tree lhs = gimple_call_lhs (stmt);
372 if (!lhs)
373 return;
375 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
376 rtx src = expand_normal (gimple_call_arg (stmt, 0));
377 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
378 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
379 class expand_operand ops[3];
380 create_output_operand (&ops[0], target, mode);
381 create_input_operand (&ops[1], src, mode);
382 create_input_operand (&ops[2], idx, SImode);
383 gcc_assert (targetm.have_omp_simt_xchg_idx ());
384 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
387 /* This should get expanded in adjust_simduid_builtins. */
389 static void
390 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
392 gcc_unreachable ();
395 /* This should get expanded in adjust_simduid_builtins. */
397 static void
398 expand_GOMP_SIMD_VF (internal_fn, gcall *)
400 gcc_unreachable ();
403 /* This should get expanded in adjust_simduid_builtins. */
405 static void
406 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
408 gcc_unreachable ();
411 /* This should get expanded in adjust_simduid_builtins. */
413 static void
414 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
416 gcc_unreachable ();
419 /* This should get expanded in adjust_simduid_builtins. */
421 static void
422 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
424 gcc_unreachable ();
427 /* This should get expanded in the sanopt pass. */
429 static void
430 expand_UBSAN_NULL (internal_fn, gcall *)
432 gcc_unreachable ();
435 /* This should get expanded in the sanopt pass. */
437 static void
438 expand_UBSAN_BOUNDS (internal_fn, gcall *)
440 gcc_unreachable ();
443 /* This should get expanded in the sanopt pass. */
445 static void
446 expand_UBSAN_VPTR (internal_fn, gcall *)
448 gcc_unreachable ();
451 /* This should get expanded in the sanopt pass. */
453 static void
454 expand_UBSAN_PTR (internal_fn, gcall *)
456 gcc_unreachable ();
459 /* This should get expanded in the sanopt pass. */
461 static void
462 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
464 gcc_unreachable ();
467 /* This should get expanded in the sanopt pass. */
469 static void
470 expand_ASAN_CHECK (internal_fn, gcall *)
472 gcc_unreachable ();
475 /* This should get expanded in the sanopt pass. */
477 static void
478 expand_ASAN_MARK (internal_fn, gcall *)
480 gcc_unreachable ();
483 /* This should get expanded in the sanopt pass. */
485 static void
486 expand_ASAN_POISON (internal_fn, gcall *)
488 gcc_unreachable ();
491 /* This should get expanded in the sanopt pass. */
493 static void
494 expand_ASAN_POISON_USE (internal_fn, gcall *)
496 gcc_unreachable ();
499 /* This should get expanded in the tsan pass. */
501 static void
502 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
504 gcc_unreachable ();
507 /* This should get expanded in the lower pass. */
509 static void
510 expand_FALLTHROUGH (internal_fn, gcall *call)
512 error_at (gimple_location (call),
513 "invalid use of attribute %<fallthrough%>");
516 /* Return minimum precision needed to represent all values
517 of ARG in SIGNed integral type. */
519 static int
520 get_min_precision (tree arg, signop sign)
522 int prec = TYPE_PRECISION (TREE_TYPE (arg));
523 int cnt = 0;
524 signop orig_sign = sign;
525 if (TREE_CODE (arg) == INTEGER_CST)
527 int p;
528 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
530 widest_int w = wi::to_widest (arg);
531 w = wi::ext (w, prec, sign);
532 p = wi::min_precision (w, sign);
534 else
535 p = wi::min_precision (wi::to_wide (arg), sign);
536 return MIN (p, prec);
538 while (CONVERT_EXPR_P (arg)
539 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
540 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
542 arg = TREE_OPERAND (arg, 0);
543 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
545 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
546 sign = UNSIGNED;
547 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
548 return prec + (orig_sign != sign);
549 prec = TYPE_PRECISION (TREE_TYPE (arg));
551 if (++cnt > 30)
552 return prec + (orig_sign != sign);
554 if (TREE_CODE (arg) != SSA_NAME)
555 return prec + (orig_sign != sign);
556 wide_int arg_min, arg_max;
557 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
559 gimple *g = SSA_NAME_DEF_STMT (arg);
560 if (is_gimple_assign (g)
561 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
563 tree t = gimple_assign_rhs1 (g);
564 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
565 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
567 arg = t;
568 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
570 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
571 sign = UNSIGNED;
572 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
573 return prec + (orig_sign != sign);
574 prec = TYPE_PRECISION (TREE_TYPE (arg));
576 if (++cnt > 30)
577 return prec + (orig_sign != sign);
578 continue;
581 return prec + (orig_sign != sign);
583 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
585 int p1 = wi::min_precision (arg_min, sign);
586 int p2 = wi::min_precision (arg_max, sign);
587 p1 = MAX (p1, p2);
588 prec = MIN (prec, p1);
590 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
592 int p = wi::min_precision (arg_max, UNSIGNED);
593 prec = MIN (prec, p);
595 return prec + (orig_sign != sign);
598 /* Helper for expand_*_overflow. Set the __imag__ part to true
599 (1 except for signed:1 type, in which case store -1). */
601 static void
602 expand_arith_set_overflow (tree lhs, rtx target)
604 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
605 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
606 write_complex_part (target, constm1_rtx, true);
607 else
608 write_complex_part (target, const1_rtx, true);
611 /* Helper for expand_*_overflow. Store RES into the __real__ part
612 of TARGET. If RES has larger MODE than __real__ part of TARGET,
613 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
614 if LHS has smaller precision than its mode. */
616 static void
617 expand_arith_overflow_result_store (tree lhs, rtx target,
618 scalar_int_mode mode, rtx res)
620 scalar_int_mode tgtmode
621 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
622 rtx lres = res;
623 if (tgtmode != mode)
625 rtx_code_label *done_label = gen_label_rtx ();
626 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
627 lres = convert_modes (tgtmode, mode, res, uns);
628 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
629 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
630 EQ, true, mode, NULL_RTX, NULL, done_label,
631 profile_probability::very_likely ());
632 expand_arith_set_overflow (lhs, target);
633 emit_label (done_label);
635 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
636 int tgtprec = GET_MODE_PRECISION (tgtmode);
637 if (prec < tgtprec)
639 rtx_code_label *done_label = gen_label_rtx ();
640 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
641 res = lres;
642 if (uns)
644 rtx mask
645 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
646 tgtmode);
647 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
648 true, OPTAB_LIB_WIDEN);
650 else
652 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
653 NULL_RTX, 1);
654 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
655 NULL_RTX, 0);
657 do_compare_rtx_and_jump (res, lres,
658 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
659 profile_probability::very_likely ());
660 expand_arith_set_overflow (lhs, target);
661 emit_label (done_label);
663 write_complex_part (target, lres, false);
666 /* Helper for expand_*_overflow. Store RES into TARGET. */
668 static void
669 expand_ubsan_result_store (rtx target, rtx res)
671 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
672 /* If this is a scalar in a register that is stored in a wider mode
673 than the declared mode, compute the result into its declared mode
674 and then convert to the wider mode. Our value is the computed
675 expression. */
676 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
677 else
678 emit_move_insn (target, res);
681 /* Add sub/add overflow checking to the statement STMT.
682 CODE says whether the operation is +, or -. */
684 static void
685 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
686 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
687 bool uns1_p, bool is_ubsan, tree *datap)
689 rtx res, target = NULL_RTX;
690 tree fn;
691 rtx_code_label *done_label = gen_label_rtx ();
692 rtx_code_label *do_error = gen_label_rtx ();
693 do_pending_stack_adjust ();
694 rtx op0 = expand_normal (arg0);
695 rtx op1 = expand_normal (arg1);
696 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
697 int prec = GET_MODE_PRECISION (mode);
698 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
699 bool do_xor = false;
701 if (is_ubsan)
702 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
704 if (lhs)
706 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
707 if (!is_ubsan)
708 write_complex_part (target, const0_rtx, true);
711 /* We assume both operands and result have the same precision
712 here (GET_MODE_BITSIZE (mode)), S stands for signed type
713 with that precision, U for unsigned type with that precision,
714 sgn for unsigned most significant bit in that precision.
715 s1 is signed first operand, u1 is unsigned first operand,
716 s2 is signed second operand, u2 is unsigned second operand,
717 sr is signed result, ur is unsigned result and the following
718 rules say how to compute result (which is always result of
719 the operands as if both were unsigned, cast to the right
720 signedness) and how to compute whether operation overflowed.
722 s1 + s2 -> sr
723 res = (S) ((U) s1 + (U) s2)
724 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
725 s1 - s2 -> sr
726 res = (S) ((U) s1 - (U) s2)
727 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
728 u1 + u2 -> ur
729 res = u1 + u2
730 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
731 u1 - u2 -> ur
732 res = u1 - u2
733 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
734 s1 + u2 -> sr
735 res = (S) ((U) s1 + u2)
736 ovf = ((U) res ^ sgn) < u2
737 s1 + u2 -> ur
738 t1 = (S) (u2 ^ sgn)
739 t2 = s1 + t1
740 res = (U) t2 ^ sgn
741 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
742 s1 - u2 -> sr
743 res = (S) ((U) s1 - u2)
744 ovf = u2 > ((U) s1 ^ sgn)
745 s1 - u2 -> ur
746 res = (U) s1 - u2
747 ovf = s1 < 0 || u2 > (U) s1
748 u1 - s2 -> sr
749 res = u1 - (U) s2
750 ovf = u1 >= ((U) s2 ^ sgn)
751 u1 - s2 -> ur
752 t1 = u1 ^ sgn
753 t2 = t1 - (U) s2
754 res = t2 ^ sgn
755 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
756 s1 + s2 -> ur
757 res = (U) s1 + (U) s2
758 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
759 u1 + u2 -> sr
760 res = (S) (u1 + u2)
761 ovf = (U) res < u2 || res < 0
762 u1 - u2 -> sr
763 res = (S) (u1 - u2)
764 ovf = u1 >= u2 ? res < 0 : res >= 0
765 s1 - s2 -> ur
766 res = (U) s1 - (U) s2
767 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
769 if (code == PLUS_EXPR && uns0_p && !uns1_p)
771 /* PLUS_EXPR is commutative, if operand signedness differs,
772 canonicalize to the first operand being signed and second
773 unsigned to simplify following code. */
774 std::swap (op0, op1);
775 std::swap (arg0, arg1);
776 uns0_p = false;
777 uns1_p = true;
780 /* u1 +- u2 -> ur */
781 if (uns0_p && uns1_p && unsr_p)
783 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
784 : usubv4_optab, mode);
785 if (icode != CODE_FOR_nothing)
787 class expand_operand ops[4];
788 rtx_insn *last = get_last_insn ();
790 res = gen_reg_rtx (mode);
791 create_output_operand (&ops[0], res, mode);
792 create_input_operand (&ops[1], op0, mode);
793 create_input_operand (&ops[2], op1, mode);
794 create_fixed_operand (&ops[3], do_error);
795 if (maybe_expand_insn (icode, 4, ops))
797 last = get_last_insn ();
798 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
799 && JUMP_P (last)
800 && any_condjump_p (last)
801 && !find_reg_note (last, REG_BR_PROB, 0))
802 add_reg_br_prob_note (last,
803 profile_probability::very_unlikely ());
804 emit_jump (done_label);
805 goto do_error_label;
808 delete_insns_since (last);
811 /* Compute the operation. On RTL level, the addition is always
812 unsigned. */
813 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
814 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
815 rtx tem = op0;
816 /* For PLUS_EXPR, the operation is commutative, so we can pick
817 operand to compare against. For prec <= BITS_PER_WORD, I think
818 preferring REG operand is better over CONST_INT, because
819 the CONST_INT might enlarge the instruction or CSE would need
820 to figure out we'd already loaded it into a register before.
821 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
822 as then the multi-word comparison can be perhaps simplified. */
823 if (code == PLUS_EXPR
824 && (prec <= BITS_PER_WORD
825 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
826 : CONST_SCALAR_INT_P (op1)))
827 tem = op1;
828 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
829 true, mode, NULL_RTX, NULL, done_label,
830 profile_probability::very_likely ());
831 goto do_error_label;
834 /* s1 +- u2 -> sr */
835 if (!uns0_p && uns1_p && !unsr_p)
837 /* Compute the operation. On RTL level, the addition is always
838 unsigned. */
839 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
840 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
841 rtx tem = expand_binop (mode, add_optab,
842 code == PLUS_EXPR ? res : op0, sgn,
843 NULL_RTX, false, OPTAB_LIB_WIDEN);
844 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
845 done_label, profile_probability::very_likely ());
846 goto do_error_label;
849 /* s1 + u2 -> ur */
850 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
852 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
853 OPTAB_LIB_WIDEN);
854 /* As we've changed op1, we have to avoid using the value range
855 for the original argument. */
856 arg1 = error_mark_node;
857 do_xor = true;
858 goto do_signed;
861 /* u1 - s2 -> ur */
862 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
864 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
865 OPTAB_LIB_WIDEN);
866 /* As we've changed op0, we have to avoid using the value range
867 for the original argument. */
868 arg0 = error_mark_node;
869 do_xor = true;
870 goto do_signed;
873 /* s1 - u2 -> ur */
874 if (code == MINUS_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, sub_optab, op0, op1, NULL_RTX, false,
879 OPTAB_LIB_WIDEN);
880 int pos_neg = get_range_pos_neg (arg0);
881 if (pos_neg == 2)
882 /* If ARG0 is known to be always negative, this is always overflow. */
883 emit_jump (do_error);
884 else if (pos_neg == 3)
885 /* If ARG0 is not known to be always positive, check at runtime. */
886 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
887 NULL, do_error, profile_probability::very_unlikely ());
888 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
889 done_label, profile_probability::very_likely ());
890 goto do_error_label;
893 /* u1 - s2 -> sr */
894 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
896 /* Compute the operation. On RTL level, the addition is always
897 unsigned. */
898 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
899 OPTAB_LIB_WIDEN);
900 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
901 OPTAB_LIB_WIDEN);
902 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
903 done_label, profile_probability::very_likely ());
904 goto do_error_label;
907 /* u1 + u2 -> sr */
908 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
910 /* Compute the operation. On RTL level, the addition is always
911 unsigned. */
912 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
913 OPTAB_LIB_WIDEN);
914 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
915 NULL, do_error, profile_probability::very_unlikely ());
916 rtx tem = op1;
917 /* The operation is commutative, so we can pick operand to compare
918 against. For prec <= BITS_PER_WORD, I think preferring REG operand
919 is better over CONST_INT, because the CONST_INT might enlarge the
920 instruction or CSE would need to figure out we'd already loaded it
921 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
922 might be more beneficial, as then the multi-word comparison can be
923 perhaps simplified. */
924 if (prec <= BITS_PER_WORD
925 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
926 : CONST_SCALAR_INT_P (op0))
927 tem = op0;
928 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
929 done_label, profile_probability::very_likely ());
930 goto do_error_label;
933 /* s1 +- s2 -> ur */
934 if (!uns0_p && !uns1_p && unsr_p)
936 /* Compute the operation. On RTL level, the addition is always
937 unsigned. */
938 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
939 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
940 int pos_neg = get_range_pos_neg (arg1);
941 if (code == PLUS_EXPR)
943 int pos_neg0 = get_range_pos_neg (arg0);
944 if (pos_neg0 != 3 && pos_neg == 3)
946 std::swap (op0, op1);
947 pos_neg = pos_neg0;
950 rtx tem;
951 if (pos_neg != 3)
953 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
954 ? and_optab : ior_optab,
955 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
956 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
957 NULL, done_label, profile_probability::very_likely ());
959 else
961 rtx_code_label *do_ior_label = gen_label_rtx ();
962 do_compare_rtx_and_jump (op1, const0_rtx,
963 code == MINUS_EXPR ? GE : LT, false, mode,
964 NULL_RTX, NULL, do_ior_label,
965 profile_probability::even ());
966 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
967 OPTAB_LIB_WIDEN);
968 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
969 NULL, done_label, profile_probability::very_likely ());
970 emit_jump (do_error);
971 emit_label (do_ior_label);
972 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
973 OPTAB_LIB_WIDEN);
974 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
975 NULL, done_label, profile_probability::very_likely ());
977 goto do_error_label;
980 /* u1 - u2 -> sr */
981 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
983 /* Compute the operation. On RTL level, the addition is always
984 unsigned. */
985 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
986 OPTAB_LIB_WIDEN);
987 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
988 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
989 op0_geu_op1, profile_probability::even ());
990 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
991 NULL, done_label, profile_probability::very_likely ());
992 emit_jump (do_error);
993 emit_label (op0_geu_op1);
994 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
995 NULL, done_label, profile_probability::very_likely ());
996 goto do_error_label;
999 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1001 /* s1 +- s2 -> sr */
1002 do_signed:
1004 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1005 : subv4_optab, mode);
1006 if (icode != CODE_FOR_nothing)
1008 class expand_operand ops[4];
1009 rtx_insn *last = get_last_insn ();
1011 res = gen_reg_rtx (mode);
1012 create_output_operand (&ops[0], res, mode);
1013 create_input_operand (&ops[1], op0, mode);
1014 create_input_operand (&ops[2], op1, mode);
1015 create_fixed_operand (&ops[3], do_error);
1016 if (maybe_expand_insn (icode, 4, ops))
1018 last = get_last_insn ();
1019 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1020 && JUMP_P (last)
1021 && any_condjump_p (last)
1022 && !find_reg_note (last, REG_BR_PROB, 0))
1023 add_reg_br_prob_note (last,
1024 profile_probability::very_unlikely ());
1025 emit_jump (done_label);
1026 goto do_error_label;
1029 delete_insns_since (last);
1032 /* Compute the operation. On RTL level, the addition is always
1033 unsigned. */
1034 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1035 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1037 /* If we can prove that one of the arguments (for MINUS_EXPR only
1038 the second operand, as subtraction is not commutative) is always
1039 non-negative or always negative, we can do just one comparison
1040 and conditional jump. */
1041 int pos_neg = get_range_pos_neg (arg1);
1042 if (code == PLUS_EXPR)
1044 int pos_neg0 = get_range_pos_neg (arg0);
1045 if (pos_neg0 != 3 && pos_neg == 3)
1047 std::swap (op0, op1);
1048 pos_neg = pos_neg0;
1052 /* Addition overflows if and only if the two operands have the same sign,
1053 and the result has the opposite sign. Subtraction overflows if and
1054 only if the two operands have opposite sign, and the subtrahend has
1055 the same sign as the result. Here 0 is counted as positive. */
1056 if (pos_neg == 3)
1058 /* Compute op0 ^ op1 (operands have opposite sign). */
1059 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1060 OPTAB_LIB_WIDEN);
1062 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1063 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1064 OPTAB_LIB_WIDEN);
1066 rtx tem;
1067 if (code == PLUS_EXPR)
1069 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1070 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1071 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1072 OPTAB_LIB_WIDEN);
1074 else
1076 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1077 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1078 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1079 OPTAB_LIB_WIDEN);
1082 /* No overflow if the result has bit sign cleared. */
1083 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1084 NULL, done_label, profile_probability::very_likely ());
1087 /* Compare the result of the operation with the first operand.
1088 No overflow for addition if second operand is positive and result
1089 is larger or second operand is negative and result is smaller.
1090 Likewise for subtraction with sign of second operand flipped. */
1091 else
1092 do_compare_rtx_and_jump (res, op0,
1093 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1094 false, mode, NULL_RTX, NULL, done_label,
1095 profile_probability::very_likely ());
1098 do_error_label:
1099 emit_label (do_error);
1100 if (is_ubsan)
1102 /* Expand the ubsan builtin call. */
1103 push_temp_slots ();
1104 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1105 arg0, arg1, datap);
1106 expand_normal (fn);
1107 pop_temp_slots ();
1108 do_pending_stack_adjust ();
1110 else if (lhs)
1111 expand_arith_set_overflow (lhs, target);
1113 /* We're done. */
1114 emit_label (done_label);
1116 if (lhs)
1118 if (is_ubsan)
1119 expand_ubsan_result_store (target, res);
1120 else
1122 if (do_xor)
1123 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1124 OPTAB_LIB_WIDEN);
1126 expand_arith_overflow_result_store (lhs, target, mode, res);
1131 /* Add negate overflow checking to the statement STMT. */
1133 static void
1134 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1135 tree *datap)
1137 rtx res, op1;
1138 tree fn;
1139 rtx_code_label *done_label, *do_error;
1140 rtx target = NULL_RTX;
1142 done_label = gen_label_rtx ();
1143 do_error = gen_label_rtx ();
1145 do_pending_stack_adjust ();
1146 op1 = expand_normal (arg1);
1148 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1149 if (lhs)
1151 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1152 if (!is_ubsan)
1153 write_complex_part (target, const0_rtx, true);
1156 enum insn_code icode = optab_handler (negv3_optab, mode);
1157 if (icode != CODE_FOR_nothing)
1159 class expand_operand ops[3];
1160 rtx_insn *last = get_last_insn ();
1162 res = gen_reg_rtx (mode);
1163 create_output_operand (&ops[0], res, mode);
1164 create_input_operand (&ops[1], op1, mode);
1165 create_fixed_operand (&ops[2], do_error);
1166 if (maybe_expand_insn (icode, 3, ops))
1168 last = get_last_insn ();
1169 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1170 && JUMP_P (last)
1171 && any_condjump_p (last)
1172 && !find_reg_note (last, REG_BR_PROB, 0))
1173 add_reg_br_prob_note (last,
1174 profile_probability::very_unlikely ());
1175 emit_jump (done_label);
1177 else
1179 delete_insns_since (last);
1180 icode = CODE_FOR_nothing;
1184 if (icode == CODE_FOR_nothing)
1186 /* Compute the operation. On RTL level, the addition is always
1187 unsigned. */
1188 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1190 /* Compare the operand with the most negative value. */
1191 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1192 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1193 done_label, profile_probability::very_likely ());
1196 emit_label (do_error);
1197 if (is_ubsan)
1199 /* Expand the ubsan builtin call. */
1200 push_temp_slots ();
1201 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1202 arg1, NULL_TREE, datap);
1203 expand_normal (fn);
1204 pop_temp_slots ();
1205 do_pending_stack_adjust ();
1207 else if (lhs)
1208 expand_arith_set_overflow (lhs, target);
1210 /* We're done. */
1211 emit_label (done_label);
1213 if (lhs)
1215 if (is_ubsan)
1216 expand_ubsan_result_store (target, res);
1217 else
1218 expand_arith_overflow_result_store (lhs, target, mode, res);
1222 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1223 mode MODE can be expanded without using a libcall. */
1225 static bool
1226 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1227 rtx op0, rtx op1, bool uns)
1229 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1230 != CODE_FOR_nothing)
1231 return true;
1233 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1234 != CODE_FOR_nothing)
1235 return true;
1237 rtx_insn *last = get_last_insn ();
1238 if (CONSTANT_P (op0))
1239 op0 = convert_modes (wmode, mode, op0, uns);
1240 else
1241 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1242 if (CONSTANT_P (op1))
1243 op1 = convert_modes (wmode, mode, op1, uns);
1244 else
1245 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1246 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1247 delete_insns_since (last);
1248 return ret != NULL_RTX;
1251 /* Add mul overflow checking to the statement STMT. */
1253 static void
1254 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1255 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1256 tree *datap)
1258 rtx res, op0, op1;
1259 tree fn, type;
1260 rtx_code_label *done_label, *do_error;
1261 rtx target = NULL_RTX;
1262 signop sign;
1263 enum insn_code icode;
1265 done_label = gen_label_rtx ();
1266 do_error = gen_label_rtx ();
1268 do_pending_stack_adjust ();
1269 op0 = expand_normal (arg0);
1270 op1 = expand_normal (arg1);
1272 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1273 bool uns = unsr_p;
1274 if (lhs)
1276 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1277 if (!is_ubsan)
1278 write_complex_part (target, const0_rtx, true);
1281 if (is_ubsan)
1282 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1284 /* We assume both operands and result have the same precision
1285 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1286 with that precision, U for unsigned type with that precision,
1287 sgn for unsigned most significant bit in that precision.
1288 s1 is signed first operand, u1 is unsigned first operand,
1289 s2 is signed second operand, u2 is unsigned second operand,
1290 sr is signed result, ur is unsigned result and the following
1291 rules say how to compute result (which is always result of
1292 the operands as if both were unsigned, cast to the right
1293 signedness) and how to compute whether operation overflowed.
1294 main_ovf (false) stands for jump on signed multiplication
1295 overflow or the main algorithm with uns == false.
1296 main_ovf (true) stands for jump on unsigned multiplication
1297 overflow or the main algorithm with uns == true.
1299 s1 * s2 -> sr
1300 res = (S) ((U) s1 * (U) s2)
1301 ovf = main_ovf (false)
1302 u1 * u2 -> ur
1303 res = u1 * u2
1304 ovf = main_ovf (true)
1305 s1 * u2 -> ur
1306 res = (U) s1 * u2
1307 ovf = (s1 < 0 && u2) || main_ovf (true)
1308 u1 * u2 -> sr
1309 res = (S) (u1 * u2)
1310 ovf = res < 0 || main_ovf (true)
1311 s1 * u2 -> sr
1312 res = (S) ((U) s1 * u2)
1313 ovf = (S) u2 >= 0 ? main_ovf (false)
1314 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1315 s1 * s2 -> ur
1316 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1317 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1318 res = t1 * t2
1319 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1321 if (uns0_p && !uns1_p)
1323 /* Multiplication is commutative, if operand signedness differs,
1324 canonicalize to the first operand being signed and second
1325 unsigned to simplify following code. */
1326 std::swap (op0, op1);
1327 std::swap (arg0, arg1);
1328 uns0_p = false;
1329 uns1_p = true;
1332 int pos_neg0 = get_range_pos_neg (arg0);
1333 int pos_neg1 = get_range_pos_neg (arg1);
1335 /* s1 * u2 -> ur */
1336 if (!uns0_p && uns1_p && unsr_p)
1338 switch (pos_neg0)
1340 case 1:
1341 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1342 goto do_main;
1343 case 2:
1344 /* If s1 is negative, avoid the main code, just multiply and
1345 signal overflow if op1 is not 0. */
1346 struct separate_ops ops;
1347 ops.code = MULT_EXPR;
1348 ops.type = TREE_TYPE (arg1);
1349 ops.op0 = make_tree (ops.type, op0);
1350 ops.op1 = make_tree (ops.type, op1);
1351 ops.op2 = NULL_TREE;
1352 ops.location = loc;
1353 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1354 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1355 NULL, done_label, profile_probability::very_likely ());
1356 goto do_error_label;
1357 case 3:
1358 rtx_code_label *do_main_label;
1359 do_main_label = gen_label_rtx ();
1360 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1361 NULL, do_main_label, profile_probability::very_likely ());
1362 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1363 NULL, do_main_label, profile_probability::very_likely ());
1364 expand_arith_set_overflow (lhs, target);
1365 emit_label (do_main_label);
1366 goto do_main;
1367 default:
1368 gcc_unreachable ();
1372 /* u1 * u2 -> sr */
1373 if (uns0_p && uns1_p && !unsr_p)
1375 uns = true;
1376 /* Rest of handling of this case after res is computed. */
1377 goto do_main;
1380 /* s1 * u2 -> sr */
1381 if (!uns0_p && uns1_p && !unsr_p)
1383 switch (pos_neg1)
1385 case 1:
1386 goto do_main;
1387 case 2:
1388 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1389 avoid the main code, just multiply and signal overflow
1390 unless 0 * u2 or -1 * ((U) Smin). */
1391 struct separate_ops ops;
1392 ops.code = MULT_EXPR;
1393 ops.type = TREE_TYPE (arg1);
1394 ops.op0 = make_tree (ops.type, op0);
1395 ops.op1 = make_tree (ops.type, op1);
1396 ops.op2 = NULL_TREE;
1397 ops.location = loc;
1398 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1399 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1400 NULL, done_label, profile_probability::very_likely ());
1401 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1402 NULL, do_error, profile_probability::very_unlikely ());
1403 int prec;
1404 prec = GET_MODE_PRECISION (mode);
1405 rtx sgn;
1406 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1407 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1408 NULL, done_label, profile_probability::very_likely ());
1409 goto do_error_label;
1410 case 3:
1411 /* Rest of handling of this case after res is computed. */
1412 goto do_main;
1413 default:
1414 gcc_unreachable ();
1418 /* s1 * s2 -> ur */
1419 if (!uns0_p && !uns1_p && unsr_p)
1421 rtx tem;
1422 switch (pos_neg0 | pos_neg1)
1424 case 1: /* Both operands known to be non-negative. */
1425 goto do_main;
1426 case 2: /* Both operands known to be negative. */
1427 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1428 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1429 /* Avoid looking at arg0/arg1 ranges, as we've changed
1430 the arguments. */
1431 arg0 = error_mark_node;
1432 arg1 = error_mark_node;
1433 goto do_main;
1434 case 3:
1435 if ((pos_neg0 ^ pos_neg1) == 3)
1437 /* If one operand is known to be negative and the other
1438 non-negative, this overflows always, unless the non-negative
1439 one is 0. Just do normal multiply and set overflow
1440 unless one of the operands is 0. */
1441 struct separate_ops ops;
1442 ops.code = MULT_EXPR;
1443 ops.type
1444 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1446 ops.op0 = make_tree (ops.type, op0);
1447 ops.op1 = make_tree (ops.type, op1);
1448 ops.op2 = NULL_TREE;
1449 ops.location = loc;
1450 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1451 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1452 true, mode, NULL_RTX, NULL, done_label,
1453 profile_probability::very_likely ());
1454 goto do_error_label;
1456 /* The general case, do all the needed comparisons at runtime. */
1457 rtx_code_label *do_main_label, *after_negate_label;
1458 rtx rop0, rop1;
1459 rop0 = gen_reg_rtx (mode);
1460 rop1 = gen_reg_rtx (mode);
1461 emit_move_insn (rop0, op0);
1462 emit_move_insn (rop1, op1);
1463 op0 = rop0;
1464 op1 = rop1;
1465 do_main_label = gen_label_rtx ();
1466 after_negate_label = gen_label_rtx ();
1467 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1468 OPTAB_LIB_WIDEN);
1469 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1470 NULL, after_negate_label, profile_probability::very_likely ());
1471 /* Both arguments negative here, negate them and continue with
1472 normal unsigned overflow checking multiplication. */
1473 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1474 NULL_RTX, false));
1475 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1476 NULL_RTX, false));
1477 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1478 the arguments. */
1479 arg0 = error_mark_node;
1480 arg1 = error_mark_node;
1481 emit_jump (do_main_label);
1482 emit_label (after_negate_label);
1483 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1484 OPTAB_LIB_WIDEN);
1485 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1486 NULL, do_main_label,
1487 profile_probability::very_likely ());
1488 /* One argument is negative here, the other positive. This
1489 overflows always, unless one of the arguments is 0. But
1490 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1491 is, thus we can keep do_main code oring in overflow as is. */
1492 if (pos_neg0 != 2)
1493 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1494 NULL, do_main_label,
1495 profile_probability::very_unlikely ());
1496 if (pos_neg1 != 2)
1497 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1498 NULL, do_main_label,
1499 profile_probability::very_unlikely ());
1500 expand_arith_set_overflow (lhs, target);
1501 emit_label (do_main_label);
1502 goto do_main;
1503 default:
1504 gcc_unreachable ();
1508 do_main:
1509 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1510 sign = uns ? UNSIGNED : SIGNED;
1511 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1512 if (uns
1513 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1514 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1516 /* Optimize unsigned multiplication by power of 2 constant
1517 using 2 shifts, one for result, one to extract the shifted
1518 out bits to see if they are all zero.
1519 Don't do this if optimizing for size and we have umulv4_optab,
1520 in that case assume multiplication will be shorter.
1521 This is heuristics based on the single target that provides
1522 umulv4 right now (i?86/x86_64), if further targets add it, this
1523 might need to be revisited.
1524 Cases where both operands are constant should be folded already
1525 during GIMPLE, and cases where one operand is constant but not
1526 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1527 below can be done without multiplication, just by shifts and adds,
1528 or we'd need to divide the result (and hope it actually doesn't
1529 really divide nor multiply) and compare the result of the division
1530 with the original operand. */
1531 rtx opn0 = op0;
1532 rtx opn1 = op1;
1533 tree argn0 = arg0;
1534 tree argn1 = arg1;
1535 if (integer_pow2p (arg0))
1537 std::swap (opn0, opn1);
1538 std::swap (argn0, argn1);
1540 int cnt = tree_log2 (argn1);
1541 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1543 rtx upper = const0_rtx;
1544 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1545 if (cnt != 0)
1546 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1547 GET_MODE_PRECISION (mode) - cnt,
1548 NULL_RTX, uns);
1549 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1550 NULL_RTX, NULL, done_label,
1551 profile_probability::very_likely ());
1552 goto do_error_label;
1555 if (icode != CODE_FOR_nothing)
1557 class expand_operand ops[4];
1558 rtx_insn *last = get_last_insn ();
1560 res = gen_reg_rtx (mode);
1561 create_output_operand (&ops[0], res, mode);
1562 create_input_operand (&ops[1], op0, mode);
1563 create_input_operand (&ops[2], op1, mode);
1564 create_fixed_operand (&ops[3], do_error);
1565 if (maybe_expand_insn (icode, 4, ops))
1567 last = get_last_insn ();
1568 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1569 && JUMP_P (last)
1570 && any_condjump_p (last)
1571 && !find_reg_note (last, REG_BR_PROB, 0))
1572 add_reg_br_prob_note (last,
1573 profile_probability::very_unlikely ());
1574 emit_jump (done_label);
1576 else
1578 delete_insns_since (last);
1579 icode = CODE_FOR_nothing;
1583 if (icode == CODE_FOR_nothing)
1585 struct separate_ops ops;
1586 int prec = GET_MODE_PRECISION (mode);
1587 scalar_int_mode hmode, wmode;
1588 ops.op0 = make_tree (type, op0);
1589 ops.op1 = make_tree (type, op1);
1590 ops.op2 = NULL_TREE;
1591 ops.location = loc;
1593 /* Optimize unsigned overflow check where we don't use the
1594 multiplication result, just whether overflow happened.
1595 If we can do MULT_HIGHPART_EXPR, that followed by
1596 comparison of the result against zero is cheapest.
1597 We'll still compute res, but it should be DCEd later. */
1598 use_operand_p use;
1599 gimple *use_stmt;
1600 if (!is_ubsan
1601 && lhs
1602 && uns
1603 && !(uns0_p && uns1_p && !unsr_p)
1604 && can_mult_highpart_p (mode, uns) == 1
1605 && single_imm_use (lhs, &use, &use_stmt)
1606 && is_gimple_assign (use_stmt)
1607 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1608 goto highpart;
1610 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1611 && targetm.scalar_mode_supported_p (wmode)
1612 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1614 twoxwider:
1615 ops.code = WIDEN_MULT_EXPR;
1616 ops.type
1617 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1619 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1620 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1621 NULL_RTX, uns);
1622 hipart = convert_modes (mode, wmode, hipart, uns);
1623 res = convert_modes (mode, wmode, res, uns);
1624 if (uns)
1625 /* For the unsigned multiplication, there was overflow if
1626 HIPART is non-zero. */
1627 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1628 NULL_RTX, NULL, done_label,
1629 profile_probability::very_likely ());
1630 else
1632 /* RES is used more than once, place it in a pseudo. */
1633 res = force_reg (mode, res);
1635 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1636 NULL_RTX, 0);
1637 /* RES is low half of the double width result, HIPART
1638 the high half. There was overflow if
1639 HIPART is different from RES < 0 ? -1 : 0. */
1640 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1641 NULL_RTX, NULL, done_label,
1642 profile_probability::very_likely ());
1645 else if (can_mult_highpart_p (mode, uns) == 1)
1647 highpart:
1648 ops.code = MULT_HIGHPART_EXPR;
1649 ops.type = type;
1651 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1652 EXPAND_NORMAL);
1653 ops.code = MULT_EXPR;
1654 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1655 if (uns)
1656 /* For the unsigned multiplication, there was overflow if
1657 HIPART is non-zero. */
1658 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1659 NULL_RTX, NULL, done_label,
1660 profile_probability::very_likely ());
1661 else
1663 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1664 NULL_RTX, 0);
1665 /* RES is low half of the double width result, HIPART
1666 the high half. There was overflow if
1667 HIPART is different from RES < 0 ? -1 : 0. */
1668 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1669 NULL_RTX, NULL, done_label,
1670 profile_probability::very_likely ());
1674 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
1675 && 2 * GET_MODE_PRECISION (hmode) == prec)
1677 rtx_code_label *large_op0 = gen_label_rtx ();
1678 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1679 rtx_code_label *one_small_one_large = gen_label_rtx ();
1680 rtx_code_label *both_ops_large = gen_label_rtx ();
1681 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1682 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1683 rtx_code_label *do_overflow = gen_label_rtx ();
1684 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1686 unsigned int hprec = GET_MODE_PRECISION (hmode);
1687 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1688 NULL_RTX, uns);
1689 hipart0 = convert_modes (hmode, mode, hipart0, uns);
1690 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1691 rtx signbit0 = const0_rtx;
1692 if (!uns)
1693 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1694 NULL_RTX, 0);
1695 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1696 NULL_RTX, uns);
1697 hipart1 = convert_modes (hmode, mode, hipart1, uns);
1698 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1699 rtx signbit1 = const0_rtx;
1700 if (!uns)
1701 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1702 NULL_RTX, 0);
1704 res = gen_reg_rtx (mode);
1706 /* True if op0 resp. op1 are known to be in the range of
1707 halfstype. */
1708 bool op0_small_p = false;
1709 bool op1_small_p = false;
1710 /* True if op0 resp. op1 are known to have all zeros or all ones
1711 in the upper half of bits, but are not known to be
1712 op{0,1}_small_p. */
1713 bool op0_medium_p = false;
1714 bool op1_medium_p = false;
1715 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1716 nonnegative, 1 if unknown. */
1717 int op0_sign = 1;
1718 int op1_sign = 1;
1720 if (pos_neg0 == 1)
1721 op0_sign = 0;
1722 else if (pos_neg0 == 2)
1723 op0_sign = -1;
1724 if (pos_neg1 == 1)
1725 op1_sign = 0;
1726 else if (pos_neg1 == 2)
1727 op1_sign = -1;
1729 unsigned int mprec0 = prec;
1730 if (arg0 != error_mark_node)
1731 mprec0 = get_min_precision (arg0, sign);
1732 if (mprec0 <= hprec)
1733 op0_small_p = true;
1734 else if (!uns && mprec0 <= hprec + 1)
1735 op0_medium_p = true;
1736 unsigned int mprec1 = prec;
1737 if (arg1 != error_mark_node)
1738 mprec1 = get_min_precision (arg1, sign);
1739 if (mprec1 <= hprec)
1740 op1_small_p = true;
1741 else if (!uns && mprec1 <= hprec + 1)
1742 op1_medium_p = true;
1744 int smaller_sign = 1;
1745 int larger_sign = 1;
1746 if (op0_small_p)
1748 smaller_sign = op0_sign;
1749 larger_sign = op1_sign;
1751 else if (op1_small_p)
1753 smaller_sign = op1_sign;
1754 larger_sign = op0_sign;
1756 else if (op0_sign == op1_sign)
1758 smaller_sign = op0_sign;
1759 larger_sign = op0_sign;
1762 if (!op0_small_p)
1763 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1764 NULL_RTX, NULL, large_op0,
1765 profile_probability::unlikely ());
1767 if (!op1_small_p)
1768 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1769 NULL_RTX, NULL, small_op0_large_op1,
1770 profile_probability::unlikely ());
1772 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1773 hmode to mode, the multiplication will never overflow. We can
1774 do just one hmode x hmode => mode widening multiplication. */
1775 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1776 ops.op0 = make_tree (halfstype, lopart0);
1777 ops.op1 = make_tree (halfstype, lopart1);
1778 ops.code = WIDEN_MULT_EXPR;
1779 ops.type = type;
1780 rtx thisres
1781 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1782 emit_move_insn (res, thisres);
1783 emit_jump (done_label);
1785 emit_label (small_op0_large_op1);
1787 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1788 but op1 is not, just swap the arguments and handle it as op1
1789 sign/zero extended, op0 not. */
1790 rtx larger = gen_reg_rtx (mode);
1791 rtx hipart = gen_reg_rtx (hmode);
1792 rtx lopart = gen_reg_rtx (hmode);
1793 emit_move_insn (larger, op1);
1794 emit_move_insn (hipart, hipart1);
1795 emit_move_insn (lopart, lopart0);
1796 emit_jump (one_small_one_large);
1798 emit_label (large_op0);
1800 if (!op1_small_p)
1801 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1802 NULL_RTX, NULL, both_ops_large,
1803 profile_probability::unlikely ());
1805 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1806 but op0 is not, prepare larger, hipart and lopart pseudos and
1807 handle it together with small_op0_large_op1. */
1808 emit_move_insn (larger, op0);
1809 emit_move_insn (hipart, hipart0);
1810 emit_move_insn (lopart, lopart1);
1812 emit_label (one_small_one_large);
1814 /* lopart is the low part of the operand that is sign extended
1815 to mode, larger is the other operand, hipart is the
1816 high part of larger and lopart0 and lopart1 are the low parts
1817 of both operands.
1818 We perform lopart0 * lopart1 and lopart * hipart widening
1819 multiplications. */
1820 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1821 ops.op0 = make_tree (halfutype, lopart0);
1822 ops.op1 = make_tree (halfutype, lopart1);
1823 rtx lo0xlo1
1824 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1826 ops.op0 = make_tree (halfutype, lopart);
1827 ops.op1 = make_tree (halfutype, hipart);
1828 rtx loxhi = gen_reg_rtx (mode);
1829 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1830 emit_move_insn (loxhi, tem);
1832 if (!uns)
1834 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1835 if (larger_sign == 0)
1836 emit_jump (after_hipart_neg);
1837 else if (larger_sign != -1)
1838 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1839 NULL_RTX, NULL, after_hipart_neg,
1840 profile_probability::even ());
1842 tem = convert_modes (mode, hmode, lopart, 1);
1843 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1844 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1845 1, OPTAB_WIDEN);
1846 emit_move_insn (loxhi, tem);
1848 emit_label (after_hipart_neg);
1850 /* if (lopart < 0) loxhi -= larger; */
1851 if (smaller_sign == 0)
1852 emit_jump (after_lopart_neg);
1853 else if (smaller_sign != -1)
1854 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1855 NULL_RTX, NULL, after_lopart_neg,
1856 profile_probability::even ());
1858 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1859 1, OPTAB_WIDEN);
1860 emit_move_insn (loxhi, tem);
1862 emit_label (after_lopart_neg);
1865 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1866 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1867 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1868 1, OPTAB_WIDEN);
1869 emit_move_insn (loxhi, tem);
1871 /* if (loxhi >> (bitsize / 2)
1872 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1873 if (loxhi >> (bitsize / 2) == 0 (if uns). */
1874 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1875 NULL_RTX, 0);
1876 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1877 rtx signbitloxhi = const0_rtx;
1878 if (!uns)
1879 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1880 convert_modes (hmode, mode,
1881 loxhi, 0),
1882 hprec - 1, NULL_RTX, 0);
1884 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1885 NULL_RTX, NULL, do_overflow,
1886 profile_probability::very_unlikely ());
1888 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1889 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1890 NULL_RTX, 1);
1891 tem = convert_modes (mode, hmode,
1892 convert_modes (hmode, mode, lo0xlo1, 1), 1);
1894 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1895 1, OPTAB_WIDEN);
1896 if (tem != res)
1897 emit_move_insn (res, tem);
1898 emit_jump (done_label);
1900 emit_label (both_ops_large);
1902 /* If both operands are large (not sign (!uns) or zero (uns)
1903 extended from hmode), then perform the full multiplication
1904 which will be the result of the operation.
1905 The only cases which don't overflow are for signed multiplication
1906 some cases where both hipart0 and highpart1 are 0 or -1.
1907 For unsigned multiplication when high parts are both non-zero
1908 this overflows always. */
1909 ops.code = MULT_EXPR;
1910 ops.op0 = make_tree (type, op0);
1911 ops.op1 = make_tree (type, op1);
1912 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1913 emit_move_insn (res, tem);
1915 if (!uns)
1917 if (!op0_medium_p)
1919 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1920 NULL_RTX, 1, OPTAB_WIDEN);
1921 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1922 NULL_RTX, NULL, do_error,
1923 profile_probability::very_unlikely ());
1926 if (!op1_medium_p)
1928 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1929 NULL_RTX, 1, OPTAB_WIDEN);
1930 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1931 NULL_RTX, NULL, do_error,
1932 profile_probability::very_unlikely ());
1935 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1936 the same, overflow happened if res is non-positive, if they
1937 are different, overflow happened if res is positive. */
1938 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1939 emit_jump (hipart_different);
1940 else if (op0_sign == 1 || op1_sign == 1)
1941 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1942 NULL_RTX, NULL, hipart_different,
1943 profile_probability::even ());
1945 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
1946 NULL_RTX, NULL, do_error,
1947 profile_probability::very_unlikely ());
1948 emit_jump (done_label);
1950 emit_label (hipart_different);
1952 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1953 NULL_RTX, NULL, do_error,
1954 profile_probability::very_unlikely ());
1955 emit_jump (done_label);
1958 emit_label (do_overflow);
1960 /* Overflow, do full multiplication and fallthru into do_error. */
1961 ops.op0 = make_tree (type, op0);
1962 ops.op1 = make_tree (type, op1);
1963 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1964 emit_move_insn (res, tem);
1966 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1967 && targetm.scalar_mode_supported_p (wmode))
1968 /* Even emitting a libcall is better than not detecting overflow
1969 at all. */
1970 goto twoxwider;
1971 else
1973 gcc_assert (!is_ubsan);
1974 ops.code = MULT_EXPR;
1975 ops.type = type;
1976 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1977 emit_jump (done_label);
1981 do_error_label:
1982 emit_label (do_error);
1983 if (is_ubsan)
1985 /* Expand the ubsan builtin call. */
1986 push_temp_slots ();
1987 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1988 arg0, arg1, datap);
1989 expand_normal (fn);
1990 pop_temp_slots ();
1991 do_pending_stack_adjust ();
1993 else if (lhs)
1994 expand_arith_set_overflow (lhs, target);
1996 /* We're done. */
1997 emit_label (done_label);
1999 /* u1 * u2 -> sr */
2000 if (uns0_p && uns1_p && !unsr_p)
2002 rtx_code_label *all_done_label = gen_label_rtx ();
2003 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2004 NULL, all_done_label, profile_probability::very_likely ());
2005 expand_arith_set_overflow (lhs, target);
2006 emit_label (all_done_label);
2009 /* s1 * u2 -> sr */
2010 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2012 rtx_code_label *all_done_label = gen_label_rtx ();
2013 rtx_code_label *set_noovf = gen_label_rtx ();
2014 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2015 NULL, all_done_label, profile_probability::very_likely ());
2016 expand_arith_set_overflow (lhs, target);
2017 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2018 NULL, set_noovf, profile_probability::very_likely ());
2019 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2020 NULL, all_done_label, profile_probability::very_unlikely ());
2021 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2022 all_done_label, profile_probability::very_unlikely ());
2023 emit_label (set_noovf);
2024 write_complex_part (target, const0_rtx, true);
2025 emit_label (all_done_label);
2028 if (lhs)
2030 if (is_ubsan)
2031 expand_ubsan_result_store (target, res);
2032 else
2033 expand_arith_overflow_result_store (lhs, target, mode, res);
2037 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2039 static void
2040 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2041 tree arg0, tree arg1)
2043 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2044 rtx_code_label *loop_lab = NULL;
2045 rtx cntvar = NULL_RTX;
2046 tree cntv = NULL_TREE;
2047 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2048 tree sz = TYPE_SIZE (eltype);
2049 tree data = NULL_TREE;
2050 tree resv = NULL_TREE;
2051 rtx lhsr = NULL_RTX;
2052 rtx resvr = NULL_RTX;
2053 unsigned HOST_WIDE_INT const_cnt = 0;
2054 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2056 if (lhs)
2058 optab op;
2059 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2060 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2061 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2062 optab_default)) == unknown_optab
2063 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2064 == CODE_FOR_nothing))
2066 if (MEM_P (lhsr))
2067 resv = make_tree (TREE_TYPE (lhs), lhsr);
2068 else
2070 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2071 resv = make_tree (TREE_TYPE (lhs), resvr);
2075 if (use_loop_p)
2077 do_pending_stack_adjust ();
2078 loop_lab = gen_label_rtx ();
2079 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2080 cntv = make_tree (sizetype, cntvar);
2081 emit_move_insn (cntvar, const0_rtx);
2082 emit_label (loop_lab);
2084 if (TREE_CODE (arg0) != VECTOR_CST)
2086 rtx arg0r = expand_normal (arg0);
2087 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2089 if (TREE_CODE (arg1) != VECTOR_CST)
2091 rtx arg1r = expand_normal (arg1);
2092 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2094 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2096 tree op0, op1, res = NULL_TREE;
2097 if (use_loop_p)
2099 tree atype = build_array_type_nelts (eltype, cnt);
2100 op0 = uniform_vector_p (arg0);
2101 if (op0 == NULL_TREE)
2103 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2104 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2105 NULL_TREE, NULL_TREE);
2107 op1 = uniform_vector_p (arg1);
2108 if (op1 == NULL_TREE)
2110 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2111 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2112 NULL_TREE, NULL_TREE);
2114 if (resv)
2116 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2117 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2118 NULL_TREE, NULL_TREE);
2121 else
2123 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2124 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2125 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2126 if (resv)
2127 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2128 bitpos);
2130 switch (code)
2132 case PLUS_EXPR:
2133 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2134 false, false, false, true, &data);
2135 break;
2136 case MINUS_EXPR:
2137 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2138 expand_neg_overflow (loc, res, op1, true, &data);
2139 else
2140 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2141 false, false, false, true, &data);
2142 break;
2143 case MULT_EXPR:
2144 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2145 true, &data);
2146 break;
2147 default:
2148 gcc_unreachable ();
2151 if (use_loop_p)
2153 struct separate_ops ops;
2154 ops.code = PLUS_EXPR;
2155 ops.type = TREE_TYPE (cntv);
2156 ops.op0 = cntv;
2157 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2158 ops.op2 = NULL_TREE;
2159 ops.location = loc;
2160 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2161 EXPAND_NORMAL);
2162 if (ret != cntvar)
2163 emit_move_insn (cntvar, ret);
2164 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2165 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2166 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2167 profile_probability::very_likely ());
2169 if (lhs && resv == NULL_TREE)
2171 struct separate_ops ops;
2172 ops.code = code;
2173 ops.type = TREE_TYPE (arg0);
2174 ops.op0 = arg0;
2175 ops.op1 = arg1;
2176 ops.op2 = NULL_TREE;
2177 ops.location = loc;
2178 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2179 EXPAND_NORMAL);
2180 if (ret != lhsr)
2181 emit_move_insn (lhsr, ret);
2183 else if (resvr)
2184 emit_move_insn (lhsr, resvr);
2187 /* Expand UBSAN_CHECK_ADD call STMT. */
2189 static void
2190 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2192 location_t loc = gimple_location (stmt);
2193 tree lhs = gimple_call_lhs (stmt);
2194 tree arg0 = gimple_call_arg (stmt, 0);
2195 tree arg1 = gimple_call_arg (stmt, 1);
2196 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2197 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2198 else
2199 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2200 false, false, false, true, NULL);
2203 /* Expand UBSAN_CHECK_SUB call STMT. */
2205 static void
2206 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2208 location_t loc = gimple_location (stmt);
2209 tree lhs = gimple_call_lhs (stmt);
2210 tree arg0 = gimple_call_arg (stmt, 0);
2211 tree arg1 = gimple_call_arg (stmt, 1);
2212 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2213 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2214 else if (integer_zerop (arg0))
2215 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2216 else
2217 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2218 false, false, false, true, NULL);
2221 /* Expand UBSAN_CHECK_MUL call STMT. */
2223 static void
2224 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2226 location_t loc = gimple_location (stmt);
2227 tree lhs = gimple_call_lhs (stmt);
2228 tree arg0 = gimple_call_arg (stmt, 0);
2229 tree arg1 = gimple_call_arg (stmt, 1);
2230 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2231 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2232 else
2233 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2234 NULL);
2237 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2239 static void
2240 expand_arith_overflow (enum tree_code code, gimple *stmt)
2242 tree lhs = gimple_call_lhs (stmt);
2243 if (lhs == NULL_TREE)
2244 return;
2245 tree arg0 = gimple_call_arg (stmt, 0);
2246 tree arg1 = gimple_call_arg (stmt, 1);
2247 tree type = TREE_TYPE (TREE_TYPE (lhs));
2248 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2249 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2250 int unsr_p = TYPE_UNSIGNED (type);
2251 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2252 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2253 int precres = TYPE_PRECISION (type);
2254 location_t loc = gimple_location (stmt);
2255 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2256 uns0_p = true;
2257 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2258 uns1_p = true;
2259 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2260 prec0 = MIN (prec0, pr);
2261 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2262 prec1 = MIN (prec1, pr);
2264 /* If uns0_p && uns1_p, precop is minimum needed precision
2265 of unsigned type to hold the exact result, otherwise
2266 precop is minimum needed precision of signed type to
2267 hold the exact result. */
2268 int precop;
2269 if (code == MULT_EXPR)
2270 precop = prec0 + prec1 + (uns0_p != uns1_p);
2271 else
2273 if (uns0_p == uns1_p)
2274 precop = MAX (prec0, prec1) + 1;
2275 else if (uns0_p)
2276 precop = MAX (prec0 + 1, prec1) + 1;
2277 else
2278 precop = MAX (prec0, prec1 + 1) + 1;
2280 int orig_precres = precres;
2284 if ((uns0_p && uns1_p)
2285 ? ((precop + !unsr_p) <= precres
2286 /* u1 - u2 -> ur can overflow, no matter what precision
2287 the result has. */
2288 && (code != MINUS_EXPR || !unsr_p))
2289 : (!unsr_p && precop <= precres))
2291 /* The infinity precision result will always fit into result. */
2292 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2293 write_complex_part (target, const0_rtx, true);
2294 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2295 struct separate_ops ops;
2296 ops.code = code;
2297 ops.type = type;
2298 ops.op0 = fold_convert_loc (loc, type, arg0);
2299 ops.op1 = fold_convert_loc (loc, type, arg1);
2300 ops.op2 = NULL_TREE;
2301 ops.location = loc;
2302 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2303 expand_arith_overflow_result_store (lhs, target, mode, tem);
2304 return;
2307 /* For operations with low precision, if target doesn't have them, start
2308 with precres widening right away, otherwise do it only if the most
2309 simple cases can't be used. */
2310 const int min_precision = targetm.min_arithmetic_precision ();
2311 if (orig_precres == precres && precres < min_precision)
2313 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2314 && prec1 <= precres)
2315 || ((!uns0_p || !uns1_p) && !unsr_p
2316 && prec0 + uns0_p <= precres
2317 && prec1 + uns1_p <= precres))
2319 arg0 = fold_convert_loc (loc, type, arg0);
2320 arg1 = fold_convert_loc (loc, type, arg1);
2321 switch (code)
2323 case MINUS_EXPR:
2324 if (integer_zerop (arg0) && !unsr_p)
2326 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2327 return;
2329 /* FALLTHRU */
2330 case PLUS_EXPR:
2331 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2332 unsr_p, unsr_p, false, NULL);
2333 return;
2334 case MULT_EXPR:
2335 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2336 unsr_p, unsr_p, false, NULL);
2337 return;
2338 default:
2339 gcc_unreachable ();
2343 /* For sub-word operations, retry with a wider type first. */
2344 if (orig_precres == precres && precop <= BITS_PER_WORD)
2346 int p = MAX (min_precision, precop);
2347 scalar_int_mode m = smallest_int_mode_for_size (p);
2348 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2349 uns0_p && uns1_p
2350 && unsr_p);
2351 p = TYPE_PRECISION (optype);
2352 if (p > precres)
2354 precres = p;
2355 unsr_p = TYPE_UNSIGNED (optype);
2356 type = optype;
2357 continue;
2361 if (prec0 <= precres && prec1 <= precres)
2363 tree types[2];
2364 if (unsr_p)
2366 types[0] = build_nonstandard_integer_type (precres, 0);
2367 types[1] = type;
2369 else
2371 types[0] = type;
2372 types[1] = build_nonstandard_integer_type (precres, 1);
2374 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2375 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2376 if (code != MULT_EXPR)
2377 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2378 uns0_p, uns1_p, false, NULL);
2379 else
2380 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2381 uns0_p, uns1_p, false, NULL);
2382 return;
2385 /* Retry with a wider type. */
2386 if (orig_precres == precres)
2388 int p = MAX (prec0, prec1);
2389 scalar_int_mode m = smallest_int_mode_for_size (p);
2390 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2391 uns0_p && uns1_p
2392 && unsr_p);
2393 p = TYPE_PRECISION (optype);
2394 if (p > precres)
2396 precres = p;
2397 unsr_p = TYPE_UNSIGNED (optype);
2398 type = optype;
2399 continue;
2403 gcc_unreachable ();
2405 while (1);
2408 /* Expand ADD_OVERFLOW STMT. */
2410 static void
2411 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2413 expand_arith_overflow (PLUS_EXPR, stmt);
2416 /* Expand SUB_OVERFLOW STMT. */
2418 static void
2419 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2421 expand_arith_overflow (MINUS_EXPR, stmt);
2424 /* Expand MUL_OVERFLOW STMT. */
2426 static void
2427 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2429 expand_arith_overflow (MULT_EXPR, stmt);
2432 /* This should get folded in tree-vectorizer.c. */
2434 static void
2435 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2437 gcc_unreachable ();
2440 /* This should get folded in tree-vectorizer.c. */
2442 static void
2443 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2445 gcc_unreachable ();
2448 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2449 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2451 static tree
2452 expand_call_mem_ref (tree type, gcall *stmt, int index)
2454 tree addr = gimple_call_arg (stmt, index);
2455 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2456 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2457 if (TYPE_ALIGN (type) != align)
2458 type = build_aligned_type (type, align);
2460 tree tmp = addr;
2461 if (TREE_CODE (tmp) == SSA_NAME)
2463 gimple *def = SSA_NAME_DEF_STMT (tmp);
2464 if (gimple_assign_single_p (def))
2465 tmp = gimple_assign_rhs1 (def);
2468 if (TREE_CODE (tmp) == ADDR_EXPR)
2470 tree mem = TREE_OPERAND (tmp, 0);
2471 if (TREE_CODE (mem) == TARGET_MEM_REF
2472 && types_compatible_p (TREE_TYPE (mem), type))
2474 tree offset = TMR_OFFSET (mem);
2475 if (type != TREE_TYPE (mem)
2476 || alias_ptr_type != TREE_TYPE (offset)
2477 || !integer_zerop (offset))
2479 mem = copy_node (mem);
2480 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2481 wi::to_poly_wide (offset));
2482 TREE_TYPE (mem) = type;
2484 return mem;
2488 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2491 /* Expand MASK_LOAD{,_LANES} or LEN_LOAD call STMT using optab OPTAB. */
2493 static void
2494 expand_partial_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2496 class expand_operand ops[3];
2497 tree type, lhs, rhs, maskt;
2498 rtx mem, target, mask;
2499 insn_code icode;
2501 maskt = gimple_call_arg (stmt, 2);
2502 lhs = gimple_call_lhs (stmt);
2503 if (lhs == NULL_TREE)
2504 return;
2505 type = TREE_TYPE (lhs);
2506 rhs = expand_call_mem_ref (type, stmt, 0);
2508 if (optab == vec_mask_load_lanes_optab)
2509 icode = get_multi_vector_move (type, optab);
2510 else if (optab == len_load_optab)
2511 icode = direct_optab_handler (optab, TYPE_MODE (type));
2512 else
2513 icode = convert_optab_handler (optab, TYPE_MODE (type),
2514 TYPE_MODE (TREE_TYPE (maskt)));
2516 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2517 gcc_assert (MEM_P (mem));
2518 mask = expand_normal (maskt);
2519 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2520 create_output_operand (&ops[0], target, TYPE_MODE (type));
2521 create_fixed_operand (&ops[1], mem);
2522 if (optab == len_load_optab)
2523 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2524 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2525 else
2526 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2527 expand_insn (icode, 3, ops);
2528 if (!rtx_equal_p (target, ops[0].value))
2529 emit_move_insn (target, ops[0].value);
2532 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
2533 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2534 #define expand_len_load_optab_fn expand_partial_load_optab_fn
2536 /* Expand MASK_STORE{,_LANES} or LEN_STORE call STMT using optab OPTAB. */
2538 static void
2539 expand_partial_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2541 class expand_operand ops[3];
2542 tree type, lhs, rhs, maskt;
2543 rtx mem, reg, mask;
2544 insn_code icode;
2546 maskt = gimple_call_arg (stmt, 2);
2547 rhs = gimple_call_arg (stmt, 3);
2548 type = TREE_TYPE (rhs);
2549 lhs = expand_call_mem_ref (type, stmt, 0);
2551 if (optab == vec_mask_store_lanes_optab)
2552 icode = get_multi_vector_move (type, optab);
2553 else if (optab == len_store_optab)
2554 icode = direct_optab_handler (optab, TYPE_MODE (type));
2555 else
2556 icode = convert_optab_handler (optab, TYPE_MODE (type),
2557 TYPE_MODE (TREE_TYPE (maskt)));
2559 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2560 gcc_assert (MEM_P (mem));
2561 mask = expand_normal (maskt);
2562 reg = expand_normal (rhs);
2563 create_fixed_operand (&ops[0], mem);
2564 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2565 if (optab == len_store_optab)
2566 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2567 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2568 else
2569 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2570 expand_insn (icode, 3, ops);
2573 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
2574 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2575 #define expand_len_store_optab_fn expand_partial_store_optab_fn
2577 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
2578 The expansion of STMT happens based on OPTAB table associated. */
2580 static void
2581 expand_vect_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2583 class expand_operand ops[6];
2584 insn_code icode;
2585 tree lhs = gimple_call_lhs (stmt);
2586 tree op0a = gimple_call_arg (stmt, 0);
2587 tree op0b = gimple_call_arg (stmt, 1);
2588 tree op1 = gimple_call_arg (stmt, 2);
2589 tree op2 = gimple_call_arg (stmt, 3);
2590 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
2592 tree vec_cond_type = TREE_TYPE (lhs);
2593 tree op_mode = TREE_TYPE (op0a);
2594 bool unsignedp = TYPE_UNSIGNED (op_mode);
2596 machine_mode mode = TYPE_MODE (vec_cond_type);
2597 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
2599 icode = convert_optab_handler (optab, mode, cmp_op_mode);
2600 rtx comparison
2601 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
2602 rtx rtx_op1 = expand_normal (op1);
2603 rtx rtx_op2 = expand_normal (op2);
2605 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2606 create_output_operand (&ops[0], target, mode);
2607 create_input_operand (&ops[1], rtx_op1, mode);
2608 create_input_operand (&ops[2], rtx_op2, mode);
2609 create_fixed_operand (&ops[3], comparison);
2610 create_fixed_operand (&ops[4], XEXP (comparison, 0));
2611 create_fixed_operand (&ops[5], XEXP (comparison, 1));
2612 expand_insn (icode, 6, ops);
2613 if (!rtx_equal_p (ops[0].value, target))
2614 emit_move_insn (target, ops[0].value);
2617 #define expand_vec_cond_optab_fn expand_vect_cond_optab_fn
2618 #define expand_vec_condu_optab_fn expand_vect_cond_optab_fn
2619 #define expand_vec_condeq_optab_fn expand_vect_cond_optab_fn
2621 /* Expand VCOND_MASK optab internal function.
2622 The expansion of STMT happens based on OPTAB table associated. */
2624 static void
2625 expand_vect_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2627 class expand_operand ops[4];
2629 tree lhs = gimple_call_lhs (stmt);
2630 tree op0 = gimple_call_arg (stmt, 0);
2631 tree op1 = gimple_call_arg (stmt, 1);
2632 tree op2 = gimple_call_arg (stmt, 2);
2633 tree vec_cond_type = TREE_TYPE (lhs);
2635 machine_mode mode = TYPE_MODE (vec_cond_type);
2636 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
2637 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
2638 rtx mask, rtx_op1, rtx_op2;
2640 gcc_assert (icode != CODE_FOR_nothing);
2642 mask = expand_normal (op0);
2643 rtx_op1 = expand_normal (op1);
2644 rtx_op2 = expand_normal (op2);
2646 mask = force_reg (mask_mode, mask);
2647 rtx_op1 = force_reg (mode, rtx_op1);
2649 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2650 create_output_operand (&ops[0], target, mode);
2651 create_input_operand (&ops[1], rtx_op1, mode);
2652 create_input_operand (&ops[2], rtx_op2, mode);
2653 create_input_operand (&ops[3], mask, mask_mode);
2654 expand_insn (icode, 4, ops);
2655 if (!rtx_equal_p (ops[0].value, target))
2656 emit_move_insn (target, ops[0].value);
2659 #define expand_vec_cond_mask_optab_fn expand_vect_cond_mask_optab_fn
2661 static void
2662 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
2666 static void
2667 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
2669 /* When guessing was done, the hints should be already stripped away. */
2670 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2672 rtx target;
2673 tree lhs = gimple_call_lhs (stmt);
2674 if (lhs)
2675 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2676 else
2677 target = const0_rtx;
2678 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2679 if (lhs && val != target)
2680 emit_move_insn (target, val);
2683 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
2684 should never be called. */
2686 static void
2687 expand_VA_ARG (internal_fn, gcall *)
2689 gcc_unreachable ();
2692 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
2693 dummy function should never be called. */
2695 static void
2696 expand_VEC_CONVERT (internal_fn, gcall *)
2698 gcc_unreachable ();
2701 /* Expand the IFN_UNIQUE function according to its first argument. */
2703 static void
2704 expand_UNIQUE (internal_fn, gcall *stmt)
2706 rtx pattern = NULL_RTX;
2707 enum ifn_unique_kind kind
2708 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2710 switch (kind)
2712 default:
2713 gcc_unreachable ();
2715 case IFN_UNIQUE_UNSPEC:
2716 if (targetm.have_unique ())
2717 pattern = targetm.gen_unique ();
2718 break;
2720 case IFN_UNIQUE_OACC_FORK:
2721 case IFN_UNIQUE_OACC_JOIN:
2722 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2724 tree lhs = gimple_call_lhs (stmt);
2725 rtx target = const0_rtx;
2727 if (lhs)
2728 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2730 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2731 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2733 if (kind == IFN_UNIQUE_OACC_FORK)
2734 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2735 else
2736 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2738 else
2739 gcc_unreachable ();
2740 break;
2743 if (pattern)
2744 emit_insn (pattern);
2747 /* The size of an OpenACC compute dimension. */
2749 static void
2750 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
2752 tree lhs = gimple_call_lhs (stmt);
2754 if (!lhs)
2755 return;
2757 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2758 if (targetm.have_oacc_dim_size ())
2760 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2761 VOIDmode, EXPAND_NORMAL);
2762 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2764 else
2765 emit_move_insn (target, GEN_INT (1));
2768 /* The position of an OpenACC execution engine along one compute axis. */
2770 static void
2771 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
2773 tree lhs = gimple_call_lhs (stmt);
2775 if (!lhs)
2776 return;
2778 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2779 if (targetm.have_oacc_dim_pos ())
2781 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2782 VOIDmode, EXPAND_NORMAL);
2783 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2785 else
2786 emit_move_insn (target, const0_rtx);
2789 /* This is expanded by oacc_device_lower pass. */
2791 static void
2792 expand_GOACC_LOOP (internal_fn, gcall *)
2794 gcc_unreachable ();
2797 /* This is expanded by oacc_device_lower pass. */
2799 static void
2800 expand_GOACC_REDUCTION (internal_fn, gcall *)
2802 gcc_unreachable ();
2805 /* This is expanded by oacc_device_lower pass. */
2807 static void
2808 expand_GOACC_TILE (internal_fn, gcall *)
2810 gcc_unreachable ();
2813 /* Set errno to EDOM. */
2815 static void
2816 expand_SET_EDOM (internal_fn, gcall *)
2818 #ifdef TARGET_EDOM
2819 #ifdef GEN_ERRNO_RTX
2820 rtx errno_rtx = GEN_ERRNO_RTX;
2821 #else
2822 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2823 #endif
2824 emit_move_insn (errno_rtx,
2825 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2826 #else
2827 gcc_unreachable ();
2828 #endif
2831 /* Expand atomic bit test and set. */
2833 static void
2834 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2836 expand_ifn_atomic_bit_test_and (call);
2839 /* Expand atomic bit test and complement. */
2841 static void
2842 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2844 expand_ifn_atomic_bit_test_and (call);
2847 /* Expand atomic bit test and reset. */
2849 static void
2850 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2852 expand_ifn_atomic_bit_test_and (call);
2855 /* Expand atomic bit test and set. */
2857 static void
2858 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2860 expand_ifn_atomic_compare_exchange (call);
2863 /* Expand LAUNDER to assignment, lhs = arg0. */
2865 static void
2866 expand_LAUNDER (internal_fn, gcall *call)
2868 tree lhs = gimple_call_lhs (call);
2870 if (!lhs)
2871 return;
2873 expand_assignment (lhs, gimple_call_arg (call, 0), false);
2876 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
2878 static void
2879 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2881 internal_fn ifn = gimple_call_internal_fn (stmt);
2882 int rhs_index = internal_fn_stored_value_index (ifn);
2883 int mask_index = internal_fn_mask_index (ifn);
2884 tree base = gimple_call_arg (stmt, 0);
2885 tree offset = gimple_call_arg (stmt, 1);
2886 tree scale = gimple_call_arg (stmt, 2);
2887 tree rhs = gimple_call_arg (stmt, rhs_index);
2889 rtx base_rtx = expand_normal (base);
2890 rtx offset_rtx = expand_normal (offset);
2891 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2892 rtx rhs_rtx = expand_normal (rhs);
2894 class expand_operand ops[6];
2895 int i = 0;
2896 create_address_operand (&ops[i++], base_rtx);
2897 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2898 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2899 create_integer_operand (&ops[i++], scale_int);
2900 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
2901 if (mask_index >= 0)
2903 tree mask = gimple_call_arg (stmt, mask_index);
2904 rtx mask_rtx = expand_normal (mask);
2905 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2908 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
2909 TYPE_MODE (TREE_TYPE (offset)));
2910 expand_insn (icode, i, ops);
2913 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
2915 static void
2916 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2918 tree lhs = gimple_call_lhs (stmt);
2919 tree base = gimple_call_arg (stmt, 0);
2920 tree offset = gimple_call_arg (stmt, 1);
2921 tree scale = gimple_call_arg (stmt, 2);
2923 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2924 rtx base_rtx = expand_normal (base);
2925 rtx offset_rtx = expand_normal (offset);
2926 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2928 int i = 0;
2929 class expand_operand ops[6];
2930 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
2931 create_address_operand (&ops[i++], base_rtx);
2932 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2933 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2934 create_integer_operand (&ops[i++], scale_int);
2935 if (optab == mask_gather_load_optab)
2937 tree mask = gimple_call_arg (stmt, 4);
2938 rtx mask_rtx = expand_normal (mask);
2939 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2941 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
2942 TYPE_MODE (TREE_TYPE (offset)));
2943 expand_insn (icode, i, ops);
2944 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2945 emit_move_insn (lhs_rtx, ops[0].value);
2948 /* Expand DIVMOD() using:
2949 a) optab handler for udivmod/sdivmod if it is available.
2950 b) If optab_handler doesn't exist, generate call to
2951 target-specific divmod libfunc. */
2953 static void
2954 expand_DIVMOD (internal_fn, gcall *call_stmt)
2956 tree lhs = gimple_call_lhs (call_stmt);
2957 tree arg0 = gimple_call_arg (call_stmt, 0);
2958 tree arg1 = gimple_call_arg (call_stmt, 1);
2960 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
2961 tree type = TREE_TYPE (TREE_TYPE (lhs));
2962 machine_mode mode = TYPE_MODE (type);
2963 bool unsignedp = TYPE_UNSIGNED (type);
2964 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
2966 rtx op0 = expand_normal (arg0);
2967 rtx op1 = expand_normal (arg1);
2968 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2970 rtx quotient, remainder, libfunc;
2972 /* Check if optab_handler exists for divmod_optab for given mode. */
2973 if (optab_handler (tab, mode) != CODE_FOR_nothing)
2975 quotient = gen_reg_rtx (mode);
2976 remainder = gen_reg_rtx (mode);
2977 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
2980 /* Generate call to divmod libfunc if it exists. */
2981 else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
2982 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
2983 &quotient, &remainder);
2985 else
2986 gcc_unreachable ();
2988 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
2989 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
2990 make_tree (TREE_TYPE (arg0), quotient),
2991 make_tree (TREE_TYPE (arg1), remainder)),
2992 target, VOIDmode, EXPAND_NORMAL);
2995 /* Expand a NOP. */
2997 static void
2998 expand_NOP (internal_fn, gcall *)
3000 /* Nothing. But it shouldn't really prevail. */
3003 /* Coroutines, all should have been processed at this stage. */
3005 static void
3006 expand_CO_FRAME (internal_fn, gcall *)
3008 gcc_unreachable ();
3011 static void
3012 expand_CO_YIELD (internal_fn, gcall *)
3014 gcc_unreachable ();
3017 static void
3018 expand_CO_SUSPN (internal_fn, gcall *)
3020 gcc_unreachable ();
3023 static void
3024 expand_CO_ACTOR (internal_fn, gcall *)
3026 gcc_unreachable ();
3029 /* Expand a call to FN using the operands in STMT. FN has a single
3030 output operand and NARGS input operands. */
3032 static void
3033 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3034 unsigned int nargs)
3036 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
3038 tree_pair types = direct_internal_fn_types (fn, stmt);
3039 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3040 gcc_assert (icode != CODE_FOR_nothing);
3042 tree lhs = gimple_call_lhs (stmt);
3043 rtx lhs_rtx = NULL_RTX;
3044 if (lhs)
3045 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3047 /* Do not assign directly to a promoted subreg, since there is no
3048 guarantee that the instruction will leave the upper bits of the
3049 register in the state required by SUBREG_PROMOTED_SIGN. */
3050 rtx dest = lhs_rtx;
3051 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
3052 dest = NULL_RTX;
3054 create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
3056 for (unsigned int i = 0; i < nargs; ++i)
3058 tree rhs = gimple_call_arg (stmt, i);
3059 tree rhs_type = TREE_TYPE (rhs);
3060 rtx rhs_rtx = expand_normal (rhs);
3061 if (INTEGRAL_TYPE_P (rhs_type))
3062 create_convert_operand_from (&ops[i + 1], rhs_rtx,
3063 TYPE_MODE (rhs_type),
3064 TYPE_UNSIGNED (rhs_type));
3065 else
3066 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
3069 expand_insn (icode, nargs + 1, ops);
3070 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
3072 /* If the return value has an integral type, convert the instruction
3073 result to that type. This is useful for things that return an
3074 int regardless of the size of the input. If the instruction result
3075 is smaller than required, assume that it is signed.
3077 If the return value has a nonintegral type, its mode must match
3078 the instruction result. */
3079 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
3081 /* If this is a scalar in a register that is stored in a wider
3082 mode than the declared mode, compute the result into its
3083 declared mode and then convert to the wider mode. */
3084 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
3085 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
3086 convert_move (SUBREG_REG (lhs_rtx), tmp,
3087 SUBREG_PROMOTED_SIGN (lhs_rtx));
3089 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
3090 emit_move_insn (lhs_rtx, ops[0].value);
3091 else
3093 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
3094 convert_move (lhs_rtx, ops[0].value, 0);
3099 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3101 static void
3102 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3104 expand_operand ops[3];
3105 tree rhs_type[2];
3107 tree lhs = gimple_call_lhs (stmt);
3108 tree lhs_type = TREE_TYPE (lhs);
3109 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3110 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3112 for (unsigned int i = 0; i < 2; ++i)
3114 tree rhs = gimple_call_arg (stmt, i);
3115 rhs_type[i] = TREE_TYPE (rhs);
3116 rtx rhs_rtx = expand_normal (rhs);
3117 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3120 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3121 TYPE_MODE (lhs_type));
3123 expand_insn (icode, 3, ops);
3124 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3125 emit_move_insn (lhs_rtx, ops[0].value);
3128 /* Expanders for optabs that can use expand_direct_optab_fn. */
3130 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3131 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3133 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3134 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3136 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3137 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3139 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3140 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3142 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3143 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3145 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3146 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3148 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3149 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3151 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3152 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3154 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3155 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3157 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3158 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3160 /* RETURN_TYPE and ARGS are a return type and argument list that are
3161 in principle compatible with FN (which satisfies direct_internal_fn_p).
3162 Return the types that should be used to determine whether the
3163 target supports FN. */
3165 tree_pair
3166 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3168 const direct_internal_fn_info &info = direct_internal_fn (fn);
3169 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3170 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3171 return tree_pair (type0, type1);
3174 /* CALL is a call whose return type and arguments are in principle
3175 compatible with FN (which satisfies direct_internal_fn_p). Return the
3176 types that should be used to determine whether the target supports FN. */
3178 tree_pair
3179 direct_internal_fn_types (internal_fn fn, gcall *call)
3181 const direct_internal_fn_info &info = direct_internal_fn (fn);
3182 tree op0 = (info.type0 < 0
3183 ? gimple_call_lhs (call)
3184 : gimple_call_arg (call, info.type0));
3185 tree op1 = (info.type1 < 0
3186 ? gimple_call_lhs (call)
3187 : gimple_call_arg (call, info.type1));
3188 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3191 /* Return true if OPTAB is supported for TYPES (whose modes should be
3192 the same) when the optimization type is OPT_TYPE. Used for simple
3193 direct optabs. */
3195 static bool
3196 direct_optab_supported_p (direct_optab optab, tree_pair types,
3197 optimization_type opt_type)
3199 machine_mode mode = TYPE_MODE (types.first);
3200 gcc_checking_assert (mode == TYPE_MODE (types.second));
3201 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3204 /* Return true if OPTAB is supported for TYPES, where the first type
3205 is the destination and the second type is the source. Used for
3206 convert optabs. */
3208 static bool
3209 convert_optab_supported_p (convert_optab optab, tree_pair types,
3210 optimization_type opt_type)
3212 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3213 TYPE_MODE (types.second), opt_type)
3214 != CODE_FOR_nothing);
3217 /* Return true if load/store lanes optab OPTAB is supported for
3218 array type TYPES.first when the optimization type is OPT_TYPE. */
3220 static bool
3221 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3222 optimization_type opt_type)
3224 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3225 machine_mode imode = TYPE_MODE (types.first);
3226 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3227 return (convert_optab_handler (optab, imode, vmode, opt_type)
3228 != CODE_FOR_nothing);
3231 #define direct_unary_optab_supported_p direct_optab_supported_p
3232 #define direct_binary_optab_supported_p direct_optab_supported_p
3233 #define direct_ternary_optab_supported_p direct_optab_supported_p
3234 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3235 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3236 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
3237 #define direct_mask_load_optab_supported_p convert_optab_supported_p
3238 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
3239 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
3240 #define direct_gather_load_optab_supported_p convert_optab_supported_p
3241 #define direct_len_load_optab_supported_p direct_optab_supported_p
3242 #define direct_mask_store_optab_supported_p convert_optab_supported_p
3243 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
3244 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
3245 #define direct_vec_cond_mask_optab_supported_p multi_vector_optab_supported_p
3246 #define direct_vec_cond_optab_supported_p multi_vector_optab_supported_p
3247 #define direct_vec_condu_optab_supported_p multi_vector_optab_supported_p
3248 #define direct_vec_condeq_optab_supported_p multi_vector_optab_supported_p
3249 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
3250 #define direct_len_store_optab_supported_p direct_optab_supported_p
3251 #define direct_while_optab_supported_p convert_optab_supported_p
3252 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
3253 #define direct_fold_left_optab_supported_p direct_optab_supported_p
3254 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
3255 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
3257 /* Return the optab used by internal function FN. */
3259 static optab
3260 direct_internal_fn_optab (internal_fn fn, tree_pair types)
3262 switch (fn)
3264 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3265 case IFN_##CODE: break;
3266 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3267 case IFN_##CODE: return OPTAB##_optab;
3268 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3269 UNSIGNED_OPTAB, TYPE) \
3270 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
3271 ? UNSIGNED_OPTAB ## _optab \
3272 : SIGNED_OPTAB ## _optab);
3273 #include "internal-fn.def"
3275 case IFN_LAST:
3276 break;
3278 gcc_unreachable ();
3281 /* Return the optab used by internal function FN. */
3283 static optab
3284 direct_internal_fn_optab (internal_fn fn)
3286 switch (fn)
3288 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3289 case IFN_##CODE: break;
3290 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3291 case IFN_##CODE: return OPTAB##_optab;
3292 #include "internal-fn.def"
3294 case IFN_LAST:
3295 break;
3297 gcc_unreachable ();
3300 /* Return true if FN is supported for the types in TYPES when the
3301 optimization type is OPT_TYPE. The types are those associated with
3302 the "type0" and "type1" fields of FN's direct_internal_fn_info
3303 structure. */
3305 bool
3306 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
3307 optimization_type opt_type)
3309 switch (fn)
3311 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3312 case IFN_##CODE: break;
3313 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3314 case IFN_##CODE: \
3315 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
3316 opt_type);
3317 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3318 UNSIGNED_OPTAB, TYPE) \
3319 case IFN_##CODE: \
3321 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
3322 ? UNSIGNED_OPTAB ## _optab \
3323 : SIGNED_OPTAB ## _optab); \
3324 return direct_##TYPE##_optab_supported_p (which_optab, types, \
3325 opt_type); \
3327 #include "internal-fn.def"
3329 case IFN_LAST:
3330 break;
3332 gcc_unreachable ();
3335 /* Return true if FN is supported for type TYPE when the optimization
3336 type is OPT_TYPE. The caller knows that the "type0" and "type1"
3337 fields of FN's direct_internal_fn_info structure are the same. */
3339 bool
3340 direct_internal_fn_supported_p (internal_fn fn, tree type,
3341 optimization_type opt_type)
3343 const direct_internal_fn_info &info = direct_internal_fn (fn);
3344 gcc_checking_assert (info.type0 == info.type1);
3345 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
3348 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
3349 given that STMT is a call to a direct internal function. */
3351 bool
3352 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
3354 internal_fn fn = gimple_call_internal_fn (stmt);
3355 tree_pair types = direct_internal_fn_types (fn, stmt);
3356 return direct_internal_fn_supported_p (fn, types, opt_type);
3359 /* If FN is commutative in two consecutive arguments, return the
3360 index of the first, otherwise return -1. */
3363 first_commutative_argument (internal_fn fn)
3365 switch (fn)
3367 case IFN_FMA:
3368 case IFN_FMS:
3369 case IFN_FNMA:
3370 case IFN_FNMS:
3371 case IFN_AVG_FLOOR:
3372 case IFN_AVG_CEIL:
3373 case IFN_MULHS:
3374 case IFN_MULHRS:
3375 case IFN_FMIN:
3376 case IFN_FMAX:
3377 return 0;
3379 case IFN_COND_ADD:
3380 case IFN_COND_MUL:
3381 case IFN_COND_MIN:
3382 case IFN_COND_MAX:
3383 case IFN_COND_AND:
3384 case IFN_COND_IOR:
3385 case IFN_COND_XOR:
3386 case IFN_COND_FMA:
3387 case IFN_COND_FMS:
3388 case IFN_COND_FNMA:
3389 case IFN_COND_FNMS:
3390 return 1;
3392 default:
3393 return -1;
3397 /* Return true if IFN_SET_EDOM is supported. */
3399 bool
3400 set_edom_supported_p (void)
3402 #ifdef TARGET_EDOM
3403 return true;
3404 #else
3405 return false;
3406 #endif
3409 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3410 static void \
3411 expand_##CODE (internal_fn fn, gcall *stmt) \
3413 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
3415 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3416 UNSIGNED_OPTAB, TYPE) \
3417 static void \
3418 expand_##CODE (internal_fn fn, gcall *stmt) \
3420 tree_pair types = direct_internal_fn_types (fn, stmt); \
3421 optab which_optab = direct_internal_fn_optab (fn, types); \
3422 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
3424 #include "internal-fn.def"
3426 /* Routines to expand each internal function, indexed by function number.
3427 Each routine has the prototype:
3429 expand_<NAME> (gcall *stmt)
3431 where STMT is the statement that performs the call. */
3432 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
3433 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
3434 #include "internal-fn.def"
3438 /* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
3439 tree code CODE. */
3440 #define FOR_EACH_CODE_MAPPING(T) \
3441 T (PLUS_EXPR, IFN_COND_ADD) \
3442 T (MINUS_EXPR, IFN_COND_SUB) \
3443 T (MULT_EXPR, IFN_COND_MUL) \
3444 T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
3445 T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
3446 T (RDIV_EXPR, IFN_COND_RDIV) \
3447 T (MIN_EXPR, IFN_COND_MIN) \
3448 T (MAX_EXPR, IFN_COND_MAX) \
3449 T (BIT_AND_EXPR, IFN_COND_AND) \
3450 T (BIT_IOR_EXPR, IFN_COND_IOR) \
3451 T (BIT_XOR_EXPR, IFN_COND_XOR) \
3452 T (LSHIFT_EXPR, IFN_COND_SHL) \
3453 T (RSHIFT_EXPR, IFN_COND_SHR)
3455 /* Return a function that only performs CODE when a certain condition is met
3456 and that uses a given fallback value otherwise. For example, if CODE is
3457 a binary operation associated with conditional function FN:
3459 LHS = FN (COND, A, B, ELSE)
3461 is equivalent to the C expression:
3463 LHS = COND ? A CODE B : ELSE;
3465 operating elementwise if the operands are vectors.
3467 Return IFN_LAST if no such function exists. */
3469 internal_fn
3470 get_conditional_internal_fn (tree_code code)
3472 switch (code)
3474 #define CASE(CODE, IFN) case CODE: return IFN;
3475 FOR_EACH_CODE_MAPPING(CASE)
3476 #undef CASE
3477 default:
3478 return IFN_LAST;
3482 /* If IFN implements the conditional form of a tree code, return that
3483 tree code, otherwise return ERROR_MARK. */
3485 tree_code
3486 conditional_internal_fn_code (internal_fn ifn)
3488 switch (ifn)
3490 #define CASE(CODE, IFN) case IFN: return CODE;
3491 FOR_EACH_CODE_MAPPING(CASE)
3492 #undef CASE
3493 default:
3494 return ERROR_MARK;
3498 /* Invoke T(IFN) for each internal function IFN that also has an
3499 IFN_COND_* form. */
3500 #define FOR_EACH_COND_FN_PAIR(T) \
3501 T (FMA) \
3502 T (FMS) \
3503 T (FNMA) \
3504 T (FNMS)
3506 /* Return a function that only performs internal function FN when a
3507 certain condition is met and that uses a given fallback value otherwise.
3508 In other words, the returned function FN' is such that:
3510 LHS = FN' (COND, A1, ... An, ELSE)
3512 is equivalent to the C expression:
3514 LHS = COND ? FN (A1, ..., An) : ELSE;
3516 operating elementwise if the operands are vectors.
3518 Return IFN_LAST if no such function exists. */
3520 internal_fn
3521 get_conditional_internal_fn (internal_fn fn)
3523 switch (fn)
3525 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
3526 FOR_EACH_COND_FN_PAIR(CASE)
3527 #undef CASE
3528 default:
3529 return IFN_LAST;
3533 /* If IFN implements the conditional form of an unconditional internal
3534 function, return that unconditional function, otherwise return IFN_LAST. */
3536 internal_fn
3537 get_unconditional_internal_fn (internal_fn ifn)
3539 switch (ifn)
3541 #define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
3542 FOR_EACH_COND_FN_PAIR(CASE)
3543 #undef CASE
3544 default:
3545 return IFN_LAST;
3549 /* Return true if STMT can be interpreted as a conditional tree code
3550 operation of the form:
3552 LHS = COND ? OP (RHS1, ...) : ELSE;
3554 operating elementwise if the operands are vectors. This includes
3555 the case of an all-true COND, so that the operation always happens.
3557 When returning true, set:
3559 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
3560 is known to be all-true
3561 - *CODE_OUT to the tree code
3562 - OPS[I] to operand I of *CODE_OUT
3563 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
3564 condition is known to be all true. */
3566 bool
3567 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
3568 tree_code *code_out,
3569 tree (&ops)[3], tree *else_out)
3571 if (gassign *assign = dyn_cast <gassign *> (stmt))
3573 *cond_out = NULL_TREE;
3574 *code_out = gimple_assign_rhs_code (assign);
3575 ops[0] = gimple_assign_rhs1 (assign);
3576 ops[1] = gimple_assign_rhs2 (assign);
3577 ops[2] = gimple_assign_rhs3 (assign);
3578 *else_out = NULL_TREE;
3579 return true;
3581 if (gcall *call = dyn_cast <gcall *> (stmt))
3582 if (gimple_call_internal_p (call))
3584 internal_fn ifn = gimple_call_internal_fn (call);
3585 tree_code code = conditional_internal_fn_code (ifn);
3586 if (code != ERROR_MARK)
3588 *cond_out = gimple_call_arg (call, 0);
3589 *code_out = code;
3590 unsigned int nops = gimple_call_num_args (call) - 2;
3591 for (unsigned int i = 0; i < 3; ++i)
3592 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
3593 *else_out = gimple_call_arg (call, nops + 1);
3594 if (integer_truep (*cond_out))
3596 *cond_out = NULL_TREE;
3597 *else_out = NULL_TREE;
3599 return true;
3602 return false;
3605 /* Return true if IFN is some form of load from memory. */
3607 bool
3608 internal_load_fn_p (internal_fn fn)
3610 switch (fn)
3612 case IFN_MASK_LOAD:
3613 case IFN_LOAD_LANES:
3614 case IFN_MASK_LOAD_LANES:
3615 case IFN_GATHER_LOAD:
3616 case IFN_MASK_GATHER_LOAD:
3617 case IFN_LEN_LOAD:
3618 return true;
3620 default:
3621 return false;
3625 /* Return true if IFN is some form of store to memory. */
3627 bool
3628 internal_store_fn_p (internal_fn fn)
3630 switch (fn)
3632 case IFN_MASK_STORE:
3633 case IFN_STORE_LANES:
3634 case IFN_MASK_STORE_LANES:
3635 case IFN_SCATTER_STORE:
3636 case IFN_MASK_SCATTER_STORE:
3637 case IFN_LEN_STORE:
3638 return true;
3640 default:
3641 return false;
3645 /* Return true if IFN is some form of gather load or scatter store. */
3647 bool
3648 internal_gather_scatter_fn_p (internal_fn fn)
3650 switch (fn)
3652 case IFN_GATHER_LOAD:
3653 case IFN_MASK_GATHER_LOAD:
3654 case IFN_SCATTER_STORE:
3655 case IFN_MASK_SCATTER_STORE:
3656 return true;
3658 default:
3659 return false;
3663 /* If FN takes a vector mask argument, return the index of that argument,
3664 otherwise return -1. */
3667 internal_fn_mask_index (internal_fn fn)
3669 switch (fn)
3671 case IFN_MASK_LOAD:
3672 case IFN_MASK_LOAD_LANES:
3673 case IFN_MASK_STORE:
3674 case IFN_MASK_STORE_LANES:
3675 return 2;
3677 case IFN_MASK_GATHER_LOAD:
3678 case IFN_MASK_SCATTER_STORE:
3679 return 4;
3681 default:
3682 return (conditional_internal_fn_code (fn) != ERROR_MARK
3683 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
3687 /* If FN takes a value that should be stored to memory, return the index
3688 of that argument, otherwise return -1. */
3691 internal_fn_stored_value_index (internal_fn fn)
3693 switch (fn)
3695 case IFN_MASK_STORE:
3696 case IFN_SCATTER_STORE:
3697 case IFN_MASK_SCATTER_STORE:
3698 case IFN_LEN_STORE:
3699 return 3;
3701 default:
3702 return -1;
3706 /* Return true if the target supports gather load or scatter store function
3707 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
3708 while for stores it is the vector type of the stored data argument.
3709 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
3710 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
3711 offset from the shared base address of each loaded or stored element.
3712 SCALE is the amount by which these offsets should be multiplied
3713 *after* they have been extended to address width. */
3715 bool
3716 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
3717 tree memory_element_type,
3718 tree offset_vector_type, int scale)
3720 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
3721 TYPE_SIZE (memory_element_type)))
3722 return false;
3723 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
3724 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
3725 return false;
3726 optab optab = direct_internal_fn_optab (ifn);
3727 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
3728 TYPE_MODE (offset_vector_type));
3729 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
3730 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
3731 return (icode != CODE_FOR_nothing
3732 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
3733 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
3736 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
3737 for pointers of type TYPE when the accesses have LENGTH bytes and their
3738 common byte alignment is ALIGN. */
3740 bool
3741 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
3742 poly_uint64 length, unsigned int align)
3744 machine_mode mode = TYPE_MODE (type);
3745 optab optab = direct_internal_fn_optab (ifn);
3746 insn_code icode = direct_optab_handler (optab, mode);
3747 if (icode == CODE_FOR_nothing)
3748 return false;
3749 rtx length_rtx = immed_wide_int_const (length, mode);
3750 return (insn_operand_matches (icode, 3, length_rtx)
3751 && insn_operand_matches (icode, 4, GEN_INT (align)));
3754 /* Expand STMT as though it were a call to internal function FN. */
3756 void
3757 expand_internal_call (internal_fn fn, gcall *stmt)
3759 internal_fn_expanders[fn] (fn, stmt);
3762 /* Expand STMT, which is a call to internal function FN. */
3764 void
3765 expand_internal_call (gcall *stmt)
3767 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
3770 /* If TYPE is a vector type, return true if IFN is a direct internal
3771 function that is supported for that type. If TYPE is a scalar type,
3772 return true if IFN is a direct internal function that is supported for
3773 the target's preferred vector version of TYPE. */
3775 bool
3776 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
3778 scalar_mode smode;
3779 if (!VECTOR_TYPE_P (type) && is_a <scalar_mode> (TYPE_MODE (type), &smode))
3781 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
3782 if (VECTOR_MODE_P (vmode))
3783 type = build_vector_type_for_mode (type, vmode);
3786 return (VECTOR_MODE_P (TYPE_MODE (type))
3787 && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
3790 void
3791 expand_PHI (internal_fn, gcall *)
3793 gcc_unreachable ();