testsuite: Update scanning symbol sections to support AIX.
[official-gcc.git] / gcc / internal-fn.c
blob792d2ca568a4a11c3e3ad8abf6443f173b0650a7
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"
53 #include "rtl-iter.h"
55 /* The names of each internal function, indexed by function number. */
56 const char *const internal_fn_name_array[] = {
57 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
58 #include "internal-fn.def"
59 "<invalid-fn>"
62 /* The ECF_* flags of each internal function, indexed by function number. */
63 const int internal_fn_flags_array[] = {
64 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
65 #include "internal-fn.def"
69 /* Return the internal function called NAME, or IFN_LAST if there's
70 no such function. */
72 internal_fn
73 lookup_internal_fn (const char *name)
75 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
76 static name_to_fn_map_type *name_to_fn_map;
78 if (!name_to_fn_map)
80 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
81 for (unsigned int i = 0; i < IFN_LAST; ++i)
82 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
83 internal_fn (i));
85 internal_fn *entry = name_to_fn_map->get (name);
86 return entry ? *entry : IFN_LAST;
89 /* Fnspec of each internal function, indexed by function number. */
90 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
92 void
93 init_internal_fns ()
95 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
96 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
97 build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
98 #include "internal-fn.def"
99 internal_fn_fnspec_array[IFN_LAST] = 0;
102 /* Create static initializers for the information returned by
103 direct_internal_fn. */
104 #define not_direct { -2, -2, false }
105 #define mask_load_direct { -1, 2, false }
106 #define load_lanes_direct { -1, -1, false }
107 #define mask_load_lanes_direct { -1, -1, false }
108 #define gather_load_direct { 3, 1, false }
109 #define len_load_direct { -1, -1, false }
110 #define mask_store_direct { 3, 2, false }
111 #define store_lanes_direct { 0, 0, false }
112 #define mask_store_lanes_direct { 0, 0, false }
113 #define vec_cond_mask_direct { 0, 0, false }
114 #define vec_cond_direct { 0, 0, false }
115 #define vec_condu_direct { 0, 0, false }
116 #define vec_condeq_direct { 0, 0, false }
117 #define scatter_store_direct { 3, 1, false }
118 #define len_store_direct { 3, 3, false }
119 #define vec_set_direct { 3, 3, false }
120 #define unary_direct { 0, 0, true }
121 #define binary_direct { 0, 0, true }
122 #define ternary_direct { 0, 0, true }
123 #define cond_unary_direct { 1, 1, true }
124 #define cond_binary_direct { 1, 1, true }
125 #define cond_ternary_direct { 1, 1, true }
126 #define while_direct { 0, 2, false }
127 #define fold_extract_direct { 2, 2, false }
128 #define fold_left_direct { 1, 1, false }
129 #define mask_fold_left_direct { 1, 1, false }
130 #define check_ptrs_direct { 0, 0, false }
132 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
133 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
134 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
135 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
136 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
137 #include "internal-fn.def"
138 not_direct
141 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
142 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
144 static enum insn_code
145 get_multi_vector_move (tree array_type, convert_optab optab)
147 machine_mode imode;
148 machine_mode vmode;
150 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
151 imode = TYPE_MODE (array_type);
152 vmode = TYPE_MODE (TREE_TYPE (array_type));
154 return convert_optab_handler (optab, imode, vmode);
157 /* Expand LOAD_LANES call STMT using optab OPTAB. */
159 static void
160 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
162 class expand_operand ops[2];
163 tree type, lhs, rhs;
164 rtx target, mem;
166 lhs = gimple_call_lhs (stmt);
167 rhs = gimple_call_arg (stmt, 0);
168 type = TREE_TYPE (lhs);
170 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
171 mem = expand_normal (rhs);
173 gcc_assert (MEM_P (mem));
174 PUT_MODE (mem, TYPE_MODE (type));
176 create_output_operand (&ops[0], target, TYPE_MODE (type));
177 create_fixed_operand (&ops[1], mem);
178 expand_insn (get_multi_vector_move (type, optab), 2, ops);
179 if (!rtx_equal_p (target, ops[0].value))
180 emit_move_insn (target, ops[0].value);
183 /* Expand STORE_LANES call STMT using optab OPTAB. */
185 static void
186 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
188 class expand_operand ops[2];
189 tree type, lhs, rhs;
190 rtx target, reg;
192 lhs = gimple_call_lhs (stmt);
193 rhs = gimple_call_arg (stmt, 0);
194 type = TREE_TYPE (rhs);
196 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
197 reg = expand_normal (rhs);
199 gcc_assert (MEM_P (target));
200 PUT_MODE (target, TYPE_MODE (type));
202 create_fixed_operand (&ops[0], target);
203 create_input_operand (&ops[1], reg, TYPE_MODE (type));
204 expand_insn (get_multi_vector_move (type, optab), 2, ops);
207 static void
208 expand_ANNOTATE (internal_fn, gcall *)
210 gcc_unreachable ();
213 /* This should get expanded in omp_device_lower pass. */
215 static void
216 expand_GOMP_USE_SIMT (internal_fn, gcall *)
218 gcc_unreachable ();
221 /* This should get expanded in omp_device_lower pass. */
223 static void
224 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
226 gcc_unreachable ();
229 /* Allocate per-lane storage and begin non-uniform execution region. */
231 static void
232 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
234 rtx target;
235 tree lhs = gimple_call_lhs (stmt);
236 if (lhs)
237 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
238 else
239 target = gen_reg_rtx (Pmode);
240 rtx size = expand_normal (gimple_call_arg (stmt, 0));
241 rtx align = expand_normal (gimple_call_arg (stmt, 1));
242 class expand_operand ops[3];
243 create_output_operand (&ops[0], target, Pmode);
244 create_input_operand (&ops[1], size, Pmode);
245 create_input_operand (&ops[2], align, Pmode);
246 gcc_assert (targetm.have_omp_simt_enter ());
247 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
250 /* Deallocate per-lane storage and leave non-uniform execution region. */
252 static void
253 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
255 gcc_checking_assert (!gimple_call_lhs (stmt));
256 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
257 class expand_operand ops[1];
258 create_input_operand (&ops[0], arg, Pmode);
259 gcc_assert (targetm.have_omp_simt_exit ());
260 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
263 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
264 without SIMT execution this should be expanded in omp_device_lower pass. */
266 static void
267 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
269 tree lhs = gimple_call_lhs (stmt);
270 if (!lhs)
271 return;
273 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
274 gcc_assert (targetm.have_omp_simt_lane ());
275 emit_insn (targetm.gen_omp_simt_lane (target));
278 /* This should get expanded in omp_device_lower pass. */
280 static void
281 expand_GOMP_SIMT_VF (internal_fn, gcall *)
283 gcc_unreachable ();
286 /* Lane index of the first SIMT lane that supplies a non-zero argument.
287 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
288 lane that executed the last iteration for handling OpenMP lastprivate. */
290 static void
291 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
293 tree lhs = gimple_call_lhs (stmt);
294 if (!lhs)
295 return;
297 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
298 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
299 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
300 class expand_operand ops[2];
301 create_output_operand (&ops[0], target, mode);
302 create_input_operand (&ops[1], cond, mode);
303 gcc_assert (targetm.have_omp_simt_last_lane ());
304 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
307 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
309 static void
310 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
312 tree lhs = gimple_call_lhs (stmt);
313 if (!lhs)
314 return;
316 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
317 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
318 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
319 class expand_operand ops[2];
320 create_output_operand (&ops[0], target, mode);
321 create_input_operand (&ops[1], ctr, mode);
322 gcc_assert (targetm.have_omp_simt_ordered ());
323 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
326 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
327 any lane supplies a non-zero argument. */
329 static void
330 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
332 tree lhs = gimple_call_lhs (stmt);
333 if (!lhs)
334 return;
336 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
337 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
338 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
339 class expand_operand ops[2];
340 create_output_operand (&ops[0], target, mode);
341 create_input_operand (&ops[1], cond, mode);
342 gcc_assert (targetm.have_omp_simt_vote_any ());
343 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
346 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
347 is destination lane index XOR given offset. */
349 static void
350 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
352 tree lhs = gimple_call_lhs (stmt);
353 if (!lhs)
354 return;
356 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
357 rtx src = expand_normal (gimple_call_arg (stmt, 0));
358 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
359 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
360 class expand_operand ops[3];
361 create_output_operand (&ops[0], target, mode);
362 create_input_operand (&ops[1], src, mode);
363 create_input_operand (&ops[2], idx, SImode);
364 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
365 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
368 /* Exchange between SIMT lanes according to given source lane index. */
370 static void
371 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
373 tree lhs = gimple_call_lhs (stmt);
374 if (!lhs)
375 return;
377 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
378 rtx src = expand_normal (gimple_call_arg (stmt, 0));
379 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
380 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
381 class expand_operand ops[3];
382 create_output_operand (&ops[0], target, mode);
383 create_input_operand (&ops[1], src, mode);
384 create_input_operand (&ops[2], idx, SImode);
385 gcc_assert (targetm.have_omp_simt_xchg_idx ());
386 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
389 /* This should get expanded in adjust_simduid_builtins. */
391 static void
392 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
394 gcc_unreachable ();
397 /* This should get expanded in adjust_simduid_builtins. */
399 static void
400 expand_GOMP_SIMD_VF (internal_fn, gcall *)
402 gcc_unreachable ();
405 /* This should get expanded in adjust_simduid_builtins. */
407 static void
408 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
410 gcc_unreachable ();
413 /* This should get expanded in adjust_simduid_builtins. */
415 static void
416 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
418 gcc_unreachable ();
421 /* This should get expanded in adjust_simduid_builtins. */
423 static void
424 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
426 gcc_unreachable ();
429 /* This should get expanded in the sanopt pass. */
431 static void
432 expand_UBSAN_NULL (internal_fn, gcall *)
434 gcc_unreachable ();
437 /* This should get expanded in the sanopt pass. */
439 static void
440 expand_UBSAN_BOUNDS (internal_fn, gcall *)
442 gcc_unreachable ();
445 /* This should get expanded in the sanopt pass. */
447 static void
448 expand_UBSAN_VPTR (internal_fn, gcall *)
450 gcc_unreachable ();
453 /* This should get expanded in the sanopt pass. */
455 static void
456 expand_UBSAN_PTR (internal_fn, gcall *)
458 gcc_unreachable ();
461 /* This should get expanded in the sanopt pass. */
463 static void
464 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
466 gcc_unreachable ();
469 /* This should get expanded in the sanopt pass. */
471 static void
472 expand_ASAN_CHECK (internal_fn, gcall *)
474 gcc_unreachable ();
477 /* This should get expanded in the sanopt pass. */
479 static void
480 expand_ASAN_MARK (internal_fn, gcall *)
482 gcc_unreachable ();
485 /* This should get expanded in the sanopt pass. */
487 static void
488 expand_ASAN_POISON (internal_fn, gcall *)
490 gcc_unreachable ();
493 /* This should get expanded in the sanopt pass. */
495 static void
496 expand_ASAN_POISON_USE (internal_fn, gcall *)
498 gcc_unreachable ();
501 /* This should get expanded in the tsan pass. */
503 static void
504 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
506 gcc_unreachable ();
509 /* This should get expanded in the lower pass. */
511 static void
512 expand_FALLTHROUGH (internal_fn, gcall *call)
514 error_at (gimple_location (call),
515 "invalid use of attribute %<fallthrough%>");
518 /* Return minimum precision needed to represent all values
519 of ARG in SIGNed integral type. */
521 static int
522 get_min_precision (tree arg, signop sign)
524 int prec = TYPE_PRECISION (TREE_TYPE (arg));
525 int cnt = 0;
526 signop orig_sign = sign;
527 if (TREE_CODE (arg) == INTEGER_CST)
529 int p;
530 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
532 widest_int w = wi::to_widest (arg);
533 w = wi::ext (w, prec, sign);
534 p = wi::min_precision (w, sign);
536 else
537 p = wi::min_precision (wi::to_wide (arg), sign);
538 return MIN (p, prec);
540 while (CONVERT_EXPR_P (arg)
541 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
542 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
544 arg = TREE_OPERAND (arg, 0);
545 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
547 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
548 sign = UNSIGNED;
549 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
550 return prec + (orig_sign != sign);
551 prec = TYPE_PRECISION (TREE_TYPE (arg));
553 if (++cnt > 30)
554 return prec + (orig_sign != sign);
556 if (TREE_CODE (arg) != SSA_NAME)
557 return prec + (orig_sign != sign);
558 wide_int arg_min, arg_max;
559 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
561 gimple *g = SSA_NAME_DEF_STMT (arg);
562 if (is_gimple_assign (g)
563 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
565 tree t = gimple_assign_rhs1 (g);
566 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
567 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
569 arg = t;
570 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
572 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
573 sign = UNSIGNED;
574 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
575 return prec + (orig_sign != sign);
576 prec = TYPE_PRECISION (TREE_TYPE (arg));
578 if (++cnt > 30)
579 return prec + (orig_sign != sign);
580 continue;
583 return prec + (orig_sign != sign);
585 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
587 int p1 = wi::min_precision (arg_min, sign);
588 int p2 = wi::min_precision (arg_max, sign);
589 p1 = MAX (p1, p2);
590 prec = MIN (prec, p1);
592 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
594 int p = wi::min_precision (arg_max, UNSIGNED);
595 prec = MIN (prec, p);
597 return prec + (orig_sign != sign);
600 /* Helper for expand_*_overflow. Set the __imag__ part to true
601 (1 except for signed:1 type, in which case store -1). */
603 static void
604 expand_arith_set_overflow (tree lhs, rtx target)
606 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
607 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
608 write_complex_part (target, constm1_rtx, true);
609 else
610 write_complex_part (target, const1_rtx, true);
613 /* Helper for expand_*_overflow. Store RES into the __real__ part
614 of TARGET. If RES has larger MODE than __real__ part of TARGET,
615 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
616 if LHS has smaller precision than its mode. */
618 static void
619 expand_arith_overflow_result_store (tree lhs, rtx target,
620 scalar_int_mode mode, rtx res)
622 scalar_int_mode tgtmode
623 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
624 rtx lres = res;
625 if (tgtmode != mode)
627 rtx_code_label *done_label = gen_label_rtx ();
628 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
629 lres = convert_modes (tgtmode, mode, res, uns);
630 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
631 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
632 EQ, true, mode, NULL_RTX, NULL, done_label,
633 profile_probability::very_likely ());
634 expand_arith_set_overflow (lhs, target);
635 emit_label (done_label);
637 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
638 int tgtprec = GET_MODE_PRECISION (tgtmode);
639 if (prec < tgtprec)
641 rtx_code_label *done_label = gen_label_rtx ();
642 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
643 res = lres;
644 if (uns)
646 rtx mask
647 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
648 tgtmode);
649 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
650 true, OPTAB_LIB_WIDEN);
652 else
654 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
655 NULL_RTX, 1);
656 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
657 NULL_RTX, 0);
659 do_compare_rtx_and_jump (res, lres,
660 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
661 profile_probability::very_likely ());
662 expand_arith_set_overflow (lhs, target);
663 emit_label (done_label);
665 write_complex_part (target, lres, false);
668 /* Helper for expand_*_overflow. Store RES into TARGET. */
670 static void
671 expand_ubsan_result_store (rtx target, rtx res)
673 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
674 /* If this is a scalar in a register that is stored in a wider mode
675 than the declared mode, compute the result into its declared mode
676 and then convert to the wider mode. Our value is the computed
677 expression. */
678 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
679 else
680 emit_move_insn (target, res);
683 /* Add sub/add overflow checking to the statement STMT.
684 CODE says whether the operation is +, or -. */
686 static void
687 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
688 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
689 bool uns1_p, bool is_ubsan, tree *datap)
691 rtx res, target = NULL_RTX;
692 tree fn;
693 rtx_code_label *done_label = gen_label_rtx ();
694 rtx_code_label *do_error = gen_label_rtx ();
695 do_pending_stack_adjust ();
696 rtx op0 = expand_normal (arg0);
697 rtx op1 = expand_normal (arg1);
698 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
699 int prec = GET_MODE_PRECISION (mode);
700 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
701 bool do_xor = false;
703 if (is_ubsan)
704 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
706 if (lhs)
708 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
709 if (!is_ubsan)
710 write_complex_part (target, const0_rtx, true);
713 /* We assume both operands and result have the same precision
714 here (GET_MODE_BITSIZE (mode)), S stands for signed type
715 with that precision, U for unsigned type with that precision,
716 sgn for unsigned most significant bit in that precision.
717 s1 is signed first operand, u1 is unsigned first operand,
718 s2 is signed second operand, u2 is unsigned second operand,
719 sr is signed result, ur is unsigned result and the following
720 rules say how to compute result (which is always result of
721 the operands as if both were unsigned, cast to the right
722 signedness) and how to compute whether operation overflowed.
724 s1 + s2 -> sr
725 res = (S) ((U) s1 + (U) s2)
726 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
727 s1 - s2 -> sr
728 res = (S) ((U) s1 - (U) s2)
729 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
730 u1 + u2 -> ur
731 res = u1 + u2
732 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
733 u1 - u2 -> ur
734 res = u1 - u2
735 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
736 s1 + u2 -> sr
737 res = (S) ((U) s1 + u2)
738 ovf = ((U) res ^ sgn) < u2
739 s1 + u2 -> ur
740 t1 = (S) (u2 ^ sgn)
741 t2 = s1 + t1
742 res = (U) t2 ^ sgn
743 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
744 s1 - u2 -> sr
745 res = (S) ((U) s1 - u2)
746 ovf = u2 > ((U) s1 ^ sgn)
747 s1 - u2 -> ur
748 res = (U) s1 - u2
749 ovf = s1 < 0 || u2 > (U) s1
750 u1 - s2 -> sr
751 res = u1 - (U) s2
752 ovf = u1 >= ((U) s2 ^ sgn)
753 u1 - s2 -> ur
754 t1 = u1 ^ sgn
755 t2 = t1 - (U) s2
756 res = t2 ^ sgn
757 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
758 s1 + s2 -> ur
759 res = (U) s1 + (U) s2
760 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
761 u1 + u2 -> sr
762 res = (S) (u1 + u2)
763 ovf = (U) res < u2 || res < 0
764 u1 - u2 -> sr
765 res = (S) (u1 - u2)
766 ovf = u1 >= u2 ? res < 0 : res >= 0
767 s1 - s2 -> ur
768 res = (U) s1 - (U) s2
769 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
771 if (code == PLUS_EXPR && uns0_p && !uns1_p)
773 /* PLUS_EXPR is commutative, if operand signedness differs,
774 canonicalize to the first operand being signed and second
775 unsigned to simplify following code. */
776 std::swap (op0, op1);
777 std::swap (arg0, arg1);
778 uns0_p = false;
779 uns1_p = true;
782 /* u1 +- u2 -> ur */
783 if (uns0_p && uns1_p && unsr_p)
785 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
786 : usubv4_optab, mode);
787 if (icode != CODE_FOR_nothing)
789 class expand_operand ops[4];
790 rtx_insn *last = get_last_insn ();
792 res = gen_reg_rtx (mode);
793 create_output_operand (&ops[0], res, mode);
794 create_input_operand (&ops[1], op0, mode);
795 create_input_operand (&ops[2], op1, mode);
796 create_fixed_operand (&ops[3], do_error);
797 if (maybe_expand_insn (icode, 4, ops))
799 last = get_last_insn ();
800 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
801 && JUMP_P (last)
802 && any_condjump_p (last)
803 && !find_reg_note (last, REG_BR_PROB, 0))
804 add_reg_br_prob_note (last,
805 profile_probability::very_unlikely ());
806 emit_jump (done_label);
807 goto do_error_label;
810 delete_insns_since (last);
813 /* Compute the operation. On RTL level, the addition is always
814 unsigned. */
815 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
816 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
817 rtx tem = op0;
818 /* For PLUS_EXPR, the operation is commutative, so we can pick
819 operand to compare against. For prec <= BITS_PER_WORD, I think
820 preferring REG operand is better over CONST_INT, because
821 the CONST_INT might enlarge the instruction or CSE would need
822 to figure out we'd already loaded it into a register before.
823 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
824 as then the multi-word comparison can be perhaps simplified. */
825 if (code == PLUS_EXPR
826 && (prec <= BITS_PER_WORD
827 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
828 : CONST_SCALAR_INT_P (op1)))
829 tem = op1;
830 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
831 true, mode, NULL_RTX, NULL, done_label,
832 profile_probability::very_likely ());
833 goto do_error_label;
836 /* s1 +- u2 -> sr */
837 if (!uns0_p && uns1_p && !unsr_p)
839 /* Compute the operation. On RTL level, the addition is always
840 unsigned. */
841 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
842 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
843 rtx tem = expand_binop (mode, add_optab,
844 code == PLUS_EXPR ? res : op0, sgn,
845 NULL_RTX, false, OPTAB_LIB_WIDEN);
846 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
847 done_label, profile_probability::very_likely ());
848 goto do_error_label;
851 /* s1 + u2 -> ur */
852 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
854 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
855 OPTAB_LIB_WIDEN);
856 /* As we've changed op1, we have to avoid using the value range
857 for the original argument. */
858 arg1 = error_mark_node;
859 do_xor = true;
860 goto do_signed;
863 /* u1 - s2 -> ur */
864 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
866 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
867 OPTAB_LIB_WIDEN);
868 /* As we've changed op0, we have to avoid using the value range
869 for the original argument. */
870 arg0 = error_mark_node;
871 do_xor = true;
872 goto do_signed;
875 /* s1 - u2 -> ur */
876 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
878 /* Compute the operation. On RTL level, the addition is always
879 unsigned. */
880 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
881 OPTAB_LIB_WIDEN);
882 int pos_neg = get_range_pos_neg (arg0);
883 if (pos_neg == 2)
884 /* If ARG0 is known to be always negative, this is always overflow. */
885 emit_jump (do_error);
886 else if (pos_neg == 3)
887 /* If ARG0 is not known to be always positive, check at runtime. */
888 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
889 NULL, do_error, profile_probability::very_unlikely ());
890 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
891 done_label, profile_probability::very_likely ());
892 goto do_error_label;
895 /* u1 - s2 -> sr */
896 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
898 /* Compute the operation. On RTL level, the addition is always
899 unsigned. */
900 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
901 OPTAB_LIB_WIDEN);
902 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
903 OPTAB_LIB_WIDEN);
904 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
905 done_label, profile_probability::very_likely ());
906 goto do_error_label;
909 /* u1 + u2 -> sr */
910 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
912 /* Compute the operation. On RTL level, the addition is always
913 unsigned. */
914 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
915 OPTAB_LIB_WIDEN);
916 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
917 NULL, do_error, profile_probability::very_unlikely ());
918 rtx tem = op1;
919 /* The operation is commutative, so we can pick operand to compare
920 against. For prec <= BITS_PER_WORD, I think preferring REG operand
921 is better over CONST_INT, because the CONST_INT might enlarge the
922 instruction or CSE would need to figure out we'd already loaded it
923 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
924 might be more beneficial, as then the multi-word comparison can be
925 perhaps simplified. */
926 if (prec <= BITS_PER_WORD
927 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
928 : CONST_SCALAR_INT_P (op0))
929 tem = op0;
930 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
931 done_label, profile_probability::very_likely ());
932 goto do_error_label;
935 /* s1 +- s2 -> ur */
936 if (!uns0_p && !uns1_p && unsr_p)
938 /* Compute the operation. On RTL level, the addition is always
939 unsigned. */
940 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
941 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
942 int pos_neg = get_range_pos_neg (arg1);
943 if (code == PLUS_EXPR)
945 int pos_neg0 = get_range_pos_neg (arg0);
946 if (pos_neg0 != 3 && pos_neg == 3)
948 std::swap (op0, op1);
949 pos_neg = pos_neg0;
952 rtx tem;
953 if (pos_neg != 3)
955 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
956 ? and_optab : ior_optab,
957 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
958 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
959 NULL, done_label, profile_probability::very_likely ());
961 else
963 rtx_code_label *do_ior_label = gen_label_rtx ();
964 do_compare_rtx_and_jump (op1, const0_rtx,
965 code == MINUS_EXPR ? GE : LT, false, mode,
966 NULL_RTX, NULL, do_ior_label,
967 profile_probability::even ());
968 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
969 OPTAB_LIB_WIDEN);
970 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
971 NULL, done_label, profile_probability::very_likely ());
972 emit_jump (do_error);
973 emit_label (do_ior_label);
974 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
975 OPTAB_LIB_WIDEN);
976 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
977 NULL, done_label, profile_probability::very_likely ());
979 goto do_error_label;
982 /* u1 - u2 -> sr */
983 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
985 /* Compute the operation. On RTL level, the addition is always
986 unsigned. */
987 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
988 OPTAB_LIB_WIDEN);
989 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
990 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
991 op0_geu_op1, profile_probability::even ());
992 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
993 NULL, done_label, profile_probability::very_likely ());
994 emit_jump (do_error);
995 emit_label (op0_geu_op1);
996 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
997 NULL, done_label, profile_probability::very_likely ());
998 goto do_error_label;
1001 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1003 /* s1 +- s2 -> sr */
1004 do_signed:
1006 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1007 : subv4_optab, mode);
1008 if (icode != CODE_FOR_nothing)
1010 class expand_operand ops[4];
1011 rtx_insn *last = get_last_insn ();
1013 res = gen_reg_rtx (mode);
1014 create_output_operand (&ops[0], res, mode);
1015 create_input_operand (&ops[1], op0, mode);
1016 create_input_operand (&ops[2], op1, mode);
1017 create_fixed_operand (&ops[3], do_error);
1018 if (maybe_expand_insn (icode, 4, ops))
1020 last = get_last_insn ();
1021 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1022 && JUMP_P (last)
1023 && any_condjump_p (last)
1024 && !find_reg_note (last, REG_BR_PROB, 0))
1025 add_reg_br_prob_note (last,
1026 profile_probability::very_unlikely ());
1027 emit_jump (done_label);
1028 goto do_error_label;
1031 delete_insns_since (last);
1034 /* Compute the operation. On RTL level, the addition is always
1035 unsigned. */
1036 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1037 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1039 /* If we can prove that one of the arguments (for MINUS_EXPR only
1040 the second operand, as subtraction is not commutative) is always
1041 non-negative or always negative, we can do just one comparison
1042 and conditional jump. */
1043 int pos_neg = get_range_pos_neg (arg1);
1044 if (code == PLUS_EXPR)
1046 int pos_neg0 = get_range_pos_neg (arg0);
1047 if (pos_neg0 != 3 && pos_neg == 3)
1049 std::swap (op0, op1);
1050 pos_neg = pos_neg0;
1054 /* Addition overflows if and only if the two operands have the same sign,
1055 and the result has the opposite sign. Subtraction overflows if and
1056 only if the two operands have opposite sign, and the subtrahend has
1057 the same sign as the result. Here 0 is counted as positive. */
1058 if (pos_neg == 3)
1060 /* Compute op0 ^ op1 (operands have opposite sign). */
1061 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1062 OPTAB_LIB_WIDEN);
1064 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1065 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1066 OPTAB_LIB_WIDEN);
1068 rtx tem;
1069 if (code == PLUS_EXPR)
1071 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1072 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1073 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1074 OPTAB_LIB_WIDEN);
1076 else
1078 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1079 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1080 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1081 OPTAB_LIB_WIDEN);
1084 /* No overflow if the result has bit sign cleared. */
1085 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1086 NULL, done_label, profile_probability::very_likely ());
1089 /* Compare the result of the operation with the first operand.
1090 No overflow for addition if second operand is positive and result
1091 is larger or second operand is negative and result is smaller.
1092 Likewise for subtraction with sign of second operand flipped. */
1093 else
1094 do_compare_rtx_and_jump (res, op0,
1095 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1096 false, mode, NULL_RTX, NULL, done_label,
1097 profile_probability::very_likely ());
1100 do_error_label:
1101 emit_label (do_error);
1102 if (is_ubsan)
1104 /* Expand the ubsan builtin call. */
1105 push_temp_slots ();
1106 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1107 arg0, arg1, datap);
1108 expand_normal (fn);
1109 pop_temp_slots ();
1110 do_pending_stack_adjust ();
1112 else if (lhs)
1113 expand_arith_set_overflow (lhs, target);
1115 /* We're done. */
1116 emit_label (done_label);
1118 if (lhs)
1120 if (is_ubsan)
1121 expand_ubsan_result_store (target, res);
1122 else
1124 if (do_xor)
1125 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1126 OPTAB_LIB_WIDEN);
1128 expand_arith_overflow_result_store (lhs, target, mode, res);
1133 /* Add negate overflow checking to the statement STMT. */
1135 static void
1136 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1137 tree *datap)
1139 rtx res, op1;
1140 tree fn;
1141 rtx_code_label *done_label, *do_error;
1142 rtx target = NULL_RTX;
1144 done_label = gen_label_rtx ();
1145 do_error = gen_label_rtx ();
1147 do_pending_stack_adjust ();
1148 op1 = expand_normal (arg1);
1150 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1151 if (lhs)
1153 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1154 if (!is_ubsan)
1155 write_complex_part (target, const0_rtx, true);
1158 enum insn_code icode = optab_handler (negv3_optab, mode);
1159 if (icode != CODE_FOR_nothing)
1161 class expand_operand ops[3];
1162 rtx_insn *last = get_last_insn ();
1164 res = gen_reg_rtx (mode);
1165 create_output_operand (&ops[0], res, mode);
1166 create_input_operand (&ops[1], op1, mode);
1167 create_fixed_operand (&ops[2], do_error);
1168 if (maybe_expand_insn (icode, 3, ops))
1170 last = get_last_insn ();
1171 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1172 && JUMP_P (last)
1173 && any_condjump_p (last)
1174 && !find_reg_note (last, REG_BR_PROB, 0))
1175 add_reg_br_prob_note (last,
1176 profile_probability::very_unlikely ());
1177 emit_jump (done_label);
1179 else
1181 delete_insns_since (last);
1182 icode = CODE_FOR_nothing;
1186 if (icode == CODE_FOR_nothing)
1188 /* Compute the operation. On RTL level, the addition is always
1189 unsigned. */
1190 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1192 /* Compare the operand with the most negative value. */
1193 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1194 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1195 done_label, profile_probability::very_likely ());
1198 emit_label (do_error);
1199 if (is_ubsan)
1201 /* Expand the ubsan builtin call. */
1202 push_temp_slots ();
1203 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1204 arg1, NULL_TREE, datap);
1205 expand_normal (fn);
1206 pop_temp_slots ();
1207 do_pending_stack_adjust ();
1209 else if (lhs)
1210 expand_arith_set_overflow (lhs, target);
1212 /* We're done. */
1213 emit_label (done_label);
1215 if (lhs)
1217 if (is_ubsan)
1218 expand_ubsan_result_store (target, res);
1219 else
1220 expand_arith_overflow_result_store (lhs, target, mode, res);
1224 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1225 mode MODE can be expanded without using a libcall. */
1227 static bool
1228 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1229 rtx op0, rtx op1, bool uns)
1231 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1232 != CODE_FOR_nothing)
1233 return true;
1235 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1236 != CODE_FOR_nothing)
1237 return true;
1239 rtx_insn *last = get_last_insn ();
1240 if (CONSTANT_P (op0))
1241 op0 = convert_modes (wmode, mode, op0, uns);
1242 else
1243 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1244 if (CONSTANT_P (op1))
1245 op1 = convert_modes (wmode, mode, op1, uns);
1246 else
1247 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1248 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1249 delete_insns_since (last);
1250 return ret != NULL_RTX;
1253 /* Add mul overflow checking to the statement STMT. */
1255 static void
1256 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1257 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1258 tree *datap)
1260 rtx res, op0, op1;
1261 tree fn, type;
1262 rtx_code_label *done_label, *do_error;
1263 rtx target = NULL_RTX;
1264 signop sign;
1265 enum insn_code icode;
1267 done_label = gen_label_rtx ();
1268 do_error = gen_label_rtx ();
1270 do_pending_stack_adjust ();
1271 op0 = expand_normal (arg0);
1272 op1 = expand_normal (arg1);
1274 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1275 bool uns = unsr_p;
1276 if (lhs)
1278 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1279 if (!is_ubsan)
1280 write_complex_part (target, const0_rtx, true);
1283 if (is_ubsan)
1284 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1286 /* We assume both operands and result have the same precision
1287 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1288 with that precision, U for unsigned type with that precision,
1289 sgn for unsigned most significant bit in that precision.
1290 s1 is signed first operand, u1 is unsigned first operand,
1291 s2 is signed second operand, u2 is unsigned second operand,
1292 sr is signed result, ur is unsigned result and the following
1293 rules say how to compute result (which is always result of
1294 the operands as if both were unsigned, cast to the right
1295 signedness) and how to compute whether operation overflowed.
1296 main_ovf (false) stands for jump on signed multiplication
1297 overflow or the main algorithm with uns == false.
1298 main_ovf (true) stands for jump on unsigned multiplication
1299 overflow or the main algorithm with uns == true.
1301 s1 * s2 -> sr
1302 res = (S) ((U) s1 * (U) s2)
1303 ovf = main_ovf (false)
1304 u1 * u2 -> ur
1305 res = u1 * u2
1306 ovf = main_ovf (true)
1307 s1 * u2 -> ur
1308 res = (U) s1 * u2
1309 ovf = (s1 < 0 && u2) || main_ovf (true)
1310 u1 * u2 -> sr
1311 res = (S) (u1 * u2)
1312 ovf = res < 0 || main_ovf (true)
1313 s1 * u2 -> sr
1314 res = (S) ((U) s1 * u2)
1315 ovf = (S) u2 >= 0 ? main_ovf (false)
1316 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1317 s1 * s2 -> ur
1318 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1319 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1320 res = t1 * t2
1321 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1323 if (uns0_p && !uns1_p)
1325 /* Multiplication is commutative, if operand signedness differs,
1326 canonicalize to the first operand being signed and second
1327 unsigned to simplify following code. */
1328 std::swap (op0, op1);
1329 std::swap (arg0, arg1);
1330 uns0_p = false;
1331 uns1_p = true;
1334 int pos_neg0 = get_range_pos_neg (arg0);
1335 int pos_neg1 = get_range_pos_neg (arg1);
1337 /* s1 * u2 -> ur */
1338 if (!uns0_p && uns1_p && unsr_p)
1340 switch (pos_neg0)
1342 case 1:
1343 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1344 goto do_main;
1345 case 2:
1346 /* If s1 is negative, avoid the main code, just multiply and
1347 signal overflow if op1 is not 0. */
1348 struct separate_ops ops;
1349 ops.code = MULT_EXPR;
1350 ops.type = TREE_TYPE (arg1);
1351 ops.op0 = make_tree (ops.type, op0);
1352 ops.op1 = make_tree (ops.type, op1);
1353 ops.op2 = NULL_TREE;
1354 ops.location = loc;
1355 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1356 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1357 NULL, done_label, profile_probability::very_likely ());
1358 goto do_error_label;
1359 case 3:
1360 rtx_code_label *do_main_label;
1361 do_main_label = gen_label_rtx ();
1362 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1363 NULL, do_main_label, profile_probability::very_likely ());
1364 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1365 NULL, do_main_label, profile_probability::very_likely ());
1366 expand_arith_set_overflow (lhs, target);
1367 emit_label (do_main_label);
1368 goto do_main;
1369 default:
1370 gcc_unreachable ();
1374 /* u1 * u2 -> sr */
1375 if (uns0_p && uns1_p && !unsr_p)
1377 uns = true;
1378 /* Rest of handling of this case after res is computed. */
1379 goto do_main;
1382 /* s1 * u2 -> sr */
1383 if (!uns0_p && uns1_p && !unsr_p)
1385 switch (pos_neg1)
1387 case 1:
1388 goto do_main;
1389 case 2:
1390 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1391 avoid the main code, just multiply and signal overflow
1392 unless 0 * u2 or -1 * ((U) Smin). */
1393 struct separate_ops ops;
1394 ops.code = MULT_EXPR;
1395 ops.type = TREE_TYPE (arg1);
1396 ops.op0 = make_tree (ops.type, op0);
1397 ops.op1 = make_tree (ops.type, op1);
1398 ops.op2 = NULL_TREE;
1399 ops.location = loc;
1400 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1401 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1402 NULL, done_label, profile_probability::very_likely ());
1403 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1404 NULL, do_error, profile_probability::very_unlikely ());
1405 int prec;
1406 prec = GET_MODE_PRECISION (mode);
1407 rtx sgn;
1408 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1409 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1410 NULL, done_label, profile_probability::very_likely ());
1411 goto do_error_label;
1412 case 3:
1413 /* Rest of handling of this case after res is computed. */
1414 goto do_main;
1415 default:
1416 gcc_unreachable ();
1420 /* s1 * s2 -> ur */
1421 if (!uns0_p && !uns1_p && unsr_p)
1423 rtx tem;
1424 switch (pos_neg0 | pos_neg1)
1426 case 1: /* Both operands known to be non-negative. */
1427 goto do_main;
1428 case 2: /* Both operands known to be negative. */
1429 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1430 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1431 /* Avoid looking at arg0/arg1 ranges, as we've changed
1432 the arguments. */
1433 arg0 = error_mark_node;
1434 arg1 = error_mark_node;
1435 goto do_main;
1436 case 3:
1437 if ((pos_neg0 ^ pos_neg1) == 3)
1439 /* If one operand is known to be negative and the other
1440 non-negative, this overflows always, unless the non-negative
1441 one is 0. Just do normal multiply and set overflow
1442 unless one of the operands is 0. */
1443 struct separate_ops ops;
1444 ops.code = MULT_EXPR;
1445 ops.type
1446 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1448 ops.op0 = make_tree (ops.type, op0);
1449 ops.op1 = make_tree (ops.type, op1);
1450 ops.op2 = NULL_TREE;
1451 ops.location = loc;
1452 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1453 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1454 true, mode, NULL_RTX, NULL, done_label,
1455 profile_probability::very_likely ());
1456 goto do_error_label;
1458 /* The general case, do all the needed comparisons at runtime. */
1459 rtx_code_label *do_main_label, *after_negate_label;
1460 rtx rop0, rop1;
1461 rop0 = gen_reg_rtx (mode);
1462 rop1 = gen_reg_rtx (mode);
1463 emit_move_insn (rop0, op0);
1464 emit_move_insn (rop1, op1);
1465 op0 = rop0;
1466 op1 = rop1;
1467 do_main_label = gen_label_rtx ();
1468 after_negate_label = gen_label_rtx ();
1469 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1470 OPTAB_LIB_WIDEN);
1471 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1472 NULL, after_negate_label, profile_probability::very_likely ());
1473 /* Both arguments negative here, negate them and continue with
1474 normal unsigned overflow checking multiplication. */
1475 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1476 NULL_RTX, false));
1477 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1478 NULL_RTX, false));
1479 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1480 the arguments. */
1481 arg0 = error_mark_node;
1482 arg1 = error_mark_node;
1483 emit_jump (do_main_label);
1484 emit_label (after_negate_label);
1485 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1486 OPTAB_LIB_WIDEN);
1487 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1488 NULL, do_main_label,
1489 profile_probability::very_likely ());
1490 /* One argument is negative here, the other positive. This
1491 overflows always, unless one of the arguments is 0. But
1492 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1493 is, thus we can keep do_main code oring in overflow as is. */
1494 if (pos_neg0 != 2)
1495 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1496 NULL, do_main_label,
1497 profile_probability::very_unlikely ());
1498 if (pos_neg1 != 2)
1499 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1500 NULL, do_main_label,
1501 profile_probability::very_unlikely ());
1502 expand_arith_set_overflow (lhs, target);
1503 emit_label (do_main_label);
1504 goto do_main;
1505 default:
1506 gcc_unreachable ();
1510 do_main:
1511 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1512 sign = uns ? UNSIGNED : SIGNED;
1513 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1514 if (uns
1515 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1516 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1518 /* Optimize unsigned multiplication by power of 2 constant
1519 using 2 shifts, one for result, one to extract the shifted
1520 out bits to see if they are all zero.
1521 Don't do this if optimizing for size and we have umulv4_optab,
1522 in that case assume multiplication will be shorter.
1523 This is heuristics based on the single target that provides
1524 umulv4 right now (i?86/x86_64), if further targets add it, this
1525 might need to be revisited.
1526 Cases where both operands are constant should be folded already
1527 during GIMPLE, and cases where one operand is constant but not
1528 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1529 below can be done without multiplication, just by shifts and adds,
1530 or we'd need to divide the result (and hope it actually doesn't
1531 really divide nor multiply) and compare the result of the division
1532 with the original operand. */
1533 rtx opn0 = op0;
1534 rtx opn1 = op1;
1535 tree argn0 = arg0;
1536 tree argn1 = arg1;
1537 if (integer_pow2p (arg0))
1539 std::swap (opn0, opn1);
1540 std::swap (argn0, argn1);
1542 int cnt = tree_log2 (argn1);
1543 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1545 rtx upper = const0_rtx;
1546 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1547 if (cnt != 0)
1548 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1549 GET_MODE_PRECISION (mode) - cnt,
1550 NULL_RTX, uns);
1551 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1552 NULL_RTX, NULL, done_label,
1553 profile_probability::very_likely ());
1554 goto do_error_label;
1557 if (icode != CODE_FOR_nothing)
1559 class expand_operand ops[4];
1560 rtx_insn *last = get_last_insn ();
1562 res = gen_reg_rtx (mode);
1563 create_output_operand (&ops[0], res, mode);
1564 create_input_operand (&ops[1], op0, mode);
1565 create_input_operand (&ops[2], op1, mode);
1566 create_fixed_operand (&ops[3], do_error);
1567 if (maybe_expand_insn (icode, 4, ops))
1569 last = get_last_insn ();
1570 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1571 && JUMP_P (last)
1572 && any_condjump_p (last)
1573 && !find_reg_note (last, REG_BR_PROB, 0))
1574 add_reg_br_prob_note (last,
1575 profile_probability::very_unlikely ());
1576 emit_jump (done_label);
1578 else
1580 delete_insns_since (last);
1581 icode = CODE_FOR_nothing;
1585 if (icode == CODE_FOR_nothing)
1587 struct separate_ops ops;
1588 int prec = GET_MODE_PRECISION (mode);
1589 scalar_int_mode hmode, wmode;
1590 ops.op0 = make_tree (type, op0);
1591 ops.op1 = make_tree (type, op1);
1592 ops.op2 = NULL_TREE;
1593 ops.location = loc;
1595 /* Optimize unsigned overflow check where we don't use the
1596 multiplication result, just whether overflow happened.
1597 If we can do MULT_HIGHPART_EXPR, that followed by
1598 comparison of the result against zero is cheapest.
1599 We'll still compute res, but it should be DCEd later. */
1600 use_operand_p use;
1601 gimple *use_stmt;
1602 if (!is_ubsan
1603 && lhs
1604 && uns
1605 && !(uns0_p && uns1_p && !unsr_p)
1606 && can_mult_highpart_p (mode, uns) == 1
1607 && single_imm_use (lhs, &use, &use_stmt)
1608 && is_gimple_assign (use_stmt)
1609 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1610 goto highpart;
1612 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1613 && targetm.scalar_mode_supported_p (wmode)
1614 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1616 twoxwider:
1617 ops.code = WIDEN_MULT_EXPR;
1618 ops.type
1619 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1621 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1622 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1623 NULL_RTX, uns);
1624 hipart = convert_modes (mode, wmode, hipart, uns);
1625 res = convert_modes (mode, wmode, res, uns);
1626 if (uns)
1627 /* For the unsigned multiplication, there was overflow if
1628 HIPART is non-zero. */
1629 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1630 NULL_RTX, NULL, done_label,
1631 profile_probability::very_likely ());
1632 else
1634 /* RES is used more than once, place it in a pseudo. */
1635 res = force_reg (mode, res);
1637 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1638 NULL_RTX, 0);
1639 /* RES is low half of the double width result, HIPART
1640 the high half. There was overflow if
1641 HIPART is different from RES < 0 ? -1 : 0. */
1642 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1643 NULL_RTX, NULL, done_label,
1644 profile_probability::very_likely ());
1647 else if (can_mult_highpart_p (mode, uns) == 1)
1649 highpart:
1650 ops.code = MULT_HIGHPART_EXPR;
1651 ops.type = type;
1653 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1654 EXPAND_NORMAL);
1655 ops.code = MULT_EXPR;
1656 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1657 if (uns)
1658 /* For the unsigned multiplication, there was overflow if
1659 HIPART is non-zero. */
1660 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1661 NULL_RTX, NULL, done_label,
1662 profile_probability::very_likely ());
1663 else
1665 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1666 NULL_RTX, 0);
1667 /* RES is low half of the double width result, HIPART
1668 the high half. There was overflow if
1669 HIPART is different from RES < 0 ? -1 : 0. */
1670 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1671 NULL_RTX, NULL, done_label,
1672 profile_probability::very_likely ());
1676 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
1677 && 2 * GET_MODE_PRECISION (hmode) == prec)
1679 rtx_code_label *large_op0 = gen_label_rtx ();
1680 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1681 rtx_code_label *one_small_one_large = gen_label_rtx ();
1682 rtx_code_label *both_ops_large = gen_label_rtx ();
1683 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1684 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1685 rtx_code_label *do_overflow = gen_label_rtx ();
1686 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1688 unsigned int hprec = GET_MODE_PRECISION (hmode);
1689 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1690 NULL_RTX, uns);
1691 hipart0 = convert_modes (hmode, mode, hipart0, uns);
1692 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1693 rtx signbit0 = const0_rtx;
1694 if (!uns)
1695 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1696 NULL_RTX, 0);
1697 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1698 NULL_RTX, uns);
1699 hipart1 = convert_modes (hmode, mode, hipart1, uns);
1700 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1701 rtx signbit1 = const0_rtx;
1702 if (!uns)
1703 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1704 NULL_RTX, 0);
1706 res = gen_reg_rtx (mode);
1708 /* True if op0 resp. op1 are known to be in the range of
1709 halfstype. */
1710 bool op0_small_p = false;
1711 bool op1_small_p = false;
1712 /* True if op0 resp. op1 are known to have all zeros or all ones
1713 in the upper half of bits, but are not known to be
1714 op{0,1}_small_p. */
1715 bool op0_medium_p = false;
1716 bool op1_medium_p = false;
1717 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1718 nonnegative, 1 if unknown. */
1719 int op0_sign = 1;
1720 int op1_sign = 1;
1722 if (pos_neg0 == 1)
1723 op0_sign = 0;
1724 else if (pos_neg0 == 2)
1725 op0_sign = -1;
1726 if (pos_neg1 == 1)
1727 op1_sign = 0;
1728 else if (pos_neg1 == 2)
1729 op1_sign = -1;
1731 unsigned int mprec0 = prec;
1732 if (arg0 != error_mark_node)
1733 mprec0 = get_min_precision (arg0, sign);
1734 if (mprec0 <= hprec)
1735 op0_small_p = true;
1736 else if (!uns && mprec0 <= hprec + 1)
1737 op0_medium_p = true;
1738 unsigned int mprec1 = prec;
1739 if (arg1 != error_mark_node)
1740 mprec1 = get_min_precision (arg1, sign);
1741 if (mprec1 <= hprec)
1742 op1_small_p = true;
1743 else if (!uns && mprec1 <= hprec + 1)
1744 op1_medium_p = true;
1746 int smaller_sign = 1;
1747 int larger_sign = 1;
1748 if (op0_small_p)
1750 smaller_sign = op0_sign;
1751 larger_sign = op1_sign;
1753 else if (op1_small_p)
1755 smaller_sign = op1_sign;
1756 larger_sign = op0_sign;
1758 else if (op0_sign == op1_sign)
1760 smaller_sign = op0_sign;
1761 larger_sign = op0_sign;
1764 if (!op0_small_p)
1765 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1766 NULL_RTX, NULL, large_op0,
1767 profile_probability::unlikely ());
1769 if (!op1_small_p)
1770 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1771 NULL_RTX, NULL, small_op0_large_op1,
1772 profile_probability::unlikely ());
1774 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1775 hmode to mode, the multiplication will never overflow. We can
1776 do just one hmode x hmode => mode widening multiplication. */
1777 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1778 ops.op0 = make_tree (halfstype, lopart0);
1779 ops.op1 = make_tree (halfstype, lopart1);
1780 ops.code = WIDEN_MULT_EXPR;
1781 ops.type = type;
1782 rtx thisres
1783 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1784 emit_move_insn (res, thisres);
1785 emit_jump (done_label);
1787 emit_label (small_op0_large_op1);
1789 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1790 but op1 is not, just swap the arguments and handle it as op1
1791 sign/zero extended, op0 not. */
1792 rtx larger = gen_reg_rtx (mode);
1793 rtx hipart = gen_reg_rtx (hmode);
1794 rtx lopart = gen_reg_rtx (hmode);
1795 emit_move_insn (larger, op1);
1796 emit_move_insn (hipart, hipart1);
1797 emit_move_insn (lopart, lopart0);
1798 emit_jump (one_small_one_large);
1800 emit_label (large_op0);
1802 if (!op1_small_p)
1803 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1804 NULL_RTX, NULL, both_ops_large,
1805 profile_probability::unlikely ());
1807 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1808 but op0 is not, prepare larger, hipart and lopart pseudos and
1809 handle it together with small_op0_large_op1. */
1810 emit_move_insn (larger, op0);
1811 emit_move_insn (hipart, hipart0);
1812 emit_move_insn (lopart, lopart1);
1814 emit_label (one_small_one_large);
1816 /* lopart is the low part of the operand that is sign extended
1817 to mode, larger is the other operand, hipart is the
1818 high part of larger and lopart0 and lopart1 are the low parts
1819 of both operands.
1820 We perform lopart0 * lopart1 and lopart * hipart widening
1821 multiplications. */
1822 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1823 ops.op0 = make_tree (halfutype, lopart0);
1824 ops.op1 = make_tree (halfutype, lopart1);
1825 rtx lo0xlo1
1826 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1828 ops.op0 = make_tree (halfutype, lopart);
1829 ops.op1 = make_tree (halfutype, hipart);
1830 rtx loxhi = gen_reg_rtx (mode);
1831 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1832 emit_move_insn (loxhi, tem);
1834 if (!uns)
1836 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1837 if (larger_sign == 0)
1838 emit_jump (after_hipart_neg);
1839 else if (larger_sign != -1)
1840 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1841 NULL_RTX, NULL, after_hipart_neg,
1842 profile_probability::even ());
1844 tem = convert_modes (mode, hmode, lopart, 1);
1845 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1846 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1847 1, OPTAB_WIDEN);
1848 emit_move_insn (loxhi, tem);
1850 emit_label (after_hipart_neg);
1852 /* if (lopart < 0) loxhi -= larger; */
1853 if (smaller_sign == 0)
1854 emit_jump (after_lopart_neg);
1855 else if (smaller_sign != -1)
1856 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1857 NULL_RTX, NULL, after_lopart_neg,
1858 profile_probability::even ());
1860 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1861 1, OPTAB_WIDEN);
1862 emit_move_insn (loxhi, tem);
1864 emit_label (after_lopart_neg);
1867 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1868 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1869 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1870 1, OPTAB_WIDEN);
1871 emit_move_insn (loxhi, tem);
1873 /* if (loxhi >> (bitsize / 2)
1874 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1875 if (loxhi >> (bitsize / 2) == 0 (if uns). */
1876 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1877 NULL_RTX, 0);
1878 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1879 rtx signbitloxhi = const0_rtx;
1880 if (!uns)
1881 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1882 convert_modes (hmode, mode,
1883 loxhi, 0),
1884 hprec - 1, NULL_RTX, 0);
1886 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1887 NULL_RTX, NULL, do_overflow,
1888 profile_probability::very_unlikely ());
1890 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1891 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1892 NULL_RTX, 1);
1893 tem = convert_modes (mode, hmode,
1894 convert_modes (hmode, mode, lo0xlo1, 1), 1);
1896 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1897 1, OPTAB_WIDEN);
1898 if (tem != res)
1899 emit_move_insn (res, tem);
1900 emit_jump (done_label);
1902 emit_label (both_ops_large);
1904 /* If both operands are large (not sign (!uns) or zero (uns)
1905 extended from hmode), then perform the full multiplication
1906 which will be the result of the operation.
1907 The only cases which don't overflow are for signed multiplication
1908 some cases where both hipart0 and highpart1 are 0 or -1.
1909 For unsigned multiplication when high parts are both non-zero
1910 this overflows always. */
1911 ops.code = MULT_EXPR;
1912 ops.op0 = make_tree (type, op0);
1913 ops.op1 = make_tree (type, op1);
1914 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1915 emit_move_insn (res, tem);
1917 if (!uns)
1919 if (!op0_medium_p)
1921 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1922 NULL_RTX, 1, OPTAB_WIDEN);
1923 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1924 NULL_RTX, NULL, do_error,
1925 profile_probability::very_unlikely ());
1928 if (!op1_medium_p)
1930 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1931 NULL_RTX, 1, OPTAB_WIDEN);
1932 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1933 NULL_RTX, NULL, do_error,
1934 profile_probability::very_unlikely ());
1937 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1938 the same, overflow happened if res is non-positive, if they
1939 are different, overflow happened if res is positive. */
1940 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1941 emit_jump (hipart_different);
1942 else if (op0_sign == 1 || op1_sign == 1)
1943 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1944 NULL_RTX, NULL, hipart_different,
1945 profile_probability::even ());
1947 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
1948 NULL_RTX, NULL, do_error,
1949 profile_probability::very_unlikely ());
1950 emit_jump (done_label);
1952 emit_label (hipart_different);
1954 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1955 NULL_RTX, NULL, do_error,
1956 profile_probability::very_unlikely ());
1957 emit_jump (done_label);
1960 emit_label (do_overflow);
1962 /* Overflow, do full multiplication and fallthru into do_error. */
1963 ops.op0 = make_tree (type, op0);
1964 ops.op1 = make_tree (type, op1);
1965 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1966 emit_move_insn (res, tem);
1968 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1969 && targetm.scalar_mode_supported_p (wmode))
1970 /* Even emitting a libcall is better than not detecting overflow
1971 at all. */
1972 goto twoxwider;
1973 else
1975 gcc_assert (!is_ubsan);
1976 ops.code = MULT_EXPR;
1977 ops.type = type;
1978 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1979 emit_jump (done_label);
1983 do_error_label:
1984 emit_label (do_error);
1985 if (is_ubsan)
1987 /* Expand the ubsan builtin call. */
1988 push_temp_slots ();
1989 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1990 arg0, arg1, datap);
1991 expand_normal (fn);
1992 pop_temp_slots ();
1993 do_pending_stack_adjust ();
1995 else if (lhs)
1996 expand_arith_set_overflow (lhs, target);
1998 /* We're done. */
1999 emit_label (done_label);
2001 /* u1 * u2 -> sr */
2002 if (uns0_p && uns1_p && !unsr_p)
2004 rtx_code_label *all_done_label = gen_label_rtx ();
2005 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2006 NULL, all_done_label, profile_probability::very_likely ());
2007 expand_arith_set_overflow (lhs, target);
2008 emit_label (all_done_label);
2011 /* s1 * u2 -> sr */
2012 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2014 rtx_code_label *all_done_label = gen_label_rtx ();
2015 rtx_code_label *set_noovf = gen_label_rtx ();
2016 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2017 NULL, all_done_label, profile_probability::very_likely ());
2018 expand_arith_set_overflow (lhs, target);
2019 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2020 NULL, set_noovf, profile_probability::very_likely ());
2021 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2022 NULL, all_done_label, profile_probability::very_unlikely ());
2023 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2024 all_done_label, profile_probability::very_unlikely ());
2025 emit_label (set_noovf);
2026 write_complex_part (target, const0_rtx, true);
2027 emit_label (all_done_label);
2030 if (lhs)
2032 if (is_ubsan)
2033 expand_ubsan_result_store (target, res);
2034 else
2035 expand_arith_overflow_result_store (lhs, target, mode, res);
2039 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2041 static void
2042 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2043 tree arg0, tree arg1)
2045 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2046 rtx_code_label *loop_lab = NULL;
2047 rtx cntvar = NULL_RTX;
2048 tree cntv = NULL_TREE;
2049 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2050 tree sz = TYPE_SIZE (eltype);
2051 tree data = NULL_TREE;
2052 tree resv = NULL_TREE;
2053 rtx lhsr = NULL_RTX;
2054 rtx resvr = NULL_RTX;
2055 unsigned HOST_WIDE_INT const_cnt = 0;
2056 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2058 if (lhs)
2060 optab op;
2061 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2062 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2063 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2064 optab_default)) == unknown_optab
2065 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2066 == CODE_FOR_nothing))
2068 if (MEM_P (lhsr))
2069 resv = make_tree (TREE_TYPE (lhs), lhsr);
2070 else
2072 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2073 resv = make_tree (TREE_TYPE (lhs), resvr);
2077 if (use_loop_p)
2079 do_pending_stack_adjust ();
2080 loop_lab = gen_label_rtx ();
2081 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2082 cntv = make_tree (sizetype, cntvar);
2083 emit_move_insn (cntvar, const0_rtx);
2084 emit_label (loop_lab);
2086 if (TREE_CODE (arg0) != VECTOR_CST)
2088 rtx arg0r = expand_normal (arg0);
2089 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2091 if (TREE_CODE (arg1) != VECTOR_CST)
2093 rtx arg1r = expand_normal (arg1);
2094 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2096 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2098 tree op0, op1, res = NULL_TREE;
2099 if (use_loop_p)
2101 tree atype = build_array_type_nelts (eltype, cnt);
2102 op0 = uniform_vector_p (arg0);
2103 if (op0 == NULL_TREE)
2105 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2106 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2107 NULL_TREE, NULL_TREE);
2109 op1 = uniform_vector_p (arg1);
2110 if (op1 == NULL_TREE)
2112 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2113 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2114 NULL_TREE, NULL_TREE);
2116 if (resv)
2118 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2119 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2120 NULL_TREE, NULL_TREE);
2123 else
2125 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2126 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2127 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2128 if (resv)
2129 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2130 bitpos);
2132 switch (code)
2134 case PLUS_EXPR:
2135 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2136 false, false, false, true, &data);
2137 break;
2138 case MINUS_EXPR:
2139 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2140 expand_neg_overflow (loc, res, op1, true, &data);
2141 else
2142 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2143 false, false, false, true, &data);
2144 break;
2145 case MULT_EXPR:
2146 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2147 true, &data);
2148 break;
2149 default:
2150 gcc_unreachable ();
2153 if (use_loop_p)
2155 struct separate_ops ops;
2156 ops.code = PLUS_EXPR;
2157 ops.type = TREE_TYPE (cntv);
2158 ops.op0 = cntv;
2159 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2160 ops.op2 = NULL_TREE;
2161 ops.location = loc;
2162 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2163 EXPAND_NORMAL);
2164 if (ret != cntvar)
2165 emit_move_insn (cntvar, ret);
2166 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2167 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2168 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2169 profile_probability::very_likely ());
2171 if (lhs && resv == NULL_TREE)
2173 struct separate_ops ops;
2174 ops.code = code;
2175 ops.type = TREE_TYPE (arg0);
2176 ops.op0 = arg0;
2177 ops.op1 = arg1;
2178 ops.op2 = NULL_TREE;
2179 ops.location = loc;
2180 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2181 EXPAND_NORMAL);
2182 if (ret != lhsr)
2183 emit_move_insn (lhsr, ret);
2185 else if (resvr)
2186 emit_move_insn (lhsr, resvr);
2189 /* Expand UBSAN_CHECK_ADD call STMT. */
2191 static void
2192 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2194 location_t loc = gimple_location (stmt);
2195 tree lhs = gimple_call_lhs (stmt);
2196 tree arg0 = gimple_call_arg (stmt, 0);
2197 tree arg1 = gimple_call_arg (stmt, 1);
2198 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2199 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2200 else
2201 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2202 false, false, false, true, NULL);
2205 /* Expand UBSAN_CHECK_SUB call STMT. */
2207 static void
2208 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2210 location_t loc = gimple_location (stmt);
2211 tree lhs = gimple_call_lhs (stmt);
2212 tree arg0 = gimple_call_arg (stmt, 0);
2213 tree arg1 = gimple_call_arg (stmt, 1);
2214 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2215 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2216 else if (integer_zerop (arg0))
2217 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2218 else
2219 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2220 false, false, false, true, NULL);
2223 /* Expand UBSAN_CHECK_MUL call STMT. */
2225 static void
2226 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2228 location_t loc = gimple_location (stmt);
2229 tree lhs = gimple_call_lhs (stmt);
2230 tree arg0 = gimple_call_arg (stmt, 0);
2231 tree arg1 = gimple_call_arg (stmt, 1);
2232 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2233 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2234 else
2235 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2236 NULL);
2239 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2241 static void
2242 expand_arith_overflow (enum tree_code code, gimple *stmt)
2244 tree lhs = gimple_call_lhs (stmt);
2245 if (lhs == NULL_TREE)
2246 return;
2247 tree arg0 = gimple_call_arg (stmt, 0);
2248 tree arg1 = gimple_call_arg (stmt, 1);
2249 tree type = TREE_TYPE (TREE_TYPE (lhs));
2250 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2251 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2252 int unsr_p = TYPE_UNSIGNED (type);
2253 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2254 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2255 int precres = TYPE_PRECISION (type);
2256 location_t loc = gimple_location (stmt);
2257 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2258 uns0_p = true;
2259 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2260 uns1_p = true;
2261 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2262 prec0 = MIN (prec0, pr);
2263 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2264 prec1 = MIN (prec1, pr);
2266 /* If uns0_p && uns1_p, precop is minimum needed precision
2267 of unsigned type to hold the exact result, otherwise
2268 precop is minimum needed precision of signed type to
2269 hold the exact result. */
2270 int precop;
2271 if (code == MULT_EXPR)
2272 precop = prec0 + prec1 + (uns0_p != uns1_p);
2273 else
2275 if (uns0_p == uns1_p)
2276 precop = MAX (prec0, prec1) + 1;
2277 else if (uns0_p)
2278 precop = MAX (prec0 + 1, prec1) + 1;
2279 else
2280 precop = MAX (prec0, prec1 + 1) + 1;
2282 int orig_precres = precres;
2286 if ((uns0_p && uns1_p)
2287 ? ((precop + !unsr_p) <= precres
2288 /* u1 - u2 -> ur can overflow, no matter what precision
2289 the result has. */
2290 && (code != MINUS_EXPR || !unsr_p))
2291 : (!unsr_p && precop <= precres))
2293 /* The infinity precision result will always fit into result. */
2294 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2295 write_complex_part (target, const0_rtx, true);
2296 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2297 struct separate_ops ops;
2298 ops.code = code;
2299 ops.type = type;
2300 ops.op0 = fold_convert_loc (loc, type, arg0);
2301 ops.op1 = fold_convert_loc (loc, type, arg1);
2302 ops.op2 = NULL_TREE;
2303 ops.location = loc;
2304 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2305 expand_arith_overflow_result_store (lhs, target, mode, tem);
2306 return;
2309 /* For operations with low precision, if target doesn't have them, start
2310 with precres widening right away, otherwise do it only if the most
2311 simple cases can't be used. */
2312 const int min_precision = targetm.min_arithmetic_precision ();
2313 if (orig_precres == precres && precres < min_precision)
2315 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2316 && prec1 <= precres)
2317 || ((!uns0_p || !uns1_p) && !unsr_p
2318 && prec0 + uns0_p <= precres
2319 && prec1 + uns1_p <= precres))
2321 arg0 = fold_convert_loc (loc, type, arg0);
2322 arg1 = fold_convert_loc (loc, type, arg1);
2323 switch (code)
2325 case MINUS_EXPR:
2326 if (integer_zerop (arg0) && !unsr_p)
2328 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2329 return;
2331 /* FALLTHRU */
2332 case PLUS_EXPR:
2333 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2334 unsr_p, unsr_p, false, NULL);
2335 return;
2336 case MULT_EXPR:
2337 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2338 unsr_p, unsr_p, false, NULL);
2339 return;
2340 default:
2341 gcc_unreachable ();
2345 /* For sub-word operations, retry with a wider type first. */
2346 if (orig_precres == precres && precop <= BITS_PER_WORD)
2348 int p = MAX (min_precision, precop);
2349 scalar_int_mode m = smallest_int_mode_for_size (p);
2350 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2351 uns0_p && uns1_p
2352 && unsr_p);
2353 p = TYPE_PRECISION (optype);
2354 if (p > precres)
2356 precres = p;
2357 unsr_p = TYPE_UNSIGNED (optype);
2358 type = optype;
2359 continue;
2363 if (prec0 <= precres && prec1 <= precres)
2365 tree types[2];
2366 if (unsr_p)
2368 types[0] = build_nonstandard_integer_type (precres, 0);
2369 types[1] = type;
2371 else
2373 types[0] = type;
2374 types[1] = build_nonstandard_integer_type (precres, 1);
2376 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2377 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2378 if (code != MULT_EXPR)
2379 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2380 uns0_p, uns1_p, false, NULL);
2381 else
2382 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2383 uns0_p, uns1_p, false, NULL);
2384 return;
2387 /* Retry with a wider type. */
2388 if (orig_precres == precres)
2390 int p = MAX (prec0, prec1);
2391 scalar_int_mode m = smallest_int_mode_for_size (p);
2392 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2393 uns0_p && uns1_p
2394 && unsr_p);
2395 p = TYPE_PRECISION (optype);
2396 if (p > precres)
2398 precres = p;
2399 unsr_p = TYPE_UNSIGNED (optype);
2400 type = optype;
2401 continue;
2405 gcc_unreachable ();
2407 while (1);
2410 /* Expand ADD_OVERFLOW STMT. */
2412 static void
2413 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2415 expand_arith_overflow (PLUS_EXPR, stmt);
2418 /* Expand SUB_OVERFLOW STMT. */
2420 static void
2421 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2423 expand_arith_overflow (MINUS_EXPR, stmt);
2426 /* Expand MUL_OVERFLOW STMT. */
2428 static void
2429 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2431 expand_arith_overflow (MULT_EXPR, stmt);
2434 /* This should get folded in tree-vectorizer.c. */
2436 static void
2437 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2439 gcc_unreachable ();
2442 /* This should get folded in tree-vectorizer.c. */
2444 static void
2445 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2447 gcc_unreachable ();
2450 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2451 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2453 static tree
2454 expand_call_mem_ref (tree type, gcall *stmt, int index)
2456 tree addr = gimple_call_arg (stmt, index);
2457 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2458 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2459 if (TYPE_ALIGN (type) != align)
2460 type = build_aligned_type (type, align);
2462 tree tmp = addr;
2463 if (TREE_CODE (tmp) == SSA_NAME)
2465 gimple *def = SSA_NAME_DEF_STMT (tmp);
2466 if (gimple_assign_single_p (def))
2467 tmp = gimple_assign_rhs1 (def);
2470 if (TREE_CODE (tmp) == ADDR_EXPR)
2472 tree mem = TREE_OPERAND (tmp, 0);
2473 if (TREE_CODE (mem) == TARGET_MEM_REF
2474 && types_compatible_p (TREE_TYPE (mem), type))
2476 tree offset = TMR_OFFSET (mem);
2477 if (type != TREE_TYPE (mem)
2478 || alias_ptr_type != TREE_TYPE (offset)
2479 || !integer_zerop (offset))
2481 mem = copy_node (mem);
2482 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2483 wi::to_poly_wide (offset));
2484 TREE_TYPE (mem) = type;
2486 return mem;
2490 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2493 /* Expand MASK_LOAD{,_LANES} or LEN_LOAD call STMT using optab OPTAB. */
2495 static void
2496 expand_partial_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2498 class expand_operand ops[3];
2499 tree type, lhs, rhs, maskt;
2500 rtx mem, target, mask;
2501 insn_code icode;
2503 maskt = gimple_call_arg (stmt, 2);
2504 lhs = gimple_call_lhs (stmt);
2505 if (lhs == NULL_TREE)
2506 return;
2507 type = TREE_TYPE (lhs);
2508 rhs = expand_call_mem_ref (type, stmt, 0);
2510 if (optab == vec_mask_load_lanes_optab)
2511 icode = get_multi_vector_move (type, optab);
2512 else if (optab == len_load_optab)
2513 icode = direct_optab_handler (optab, TYPE_MODE (type));
2514 else
2515 icode = convert_optab_handler (optab, TYPE_MODE (type),
2516 TYPE_MODE (TREE_TYPE (maskt)));
2518 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2519 gcc_assert (MEM_P (mem));
2520 mask = expand_normal (maskt);
2521 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2522 create_output_operand (&ops[0], target, TYPE_MODE (type));
2523 create_fixed_operand (&ops[1], mem);
2524 if (optab == len_load_optab)
2525 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2526 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2527 else
2528 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2529 expand_insn (icode, 3, ops);
2530 if (!rtx_equal_p (target, ops[0].value))
2531 emit_move_insn (target, ops[0].value);
2534 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
2535 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2536 #define expand_len_load_optab_fn expand_partial_load_optab_fn
2538 /* Expand MASK_STORE{,_LANES} or LEN_STORE call STMT using optab OPTAB. */
2540 static void
2541 expand_partial_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2543 class expand_operand ops[3];
2544 tree type, lhs, rhs, maskt;
2545 rtx mem, reg, mask;
2546 insn_code icode;
2548 maskt = gimple_call_arg (stmt, 2);
2549 rhs = gimple_call_arg (stmt, 3);
2550 type = TREE_TYPE (rhs);
2551 lhs = expand_call_mem_ref (type, stmt, 0);
2553 if (optab == vec_mask_store_lanes_optab)
2554 icode = get_multi_vector_move (type, optab);
2555 else if (optab == len_store_optab)
2556 icode = direct_optab_handler (optab, TYPE_MODE (type));
2557 else
2558 icode = convert_optab_handler (optab, TYPE_MODE (type),
2559 TYPE_MODE (TREE_TYPE (maskt)));
2561 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2562 gcc_assert (MEM_P (mem));
2563 mask = expand_normal (maskt);
2564 reg = expand_normal (rhs);
2565 create_fixed_operand (&ops[0], mem);
2566 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2567 if (optab == len_store_optab)
2568 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2569 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2570 else
2571 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2572 expand_insn (icode, 3, ops);
2575 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
2576 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2577 #define expand_len_store_optab_fn expand_partial_store_optab_fn
2579 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
2580 The expansion of STMT happens based on OPTAB table associated. */
2582 static void
2583 expand_vect_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2585 class expand_operand ops[6];
2586 insn_code icode;
2587 tree lhs = gimple_call_lhs (stmt);
2588 tree op0a = gimple_call_arg (stmt, 0);
2589 tree op0b = gimple_call_arg (stmt, 1);
2590 tree op1 = gimple_call_arg (stmt, 2);
2591 tree op2 = gimple_call_arg (stmt, 3);
2592 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
2594 tree vec_cond_type = TREE_TYPE (lhs);
2595 tree op_mode = TREE_TYPE (op0a);
2596 bool unsignedp = TYPE_UNSIGNED (op_mode);
2598 machine_mode mode = TYPE_MODE (vec_cond_type);
2599 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
2601 icode = convert_optab_handler (optab, mode, cmp_op_mode);
2602 rtx comparison
2603 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
2604 rtx rtx_op1 = expand_normal (op1);
2605 rtx rtx_op2 = expand_normal (op2);
2607 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2608 create_output_operand (&ops[0], target, mode);
2609 create_input_operand (&ops[1], rtx_op1, mode);
2610 create_input_operand (&ops[2], rtx_op2, mode);
2611 create_fixed_operand (&ops[3], comparison);
2612 create_fixed_operand (&ops[4], XEXP (comparison, 0));
2613 create_fixed_operand (&ops[5], XEXP (comparison, 1));
2614 expand_insn (icode, 6, ops);
2615 if (!rtx_equal_p (ops[0].value, target))
2616 emit_move_insn (target, ops[0].value);
2619 #define expand_vec_cond_optab_fn expand_vect_cond_optab_fn
2620 #define expand_vec_condu_optab_fn expand_vect_cond_optab_fn
2621 #define expand_vec_condeq_optab_fn expand_vect_cond_optab_fn
2623 /* Expand VCOND_MASK optab internal function.
2624 The expansion of STMT happens based on OPTAB table associated. */
2626 static void
2627 expand_vect_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2629 class expand_operand ops[4];
2631 tree lhs = gimple_call_lhs (stmt);
2632 tree op0 = gimple_call_arg (stmt, 0);
2633 tree op1 = gimple_call_arg (stmt, 1);
2634 tree op2 = gimple_call_arg (stmt, 2);
2635 tree vec_cond_type = TREE_TYPE (lhs);
2637 machine_mode mode = TYPE_MODE (vec_cond_type);
2638 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
2639 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
2640 rtx mask, rtx_op1, rtx_op2;
2642 gcc_assert (icode != CODE_FOR_nothing);
2644 mask = expand_normal (op0);
2645 rtx_op1 = expand_normal (op1);
2646 rtx_op2 = expand_normal (op2);
2648 mask = force_reg (mask_mode, mask);
2649 rtx_op1 = force_reg (mode, rtx_op1);
2651 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2652 create_output_operand (&ops[0], target, mode);
2653 create_input_operand (&ops[1], rtx_op1, mode);
2654 create_input_operand (&ops[2], rtx_op2, mode);
2655 create_input_operand (&ops[3], mask, mask_mode);
2656 expand_insn (icode, 4, ops);
2657 if (!rtx_equal_p (ops[0].value, target))
2658 emit_move_insn (target, ops[0].value);
2661 #define expand_vec_cond_mask_optab_fn expand_vect_cond_mask_optab_fn
2663 /* Expand VEC_SET internal functions. */
2665 static void
2666 expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2668 tree lhs = gimple_call_lhs (stmt);
2669 tree op0 = gimple_call_arg (stmt, 0);
2670 tree op1 = gimple_call_arg (stmt, 1);
2671 tree op2 = gimple_call_arg (stmt, 2);
2672 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2673 rtx src = expand_normal (op0);
2675 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
2676 scalar_mode innermode = GET_MODE_INNER (outermode);
2678 rtx value = expand_normal (op1);
2679 rtx pos = expand_normal (op2);
2681 class expand_operand ops[3];
2682 enum insn_code icode = optab_handler (optab, outermode);
2684 if (icode != CODE_FOR_nothing)
2686 rtx temp = gen_reg_rtx (outermode);
2687 emit_move_insn (temp, src);
2689 create_fixed_operand (&ops[0], temp);
2690 create_input_operand (&ops[1], value, innermode);
2691 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
2692 true);
2693 if (maybe_expand_insn (icode, 3, ops))
2695 emit_move_insn (target, temp);
2696 return;
2699 gcc_unreachable ();
2702 static void
2703 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
2707 static void
2708 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
2710 /* When guessing was done, the hints should be already stripped away. */
2711 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2713 rtx target;
2714 tree lhs = gimple_call_lhs (stmt);
2715 if (lhs)
2716 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2717 else
2718 target = const0_rtx;
2719 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2720 if (lhs && val != target)
2721 emit_move_insn (target, val);
2724 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
2725 should never be called. */
2727 static void
2728 expand_VA_ARG (internal_fn, gcall *)
2730 gcc_unreachable ();
2733 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
2734 dummy function should never be called. */
2736 static void
2737 expand_VEC_CONVERT (internal_fn, gcall *)
2739 gcc_unreachable ();
2742 /* Expand the IFN_UNIQUE function according to its first argument. */
2744 static void
2745 expand_UNIQUE (internal_fn, gcall *stmt)
2747 rtx pattern = NULL_RTX;
2748 enum ifn_unique_kind kind
2749 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2751 switch (kind)
2753 default:
2754 gcc_unreachable ();
2756 case IFN_UNIQUE_UNSPEC:
2757 if (targetm.have_unique ())
2758 pattern = targetm.gen_unique ();
2759 break;
2761 case IFN_UNIQUE_OACC_FORK:
2762 case IFN_UNIQUE_OACC_JOIN:
2763 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2765 tree lhs = gimple_call_lhs (stmt);
2766 rtx target = const0_rtx;
2768 if (lhs)
2769 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2771 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2772 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2774 if (kind == IFN_UNIQUE_OACC_FORK)
2775 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2776 else
2777 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2779 else
2780 gcc_unreachable ();
2781 break;
2784 if (pattern)
2785 emit_insn (pattern);
2788 /* The size of an OpenACC compute dimension. */
2790 static void
2791 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
2793 tree lhs = gimple_call_lhs (stmt);
2795 if (!lhs)
2796 return;
2798 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2799 if (targetm.have_oacc_dim_size ())
2801 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2802 VOIDmode, EXPAND_NORMAL);
2803 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2805 else
2806 emit_move_insn (target, GEN_INT (1));
2809 /* The position of an OpenACC execution engine along one compute axis. */
2811 static void
2812 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
2814 tree lhs = gimple_call_lhs (stmt);
2816 if (!lhs)
2817 return;
2819 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2820 if (targetm.have_oacc_dim_pos ())
2822 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2823 VOIDmode, EXPAND_NORMAL);
2824 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2826 else
2827 emit_move_insn (target, const0_rtx);
2830 /* This is expanded by oacc_device_lower pass. */
2832 static void
2833 expand_GOACC_LOOP (internal_fn, gcall *)
2835 gcc_unreachable ();
2838 /* This is expanded by oacc_device_lower pass. */
2840 static void
2841 expand_GOACC_REDUCTION (internal_fn, gcall *)
2843 gcc_unreachable ();
2846 /* This is expanded by oacc_device_lower pass. */
2848 static void
2849 expand_GOACC_TILE (internal_fn, gcall *)
2851 gcc_unreachable ();
2854 /* Set errno to EDOM. */
2856 static void
2857 expand_SET_EDOM (internal_fn, gcall *)
2859 #ifdef TARGET_EDOM
2860 #ifdef GEN_ERRNO_RTX
2861 rtx errno_rtx = GEN_ERRNO_RTX;
2862 #else
2863 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2864 #endif
2865 emit_move_insn (errno_rtx,
2866 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2867 #else
2868 gcc_unreachable ();
2869 #endif
2872 /* Expand atomic bit test and set. */
2874 static void
2875 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2877 expand_ifn_atomic_bit_test_and (call);
2880 /* Expand atomic bit test and complement. */
2882 static void
2883 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2885 expand_ifn_atomic_bit_test_and (call);
2888 /* Expand atomic bit test and reset. */
2890 static void
2891 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2893 expand_ifn_atomic_bit_test_and (call);
2896 /* Expand atomic bit test and set. */
2898 static void
2899 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2901 expand_ifn_atomic_compare_exchange (call);
2904 /* Expand LAUNDER to assignment, lhs = arg0. */
2906 static void
2907 expand_LAUNDER (internal_fn, gcall *call)
2909 tree lhs = gimple_call_lhs (call);
2911 if (!lhs)
2912 return;
2914 expand_assignment (lhs, gimple_call_arg (call, 0), false);
2917 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
2919 static void
2920 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2922 internal_fn ifn = gimple_call_internal_fn (stmt);
2923 int rhs_index = internal_fn_stored_value_index (ifn);
2924 int mask_index = internal_fn_mask_index (ifn);
2925 tree base = gimple_call_arg (stmt, 0);
2926 tree offset = gimple_call_arg (stmt, 1);
2927 tree scale = gimple_call_arg (stmt, 2);
2928 tree rhs = gimple_call_arg (stmt, rhs_index);
2930 rtx base_rtx = expand_normal (base);
2931 rtx offset_rtx = expand_normal (offset);
2932 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2933 rtx rhs_rtx = expand_normal (rhs);
2935 class expand_operand ops[6];
2936 int i = 0;
2937 create_address_operand (&ops[i++], base_rtx);
2938 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2939 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2940 create_integer_operand (&ops[i++], scale_int);
2941 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
2942 if (mask_index >= 0)
2944 tree mask = gimple_call_arg (stmt, mask_index);
2945 rtx mask_rtx = expand_normal (mask);
2946 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2949 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
2950 TYPE_MODE (TREE_TYPE (offset)));
2951 expand_insn (icode, i, ops);
2954 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
2956 static void
2957 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
2959 tree lhs = gimple_call_lhs (stmt);
2960 tree base = gimple_call_arg (stmt, 0);
2961 tree offset = gimple_call_arg (stmt, 1);
2962 tree scale = gimple_call_arg (stmt, 2);
2964 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2965 rtx base_rtx = expand_normal (base);
2966 rtx offset_rtx = expand_normal (offset);
2967 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
2969 int i = 0;
2970 class expand_operand ops[6];
2971 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
2972 create_address_operand (&ops[i++], base_rtx);
2973 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
2974 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
2975 create_integer_operand (&ops[i++], scale_int);
2976 if (optab == mask_gather_load_optab)
2978 tree mask = gimple_call_arg (stmt, 4);
2979 rtx mask_rtx = expand_normal (mask);
2980 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
2982 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
2983 TYPE_MODE (TREE_TYPE (offset)));
2984 expand_insn (icode, i, ops);
2985 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2986 emit_move_insn (lhs_rtx, ops[0].value);
2989 /* Helper for expand_DIVMOD. Return true if the sequence starting with
2990 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
2992 static bool
2993 contains_call_div_mod (rtx_insn *insn)
2995 subrtx_iterator::array_type array;
2996 for (; insn; insn = NEXT_INSN (insn))
2997 if (CALL_P (insn))
2998 return true;
2999 else if (INSN_P (insn))
3000 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3001 switch (GET_CODE (*iter))
3003 case CALL:
3004 case DIV:
3005 case UDIV:
3006 case MOD:
3007 case UMOD:
3008 return true;
3009 default:
3010 break;
3012 return false;
3015 /* Expand DIVMOD() using:
3016 a) optab handler for udivmod/sdivmod if it is available.
3017 b) If optab_handler doesn't exist, generate call to
3018 target-specific divmod libfunc. */
3020 static void
3021 expand_DIVMOD (internal_fn, gcall *call_stmt)
3023 tree lhs = gimple_call_lhs (call_stmt);
3024 tree arg0 = gimple_call_arg (call_stmt, 0);
3025 tree arg1 = gimple_call_arg (call_stmt, 1);
3027 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3028 tree type = TREE_TYPE (TREE_TYPE (lhs));
3029 machine_mode mode = TYPE_MODE (type);
3030 bool unsignedp = TYPE_UNSIGNED (type);
3031 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3033 rtx op0 = expand_normal (arg0);
3034 rtx op1 = expand_normal (arg1);
3035 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3037 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3038 rtx_insn *insns = NULL;
3040 if (TREE_CODE (arg1) == INTEGER_CST)
3042 /* For DIVMOD by integral constants, there could be efficient code
3043 expanded inline e.g. using shifts and plus/minus. Try to expand
3044 the division and modulo and if it emits any library calls or any
3045 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3046 divmod libcall. */
3047 struct separate_ops ops;
3048 ops.code = TRUNC_DIV_EXPR;
3049 ops.type = type;
3050 ops.op0 = make_tree (ops.type, op0);
3051 ops.op1 = arg1;
3052 ops.op2 = NULL_TREE;
3053 ops.location = gimple_location (call_stmt);
3054 start_sequence ();
3055 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3056 if (contains_call_div_mod (get_insns ()))
3057 quotient = NULL_RTX;
3058 else
3060 ops.code = TRUNC_MOD_EXPR;
3061 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3062 if (contains_call_div_mod (get_insns ()))
3063 remainder = NULL_RTX;
3065 if (remainder)
3066 insns = get_insns ();
3067 end_sequence ();
3070 if (remainder)
3071 emit_insn (insns);
3073 /* Check if optab_handler exists for divmod_optab for given mode. */
3074 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
3076 quotient = gen_reg_rtx (mode);
3077 remainder = gen_reg_rtx (mode);
3078 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3081 /* Generate call to divmod libfunc if it exists. */
3082 else if (rtx libfunc = optab_libfunc (tab, mode))
3083 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3084 &quotient, &remainder);
3086 else
3087 gcc_unreachable ();
3089 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3090 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3091 make_tree (TREE_TYPE (arg0), quotient),
3092 make_tree (TREE_TYPE (arg1), remainder)),
3093 target, VOIDmode, EXPAND_NORMAL);
3096 /* Expand a NOP. */
3098 static void
3099 expand_NOP (internal_fn, gcall *)
3101 /* Nothing. But it shouldn't really prevail. */
3104 /* Coroutines, all should have been processed at this stage. */
3106 static void
3107 expand_CO_FRAME (internal_fn, gcall *)
3109 gcc_unreachable ();
3112 static void
3113 expand_CO_YIELD (internal_fn, gcall *)
3115 gcc_unreachable ();
3118 static void
3119 expand_CO_SUSPN (internal_fn, gcall *)
3121 gcc_unreachable ();
3124 static void
3125 expand_CO_ACTOR (internal_fn, gcall *)
3127 gcc_unreachable ();
3130 /* Expand a call to FN using the operands in STMT. FN has a single
3131 output operand and NARGS input operands. */
3133 static void
3134 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3135 unsigned int nargs)
3137 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
3139 tree_pair types = direct_internal_fn_types (fn, stmt);
3140 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3141 gcc_assert (icode != CODE_FOR_nothing);
3143 tree lhs = gimple_call_lhs (stmt);
3144 rtx lhs_rtx = NULL_RTX;
3145 if (lhs)
3146 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3148 /* Do not assign directly to a promoted subreg, since there is no
3149 guarantee that the instruction will leave the upper bits of the
3150 register in the state required by SUBREG_PROMOTED_SIGN. */
3151 rtx dest = lhs_rtx;
3152 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
3153 dest = NULL_RTX;
3155 create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode);
3157 for (unsigned int i = 0; i < nargs; ++i)
3159 tree rhs = gimple_call_arg (stmt, i);
3160 tree rhs_type = TREE_TYPE (rhs);
3161 rtx rhs_rtx = expand_normal (rhs);
3162 if (INTEGRAL_TYPE_P (rhs_type))
3163 create_convert_operand_from (&ops[i + 1], rhs_rtx,
3164 TYPE_MODE (rhs_type),
3165 TYPE_UNSIGNED (rhs_type));
3166 else
3167 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
3170 expand_insn (icode, nargs + 1, ops);
3171 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
3173 /* If the return value has an integral type, convert the instruction
3174 result to that type. This is useful for things that return an
3175 int regardless of the size of the input. If the instruction result
3176 is smaller than required, assume that it is signed.
3178 If the return value has a nonintegral type, its mode must match
3179 the instruction result. */
3180 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
3182 /* If this is a scalar in a register that is stored in a wider
3183 mode than the declared mode, compute the result into its
3184 declared mode and then convert to the wider mode. */
3185 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
3186 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
3187 convert_move (SUBREG_REG (lhs_rtx), tmp,
3188 SUBREG_PROMOTED_SIGN (lhs_rtx));
3190 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
3191 emit_move_insn (lhs_rtx, ops[0].value);
3192 else
3194 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
3195 convert_move (lhs_rtx, ops[0].value, 0);
3200 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3202 static void
3203 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3205 expand_operand ops[3];
3206 tree rhs_type[2];
3208 tree lhs = gimple_call_lhs (stmt);
3209 tree lhs_type = TREE_TYPE (lhs);
3210 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3211 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3213 for (unsigned int i = 0; i < 2; ++i)
3215 tree rhs = gimple_call_arg (stmt, i);
3216 rhs_type[i] = TREE_TYPE (rhs);
3217 rtx rhs_rtx = expand_normal (rhs);
3218 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3221 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3222 TYPE_MODE (lhs_type));
3224 expand_insn (icode, 3, ops);
3225 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3226 emit_move_insn (lhs_rtx, ops[0].value);
3229 /* Expanders for optabs that can use expand_direct_optab_fn. */
3231 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3232 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3234 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3235 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3237 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3238 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3240 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3241 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3243 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3244 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3246 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3247 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3249 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3250 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3252 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3253 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3255 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3256 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3258 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3259 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3261 /* RETURN_TYPE and ARGS are a return type and argument list that are
3262 in principle compatible with FN (which satisfies direct_internal_fn_p).
3263 Return the types that should be used to determine whether the
3264 target supports FN. */
3266 tree_pair
3267 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3269 const direct_internal_fn_info &info = direct_internal_fn (fn);
3270 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3271 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3272 return tree_pair (type0, type1);
3275 /* CALL is a call whose return type and arguments are in principle
3276 compatible with FN (which satisfies direct_internal_fn_p). Return the
3277 types that should be used to determine whether the target supports FN. */
3279 tree_pair
3280 direct_internal_fn_types (internal_fn fn, gcall *call)
3282 const direct_internal_fn_info &info = direct_internal_fn (fn);
3283 tree op0 = (info.type0 < 0
3284 ? gimple_call_lhs (call)
3285 : gimple_call_arg (call, info.type0));
3286 tree op1 = (info.type1 < 0
3287 ? gimple_call_lhs (call)
3288 : gimple_call_arg (call, info.type1));
3289 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3292 /* Return true if OPTAB is supported for TYPES (whose modes should be
3293 the same) when the optimization type is OPT_TYPE. Used for simple
3294 direct optabs. */
3296 static bool
3297 direct_optab_supported_p (direct_optab optab, tree_pair types,
3298 optimization_type opt_type)
3300 machine_mode mode = TYPE_MODE (types.first);
3301 gcc_checking_assert (mode == TYPE_MODE (types.second));
3302 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3305 /* Return true if OPTAB is supported for TYPES, where the first type
3306 is the destination and the second type is the source. Used for
3307 convert optabs. */
3309 static bool
3310 convert_optab_supported_p (convert_optab optab, tree_pair types,
3311 optimization_type opt_type)
3313 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3314 TYPE_MODE (types.second), opt_type)
3315 != CODE_FOR_nothing);
3318 /* Return true if load/store lanes optab OPTAB is supported for
3319 array type TYPES.first when the optimization type is OPT_TYPE. */
3321 static bool
3322 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3323 optimization_type opt_type)
3325 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3326 machine_mode imode = TYPE_MODE (types.first);
3327 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3328 return (convert_optab_handler (optab, imode, vmode, opt_type)
3329 != CODE_FOR_nothing);
3332 #define direct_unary_optab_supported_p direct_optab_supported_p
3333 #define direct_binary_optab_supported_p direct_optab_supported_p
3334 #define direct_ternary_optab_supported_p direct_optab_supported_p
3335 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3336 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3337 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
3338 #define direct_mask_load_optab_supported_p convert_optab_supported_p
3339 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
3340 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
3341 #define direct_gather_load_optab_supported_p convert_optab_supported_p
3342 #define direct_len_load_optab_supported_p direct_optab_supported_p
3343 #define direct_mask_store_optab_supported_p convert_optab_supported_p
3344 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
3345 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
3346 #define direct_vec_cond_mask_optab_supported_p multi_vector_optab_supported_p
3347 #define direct_vec_cond_optab_supported_p multi_vector_optab_supported_p
3348 #define direct_vec_condu_optab_supported_p multi_vector_optab_supported_p
3349 #define direct_vec_condeq_optab_supported_p multi_vector_optab_supported_p
3350 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
3351 #define direct_len_store_optab_supported_p direct_optab_supported_p
3352 #define direct_while_optab_supported_p convert_optab_supported_p
3353 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
3354 #define direct_fold_left_optab_supported_p direct_optab_supported_p
3355 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
3356 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
3357 #define direct_vec_set_optab_supported_p direct_optab_supported_p
3359 /* Return the optab used by internal function FN. */
3361 static optab
3362 direct_internal_fn_optab (internal_fn fn, tree_pair types)
3364 switch (fn)
3366 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3367 case IFN_##CODE: break;
3368 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3369 case IFN_##CODE: return OPTAB##_optab;
3370 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3371 UNSIGNED_OPTAB, TYPE) \
3372 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
3373 ? UNSIGNED_OPTAB ## _optab \
3374 : SIGNED_OPTAB ## _optab);
3375 #include "internal-fn.def"
3377 case IFN_LAST:
3378 break;
3380 gcc_unreachable ();
3383 /* Return the optab used by internal function FN. */
3385 static optab
3386 direct_internal_fn_optab (internal_fn fn)
3388 switch (fn)
3390 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3391 case IFN_##CODE: break;
3392 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3393 case IFN_##CODE: return OPTAB##_optab;
3394 #include "internal-fn.def"
3396 case IFN_LAST:
3397 break;
3399 gcc_unreachable ();
3402 /* Return true if FN is supported for the types in TYPES when the
3403 optimization type is OPT_TYPE. The types are those associated with
3404 the "type0" and "type1" fields of FN's direct_internal_fn_info
3405 structure. */
3407 bool
3408 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
3409 optimization_type opt_type)
3411 switch (fn)
3413 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3414 case IFN_##CODE: break;
3415 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3416 case IFN_##CODE: \
3417 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
3418 opt_type);
3419 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3420 UNSIGNED_OPTAB, TYPE) \
3421 case IFN_##CODE: \
3423 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
3424 ? UNSIGNED_OPTAB ## _optab \
3425 : SIGNED_OPTAB ## _optab); \
3426 return direct_##TYPE##_optab_supported_p (which_optab, types, \
3427 opt_type); \
3429 #include "internal-fn.def"
3431 case IFN_LAST:
3432 break;
3434 gcc_unreachable ();
3437 /* Return true if FN is supported for type TYPE when the optimization
3438 type is OPT_TYPE. The caller knows that the "type0" and "type1"
3439 fields of FN's direct_internal_fn_info structure are the same. */
3441 bool
3442 direct_internal_fn_supported_p (internal_fn fn, tree type,
3443 optimization_type opt_type)
3445 const direct_internal_fn_info &info = direct_internal_fn (fn);
3446 gcc_checking_assert (info.type0 == info.type1);
3447 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
3450 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
3451 given that STMT is a call to a direct internal function. */
3453 bool
3454 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
3456 internal_fn fn = gimple_call_internal_fn (stmt);
3457 tree_pair types = direct_internal_fn_types (fn, stmt);
3458 return direct_internal_fn_supported_p (fn, types, opt_type);
3461 /* If FN is commutative in two consecutive arguments, return the
3462 index of the first, otherwise return -1. */
3465 first_commutative_argument (internal_fn fn)
3467 switch (fn)
3469 case IFN_FMA:
3470 case IFN_FMS:
3471 case IFN_FNMA:
3472 case IFN_FNMS:
3473 case IFN_AVG_FLOOR:
3474 case IFN_AVG_CEIL:
3475 case IFN_MULHS:
3476 case IFN_MULHRS:
3477 case IFN_FMIN:
3478 case IFN_FMAX:
3479 return 0;
3481 case IFN_COND_ADD:
3482 case IFN_COND_MUL:
3483 case IFN_COND_MIN:
3484 case IFN_COND_MAX:
3485 case IFN_COND_AND:
3486 case IFN_COND_IOR:
3487 case IFN_COND_XOR:
3488 case IFN_COND_FMA:
3489 case IFN_COND_FMS:
3490 case IFN_COND_FNMA:
3491 case IFN_COND_FNMS:
3492 return 1;
3494 default:
3495 return -1;
3499 /* Return true if IFN_SET_EDOM is supported. */
3501 bool
3502 set_edom_supported_p (void)
3504 #ifdef TARGET_EDOM
3505 return true;
3506 #else
3507 return false;
3508 #endif
3511 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3512 static void \
3513 expand_##CODE (internal_fn fn, gcall *stmt) \
3515 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
3517 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3518 UNSIGNED_OPTAB, TYPE) \
3519 static void \
3520 expand_##CODE (internal_fn fn, gcall *stmt) \
3522 tree_pair types = direct_internal_fn_types (fn, stmt); \
3523 optab which_optab = direct_internal_fn_optab (fn, types); \
3524 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
3526 #include "internal-fn.def"
3528 /* Routines to expand each internal function, indexed by function number.
3529 Each routine has the prototype:
3531 expand_<NAME> (gcall *stmt)
3533 where STMT is the statement that performs the call. */
3534 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
3535 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
3536 #include "internal-fn.def"
3540 /* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
3541 tree code CODE. */
3542 #define FOR_EACH_CODE_MAPPING(T) \
3543 T (PLUS_EXPR, IFN_COND_ADD) \
3544 T (MINUS_EXPR, IFN_COND_SUB) \
3545 T (MULT_EXPR, IFN_COND_MUL) \
3546 T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
3547 T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
3548 T (RDIV_EXPR, IFN_COND_RDIV) \
3549 T (MIN_EXPR, IFN_COND_MIN) \
3550 T (MAX_EXPR, IFN_COND_MAX) \
3551 T (BIT_AND_EXPR, IFN_COND_AND) \
3552 T (BIT_IOR_EXPR, IFN_COND_IOR) \
3553 T (BIT_XOR_EXPR, IFN_COND_XOR) \
3554 T (LSHIFT_EXPR, IFN_COND_SHL) \
3555 T (RSHIFT_EXPR, IFN_COND_SHR)
3557 /* Return a function that only performs CODE when a certain condition is met
3558 and that uses a given fallback value otherwise. For example, if CODE is
3559 a binary operation associated with conditional function FN:
3561 LHS = FN (COND, A, B, ELSE)
3563 is equivalent to the C expression:
3565 LHS = COND ? A CODE B : ELSE;
3567 operating elementwise if the operands are vectors.
3569 Return IFN_LAST if no such function exists. */
3571 internal_fn
3572 get_conditional_internal_fn (tree_code code)
3574 switch (code)
3576 #define CASE(CODE, IFN) case CODE: return IFN;
3577 FOR_EACH_CODE_MAPPING(CASE)
3578 #undef CASE
3579 default:
3580 return IFN_LAST;
3584 /* If IFN implements the conditional form of a tree code, return that
3585 tree code, otherwise return ERROR_MARK. */
3587 tree_code
3588 conditional_internal_fn_code (internal_fn ifn)
3590 switch (ifn)
3592 #define CASE(CODE, IFN) case IFN: return CODE;
3593 FOR_EACH_CODE_MAPPING(CASE)
3594 #undef CASE
3595 default:
3596 return ERROR_MARK;
3600 /* Invoke T(IFN) for each internal function IFN that also has an
3601 IFN_COND_* form. */
3602 #define FOR_EACH_COND_FN_PAIR(T) \
3603 T (FMA) \
3604 T (FMS) \
3605 T (FNMA) \
3606 T (FNMS)
3608 /* Return a function that only performs internal function FN when a
3609 certain condition is met and that uses a given fallback value otherwise.
3610 In other words, the returned function FN' is such that:
3612 LHS = FN' (COND, A1, ... An, ELSE)
3614 is equivalent to the C expression:
3616 LHS = COND ? FN (A1, ..., An) : ELSE;
3618 operating elementwise if the operands are vectors.
3620 Return IFN_LAST if no such function exists. */
3622 internal_fn
3623 get_conditional_internal_fn (internal_fn fn)
3625 switch (fn)
3627 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
3628 FOR_EACH_COND_FN_PAIR(CASE)
3629 #undef CASE
3630 default:
3631 return IFN_LAST;
3635 /* If IFN implements the conditional form of an unconditional internal
3636 function, return that unconditional function, otherwise return IFN_LAST. */
3638 internal_fn
3639 get_unconditional_internal_fn (internal_fn ifn)
3641 switch (ifn)
3643 #define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
3644 FOR_EACH_COND_FN_PAIR(CASE)
3645 #undef CASE
3646 default:
3647 return IFN_LAST;
3651 /* Return true if STMT can be interpreted as a conditional tree code
3652 operation of the form:
3654 LHS = COND ? OP (RHS1, ...) : ELSE;
3656 operating elementwise if the operands are vectors. This includes
3657 the case of an all-true COND, so that the operation always happens.
3659 When returning true, set:
3661 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
3662 is known to be all-true
3663 - *CODE_OUT to the tree code
3664 - OPS[I] to operand I of *CODE_OUT
3665 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
3666 condition is known to be all true. */
3668 bool
3669 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
3670 tree_code *code_out,
3671 tree (&ops)[3], tree *else_out)
3673 if (gassign *assign = dyn_cast <gassign *> (stmt))
3675 *cond_out = NULL_TREE;
3676 *code_out = gimple_assign_rhs_code (assign);
3677 ops[0] = gimple_assign_rhs1 (assign);
3678 ops[1] = gimple_assign_rhs2 (assign);
3679 ops[2] = gimple_assign_rhs3 (assign);
3680 *else_out = NULL_TREE;
3681 return true;
3683 if (gcall *call = dyn_cast <gcall *> (stmt))
3684 if (gimple_call_internal_p (call))
3686 internal_fn ifn = gimple_call_internal_fn (call);
3687 tree_code code = conditional_internal_fn_code (ifn);
3688 if (code != ERROR_MARK)
3690 *cond_out = gimple_call_arg (call, 0);
3691 *code_out = code;
3692 unsigned int nops = gimple_call_num_args (call) - 2;
3693 for (unsigned int i = 0; i < 3; ++i)
3694 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
3695 *else_out = gimple_call_arg (call, nops + 1);
3696 if (integer_truep (*cond_out))
3698 *cond_out = NULL_TREE;
3699 *else_out = NULL_TREE;
3701 return true;
3704 return false;
3707 /* Return true if IFN is some form of load from memory. */
3709 bool
3710 internal_load_fn_p (internal_fn fn)
3712 switch (fn)
3714 case IFN_MASK_LOAD:
3715 case IFN_LOAD_LANES:
3716 case IFN_MASK_LOAD_LANES:
3717 case IFN_GATHER_LOAD:
3718 case IFN_MASK_GATHER_LOAD:
3719 case IFN_LEN_LOAD:
3720 return true;
3722 default:
3723 return false;
3727 /* Return true if IFN is some form of store to memory. */
3729 bool
3730 internal_store_fn_p (internal_fn fn)
3732 switch (fn)
3734 case IFN_MASK_STORE:
3735 case IFN_STORE_LANES:
3736 case IFN_MASK_STORE_LANES:
3737 case IFN_SCATTER_STORE:
3738 case IFN_MASK_SCATTER_STORE:
3739 case IFN_LEN_STORE:
3740 return true;
3742 default:
3743 return false;
3747 /* Return true if IFN is some form of gather load or scatter store. */
3749 bool
3750 internal_gather_scatter_fn_p (internal_fn fn)
3752 switch (fn)
3754 case IFN_GATHER_LOAD:
3755 case IFN_MASK_GATHER_LOAD:
3756 case IFN_SCATTER_STORE:
3757 case IFN_MASK_SCATTER_STORE:
3758 return true;
3760 default:
3761 return false;
3765 /* If FN takes a vector mask argument, return the index of that argument,
3766 otherwise return -1. */
3769 internal_fn_mask_index (internal_fn fn)
3771 switch (fn)
3773 case IFN_MASK_LOAD:
3774 case IFN_MASK_LOAD_LANES:
3775 case IFN_MASK_STORE:
3776 case IFN_MASK_STORE_LANES:
3777 return 2;
3779 case IFN_MASK_GATHER_LOAD:
3780 case IFN_MASK_SCATTER_STORE:
3781 return 4;
3783 default:
3784 return (conditional_internal_fn_code (fn) != ERROR_MARK
3785 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
3789 /* If FN takes a value that should be stored to memory, return the index
3790 of that argument, otherwise return -1. */
3793 internal_fn_stored_value_index (internal_fn fn)
3795 switch (fn)
3797 case IFN_MASK_STORE:
3798 case IFN_MASK_STORE_LANES:
3799 case IFN_SCATTER_STORE:
3800 case IFN_MASK_SCATTER_STORE:
3801 case IFN_LEN_STORE:
3802 return 3;
3804 default:
3805 return -1;
3809 /* Return true if the target supports gather load or scatter store function
3810 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
3811 while for stores it is the vector type of the stored data argument.
3812 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
3813 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
3814 offset from the shared base address of each loaded or stored element.
3815 SCALE is the amount by which these offsets should be multiplied
3816 *after* they have been extended to address width. */
3818 bool
3819 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
3820 tree memory_element_type,
3821 tree offset_vector_type, int scale)
3823 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
3824 TYPE_SIZE (memory_element_type)))
3825 return false;
3826 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
3827 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
3828 return false;
3829 optab optab = direct_internal_fn_optab (ifn);
3830 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
3831 TYPE_MODE (offset_vector_type));
3832 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
3833 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
3834 return (icode != CODE_FOR_nothing
3835 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
3836 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
3839 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
3840 for pointers of type TYPE when the accesses have LENGTH bytes and their
3841 common byte alignment is ALIGN. */
3843 bool
3844 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
3845 poly_uint64 length, unsigned int align)
3847 machine_mode mode = TYPE_MODE (type);
3848 optab optab = direct_internal_fn_optab (ifn);
3849 insn_code icode = direct_optab_handler (optab, mode);
3850 if (icode == CODE_FOR_nothing)
3851 return false;
3852 rtx length_rtx = immed_wide_int_const (length, mode);
3853 return (insn_operand_matches (icode, 3, length_rtx)
3854 && insn_operand_matches (icode, 4, GEN_INT (align)));
3857 /* Expand STMT as though it were a call to internal function FN. */
3859 void
3860 expand_internal_call (internal_fn fn, gcall *stmt)
3862 internal_fn_expanders[fn] (fn, stmt);
3865 /* Expand STMT, which is a call to internal function FN. */
3867 void
3868 expand_internal_call (gcall *stmt)
3870 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
3873 /* If TYPE is a vector type, return true if IFN is a direct internal
3874 function that is supported for that type. If TYPE is a scalar type,
3875 return true if IFN is a direct internal function that is supported for
3876 the target's preferred vector version of TYPE. */
3878 bool
3879 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
3881 scalar_mode smode;
3882 if (!VECTOR_TYPE_P (type) && is_a <scalar_mode> (TYPE_MODE (type), &smode))
3884 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
3885 if (VECTOR_MODE_P (vmode))
3886 type = build_vector_type_for_mode (type, vmode);
3889 return (VECTOR_MODE_P (TYPE_MODE (type))
3890 && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
3893 void
3894 expand_PHI (internal_fn, gcall *)
3896 gcc_unreachable ();