Require target lra in gcc.c-torture/compile/asmgoto-6.c
[official-gcc.git] / gcc / internal-fn.cc
blob8e294286388d0fa742dea6429ae2ece6d62ab5ba
1 /* Internal functions.
2 Copyright (C) 2011-2023 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"
54 #include "gimple-range.h"
56 /* For lang_hooks.types.type_for_mode. */
57 #include "langhooks.h"
59 /* The names of each internal function, indexed by function number. */
60 const char *const internal_fn_name_array[] = {
61 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
62 #include "internal-fn.def"
63 "<invalid-fn>"
66 /* The ECF_* flags of each internal function, indexed by function number. */
67 const int internal_fn_flags_array[] = {
68 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
69 #include "internal-fn.def"
73 /* Return the internal function called NAME, or IFN_LAST if there's
74 no such function. */
76 internal_fn
77 lookup_internal_fn (const char *name)
79 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
80 static name_to_fn_map_type *name_to_fn_map;
82 if (!name_to_fn_map)
84 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
85 for (unsigned int i = 0; i < IFN_LAST; ++i)
86 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
87 internal_fn (i));
89 internal_fn *entry = name_to_fn_map->get (name);
90 return entry ? *entry : IFN_LAST;
93 /* Geven an internal_fn IFN that is a widening function, return its
94 corresponding LO and HI internal_fns. */
96 extern void
97 lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi)
99 gcc_assert (widening_fn_p (ifn));
101 switch (ifn)
103 default:
104 gcc_unreachable ();
105 #undef DEF_INTERNAL_FN
106 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
107 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
108 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
109 case IFN_##NAME: \
110 *lo = internal_fn (IFN_##NAME##_LO); \
111 *hi = internal_fn (IFN_##NAME##_HI); \
112 break;
113 #include "internal-fn.def"
114 #undef DEF_INTERNAL_FN
115 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
119 /* Given an internal_fn IFN that is a widening function, return its
120 corresponding _EVEN and _ODD internal_fns in *EVEN and *ODD. */
122 extern void
123 lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even,
124 internal_fn *odd)
126 gcc_assert (widening_fn_p (ifn));
128 switch (ifn)
130 default:
131 gcc_unreachable ();
132 #undef DEF_INTERNAL_FN
133 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
134 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
135 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
136 case IFN_##NAME: \
137 *even = internal_fn (IFN_##NAME##_EVEN); \
138 *odd = internal_fn (IFN_##NAME##_ODD); \
139 break;
140 #include "internal-fn.def"
141 #undef DEF_INTERNAL_FN
142 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
147 /* Fnspec of each internal function, indexed by function number. */
148 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
150 void
151 init_internal_fns ()
153 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
154 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
155 build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
156 #include "internal-fn.def"
157 internal_fn_fnspec_array[IFN_LAST] = 0;
160 /* Create static initializers for the information returned by
161 direct_internal_fn. */
162 #define not_direct { -2, -2, false }
163 #define mask_load_direct { -1, 2, false }
164 #define load_lanes_direct { -1, -1, false }
165 #define mask_load_lanes_direct { -1, -1, false }
166 #define gather_load_direct { 3, 1, false }
167 #define len_load_direct { -1, -1, false }
168 #define mask_len_load_direct { -1, 4, false }
169 #define mask_store_direct { 3, 2, false }
170 #define store_lanes_direct { 0, 0, false }
171 #define mask_store_lanes_direct { 0, 0, false }
172 #define vec_cond_mask_direct { 1, 0, false }
173 #define vec_cond_direct { 2, 0, false }
174 #define scatter_store_direct { 3, 1, false }
175 #define len_store_direct { 3, 3, false }
176 #define mask_len_store_direct { 4, 5, false }
177 #define vec_set_direct { 3, 3, false }
178 #define vec_extract_direct { 3, 3, false }
179 #define unary_direct { 0, 0, true }
180 #define unary_convert_direct { -1, 0, true }
181 #define binary_direct { 0, 0, true }
182 #define ternary_direct { 0, 0, true }
183 #define cond_unary_direct { 1, 1, true }
184 #define cond_binary_direct { 1, 1, true }
185 #define cond_ternary_direct { 1, 1, true }
186 #define cond_len_unary_direct { 1, 1, true }
187 #define cond_len_binary_direct { 1, 1, true }
188 #define cond_len_ternary_direct { 1, 1, true }
189 #define while_direct { 0, 2, false }
190 #define fold_extract_direct { 2, 2, false }
191 #define fold_left_direct { 1, 1, false }
192 #define mask_fold_left_direct { 1, 1, false }
193 #define mask_len_fold_left_direct { 1, 1, false }
194 #define check_ptrs_direct { 0, 0, false }
196 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
197 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
198 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
199 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
200 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
201 #include "internal-fn.def"
202 not_direct
205 /* Expand STMT using instruction ICODE. The instruction has NOUTPUTS
206 output operands and NINPUTS input operands, where NOUTPUTS is either
207 0 or 1. The output operand (if any) comes first, followed by the
208 NINPUTS input operands. */
210 static void
211 expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
212 unsigned int ninputs)
214 gcc_assert (icode != CODE_FOR_nothing);
216 expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
217 unsigned int opno = 0;
218 rtx lhs_rtx = NULL_RTX;
219 tree lhs = gimple_call_lhs (stmt);
221 if (noutputs)
223 gcc_assert (noutputs == 1);
224 if (lhs)
225 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
227 /* Do not assign directly to a promoted subreg, since there is no
228 guarantee that the instruction will leave the upper bits of the
229 register in the state required by SUBREG_PROMOTED_SIGN. */
230 rtx dest = lhs_rtx;
231 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
232 dest = NULL_RTX;
233 create_output_operand (&ops[opno], dest,
234 insn_data[icode].operand[opno].mode);
235 opno += 1;
237 else
238 gcc_assert (!lhs);
240 for (unsigned int i = 0; i < ninputs; ++i)
242 tree rhs = gimple_call_arg (stmt, i);
243 tree rhs_type = TREE_TYPE (rhs);
244 rtx rhs_rtx = expand_normal (rhs);
245 if (INTEGRAL_TYPE_P (rhs_type))
246 create_convert_operand_from (&ops[opno], rhs_rtx,
247 TYPE_MODE (rhs_type),
248 TYPE_UNSIGNED (rhs_type));
249 else
250 create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
251 opno += 1;
254 gcc_assert (opno == noutputs + ninputs);
255 expand_insn (icode, opno, ops);
256 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
258 /* If the return value has an integral type, convert the instruction
259 result to that type. This is useful for things that return an
260 int regardless of the size of the input. If the instruction result
261 is smaller than required, assume that it is signed.
263 If the return value has a nonintegral type, its mode must match
264 the instruction result. */
265 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
267 /* If this is a scalar in a register that is stored in a wider
268 mode than the declared mode, compute the result into its
269 declared mode and then convert to the wider mode. */
270 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
271 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
272 convert_move (SUBREG_REG (lhs_rtx), tmp,
273 SUBREG_PROMOTED_SIGN (lhs_rtx));
275 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
276 emit_move_insn (lhs_rtx, ops[0].value);
277 else
279 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
280 convert_move (lhs_rtx, ops[0].value, 0);
285 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
286 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
288 static enum insn_code
289 get_multi_vector_move (tree array_type, convert_optab optab)
291 machine_mode imode;
292 machine_mode vmode;
294 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
295 imode = TYPE_MODE (array_type);
296 vmode = TYPE_MODE (TREE_TYPE (array_type));
298 return convert_optab_handler (optab, imode, vmode);
301 /* Add mask and len arguments according to the STMT. */
303 static unsigned int
304 add_mask_and_len_args (expand_operand *ops, unsigned int opno, gcall *stmt)
306 internal_fn ifn = gimple_call_internal_fn (stmt);
307 int len_index = internal_fn_len_index (ifn);
308 /* BIAS is always consecutive next of LEN. */
309 int bias_index = len_index + 1;
310 int mask_index = internal_fn_mask_index (ifn);
311 /* The order of arguments are always {len,bias,mask}. */
312 if (mask_index >= 0)
314 tree mask = gimple_call_arg (stmt, mask_index);
315 rtx mask_rtx = expand_normal (mask);
316 create_input_operand (&ops[opno++], mask_rtx,
317 TYPE_MODE (TREE_TYPE (mask)));
319 if (len_index >= 0)
321 tree len = gimple_call_arg (stmt, len_index);
322 rtx len_rtx = expand_normal (len);
323 create_convert_operand_from (&ops[opno++], len_rtx,
324 TYPE_MODE (TREE_TYPE (len)),
325 TYPE_UNSIGNED (TREE_TYPE (len)));
326 tree biast = gimple_call_arg (stmt, bias_index);
327 rtx bias = expand_normal (biast);
328 create_input_operand (&ops[opno++], bias, QImode);
330 return opno;
333 /* Expand LOAD_LANES call STMT using optab OPTAB. */
335 static void
336 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
338 class expand_operand ops[2];
339 tree type, lhs, rhs;
340 rtx target, mem;
342 lhs = gimple_call_lhs (stmt);
343 rhs = gimple_call_arg (stmt, 0);
344 type = TREE_TYPE (lhs);
346 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
347 mem = expand_normal (rhs);
349 gcc_assert (MEM_P (mem));
350 PUT_MODE (mem, TYPE_MODE (type));
352 create_output_operand (&ops[0], target, TYPE_MODE (type));
353 create_fixed_operand (&ops[1], mem);
354 expand_insn (get_multi_vector_move (type, optab), 2, ops);
355 if (!rtx_equal_p (target, ops[0].value))
356 emit_move_insn (target, ops[0].value);
359 /* Expand STORE_LANES call STMT using optab OPTAB. */
361 static void
362 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
364 class expand_operand ops[2];
365 tree type, lhs, rhs;
366 rtx target, reg;
368 lhs = gimple_call_lhs (stmt);
369 rhs = gimple_call_arg (stmt, 0);
370 type = TREE_TYPE (rhs);
372 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
373 reg = expand_normal (rhs);
375 gcc_assert (MEM_P (target));
376 PUT_MODE (target, TYPE_MODE (type));
378 create_fixed_operand (&ops[0], target);
379 create_input_operand (&ops[1], reg, TYPE_MODE (type));
380 expand_insn (get_multi_vector_move (type, optab), 2, ops);
383 static void
384 expand_ANNOTATE (internal_fn, gcall *)
386 gcc_unreachable ();
389 /* This should get expanded in omp_device_lower pass. */
391 static void
392 expand_GOMP_USE_SIMT (internal_fn, gcall *)
394 gcc_unreachable ();
397 /* This should get expanded in omp_device_lower pass. */
399 static void
400 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
402 gcc_unreachable ();
405 /* Allocate per-lane storage and begin non-uniform execution region. */
407 static void
408 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
410 rtx target;
411 tree lhs = gimple_call_lhs (stmt);
412 if (lhs)
413 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
414 else
415 target = gen_reg_rtx (Pmode);
416 rtx size = expand_normal (gimple_call_arg (stmt, 0));
417 rtx align = expand_normal (gimple_call_arg (stmt, 1));
418 class expand_operand ops[3];
419 create_output_operand (&ops[0], target, Pmode);
420 create_input_operand (&ops[1], size, Pmode);
421 create_input_operand (&ops[2], align, Pmode);
422 gcc_assert (targetm.have_omp_simt_enter ());
423 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
424 if (!rtx_equal_p (target, ops[0].value))
425 emit_move_insn (target, ops[0].value);
428 /* Deallocate per-lane storage and leave non-uniform execution region. */
430 static void
431 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
433 gcc_checking_assert (!gimple_call_lhs (stmt));
434 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
435 class expand_operand ops[1];
436 create_input_operand (&ops[0], arg, Pmode);
437 gcc_assert (targetm.have_omp_simt_exit ());
438 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
441 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
442 without SIMT execution this should be expanded in omp_device_lower pass. */
444 static void
445 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
447 tree lhs = gimple_call_lhs (stmt);
448 if (!lhs)
449 return;
451 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
452 gcc_assert (targetm.have_omp_simt_lane ());
453 emit_insn (targetm.gen_omp_simt_lane (target));
456 /* This should get expanded in omp_device_lower pass. */
458 static void
459 expand_GOMP_SIMT_VF (internal_fn, gcall *)
461 gcc_unreachable ();
464 /* This should get expanded in omp_device_lower pass. */
466 static void
467 expand_GOMP_TARGET_REV (internal_fn, gcall *)
469 gcc_unreachable ();
472 /* Lane index of the first SIMT lane that supplies a non-zero argument.
473 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
474 lane that executed the last iteration for handling OpenMP lastprivate. */
476 static void
477 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
479 tree lhs = gimple_call_lhs (stmt);
480 if (!lhs)
481 return;
483 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
484 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
485 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
486 class expand_operand ops[2];
487 create_output_operand (&ops[0], target, mode);
488 create_input_operand (&ops[1], cond, mode);
489 gcc_assert (targetm.have_omp_simt_last_lane ());
490 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
491 if (!rtx_equal_p (target, ops[0].value))
492 emit_move_insn (target, ops[0].value);
495 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
497 static void
498 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
500 tree lhs = gimple_call_lhs (stmt);
501 if (!lhs)
502 return;
504 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
505 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
506 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
507 class expand_operand ops[2];
508 create_output_operand (&ops[0], target, mode);
509 create_input_operand (&ops[1], ctr, mode);
510 gcc_assert (targetm.have_omp_simt_ordered ());
511 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
512 if (!rtx_equal_p (target, ops[0].value))
513 emit_move_insn (target, ops[0].value);
516 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
517 any lane supplies a non-zero argument. */
519 static void
520 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
522 tree lhs = gimple_call_lhs (stmt);
523 if (!lhs)
524 return;
526 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
527 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
528 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
529 class expand_operand ops[2];
530 create_output_operand (&ops[0], target, mode);
531 create_input_operand (&ops[1], cond, mode);
532 gcc_assert (targetm.have_omp_simt_vote_any ());
533 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
534 if (!rtx_equal_p (target, ops[0].value))
535 emit_move_insn (target, ops[0].value);
538 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
539 is destination lane index XOR given offset. */
541 static void
542 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
544 tree lhs = gimple_call_lhs (stmt);
545 if (!lhs)
546 return;
548 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
549 rtx src = expand_normal (gimple_call_arg (stmt, 0));
550 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
551 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
552 class expand_operand ops[3];
553 create_output_operand (&ops[0], target, mode);
554 create_input_operand (&ops[1], src, mode);
555 create_input_operand (&ops[2], idx, SImode);
556 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
557 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
558 if (!rtx_equal_p (target, ops[0].value))
559 emit_move_insn (target, ops[0].value);
562 /* Exchange between SIMT lanes according to given source lane index. */
564 static void
565 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
567 tree lhs = gimple_call_lhs (stmt);
568 if (!lhs)
569 return;
571 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
572 rtx src = expand_normal (gimple_call_arg (stmt, 0));
573 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
574 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
575 class expand_operand ops[3];
576 create_output_operand (&ops[0], target, mode);
577 create_input_operand (&ops[1], src, mode);
578 create_input_operand (&ops[2], idx, SImode);
579 gcc_assert (targetm.have_omp_simt_xchg_idx ());
580 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
581 if (!rtx_equal_p (target, ops[0].value))
582 emit_move_insn (target, ops[0].value);
585 /* This should get expanded in adjust_simduid_builtins. */
587 static void
588 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
590 gcc_unreachable ();
593 /* This should get expanded in adjust_simduid_builtins. */
595 static void
596 expand_GOMP_SIMD_VF (internal_fn, gcall *)
598 gcc_unreachable ();
601 /* This should get expanded in adjust_simduid_builtins. */
603 static void
604 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
606 gcc_unreachable ();
609 /* This should get expanded in adjust_simduid_builtins. */
611 static void
612 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
614 gcc_unreachable ();
617 /* This should get expanded in adjust_simduid_builtins. */
619 static void
620 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
622 gcc_unreachable ();
625 /* This should get expanded in the sanopt pass. */
627 static void
628 expand_UBSAN_NULL (internal_fn, gcall *)
630 gcc_unreachable ();
633 /* This should get expanded in the sanopt pass. */
635 static void
636 expand_UBSAN_BOUNDS (internal_fn, gcall *)
638 gcc_unreachable ();
641 /* This should get expanded in the sanopt pass. */
643 static void
644 expand_UBSAN_VPTR (internal_fn, gcall *)
646 gcc_unreachable ();
649 /* This should get expanded in the sanopt pass. */
651 static void
652 expand_UBSAN_PTR (internal_fn, gcall *)
654 gcc_unreachable ();
657 /* This should get expanded in the sanopt pass. */
659 static void
660 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
662 gcc_unreachable ();
665 /* This should get expanded in the sanopt pass. */
667 static void
668 expand_HWASAN_CHECK (internal_fn, gcall *)
670 gcc_unreachable ();
673 /* For hwasan stack tagging:
674 Clear tags on the dynamically allocated space.
675 For use after an object dynamically allocated on the stack goes out of
676 scope. */
677 static void
678 expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
680 gcc_assert (Pmode == ptr_mode);
681 tree restored_position = gimple_call_arg (gc, 0);
682 rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
683 EXPAND_NORMAL);
684 rtx func = init_one_libfunc ("__hwasan_tag_memory");
685 rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
686 stack_pointer_rtx, NULL_RTX, 0,
687 OPTAB_WIDEN);
688 emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
689 virtual_stack_dynamic_rtx, Pmode,
690 HWASAN_STACK_BACKGROUND, QImode,
691 off, Pmode);
694 /* For hwasan stack tagging:
695 Return a tag to be used for a dynamic allocation. */
696 static void
697 expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
699 tree tag = gimple_call_lhs (gc);
700 rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
701 machine_mode mode = GET_MODE (target);
702 gcc_assert (mode == QImode);
704 rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
705 gcc_assert (base_tag);
706 rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
707 rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
708 target, /* unsignedp = */1,
709 OPTAB_WIDEN);
710 chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
712 /* Really need to put the tag into the `target` RTX. */
713 if (chosen_tag != target)
715 rtx temp = chosen_tag;
716 gcc_assert (GET_MODE (chosen_tag) == mode);
717 emit_move_insn (target, temp);
720 hwasan_increment_frame_tag ();
723 /* For hwasan stack tagging:
724 Tag a region of space in the shadow stack according to the base pointer of
725 an object on the stack. N.b. the length provided in the internal call is
726 required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
727 static void
728 expand_HWASAN_MARK (internal_fn, gcall *gc)
730 gcc_assert (ptr_mode == Pmode);
731 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
732 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
734 tree base = gimple_call_arg (gc, 1);
735 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
736 rtx base_rtx = expand_normal (base);
738 rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
739 : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
740 rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
742 tree len = gimple_call_arg (gc, 2);
743 rtx r_len = expand_normal (len);
745 rtx func = init_one_libfunc ("__hwasan_tag_memory");
746 emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
747 tag, QImode, r_len, Pmode);
750 /* For hwasan stack tagging:
751 Store a tag into a pointer. */
752 static void
753 expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
755 gcc_assert (ptr_mode == Pmode);
756 tree g_target = gimple_call_lhs (gc);
757 tree g_ptr = gimple_call_arg (gc, 0);
758 tree g_tag = gimple_call_arg (gc, 1);
760 rtx ptr = expand_normal (g_ptr);
761 rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
762 rtx target = expand_normal (g_target);
764 rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
765 rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
766 if (tagged_value != target)
767 emit_move_insn (target, tagged_value);
770 /* This should get expanded in the sanopt pass. */
772 static void
773 expand_ASAN_CHECK (internal_fn, gcall *)
775 gcc_unreachable ();
778 /* This should get expanded in the sanopt pass. */
780 static void
781 expand_ASAN_MARK (internal_fn, gcall *)
783 gcc_unreachable ();
786 /* This should get expanded in the sanopt pass. */
788 static void
789 expand_ASAN_POISON (internal_fn, gcall *)
791 gcc_unreachable ();
794 /* This should get expanded in the sanopt pass. */
796 static void
797 expand_ASAN_POISON_USE (internal_fn, gcall *)
799 gcc_unreachable ();
802 /* This should get expanded in the tsan pass. */
804 static void
805 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
807 gcc_unreachable ();
810 /* This should get expanded in the lower pass. */
812 static void
813 expand_FALLTHROUGH (internal_fn, gcall *call)
815 error_at (gimple_location (call),
816 "invalid use of attribute %<fallthrough%>");
819 /* Return minimum precision needed to represent all values
820 of ARG in SIGNed integral type. */
822 static int
823 get_min_precision (tree arg, signop sign)
825 int prec = TYPE_PRECISION (TREE_TYPE (arg));
826 int cnt = 0;
827 signop orig_sign = sign;
828 if (TREE_CODE (arg) == INTEGER_CST)
830 int p;
831 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
833 widest_int w = wi::to_widest (arg);
834 w = wi::ext (w, prec, sign);
835 p = wi::min_precision (w, sign);
837 else
838 p = wi::min_precision (wi::to_wide (arg), sign);
839 return MIN (p, prec);
841 while (CONVERT_EXPR_P (arg)
842 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
843 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
845 arg = TREE_OPERAND (arg, 0);
846 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
848 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
849 sign = UNSIGNED;
850 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
851 return prec + (orig_sign != sign);
852 prec = TYPE_PRECISION (TREE_TYPE (arg));
854 if (++cnt > 30)
855 return prec + (orig_sign != sign);
857 if (CONVERT_EXPR_P (arg)
858 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
859 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
861 /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
862 If y_2's min precision is smaller than prec, return that. */
863 int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
864 if (oprec < prec)
865 return oprec + (orig_sign != sign);
867 if (TREE_CODE (arg) != SSA_NAME)
868 return prec + (orig_sign != sign);
869 value_range r;
870 while (!get_global_range_query ()->range_of_expr (r, arg)
871 || r.varying_p ()
872 || r.undefined_p ())
874 gimple *g = SSA_NAME_DEF_STMT (arg);
875 if (is_gimple_assign (g)
876 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
878 tree t = gimple_assign_rhs1 (g);
879 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
880 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
882 arg = t;
883 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
885 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
886 sign = UNSIGNED;
887 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
888 return prec + (orig_sign != sign);
889 prec = TYPE_PRECISION (TREE_TYPE (arg));
891 if (++cnt > 30)
892 return prec + (orig_sign != sign);
893 continue;
896 return prec + (orig_sign != sign);
898 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
900 int p1 = wi::min_precision (r.lower_bound (), sign);
901 int p2 = wi::min_precision (r.upper_bound (), sign);
902 p1 = MAX (p1, p2);
903 prec = MIN (prec, p1);
905 else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
907 int p = wi::min_precision (r.upper_bound (), UNSIGNED);
908 prec = MIN (prec, p);
910 return prec + (orig_sign != sign);
913 /* Helper for expand_*_overflow. Set the __imag__ part to true
914 (1 except for signed:1 type, in which case store -1). */
916 static void
917 expand_arith_set_overflow (tree lhs, rtx target)
919 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
920 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
921 write_complex_part (target, constm1_rtx, true, false);
922 else
923 write_complex_part (target, const1_rtx, true, false);
926 /* Helper for expand_*_overflow. Store RES into the __real__ part
927 of TARGET. If RES has larger MODE than __real__ part of TARGET,
928 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
929 if LHS has smaller precision than its mode. */
931 static void
932 expand_arith_overflow_result_store (tree lhs, rtx target,
933 scalar_int_mode mode, rtx res)
935 scalar_int_mode tgtmode
936 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
937 rtx lres = res;
938 if (tgtmode != mode)
940 rtx_code_label *done_label = gen_label_rtx ();
941 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
942 lres = convert_modes (tgtmode, mode, res, uns);
943 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
944 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
945 EQ, true, mode, NULL_RTX, NULL, done_label,
946 profile_probability::very_likely ());
947 expand_arith_set_overflow (lhs, target);
948 emit_label (done_label);
950 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
951 int tgtprec = GET_MODE_PRECISION (tgtmode);
952 if (prec < tgtprec)
954 rtx_code_label *done_label = gen_label_rtx ();
955 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
956 res = lres;
957 if (uns)
959 rtx mask
960 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
961 tgtmode);
962 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
963 true, OPTAB_LIB_WIDEN);
965 else
967 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
968 NULL_RTX, 1);
969 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
970 NULL_RTX, 0);
972 do_compare_rtx_and_jump (res, lres,
973 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
974 profile_probability::very_likely ());
975 expand_arith_set_overflow (lhs, target);
976 emit_label (done_label);
978 write_complex_part (target, lres, false, false);
981 /* Helper for expand_*_overflow. Store RES into TARGET. */
983 static void
984 expand_ubsan_result_store (rtx target, rtx res)
986 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
987 /* If this is a scalar in a register that is stored in a wider mode
988 than the declared mode, compute the result into its declared mode
989 and then convert to the wider mode. Our value is the computed
990 expression. */
991 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
992 else
993 emit_move_insn (target, res);
996 /* Add sub/add overflow checking to the statement STMT.
997 CODE says whether the operation is +, or -. */
999 void
1000 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
1001 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
1002 bool uns1_p, bool is_ubsan, tree *datap)
1004 rtx res, target = NULL_RTX;
1005 tree fn;
1006 rtx_code_label *done_label = gen_label_rtx ();
1007 rtx_code_label *do_error = gen_label_rtx ();
1008 do_pending_stack_adjust ();
1009 rtx op0 = expand_normal (arg0);
1010 rtx op1 = expand_normal (arg1);
1011 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1012 int prec = GET_MODE_PRECISION (mode);
1013 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1014 bool do_xor = false;
1016 if (is_ubsan)
1017 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1019 if (lhs)
1021 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1022 if (!is_ubsan)
1023 write_complex_part (target, const0_rtx, true, false);
1026 /* We assume both operands and result have the same precision
1027 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1028 with that precision, U for unsigned type with that precision,
1029 sgn for unsigned most significant bit in that precision.
1030 s1 is signed first operand, u1 is unsigned first operand,
1031 s2 is signed second operand, u2 is unsigned second operand,
1032 sr is signed result, ur is unsigned result and the following
1033 rules say how to compute result (which is always result of
1034 the operands as if both were unsigned, cast to the right
1035 signedness) and how to compute whether operation overflowed.
1037 s1 + s2 -> sr
1038 res = (S) ((U) s1 + (U) s2)
1039 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
1040 s1 - s2 -> sr
1041 res = (S) ((U) s1 - (U) s2)
1042 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
1043 u1 + u2 -> ur
1044 res = u1 + u2
1045 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
1046 u1 - u2 -> ur
1047 res = u1 - u2
1048 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
1049 s1 + u2 -> sr
1050 res = (S) ((U) s1 + u2)
1051 ovf = ((U) res ^ sgn) < u2
1052 s1 + u2 -> ur
1053 t1 = (S) (u2 ^ sgn)
1054 t2 = s1 + t1
1055 res = (U) t2 ^ sgn
1056 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
1057 s1 - u2 -> sr
1058 res = (S) ((U) s1 - u2)
1059 ovf = u2 > ((U) s1 ^ sgn)
1060 s1 - u2 -> ur
1061 res = (U) s1 - u2
1062 ovf = s1 < 0 || u2 > (U) s1
1063 u1 - s2 -> sr
1064 res = u1 - (U) s2
1065 ovf = u1 >= ((U) s2 ^ sgn)
1066 u1 - s2 -> ur
1067 t1 = u1 ^ sgn
1068 t2 = t1 - (U) s2
1069 res = t2 ^ sgn
1070 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
1071 s1 + s2 -> ur
1072 res = (U) s1 + (U) s2
1073 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
1074 u1 + u2 -> sr
1075 res = (S) (u1 + u2)
1076 ovf = (U) res < u2 || res < 0
1077 u1 - u2 -> sr
1078 res = (S) (u1 - u2)
1079 ovf = u1 >= u2 ? res < 0 : res >= 0
1080 s1 - s2 -> ur
1081 res = (U) s1 - (U) s2
1082 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
1084 if (code == PLUS_EXPR && uns0_p && !uns1_p)
1086 /* PLUS_EXPR is commutative, if operand signedness differs,
1087 canonicalize to the first operand being signed and second
1088 unsigned to simplify following code. */
1089 std::swap (op0, op1);
1090 std::swap (arg0, arg1);
1091 uns0_p = false;
1092 uns1_p = true;
1095 /* u1 +- u2 -> ur */
1096 if (uns0_p && uns1_p && unsr_p)
1098 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
1099 : usubv4_optab, mode);
1100 if (icode != CODE_FOR_nothing)
1102 class expand_operand ops[4];
1103 rtx_insn *last = get_last_insn ();
1105 res = gen_reg_rtx (mode);
1106 create_output_operand (&ops[0], res, mode);
1107 create_input_operand (&ops[1], op0, mode);
1108 create_input_operand (&ops[2], op1, mode);
1109 create_fixed_operand (&ops[3], do_error);
1110 if (maybe_expand_insn (icode, 4, ops))
1112 last = get_last_insn ();
1113 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1114 && JUMP_P (last)
1115 && any_condjump_p (last)
1116 && !find_reg_note (last, REG_BR_PROB, 0))
1117 add_reg_br_prob_note (last,
1118 profile_probability::very_unlikely ());
1119 emit_jump (done_label);
1120 goto do_error_label;
1123 delete_insns_since (last);
1126 /* Compute the operation. On RTL level, the addition is always
1127 unsigned. */
1128 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1129 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1130 rtx tem = op0;
1131 /* For PLUS_EXPR, the operation is commutative, so we can pick
1132 operand to compare against. For prec <= BITS_PER_WORD, I think
1133 preferring REG operand is better over CONST_INT, because
1134 the CONST_INT might enlarge the instruction or CSE would need
1135 to figure out we'd already loaded it into a register before.
1136 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
1137 as then the multi-word comparison can be perhaps simplified. */
1138 if (code == PLUS_EXPR
1139 && (prec <= BITS_PER_WORD
1140 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
1141 : CONST_SCALAR_INT_P (op1)))
1142 tem = op1;
1143 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1144 true, mode, NULL_RTX, NULL, done_label,
1145 profile_probability::very_likely ());
1146 goto do_error_label;
1149 /* s1 +- u2 -> sr */
1150 if (!uns0_p && uns1_p && !unsr_p)
1152 /* Compute the operation. On RTL level, the addition is always
1153 unsigned. */
1154 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1155 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1156 rtx tem = expand_binop (mode, add_optab,
1157 code == PLUS_EXPR ? res : op0, sgn,
1158 NULL_RTX, false, OPTAB_LIB_WIDEN);
1159 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1160 done_label, profile_probability::very_likely ());
1161 goto do_error_label;
1164 /* s1 + u2 -> ur */
1165 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
1167 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1168 OPTAB_LIB_WIDEN);
1169 /* As we've changed op1, we have to avoid using the value range
1170 for the original argument. */
1171 arg1 = error_mark_node;
1172 do_xor = true;
1173 goto do_signed;
1176 /* u1 - s2 -> ur */
1177 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
1179 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
1180 OPTAB_LIB_WIDEN);
1181 /* As we've changed op0, we have to avoid using the value range
1182 for the original argument. */
1183 arg0 = error_mark_node;
1184 do_xor = true;
1185 goto do_signed;
1188 /* s1 - u2 -> ur */
1189 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
1191 /* Compute the operation. On RTL level, the addition is always
1192 unsigned. */
1193 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1194 OPTAB_LIB_WIDEN);
1195 int pos_neg = get_range_pos_neg (arg0);
1196 if (pos_neg == 2)
1197 /* If ARG0 is known to be always negative, this is always overflow. */
1198 emit_jump (do_error);
1199 else if (pos_neg == 3)
1200 /* If ARG0 is not known to be always positive, check at runtime. */
1201 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1202 NULL, do_error, profile_probability::very_unlikely ());
1203 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1204 done_label, profile_probability::very_likely ());
1205 goto do_error_label;
1208 /* u1 - s2 -> sr */
1209 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
1211 /* Compute the operation. On RTL level, the addition is always
1212 unsigned. */
1213 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1214 OPTAB_LIB_WIDEN);
1215 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1216 OPTAB_LIB_WIDEN);
1217 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1218 done_label, profile_probability::very_likely ());
1219 goto do_error_label;
1222 /* u1 + u2 -> sr */
1223 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
1225 /* Compute the operation. On RTL level, the addition is always
1226 unsigned. */
1227 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
1228 OPTAB_LIB_WIDEN);
1229 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1230 NULL, do_error, profile_probability::very_unlikely ());
1231 rtx tem = op1;
1232 /* The operation is commutative, so we can pick operand to compare
1233 against. For prec <= BITS_PER_WORD, I think preferring REG operand
1234 is better over CONST_INT, because the CONST_INT might enlarge the
1235 instruction or CSE would need to figure out we'd already loaded it
1236 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
1237 might be more beneficial, as then the multi-word comparison can be
1238 perhaps simplified. */
1239 if (prec <= BITS_PER_WORD
1240 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
1241 : CONST_SCALAR_INT_P (op0))
1242 tem = op0;
1243 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1244 done_label, profile_probability::very_likely ());
1245 goto do_error_label;
1248 /* s1 +- s2 -> ur */
1249 if (!uns0_p && !uns1_p && unsr_p)
1251 /* Compute the operation. On RTL level, the addition is always
1252 unsigned. */
1253 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1254 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1255 int pos_neg = get_range_pos_neg (arg1);
1256 if (code == PLUS_EXPR)
1258 int pos_neg0 = get_range_pos_neg (arg0);
1259 if (pos_neg0 != 3 && pos_neg == 3)
1261 std::swap (op0, op1);
1262 pos_neg = pos_neg0;
1265 rtx tem;
1266 if (pos_neg != 3)
1268 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
1269 ? and_optab : ior_optab,
1270 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1271 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
1272 NULL, done_label, profile_probability::very_likely ());
1274 else
1276 rtx_code_label *do_ior_label = gen_label_rtx ();
1277 do_compare_rtx_and_jump (op1, const0_rtx,
1278 code == MINUS_EXPR ? GE : LT, false, mode,
1279 NULL_RTX, NULL, do_ior_label,
1280 profile_probability::even ());
1281 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
1282 OPTAB_LIB_WIDEN);
1283 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1284 NULL, done_label, profile_probability::very_likely ());
1285 emit_jump (do_error);
1286 emit_label (do_ior_label);
1287 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
1288 OPTAB_LIB_WIDEN);
1289 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1290 NULL, done_label, profile_probability::very_likely ());
1292 goto do_error_label;
1295 /* u1 - u2 -> sr */
1296 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
1298 /* Compute the operation. On RTL level, the addition is always
1299 unsigned. */
1300 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1301 OPTAB_LIB_WIDEN);
1302 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1303 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1304 op0_geu_op1, profile_probability::even ());
1305 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1306 NULL, done_label, profile_probability::very_likely ());
1307 emit_jump (do_error);
1308 emit_label (op0_geu_op1);
1309 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1310 NULL, done_label, profile_probability::very_likely ());
1311 goto do_error_label;
1314 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1316 /* s1 +- s2 -> sr */
1317 do_signed:
1319 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1320 : subv4_optab, mode);
1321 if (icode != CODE_FOR_nothing)
1323 class expand_operand ops[4];
1324 rtx_insn *last = get_last_insn ();
1326 res = gen_reg_rtx (mode);
1327 create_output_operand (&ops[0], res, mode);
1328 create_input_operand (&ops[1], op0, mode);
1329 create_input_operand (&ops[2], op1, mode);
1330 create_fixed_operand (&ops[3], do_error);
1331 if (maybe_expand_insn (icode, 4, ops))
1333 last = get_last_insn ();
1334 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1335 && JUMP_P (last)
1336 && any_condjump_p (last)
1337 && !find_reg_note (last, REG_BR_PROB, 0))
1338 add_reg_br_prob_note (last,
1339 profile_probability::very_unlikely ());
1340 emit_jump (done_label);
1341 goto do_error_label;
1344 delete_insns_since (last);
1347 /* Compute the operation. On RTL level, the addition is always
1348 unsigned. */
1349 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1350 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1352 /* If we can prove that one of the arguments (for MINUS_EXPR only
1353 the second operand, as subtraction is not commutative) is always
1354 non-negative or always negative, we can do just one comparison
1355 and conditional jump. */
1356 int pos_neg = get_range_pos_neg (arg1);
1357 if (code == PLUS_EXPR)
1359 int pos_neg0 = get_range_pos_neg (arg0);
1360 if (pos_neg0 != 3 && pos_neg == 3)
1362 std::swap (op0, op1);
1363 pos_neg = pos_neg0;
1367 /* Addition overflows if and only if the two operands have the same sign,
1368 and the result has the opposite sign. Subtraction overflows if and
1369 only if the two operands have opposite sign, and the subtrahend has
1370 the same sign as the result. Here 0 is counted as positive. */
1371 if (pos_neg == 3)
1373 /* Compute op0 ^ op1 (operands have opposite sign). */
1374 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1375 OPTAB_LIB_WIDEN);
1377 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1378 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1379 OPTAB_LIB_WIDEN);
1381 rtx tem;
1382 if (code == PLUS_EXPR)
1384 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1385 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1386 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1387 OPTAB_LIB_WIDEN);
1389 else
1391 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1392 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1393 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1394 OPTAB_LIB_WIDEN);
1397 /* No overflow if the result has bit sign cleared. */
1398 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1399 NULL, done_label, profile_probability::very_likely ());
1402 /* Compare the result of the operation with the first operand.
1403 No overflow for addition if second operand is positive and result
1404 is larger or second operand is negative and result is smaller.
1405 Likewise for subtraction with sign of second operand flipped. */
1406 else
1407 do_compare_rtx_and_jump (res, op0,
1408 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1409 false, mode, NULL_RTX, NULL, done_label,
1410 profile_probability::very_likely ());
1413 do_error_label:
1414 emit_label (do_error);
1415 if (is_ubsan)
1417 /* Expand the ubsan builtin call. */
1418 push_temp_slots ();
1419 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1420 arg0, arg1, datap);
1421 expand_normal (fn);
1422 pop_temp_slots ();
1423 do_pending_stack_adjust ();
1425 else if (lhs)
1426 expand_arith_set_overflow (lhs, target);
1428 /* We're done. */
1429 emit_label (done_label);
1431 if (lhs)
1433 if (is_ubsan)
1434 expand_ubsan_result_store (target, res);
1435 else
1437 if (do_xor)
1438 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1439 OPTAB_LIB_WIDEN);
1441 expand_arith_overflow_result_store (lhs, target, mode, res);
1446 /* Add negate overflow checking to the statement STMT. */
1448 static void
1449 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1450 tree *datap)
1452 rtx res, op1;
1453 tree fn;
1454 rtx_code_label *done_label, *do_error;
1455 rtx target = NULL_RTX;
1457 done_label = gen_label_rtx ();
1458 do_error = gen_label_rtx ();
1460 do_pending_stack_adjust ();
1461 op1 = expand_normal (arg1);
1463 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1464 if (lhs)
1466 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1467 if (!is_ubsan)
1468 write_complex_part (target, const0_rtx, true, false);
1471 enum insn_code icode = optab_handler (negv3_optab, mode);
1472 if (icode != CODE_FOR_nothing)
1474 class expand_operand ops[3];
1475 rtx_insn *last = get_last_insn ();
1477 res = gen_reg_rtx (mode);
1478 create_output_operand (&ops[0], res, mode);
1479 create_input_operand (&ops[1], op1, mode);
1480 create_fixed_operand (&ops[2], do_error);
1481 if (maybe_expand_insn (icode, 3, ops))
1483 last = get_last_insn ();
1484 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1485 && JUMP_P (last)
1486 && any_condjump_p (last)
1487 && !find_reg_note (last, REG_BR_PROB, 0))
1488 add_reg_br_prob_note (last,
1489 profile_probability::very_unlikely ());
1490 emit_jump (done_label);
1492 else
1494 delete_insns_since (last);
1495 icode = CODE_FOR_nothing;
1499 if (icode == CODE_FOR_nothing)
1501 /* Compute the operation. On RTL level, the addition is always
1502 unsigned. */
1503 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1505 /* Compare the operand with the most negative value. */
1506 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1507 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1508 done_label, profile_probability::very_likely ());
1511 emit_label (do_error);
1512 if (is_ubsan)
1514 /* Expand the ubsan builtin call. */
1515 push_temp_slots ();
1516 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1517 arg1, NULL_TREE, datap);
1518 expand_normal (fn);
1519 pop_temp_slots ();
1520 do_pending_stack_adjust ();
1522 else if (lhs)
1523 expand_arith_set_overflow (lhs, target);
1525 /* We're done. */
1526 emit_label (done_label);
1528 if (lhs)
1530 if (is_ubsan)
1531 expand_ubsan_result_store (target, res);
1532 else
1533 expand_arith_overflow_result_store (lhs, target, mode, res);
1537 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1538 mode MODE can be expanded without using a libcall. */
1540 static bool
1541 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1542 rtx op0, rtx op1, bool uns)
1544 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1545 != CODE_FOR_nothing)
1546 return true;
1548 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1549 != CODE_FOR_nothing)
1550 return true;
1552 rtx_insn *last = get_last_insn ();
1553 if (CONSTANT_P (op0))
1554 op0 = convert_modes (wmode, mode, op0, uns);
1555 else
1556 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1557 if (CONSTANT_P (op1))
1558 op1 = convert_modes (wmode, mode, op1, uns);
1559 else
1560 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1561 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1562 delete_insns_since (last);
1563 return ret != NULL_RTX;
1566 /* Add mul overflow checking to the statement STMT. */
1568 static void
1569 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1570 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1571 tree *datap)
1573 rtx res, op0, op1;
1574 tree fn, type;
1575 rtx_code_label *done_label, *do_error;
1576 rtx target = NULL_RTX;
1577 signop sign;
1578 enum insn_code icode;
1580 done_label = gen_label_rtx ();
1581 do_error = gen_label_rtx ();
1583 do_pending_stack_adjust ();
1584 op0 = expand_normal (arg0);
1585 op1 = expand_normal (arg1);
1587 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1588 bool uns = unsr_p;
1589 if (lhs)
1591 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1592 if (!is_ubsan)
1593 write_complex_part (target, const0_rtx, true, false);
1596 if (is_ubsan)
1597 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1599 /* We assume both operands and result have the same precision
1600 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1601 with that precision, U for unsigned type with that precision,
1602 sgn for unsigned most significant bit in that precision.
1603 s1 is signed first operand, u1 is unsigned first operand,
1604 s2 is signed second operand, u2 is unsigned second operand,
1605 sr is signed result, ur is unsigned result and the following
1606 rules say how to compute result (which is always result of
1607 the operands as if both were unsigned, cast to the right
1608 signedness) and how to compute whether operation overflowed.
1609 main_ovf (false) stands for jump on signed multiplication
1610 overflow or the main algorithm with uns == false.
1611 main_ovf (true) stands for jump on unsigned multiplication
1612 overflow or the main algorithm with uns == true.
1614 s1 * s2 -> sr
1615 res = (S) ((U) s1 * (U) s2)
1616 ovf = main_ovf (false)
1617 u1 * u2 -> ur
1618 res = u1 * u2
1619 ovf = main_ovf (true)
1620 s1 * u2 -> ur
1621 res = (U) s1 * u2
1622 ovf = (s1 < 0 && u2) || main_ovf (true)
1623 u1 * u2 -> sr
1624 res = (S) (u1 * u2)
1625 ovf = res < 0 || main_ovf (true)
1626 s1 * u2 -> sr
1627 res = (S) ((U) s1 * u2)
1628 ovf = (S) u2 >= 0 ? main_ovf (false)
1629 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1630 s1 * s2 -> ur
1631 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1632 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1633 res = t1 * t2
1634 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1636 if (uns0_p && !uns1_p)
1638 /* Multiplication is commutative, if operand signedness differs,
1639 canonicalize to the first operand being signed and second
1640 unsigned to simplify following code. */
1641 std::swap (op0, op1);
1642 std::swap (arg0, arg1);
1643 uns0_p = false;
1644 uns1_p = true;
1647 int pos_neg0 = get_range_pos_neg (arg0);
1648 int pos_neg1 = get_range_pos_neg (arg1);
1650 /* s1 * u2 -> ur */
1651 if (!uns0_p && uns1_p && unsr_p)
1653 switch (pos_neg0)
1655 case 1:
1656 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1657 goto do_main;
1658 case 2:
1659 /* If s1 is negative, avoid the main code, just multiply and
1660 signal overflow if op1 is not 0. */
1661 struct separate_ops ops;
1662 ops.code = MULT_EXPR;
1663 ops.type = TREE_TYPE (arg1);
1664 ops.op0 = make_tree (ops.type, op0);
1665 ops.op1 = make_tree (ops.type, op1);
1666 ops.op2 = NULL_TREE;
1667 ops.location = loc;
1668 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1669 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1670 NULL, done_label, profile_probability::very_likely ());
1671 goto do_error_label;
1672 case 3:
1673 if (get_min_precision (arg1, UNSIGNED)
1674 + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
1676 /* If the first operand is sign extended from narrower type, the
1677 second operand is zero extended from narrower type and
1678 the sum of the two precisions is smaller or equal to the
1679 result precision: if the first argument is at runtime
1680 non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
1681 and there will be no overflow, if the first argument is
1682 negative and the second argument zero, the result will be
1683 0 and there will be no overflow, if the first argument is
1684 negative and the second argument positive, the result when
1685 treated as signed will be negative (minimum -0x7f80 or
1686 -0x7f..f80..0) there will be always overflow. So, do
1687 res = (U) (s1 * u2)
1688 ovf = (S) res < 0 */
1689 struct separate_ops ops;
1690 ops.code = MULT_EXPR;
1691 ops.type
1692 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1694 ops.op0 = make_tree (ops.type, op0);
1695 ops.op1 = make_tree (ops.type, op1);
1696 ops.op2 = NULL_TREE;
1697 ops.location = loc;
1698 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1699 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1700 mode, NULL_RTX, NULL, done_label,
1701 profile_probability::very_likely ());
1702 goto do_error_label;
1704 rtx_code_label *do_main_label;
1705 do_main_label = gen_label_rtx ();
1706 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1707 NULL, do_main_label, profile_probability::very_likely ());
1708 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1709 NULL, do_main_label, profile_probability::very_likely ());
1710 expand_arith_set_overflow (lhs, target);
1711 emit_label (do_main_label);
1712 goto do_main;
1713 default:
1714 gcc_unreachable ();
1718 /* u1 * u2 -> sr */
1719 if (uns0_p && uns1_p && !unsr_p)
1721 if ((pos_neg0 | pos_neg1) == 1)
1723 /* If both arguments are zero extended from narrower types,
1724 the MSB will be clear on both and so we can pretend it is
1725 a normal s1 * s2 -> sr multiplication. */
1726 uns0_p = false;
1727 uns1_p = false;
1729 else
1730 uns = true;
1731 /* Rest of handling of this case after res is computed. */
1732 goto do_main;
1735 /* s1 * u2 -> sr */
1736 if (!uns0_p && uns1_p && !unsr_p)
1738 switch (pos_neg1)
1740 case 1:
1741 goto do_main;
1742 case 2:
1743 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1744 avoid the main code, just multiply and signal overflow
1745 unless 0 * u2 or -1 * ((U) Smin). */
1746 struct separate_ops ops;
1747 ops.code = MULT_EXPR;
1748 ops.type = TREE_TYPE (arg1);
1749 ops.op0 = make_tree (ops.type, op0);
1750 ops.op1 = make_tree (ops.type, op1);
1751 ops.op2 = NULL_TREE;
1752 ops.location = loc;
1753 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1754 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1755 NULL, done_label, profile_probability::very_likely ());
1756 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1757 NULL, do_error, profile_probability::very_unlikely ());
1758 int prec;
1759 prec = GET_MODE_PRECISION (mode);
1760 rtx sgn;
1761 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1762 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1763 NULL, done_label, profile_probability::very_likely ());
1764 goto do_error_label;
1765 case 3:
1766 /* Rest of handling of this case after res is computed. */
1767 goto do_main;
1768 default:
1769 gcc_unreachable ();
1773 /* s1 * s2 -> ur */
1774 if (!uns0_p && !uns1_p && unsr_p)
1776 rtx tem;
1777 switch (pos_neg0 | pos_neg1)
1779 case 1: /* Both operands known to be non-negative. */
1780 goto do_main;
1781 case 2: /* Both operands known to be negative. */
1782 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1783 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1784 /* Avoid looking at arg0/arg1 ranges, as we've changed
1785 the arguments. */
1786 arg0 = error_mark_node;
1787 arg1 = error_mark_node;
1788 goto do_main;
1789 case 3:
1790 if ((pos_neg0 ^ pos_neg1) == 3)
1792 /* If one operand is known to be negative and the other
1793 non-negative, this overflows always, unless the non-negative
1794 one is 0. Just do normal multiply and set overflow
1795 unless one of the operands is 0. */
1796 struct separate_ops ops;
1797 ops.code = MULT_EXPR;
1798 ops.type
1799 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1801 ops.op0 = make_tree (ops.type, op0);
1802 ops.op1 = make_tree (ops.type, op1);
1803 ops.op2 = NULL_TREE;
1804 ops.location = loc;
1805 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1806 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1807 true, mode, NULL_RTX, NULL, done_label,
1808 profile_probability::very_likely ());
1809 goto do_error_label;
1811 if (get_min_precision (arg0, SIGNED)
1812 + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
1814 /* If both operands are sign extended from narrower types and
1815 the sum of the two precisions is smaller or equal to the
1816 result precision: if both arguments are at runtime
1817 non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
1818 and there will be no overflow, if both arguments are negative,
1819 maximum result will be 0x40..00 and there will be no overflow
1820 either, if one argument is positive and the other argument
1821 negative, the result when treated as signed will be negative
1822 and there will be always overflow, and if one argument is
1823 zero and the other negative the result will be zero and no
1824 overflow. So, do
1825 res = (U) (s1 * s2)
1826 ovf = (S) res < 0 */
1827 struct separate_ops ops;
1828 ops.code = MULT_EXPR;
1829 ops.type
1830 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1832 ops.op0 = make_tree (ops.type, op0);
1833 ops.op1 = make_tree (ops.type, op1);
1834 ops.op2 = NULL_TREE;
1835 ops.location = loc;
1836 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1837 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1838 mode, NULL_RTX, NULL, done_label,
1839 profile_probability::very_likely ());
1840 goto do_error_label;
1842 /* The general case, do all the needed comparisons at runtime. */
1843 rtx_code_label *do_main_label, *after_negate_label;
1844 rtx rop0, rop1;
1845 rop0 = gen_reg_rtx (mode);
1846 rop1 = gen_reg_rtx (mode);
1847 emit_move_insn (rop0, op0);
1848 emit_move_insn (rop1, op1);
1849 op0 = rop0;
1850 op1 = rop1;
1851 do_main_label = gen_label_rtx ();
1852 after_negate_label = gen_label_rtx ();
1853 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1854 OPTAB_LIB_WIDEN);
1855 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1856 NULL, after_negate_label, profile_probability::very_likely ());
1857 /* Both arguments negative here, negate them and continue with
1858 normal unsigned overflow checking multiplication. */
1859 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1860 NULL_RTX, false));
1861 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1862 NULL_RTX, false));
1863 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1864 the arguments. */
1865 arg0 = error_mark_node;
1866 arg1 = error_mark_node;
1867 emit_jump (do_main_label);
1868 emit_label (after_negate_label);
1869 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1870 OPTAB_LIB_WIDEN);
1871 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1872 NULL, do_main_label,
1873 profile_probability::very_likely ());
1874 /* One argument is negative here, the other positive. This
1875 overflows always, unless one of the arguments is 0. But
1876 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1877 is, thus we can keep do_main code oring in overflow as is. */
1878 if (pos_neg0 != 2)
1879 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1880 NULL, do_main_label,
1881 profile_probability::very_unlikely ());
1882 if (pos_neg1 != 2)
1883 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1884 NULL, do_main_label,
1885 profile_probability::very_unlikely ());
1886 expand_arith_set_overflow (lhs, target);
1887 emit_label (do_main_label);
1888 goto do_main;
1889 default:
1890 gcc_unreachable ();
1894 do_main:
1895 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1896 sign = uns ? UNSIGNED : SIGNED;
1897 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1898 if (uns
1899 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1900 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1902 /* Optimize unsigned multiplication by power of 2 constant
1903 using 2 shifts, one for result, one to extract the shifted
1904 out bits to see if they are all zero.
1905 Don't do this if optimizing for size and we have umulv4_optab,
1906 in that case assume multiplication will be shorter.
1907 This is heuristics based on the single target that provides
1908 umulv4 right now (i?86/x86_64), if further targets add it, this
1909 might need to be revisited.
1910 Cases where both operands are constant should be folded already
1911 during GIMPLE, and cases where one operand is constant but not
1912 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1913 below can be done without multiplication, just by shifts and adds,
1914 or we'd need to divide the result (and hope it actually doesn't
1915 really divide nor multiply) and compare the result of the division
1916 with the original operand. */
1917 rtx opn0 = op0;
1918 rtx opn1 = op1;
1919 tree argn0 = arg0;
1920 tree argn1 = arg1;
1921 if (integer_pow2p (arg0))
1923 std::swap (opn0, opn1);
1924 std::swap (argn0, argn1);
1926 int cnt = tree_log2 (argn1);
1927 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1929 rtx upper = const0_rtx;
1930 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1931 if (cnt != 0)
1932 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1933 GET_MODE_PRECISION (mode) - cnt,
1934 NULL_RTX, uns);
1935 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1936 NULL_RTX, NULL, done_label,
1937 profile_probability::very_likely ());
1938 goto do_error_label;
1941 if (icode != CODE_FOR_nothing)
1943 class expand_operand ops[4];
1944 rtx_insn *last = get_last_insn ();
1946 res = gen_reg_rtx (mode);
1947 create_output_operand (&ops[0], res, mode);
1948 create_input_operand (&ops[1], op0, mode);
1949 create_input_operand (&ops[2], op1, mode);
1950 create_fixed_operand (&ops[3], do_error);
1951 if (maybe_expand_insn (icode, 4, ops))
1953 last = get_last_insn ();
1954 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1955 && JUMP_P (last)
1956 && any_condjump_p (last)
1957 && !find_reg_note (last, REG_BR_PROB, 0))
1958 add_reg_br_prob_note (last,
1959 profile_probability::very_unlikely ());
1960 emit_jump (done_label);
1962 else
1964 delete_insns_since (last);
1965 icode = CODE_FOR_nothing;
1969 if (icode == CODE_FOR_nothing)
1971 struct separate_ops ops;
1972 int prec = GET_MODE_PRECISION (mode);
1973 scalar_int_mode hmode, wmode;
1974 ops.op0 = make_tree (type, op0);
1975 ops.op1 = make_tree (type, op1);
1976 ops.op2 = NULL_TREE;
1977 ops.location = loc;
1979 /* Optimize unsigned overflow check where we don't use the
1980 multiplication result, just whether overflow happened.
1981 If we can do MULT_HIGHPART_EXPR, that followed by
1982 comparison of the result against zero is cheapest.
1983 We'll still compute res, but it should be DCEd later. */
1984 use_operand_p use;
1985 gimple *use_stmt;
1986 if (!is_ubsan
1987 && lhs
1988 && uns
1989 && !(uns0_p && uns1_p && !unsr_p)
1990 && can_mult_highpart_p (mode, uns) == 1
1991 && single_imm_use (lhs, &use, &use_stmt)
1992 && is_gimple_assign (use_stmt)
1993 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1994 goto highpart;
1996 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1997 && targetm.scalar_mode_supported_p (wmode)
1998 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
2000 twoxwider:
2001 ops.code = WIDEN_MULT_EXPR;
2002 ops.type
2003 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
2005 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
2006 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
2007 NULL_RTX, uns);
2008 hipart = convert_modes (mode, wmode, hipart, uns);
2009 res = convert_modes (mode, wmode, res, uns);
2010 if (uns)
2011 /* For the unsigned multiplication, there was overflow if
2012 HIPART is non-zero. */
2013 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2014 NULL_RTX, NULL, done_label,
2015 profile_probability::very_likely ());
2016 else
2018 /* RES is used more than once, place it in a pseudo. */
2019 res = force_reg (mode, res);
2021 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2022 NULL_RTX, 0);
2023 /* RES is low half of the double width result, HIPART
2024 the high half. There was overflow if
2025 HIPART is different from RES < 0 ? -1 : 0. */
2026 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2027 NULL_RTX, NULL, done_label,
2028 profile_probability::very_likely ());
2031 else if (can_mult_highpart_p (mode, uns) == 1)
2033 highpart:
2034 ops.code = MULT_HIGHPART_EXPR;
2035 ops.type = type;
2037 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
2038 EXPAND_NORMAL);
2039 ops.code = MULT_EXPR;
2040 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2041 if (uns)
2042 /* For the unsigned multiplication, there was overflow if
2043 HIPART is non-zero. */
2044 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2045 NULL_RTX, NULL, done_label,
2046 profile_probability::very_likely ());
2047 else
2049 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2050 NULL_RTX, 0);
2051 /* RES is low half of the double width result, HIPART
2052 the high half. There was overflow if
2053 HIPART is different from RES < 0 ? -1 : 0. */
2054 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2055 NULL_RTX, NULL, done_label,
2056 profile_probability::very_likely ());
2060 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
2061 && 2 * GET_MODE_PRECISION (hmode) == prec)
2063 rtx_code_label *large_op0 = gen_label_rtx ();
2064 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
2065 rtx_code_label *one_small_one_large = gen_label_rtx ();
2066 rtx_code_label *both_ops_large = gen_label_rtx ();
2067 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
2068 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
2069 rtx_code_label *do_overflow = gen_label_rtx ();
2070 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
2072 unsigned int hprec = GET_MODE_PRECISION (hmode);
2073 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
2074 NULL_RTX, uns);
2075 hipart0 = convert_modes (hmode, mode, hipart0, uns);
2076 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
2077 rtx signbit0 = const0_rtx;
2078 if (!uns)
2079 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
2080 NULL_RTX, 0);
2081 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
2082 NULL_RTX, uns);
2083 hipart1 = convert_modes (hmode, mode, hipart1, uns);
2084 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
2085 rtx signbit1 = const0_rtx;
2086 if (!uns)
2087 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
2088 NULL_RTX, 0);
2090 res = gen_reg_rtx (mode);
2092 /* True if op0 resp. op1 are known to be in the range of
2093 halfstype. */
2094 bool op0_small_p = false;
2095 bool op1_small_p = false;
2096 /* True if op0 resp. op1 are known to have all zeros or all ones
2097 in the upper half of bits, but are not known to be
2098 op{0,1}_small_p. */
2099 bool op0_medium_p = false;
2100 bool op1_medium_p = false;
2101 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
2102 nonnegative, 1 if unknown. */
2103 int op0_sign = 1;
2104 int op1_sign = 1;
2106 if (pos_neg0 == 1)
2107 op0_sign = 0;
2108 else if (pos_neg0 == 2)
2109 op0_sign = -1;
2110 if (pos_neg1 == 1)
2111 op1_sign = 0;
2112 else if (pos_neg1 == 2)
2113 op1_sign = -1;
2115 unsigned int mprec0 = prec;
2116 if (arg0 != error_mark_node)
2117 mprec0 = get_min_precision (arg0, sign);
2118 if (mprec0 <= hprec)
2119 op0_small_p = true;
2120 else if (!uns && mprec0 <= hprec + 1)
2121 op0_medium_p = true;
2122 unsigned int mprec1 = prec;
2123 if (arg1 != error_mark_node)
2124 mprec1 = get_min_precision (arg1, sign);
2125 if (mprec1 <= hprec)
2126 op1_small_p = true;
2127 else if (!uns && mprec1 <= hprec + 1)
2128 op1_medium_p = true;
2130 int smaller_sign = 1;
2131 int larger_sign = 1;
2132 if (op0_small_p)
2134 smaller_sign = op0_sign;
2135 larger_sign = op1_sign;
2137 else if (op1_small_p)
2139 smaller_sign = op1_sign;
2140 larger_sign = op0_sign;
2142 else if (op0_sign == op1_sign)
2144 smaller_sign = op0_sign;
2145 larger_sign = op0_sign;
2148 if (!op0_small_p)
2149 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
2150 NULL_RTX, NULL, large_op0,
2151 profile_probability::unlikely ());
2153 if (!op1_small_p)
2154 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2155 NULL_RTX, NULL, small_op0_large_op1,
2156 profile_probability::unlikely ());
2158 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
2159 hmode to mode, the multiplication will never overflow. We can
2160 do just one hmode x hmode => mode widening multiplication. */
2161 tree halfstype = build_nonstandard_integer_type (hprec, uns);
2162 ops.op0 = make_tree (halfstype, lopart0);
2163 ops.op1 = make_tree (halfstype, lopart1);
2164 ops.code = WIDEN_MULT_EXPR;
2165 ops.type = type;
2166 rtx thisres
2167 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2168 emit_move_insn (res, thisres);
2169 emit_jump (done_label);
2171 emit_label (small_op0_large_op1);
2173 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
2174 but op1 is not, just swap the arguments and handle it as op1
2175 sign/zero extended, op0 not. */
2176 rtx larger = gen_reg_rtx (mode);
2177 rtx hipart = gen_reg_rtx (hmode);
2178 rtx lopart = gen_reg_rtx (hmode);
2179 emit_move_insn (larger, op1);
2180 emit_move_insn (hipart, hipart1);
2181 emit_move_insn (lopart, lopart0);
2182 emit_jump (one_small_one_large);
2184 emit_label (large_op0);
2186 if (!op1_small_p)
2187 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2188 NULL_RTX, NULL, both_ops_large,
2189 profile_probability::unlikely ());
2191 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
2192 but op0 is not, prepare larger, hipart and lopart pseudos and
2193 handle it together with small_op0_large_op1. */
2194 emit_move_insn (larger, op0);
2195 emit_move_insn (hipart, hipart0);
2196 emit_move_insn (lopart, lopart1);
2198 emit_label (one_small_one_large);
2200 /* lopart is the low part of the operand that is sign extended
2201 to mode, larger is the other operand, hipart is the
2202 high part of larger and lopart0 and lopart1 are the low parts
2203 of both operands.
2204 We perform lopart0 * lopart1 and lopart * hipart widening
2205 multiplications. */
2206 tree halfutype = build_nonstandard_integer_type (hprec, 1);
2207 ops.op0 = make_tree (halfutype, lopart0);
2208 ops.op1 = make_tree (halfutype, lopart1);
2209 rtx lo0xlo1
2210 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2212 ops.op0 = make_tree (halfutype, lopart);
2213 ops.op1 = make_tree (halfutype, hipart);
2214 rtx loxhi = gen_reg_rtx (mode);
2215 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2216 emit_move_insn (loxhi, tem);
2218 if (!uns)
2220 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
2221 if (larger_sign == 0)
2222 emit_jump (after_hipart_neg);
2223 else if (larger_sign != -1)
2224 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
2225 NULL_RTX, NULL, after_hipart_neg,
2226 profile_probability::even ());
2228 tem = convert_modes (mode, hmode, lopart, 1);
2229 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
2230 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
2231 1, OPTAB_WIDEN);
2232 emit_move_insn (loxhi, tem);
2234 emit_label (after_hipart_neg);
2236 /* if (lopart < 0) loxhi -= larger; */
2237 if (smaller_sign == 0)
2238 emit_jump (after_lopart_neg);
2239 else if (smaller_sign != -1)
2240 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
2241 NULL_RTX, NULL, after_lopart_neg,
2242 profile_probability::even ());
2244 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
2245 1, OPTAB_WIDEN);
2246 emit_move_insn (loxhi, tem);
2248 emit_label (after_lopart_neg);
2251 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
2252 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
2253 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
2254 1, OPTAB_WIDEN);
2255 emit_move_insn (loxhi, tem);
2257 /* if (loxhi >> (bitsize / 2)
2258 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
2259 if (loxhi >> (bitsize / 2) == 0 (if uns). */
2260 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
2261 NULL_RTX, 0);
2262 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
2263 rtx signbitloxhi = const0_rtx;
2264 if (!uns)
2265 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
2266 convert_modes (hmode, mode,
2267 loxhi, 0),
2268 hprec - 1, NULL_RTX, 0);
2270 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
2271 NULL_RTX, NULL, do_overflow,
2272 profile_probability::very_unlikely ());
2274 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
2275 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
2276 NULL_RTX, 1);
2277 tem = convert_modes (mode, hmode,
2278 convert_modes (hmode, mode, lo0xlo1, 1), 1);
2280 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
2281 1, OPTAB_WIDEN);
2282 if (tem != res)
2283 emit_move_insn (res, tem);
2284 emit_jump (done_label);
2286 emit_label (both_ops_large);
2288 /* If both operands are large (not sign (!uns) or zero (uns)
2289 extended from hmode), then perform the full multiplication
2290 which will be the result of the operation.
2291 The only cases which don't overflow are for signed multiplication
2292 some cases where both hipart0 and highpart1 are 0 or -1.
2293 For unsigned multiplication when high parts are both non-zero
2294 this overflows always. */
2295 ops.code = MULT_EXPR;
2296 ops.op0 = make_tree (type, op0);
2297 ops.op1 = make_tree (type, op1);
2298 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2299 emit_move_insn (res, tem);
2301 if (!uns)
2303 if (!op0_medium_p)
2305 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
2306 NULL_RTX, 1, OPTAB_WIDEN);
2307 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2308 NULL_RTX, NULL, do_error,
2309 profile_probability::very_unlikely ());
2312 if (!op1_medium_p)
2314 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
2315 NULL_RTX, 1, OPTAB_WIDEN);
2316 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2317 NULL_RTX, NULL, do_error,
2318 profile_probability::very_unlikely ());
2321 /* At this point hipart{0,1} are both in [-1, 0]. If they are
2322 the same, overflow happened if res is non-positive, if they
2323 are different, overflow happened if res is positive. */
2324 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
2325 emit_jump (hipart_different);
2326 else if (op0_sign == 1 || op1_sign == 1)
2327 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
2328 NULL_RTX, NULL, hipart_different,
2329 profile_probability::even ());
2331 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
2332 NULL_RTX, NULL, do_error,
2333 profile_probability::very_unlikely ());
2334 emit_jump (done_label);
2336 emit_label (hipart_different);
2338 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
2339 NULL_RTX, NULL, do_error,
2340 profile_probability::very_unlikely ());
2341 emit_jump (done_label);
2344 emit_label (do_overflow);
2346 /* Overflow, do full multiplication and fallthru into do_error. */
2347 ops.op0 = make_tree (type, op0);
2348 ops.op1 = make_tree (type, op1);
2349 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2350 emit_move_insn (res, tem);
2352 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2353 && targetm.scalar_mode_supported_p (wmode))
2354 /* Even emitting a libcall is better than not detecting overflow
2355 at all. */
2356 goto twoxwider;
2357 else
2359 gcc_assert (!is_ubsan);
2360 ops.code = MULT_EXPR;
2361 ops.type = type;
2362 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2363 emit_jump (done_label);
2367 do_error_label:
2368 emit_label (do_error);
2369 if (is_ubsan)
2371 /* Expand the ubsan builtin call. */
2372 push_temp_slots ();
2373 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
2374 arg0, arg1, datap);
2375 expand_normal (fn);
2376 pop_temp_slots ();
2377 do_pending_stack_adjust ();
2379 else if (lhs)
2380 expand_arith_set_overflow (lhs, target);
2382 /* We're done. */
2383 emit_label (done_label);
2385 /* u1 * u2 -> sr */
2386 if (uns0_p && uns1_p && !unsr_p)
2388 rtx_code_label *all_done_label = gen_label_rtx ();
2389 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2390 NULL, all_done_label, profile_probability::very_likely ());
2391 expand_arith_set_overflow (lhs, target);
2392 emit_label (all_done_label);
2395 /* s1 * u2 -> sr */
2396 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2398 rtx_code_label *all_done_label = gen_label_rtx ();
2399 rtx_code_label *set_noovf = gen_label_rtx ();
2400 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2401 NULL, all_done_label, profile_probability::very_likely ());
2402 expand_arith_set_overflow (lhs, target);
2403 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2404 NULL, set_noovf, profile_probability::very_likely ());
2405 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2406 NULL, all_done_label, profile_probability::very_unlikely ());
2407 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2408 all_done_label, profile_probability::very_unlikely ());
2409 emit_label (set_noovf);
2410 write_complex_part (target, const0_rtx, true, false);
2411 emit_label (all_done_label);
2414 if (lhs)
2416 if (is_ubsan)
2417 expand_ubsan_result_store (target, res);
2418 else
2419 expand_arith_overflow_result_store (lhs, target, mode, res);
2423 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2425 static void
2426 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2427 tree arg0, tree arg1)
2429 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2430 rtx_code_label *loop_lab = NULL;
2431 rtx cntvar = NULL_RTX;
2432 tree cntv = NULL_TREE;
2433 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2434 tree sz = TYPE_SIZE (eltype);
2435 tree data = NULL_TREE;
2436 tree resv = NULL_TREE;
2437 rtx lhsr = NULL_RTX;
2438 rtx resvr = NULL_RTX;
2439 unsigned HOST_WIDE_INT const_cnt = 0;
2440 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2442 if (lhs)
2444 optab op;
2445 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2446 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2447 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2448 optab_default)) == unknown_optab
2449 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2450 == CODE_FOR_nothing))
2452 if (MEM_P (lhsr))
2453 resv = make_tree (TREE_TYPE (lhs), lhsr);
2454 else
2456 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2457 resv = make_tree (TREE_TYPE (lhs), resvr);
2461 if (use_loop_p)
2463 do_pending_stack_adjust ();
2464 loop_lab = gen_label_rtx ();
2465 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2466 cntv = make_tree (sizetype, cntvar);
2467 emit_move_insn (cntvar, const0_rtx);
2468 emit_label (loop_lab);
2470 if (TREE_CODE (arg0) != VECTOR_CST)
2472 rtx arg0r = expand_normal (arg0);
2473 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2475 if (TREE_CODE (arg1) != VECTOR_CST)
2477 rtx arg1r = expand_normal (arg1);
2478 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2480 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2482 tree op0, op1, res = NULL_TREE;
2483 if (use_loop_p)
2485 tree atype = build_array_type_nelts (eltype, cnt);
2486 op0 = uniform_vector_p (arg0);
2487 if (op0 == NULL_TREE)
2489 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2490 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2491 NULL_TREE, NULL_TREE);
2493 op1 = uniform_vector_p (arg1);
2494 if (op1 == NULL_TREE)
2496 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2497 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2498 NULL_TREE, NULL_TREE);
2500 if (resv)
2502 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2503 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2504 NULL_TREE, NULL_TREE);
2507 else
2509 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2510 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2511 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2512 if (resv)
2513 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2514 bitpos);
2516 switch (code)
2518 case PLUS_EXPR:
2519 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2520 false, false, false, true, &data);
2521 break;
2522 case MINUS_EXPR:
2523 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2524 expand_neg_overflow (loc, res, op1, true, &data);
2525 else
2526 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2527 false, false, false, true, &data);
2528 break;
2529 case MULT_EXPR:
2530 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2531 true, &data);
2532 break;
2533 default:
2534 gcc_unreachable ();
2537 if (use_loop_p)
2539 struct separate_ops ops;
2540 ops.code = PLUS_EXPR;
2541 ops.type = TREE_TYPE (cntv);
2542 ops.op0 = cntv;
2543 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2544 ops.op2 = NULL_TREE;
2545 ops.location = loc;
2546 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2547 EXPAND_NORMAL);
2548 if (ret != cntvar)
2549 emit_move_insn (cntvar, ret);
2550 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2551 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2552 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2553 profile_probability::very_likely ());
2555 if (lhs && resv == NULL_TREE)
2557 struct separate_ops ops;
2558 ops.code = code;
2559 ops.type = TREE_TYPE (arg0);
2560 ops.op0 = arg0;
2561 ops.op1 = arg1;
2562 ops.op2 = NULL_TREE;
2563 ops.location = loc;
2564 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2565 EXPAND_NORMAL);
2566 if (ret != lhsr)
2567 emit_move_insn (lhsr, ret);
2569 else if (resvr)
2570 emit_move_insn (lhsr, resvr);
2573 /* Expand UBSAN_CHECK_ADD call STMT. */
2575 static void
2576 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2578 location_t loc = gimple_location (stmt);
2579 tree lhs = gimple_call_lhs (stmt);
2580 tree arg0 = gimple_call_arg (stmt, 0);
2581 tree arg1 = gimple_call_arg (stmt, 1);
2582 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2583 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2584 else
2585 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2586 false, false, false, true, NULL);
2589 /* Expand UBSAN_CHECK_SUB call STMT. */
2591 static void
2592 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2594 location_t loc = gimple_location (stmt);
2595 tree lhs = gimple_call_lhs (stmt);
2596 tree arg0 = gimple_call_arg (stmt, 0);
2597 tree arg1 = gimple_call_arg (stmt, 1);
2598 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2599 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2600 else if (integer_zerop (arg0))
2601 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2602 else
2603 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2604 false, false, false, true, NULL);
2607 /* Expand UBSAN_CHECK_MUL call STMT. */
2609 static void
2610 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2612 location_t loc = gimple_location (stmt);
2613 tree lhs = gimple_call_lhs (stmt);
2614 tree arg0 = gimple_call_arg (stmt, 0);
2615 tree arg1 = gimple_call_arg (stmt, 1);
2616 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2617 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2618 else
2619 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2620 NULL);
2623 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2625 static void
2626 expand_arith_overflow (enum tree_code code, gimple *stmt)
2628 tree lhs = gimple_call_lhs (stmt);
2629 if (lhs == NULL_TREE)
2630 return;
2631 tree arg0 = gimple_call_arg (stmt, 0);
2632 tree arg1 = gimple_call_arg (stmt, 1);
2633 tree type = TREE_TYPE (TREE_TYPE (lhs));
2634 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2635 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2636 int unsr_p = TYPE_UNSIGNED (type);
2637 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2638 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2639 int precres = TYPE_PRECISION (type);
2640 location_t loc = gimple_location (stmt);
2641 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2642 uns0_p = true;
2643 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2644 uns1_p = true;
2645 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2646 prec0 = MIN (prec0, pr);
2647 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2648 prec1 = MIN (prec1, pr);
2650 /* If uns0_p && uns1_p, precop is minimum needed precision
2651 of unsigned type to hold the exact result, otherwise
2652 precop is minimum needed precision of signed type to
2653 hold the exact result. */
2654 int precop;
2655 if (code == MULT_EXPR)
2656 precop = prec0 + prec1 + (uns0_p != uns1_p);
2657 else
2659 if (uns0_p == uns1_p)
2660 precop = MAX (prec0, prec1) + 1;
2661 else if (uns0_p)
2662 precop = MAX (prec0 + 1, prec1) + 1;
2663 else
2664 precop = MAX (prec0, prec1 + 1) + 1;
2666 int orig_precres = precres;
2670 if ((uns0_p && uns1_p)
2671 ? ((precop + !unsr_p) <= precres
2672 /* u1 - u2 -> ur can overflow, no matter what precision
2673 the result has. */
2674 && (code != MINUS_EXPR || !unsr_p))
2675 : (!unsr_p && precop <= precres))
2677 /* The infinity precision result will always fit into result. */
2678 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2679 write_complex_part (target, const0_rtx, true, false);
2680 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2681 struct separate_ops ops;
2682 ops.code = code;
2683 ops.type = type;
2684 ops.op0 = fold_convert_loc (loc, type, arg0);
2685 ops.op1 = fold_convert_loc (loc, type, arg1);
2686 ops.op2 = NULL_TREE;
2687 ops.location = loc;
2688 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2689 expand_arith_overflow_result_store (lhs, target, mode, tem);
2690 return;
2693 /* For operations with low precision, if target doesn't have them, start
2694 with precres widening right away, otherwise do it only if the most
2695 simple cases can't be used. */
2696 const int min_precision = targetm.min_arithmetic_precision ();
2697 if (orig_precres == precres && precres < min_precision)
2699 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2700 && prec1 <= precres)
2701 || ((!uns0_p || !uns1_p) && !unsr_p
2702 && prec0 + uns0_p <= precres
2703 && prec1 + uns1_p <= precres))
2705 arg0 = fold_convert_loc (loc, type, arg0);
2706 arg1 = fold_convert_loc (loc, type, arg1);
2707 switch (code)
2709 case MINUS_EXPR:
2710 if (integer_zerop (arg0) && !unsr_p)
2712 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2713 return;
2715 /* FALLTHRU */
2716 case PLUS_EXPR:
2717 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2718 unsr_p, unsr_p, false, NULL);
2719 return;
2720 case MULT_EXPR:
2721 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2722 unsr_p, unsr_p, false, NULL);
2723 return;
2724 default:
2725 gcc_unreachable ();
2729 /* For sub-word operations, retry with a wider type first. */
2730 if (orig_precres == precres && precop <= BITS_PER_WORD)
2732 int p = MAX (min_precision, precop);
2733 scalar_int_mode m = smallest_int_mode_for_size (p);
2734 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2735 uns0_p && uns1_p
2736 && unsr_p);
2737 p = TYPE_PRECISION (optype);
2738 if (p > precres)
2740 precres = p;
2741 unsr_p = TYPE_UNSIGNED (optype);
2742 type = optype;
2743 continue;
2747 if (prec0 <= precres && prec1 <= precres)
2749 tree types[2];
2750 if (unsr_p)
2752 types[0] = build_nonstandard_integer_type (precres, 0);
2753 types[1] = type;
2755 else
2757 types[0] = type;
2758 types[1] = build_nonstandard_integer_type (precres, 1);
2760 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2761 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2762 if (code != MULT_EXPR)
2763 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2764 uns0_p, uns1_p, false, NULL);
2765 else
2766 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2767 uns0_p, uns1_p, false, NULL);
2768 return;
2771 /* Retry with a wider type. */
2772 if (orig_precres == precres)
2774 int p = MAX (prec0, prec1);
2775 scalar_int_mode m = smallest_int_mode_for_size (p);
2776 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2777 uns0_p && uns1_p
2778 && unsr_p);
2779 p = TYPE_PRECISION (optype);
2780 if (p > precres)
2782 precres = p;
2783 unsr_p = TYPE_UNSIGNED (optype);
2784 type = optype;
2785 continue;
2789 gcc_unreachable ();
2791 while (1);
2794 /* Expand ADD_OVERFLOW STMT. */
2796 static void
2797 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2799 expand_arith_overflow (PLUS_EXPR, stmt);
2802 /* Expand SUB_OVERFLOW STMT. */
2804 static void
2805 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2807 expand_arith_overflow (MINUS_EXPR, stmt);
2810 /* Expand MUL_OVERFLOW STMT. */
2812 static void
2813 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2815 expand_arith_overflow (MULT_EXPR, stmt);
2818 /* Expand UADDC STMT. */
2820 static void
2821 expand_UADDC (internal_fn ifn, gcall *stmt)
2823 tree lhs = gimple_call_lhs (stmt);
2824 tree arg1 = gimple_call_arg (stmt, 0);
2825 tree arg2 = gimple_call_arg (stmt, 1);
2826 tree arg3 = gimple_call_arg (stmt, 2);
2827 tree type = TREE_TYPE (arg1);
2828 machine_mode mode = TYPE_MODE (type);
2829 insn_code icode = optab_handler (ifn == IFN_UADDC
2830 ? uaddc5_optab : usubc5_optab, mode);
2831 rtx op1 = expand_normal (arg1);
2832 rtx op2 = expand_normal (arg2);
2833 rtx op3 = expand_normal (arg3);
2834 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2835 rtx re = gen_reg_rtx (mode);
2836 rtx im = gen_reg_rtx (mode);
2837 class expand_operand ops[5];
2838 create_output_operand (&ops[0], re, mode);
2839 create_output_operand (&ops[1], im, mode);
2840 create_input_operand (&ops[2], op1, mode);
2841 create_input_operand (&ops[3], op2, mode);
2842 create_input_operand (&ops[4], op3, mode);
2843 expand_insn (icode, 5, ops);
2844 write_complex_part (target, re, false, false);
2845 write_complex_part (target, im, true, false);
2848 /* Expand USUBC STMT. */
2850 static void
2851 expand_USUBC (internal_fn ifn, gcall *stmt)
2853 expand_UADDC (ifn, stmt);
2856 /* This should get folded in tree-vectorizer.cc. */
2858 static void
2859 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2861 gcc_unreachable ();
2864 /* This should get folded in tree-vectorizer.cc. */
2866 static void
2867 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2869 gcc_unreachable ();
2872 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2873 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2875 static tree
2876 expand_call_mem_ref (tree type, gcall *stmt, int index)
2878 tree addr = gimple_call_arg (stmt, index);
2879 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2880 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2881 if (TYPE_ALIGN (type) != align)
2882 type = build_aligned_type (type, align);
2884 tree tmp = addr;
2885 if (TREE_CODE (tmp) == SSA_NAME)
2887 gimple *def = SSA_NAME_DEF_STMT (tmp);
2888 if (gimple_assign_single_p (def))
2889 tmp = gimple_assign_rhs1 (def);
2892 if (TREE_CODE (tmp) == ADDR_EXPR)
2894 tree mem = TREE_OPERAND (tmp, 0);
2895 if (TREE_CODE (mem) == TARGET_MEM_REF
2896 && types_compatible_p (TREE_TYPE (mem), type))
2898 tree offset = TMR_OFFSET (mem);
2899 if (type != TREE_TYPE (mem)
2900 || alias_ptr_type != TREE_TYPE (offset)
2901 || !integer_zerop (offset))
2903 mem = copy_node (mem);
2904 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2905 wi::to_poly_wide (offset));
2906 TREE_TYPE (mem) = type;
2908 return mem;
2912 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2915 /* Expand MASK_LOAD{,_LANES}, MASK_LEN_LOAD or LEN_LOAD call STMT using optab
2916 * OPTAB. */
2918 static void
2919 expand_partial_load_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
2921 int i = 0;
2922 class expand_operand ops[5];
2923 tree type, lhs, rhs, maskt;
2924 rtx mem, target;
2925 insn_code icode;
2927 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
2928 lhs = gimple_call_lhs (stmt);
2929 if (lhs == NULL_TREE)
2930 return;
2931 type = TREE_TYPE (lhs);
2932 rhs = expand_call_mem_ref (type, stmt, 0);
2934 if (optab == vec_mask_load_lanes_optab)
2935 icode = get_multi_vector_move (type, optab);
2936 else if (optab == len_load_optab)
2937 icode = direct_optab_handler (optab, TYPE_MODE (type));
2938 else
2939 icode = convert_optab_handler (optab, TYPE_MODE (type),
2940 TYPE_MODE (TREE_TYPE (maskt)));
2942 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2943 gcc_assert (MEM_P (mem));
2944 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2945 create_output_operand (&ops[i++], target, TYPE_MODE (type));
2946 create_fixed_operand (&ops[i++], mem);
2947 i = add_mask_and_len_args (ops, i, stmt);
2948 expand_insn (icode, i, ops);
2950 if (!rtx_equal_p (target, ops[0].value))
2951 emit_move_insn (target, ops[0].value);
2954 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
2955 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2956 #define expand_len_load_optab_fn expand_partial_load_optab_fn
2957 #define expand_mask_len_load_optab_fn expand_partial_load_optab_fn
2959 /* Expand MASK_STORE{,_LANES}, MASK_LEN_STORE or LEN_STORE call STMT using optab
2960 * OPTAB. */
2962 static void
2963 expand_partial_store_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
2965 int i = 0;
2966 class expand_operand ops[5];
2967 tree type, lhs, rhs, maskt;
2968 rtx mem, reg;
2969 insn_code icode;
2971 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
2972 rhs = gimple_call_arg (stmt, internal_fn_stored_value_index (ifn));
2973 type = TREE_TYPE (rhs);
2974 lhs = expand_call_mem_ref (type, stmt, 0);
2976 if (optab == vec_mask_store_lanes_optab)
2977 icode = get_multi_vector_move (type, optab);
2978 else if (optab == len_store_optab)
2979 icode = direct_optab_handler (optab, TYPE_MODE (type));
2980 else
2981 icode = convert_optab_handler (optab, TYPE_MODE (type),
2982 TYPE_MODE (TREE_TYPE (maskt)));
2984 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2985 gcc_assert (MEM_P (mem));
2986 reg = expand_normal (rhs);
2987 create_fixed_operand (&ops[i++], mem);
2988 create_input_operand (&ops[i++], reg, TYPE_MODE (type));
2989 i = add_mask_and_len_args (ops, i, stmt);
2990 expand_insn (icode, i, ops);
2993 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
2994 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2995 #define expand_len_store_optab_fn expand_partial_store_optab_fn
2996 #define expand_mask_len_store_optab_fn expand_partial_store_optab_fn
2998 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
2999 The expansion of STMT happens based on OPTAB table associated. */
3001 static void
3002 expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3004 class expand_operand ops[6];
3005 insn_code icode;
3006 tree lhs = gimple_call_lhs (stmt);
3007 tree op0a = gimple_call_arg (stmt, 0);
3008 tree op0b = gimple_call_arg (stmt, 1);
3009 tree op1 = gimple_call_arg (stmt, 2);
3010 tree op2 = gimple_call_arg (stmt, 3);
3011 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
3013 tree vec_cond_type = TREE_TYPE (lhs);
3014 tree op_mode = TREE_TYPE (op0a);
3015 bool unsignedp = TYPE_UNSIGNED (op_mode);
3017 machine_mode mode = TYPE_MODE (vec_cond_type);
3018 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
3020 icode = convert_optab_handler (optab, mode, cmp_op_mode);
3021 rtx comparison
3022 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
3023 /* vector_compare_rtx legitimizes operands, preserve equality when
3024 expanding op1/op2. */
3025 rtx rtx_op1, rtx_op2;
3026 if (operand_equal_p (op1, op0a))
3027 rtx_op1 = XEXP (comparison, 0);
3028 else if (operand_equal_p (op1, op0b))
3029 rtx_op1 = XEXP (comparison, 1);
3030 else
3031 rtx_op1 = expand_normal (op1);
3032 if (operand_equal_p (op2, op0a))
3033 rtx_op2 = XEXP (comparison, 0);
3034 else if (operand_equal_p (op2, op0b))
3035 rtx_op2 = XEXP (comparison, 1);
3036 else
3037 rtx_op2 = expand_normal (op2);
3039 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3040 create_output_operand (&ops[0], target, mode);
3041 create_input_operand (&ops[1], rtx_op1, mode);
3042 create_input_operand (&ops[2], rtx_op2, mode);
3043 create_fixed_operand (&ops[3], comparison);
3044 create_fixed_operand (&ops[4], XEXP (comparison, 0));
3045 create_fixed_operand (&ops[5], XEXP (comparison, 1));
3046 expand_insn (icode, 6, ops);
3047 if (!rtx_equal_p (ops[0].value, target))
3048 emit_move_insn (target, ops[0].value);
3051 /* Expand VCOND_MASK optab internal function.
3052 The expansion of STMT happens based on OPTAB table associated. */
3054 static void
3055 expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3057 class expand_operand ops[4];
3059 tree lhs = gimple_call_lhs (stmt);
3060 tree op0 = gimple_call_arg (stmt, 0);
3061 tree op1 = gimple_call_arg (stmt, 1);
3062 tree op2 = gimple_call_arg (stmt, 2);
3063 tree vec_cond_type = TREE_TYPE (lhs);
3065 machine_mode mode = TYPE_MODE (vec_cond_type);
3066 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
3067 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
3068 rtx mask, rtx_op1, rtx_op2;
3070 gcc_assert (icode != CODE_FOR_nothing);
3072 mask = expand_normal (op0);
3073 rtx_op1 = expand_normal (op1);
3074 rtx_op2 = expand_normal (op2);
3076 mask = force_reg (mask_mode, mask);
3077 rtx_op1 = force_reg (mode, rtx_op1);
3079 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3080 create_output_operand (&ops[0], target, mode);
3081 create_input_operand (&ops[1], rtx_op1, mode);
3082 create_input_operand (&ops[2], rtx_op2, mode);
3083 create_input_operand (&ops[3], mask, mask_mode);
3084 expand_insn (icode, 4, ops);
3085 if (!rtx_equal_p (ops[0].value, target))
3086 emit_move_insn (target, ops[0].value);
3089 /* Expand VEC_SET internal functions. */
3091 static void
3092 expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3094 tree lhs = gimple_call_lhs (stmt);
3095 tree op0 = gimple_call_arg (stmt, 0);
3096 tree op1 = gimple_call_arg (stmt, 1);
3097 tree op2 = gimple_call_arg (stmt, 2);
3098 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3099 rtx src = expand_normal (op0);
3101 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3102 scalar_mode innermode = GET_MODE_INNER (outermode);
3104 rtx value = expand_normal (op1);
3105 rtx pos = expand_normal (op2);
3107 class expand_operand ops[3];
3108 enum insn_code icode = optab_handler (optab, outermode);
3110 if (icode != CODE_FOR_nothing)
3112 rtx temp = gen_reg_rtx (outermode);
3113 emit_move_insn (temp, src);
3115 create_fixed_operand (&ops[0], temp);
3116 create_input_operand (&ops[1], value, innermode);
3117 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
3118 true);
3119 if (maybe_expand_insn (icode, 3, ops))
3121 emit_move_insn (target, temp);
3122 return;
3125 gcc_unreachable ();
3128 /* Expand VEC_EXTRACT optab internal function. */
3130 static void
3131 expand_vec_extract_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3133 tree lhs = gimple_call_lhs (stmt);
3134 tree op0 = gimple_call_arg (stmt, 0);
3135 tree op1 = gimple_call_arg (stmt, 1);
3137 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3139 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3140 machine_mode extract_mode = TYPE_MODE (TREE_TYPE (lhs));
3142 rtx src = expand_normal (op0);
3143 rtx pos = expand_normal (op1);
3145 class expand_operand ops[3];
3146 enum insn_code icode = convert_optab_handler (optab, outermode,
3147 extract_mode);
3149 if (icode != CODE_FOR_nothing)
3151 create_output_operand (&ops[0], target, extract_mode);
3152 create_input_operand (&ops[1], src, outermode);
3153 create_convert_operand_from (&ops[2], pos,
3154 TYPE_MODE (TREE_TYPE (op1)), true);
3155 if (maybe_expand_insn (icode, 3, ops))
3157 if (!rtx_equal_p (target, ops[0].value))
3158 emit_move_insn (target, ops[0].value);
3159 return;
3162 gcc_unreachable ();
3165 static void
3166 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
3170 static void
3171 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
3173 /* When guessing was done, the hints should be already stripped away. */
3174 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
3176 rtx target;
3177 tree lhs = gimple_call_lhs (stmt);
3178 if (lhs)
3179 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3180 else
3181 target = const0_rtx;
3182 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
3183 if (lhs && val != target)
3184 emit_move_insn (target, val);
3187 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
3188 should never be called. */
3190 static void
3191 expand_VA_ARG (internal_fn, gcall *)
3193 gcc_unreachable ();
3196 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
3197 dummy function should never be called. */
3199 static void
3200 expand_VEC_CONVERT (internal_fn, gcall *)
3202 gcc_unreachable ();
3205 /* Expand IFN_RAWMEMCHAR internal function. */
3207 void
3208 expand_RAWMEMCHR (internal_fn, gcall *stmt)
3210 expand_operand ops[3];
3212 tree lhs = gimple_call_lhs (stmt);
3213 if (!lhs)
3214 return;
3215 machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
3216 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3217 create_output_operand (&ops[0], lhs_rtx, lhs_mode);
3219 tree mem = gimple_call_arg (stmt, 0);
3220 rtx mem_rtx = get_memory_rtx (mem, NULL);
3221 create_fixed_operand (&ops[1], mem_rtx);
3223 tree pattern = gimple_call_arg (stmt, 1);
3224 machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
3225 rtx pattern_rtx = expand_normal (pattern);
3226 create_input_operand (&ops[2], pattern_rtx, mode);
3228 insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
3230 expand_insn (icode, 3, ops);
3231 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3232 emit_move_insn (lhs_rtx, ops[0].value);
3235 /* Expand the IFN_UNIQUE function according to its first argument. */
3237 static void
3238 expand_UNIQUE (internal_fn, gcall *stmt)
3240 rtx pattern = NULL_RTX;
3241 enum ifn_unique_kind kind
3242 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
3244 switch (kind)
3246 default:
3247 gcc_unreachable ();
3249 case IFN_UNIQUE_UNSPEC:
3250 if (targetm.have_unique ())
3251 pattern = targetm.gen_unique ();
3252 break;
3254 case IFN_UNIQUE_OACC_FORK:
3255 case IFN_UNIQUE_OACC_JOIN:
3256 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
3258 tree lhs = gimple_call_lhs (stmt);
3259 rtx target = const0_rtx;
3261 if (lhs)
3262 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3264 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
3265 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
3267 if (kind == IFN_UNIQUE_OACC_FORK)
3268 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
3269 else
3270 pattern = targetm.gen_oacc_join (target, data_dep, axis);
3272 else
3273 gcc_unreachable ();
3274 break;
3277 if (pattern)
3278 emit_insn (pattern);
3281 /* Expand the IFN_DEFERRED_INIT function:
3282 LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
3284 Initialize the LHS with zero/pattern according to its second argument
3285 INIT_TYPE:
3286 if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
3287 if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
3288 to initialize;
3289 The LHS variable is initialized including paddings.
3290 The reasons to choose 0xFE for pattern initialization are:
3291 1. It is a non-canonical virtual address on x86_64, and at the
3292 high end of the i386 kernel address space.
3293 2. It is a very large float value (-1.694739530317379e+38).
3294 3. It is also an unusual number for integers. */
3295 #define INIT_PATTERN_VALUE 0xFE
3296 static void
3297 expand_DEFERRED_INIT (internal_fn, gcall *stmt)
3299 tree lhs = gimple_call_lhs (stmt);
3300 tree var_size = gimple_call_arg (stmt, 0);
3301 enum auto_init_type init_type
3302 = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
3303 bool reg_lhs = true;
3305 tree var_type = TREE_TYPE (lhs);
3306 gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
3308 if (TREE_CODE (lhs) == SSA_NAME)
3309 reg_lhs = true;
3310 else
3312 tree lhs_base = lhs;
3313 while (handled_component_p (lhs_base))
3314 lhs_base = TREE_OPERAND (lhs_base, 0);
3315 reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
3316 || non_mem_decl_p (lhs_base));
3317 /* If this expands to a register and the underlying decl is wrapped in
3318 a MEM_REF that just serves as an access type change expose the decl
3319 if it is of correct size. This avoids a situation as in PR103271
3320 if the target does not support a direct move to the registers mode. */
3321 if (reg_lhs
3322 && TREE_CODE (lhs_base) == MEM_REF
3323 && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
3324 && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
3325 && integer_zerop (TREE_OPERAND (lhs_base, 1))
3326 && tree_fits_uhwi_p (var_size)
3327 && tree_int_cst_equal
3328 (var_size,
3329 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
3331 lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
3332 var_type = TREE_TYPE (lhs);
3336 if (!reg_lhs)
3338 /* If the variable is not in register, expand to a memset
3339 to initialize it. */
3340 mark_addressable (lhs);
3341 tree var_addr = build_fold_addr_expr (lhs);
3343 tree value = (init_type == AUTO_INIT_PATTERN)
3344 ? build_int_cst (integer_type_node,
3345 INIT_PATTERN_VALUE)
3346 : integer_zero_node;
3347 tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
3348 3, var_addr, value, var_size);
3349 /* Expand this memset call. */
3350 expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
3352 else
3354 /* If this variable is in a register use expand_assignment.
3355 For boolean scalars force zero-init. */
3356 tree init;
3357 scalar_int_mode var_mode;
3358 if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
3359 && tree_fits_uhwi_p (var_size)
3360 && (init_type == AUTO_INIT_PATTERN
3361 || !is_gimple_reg_type (var_type))
3362 && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
3363 0).exists (&var_mode)
3364 && have_insn_for (SET, var_mode))
3366 unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
3367 unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
3368 memset (buf, (init_type == AUTO_INIT_PATTERN
3369 ? INIT_PATTERN_VALUE : 0), total_bytes);
3370 tree itype = build_nonstandard_integer_type
3371 (total_bytes * BITS_PER_UNIT, 1);
3372 wide_int w = wi::from_buffer (buf, total_bytes);
3373 init = wide_int_to_tree (itype, w);
3374 /* Pun the LHS to make sure its type has constant size
3375 unless it is an SSA name where that's already known. */
3376 if (TREE_CODE (lhs) != SSA_NAME)
3377 lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
3378 else
3379 init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
3381 else
3382 /* Use zero-init also for variable-length sizes. */
3383 init = build_zero_cst (var_type);
3385 expand_assignment (lhs, init, false);
3389 /* The size of an OpenACC compute dimension. */
3391 static void
3392 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
3394 tree lhs = gimple_call_lhs (stmt);
3396 if (!lhs)
3397 return;
3399 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3400 if (targetm.have_oacc_dim_size ())
3402 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3403 VOIDmode, EXPAND_NORMAL);
3404 emit_insn (targetm.gen_oacc_dim_size (target, dim));
3406 else
3407 emit_move_insn (target, GEN_INT (1));
3410 /* The position of an OpenACC execution engine along one compute axis. */
3412 static void
3413 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
3415 tree lhs = gimple_call_lhs (stmt);
3417 if (!lhs)
3418 return;
3420 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3421 if (targetm.have_oacc_dim_pos ())
3423 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3424 VOIDmode, EXPAND_NORMAL);
3425 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
3427 else
3428 emit_move_insn (target, const0_rtx);
3431 /* This is expanded by oacc_device_lower pass. */
3433 static void
3434 expand_GOACC_LOOP (internal_fn, gcall *)
3436 gcc_unreachable ();
3439 /* This is expanded by oacc_device_lower pass. */
3441 static void
3442 expand_GOACC_REDUCTION (internal_fn, gcall *)
3444 gcc_unreachable ();
3447 /* This is expanded by oacc_device_lower pass. */
3449 static void
3450 expand_GOACC_TILE (internal_fn, gcall *)
3452 gcc_unreachable ();
3455 /* Set errno to EDOM. */
3457 static void
3458 expand_SET_EDOM (internal_fn, gcall *)
3460 #ifdef TARGET_EDOM
3461 #ifdef GEN_ERRNO_RTX
3462 rtx errno_rtx = GEN_ERRNO_RTX;
3463 #else
3464 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
3465 #endif
3466 emit_move_insn (errno_rtx,
3467 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
3468 #else
3469 gcc_unreachable ();
3470 #endif
3473 /* Expand atomic bit test and set. */
3475 static void
3476 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
3478 expand_ifn_atomic_bit_test_and (call);
3481 /* Expand atomic bit test and complement. */
3483 static void
3484 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
3486 expand_ifn_atomic_bit_test_and (call);
3489 /* Expand atomic bit test and reset. */
3491 static void
3492 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
3494 expand_ifn_atomic_bit_test_and (call);
3497 /* Expand atomic bit test and set. */
3499 static void
3500 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
3502 expand_ifn_atomic_compare_exchange (call);
3505 /* Expand atomic add fetch and cmp with 0. */
3507 static void
3508 expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
3510 expand_ifn_atomic_op_fetch_cmp_0 (call);
3513 /* Expand atomic sub fetch and cmp with 0. */
3515 static void
3516 expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
3518 expand_ifn_atomic_op_fetch_cmp_0 (call);
3521 /* Expand atomic and fetch and cmp with 0. */
3523 static void
3524 expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
3526 expand_ifn_atomic_op_fetch_cmp_0 (call);
3529 /* Expand atomic or fetch and cmp with 0. */
3531 static void
3532 expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
3534 expand_ifn_atomic_op_fetch_cmp_0 (call);
3537 /* Expand atomic xor fetch and cmp with 0. */
3539 static void
3540 expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
3542 expand_ifn_atomic_op_fetch_cmp_0 (call);
3545 /* Expand LAUNDER to assignment, lhs = arg0. */
3547 static void
3548 expand_LAUNDER (internal_fn, gcall *call)
3550 tree lhs = gimple_call_lhs (call);
3552 if (!lhs)
3553 return;
3555 expand_assignment (lhs, gimple_call_arg (call, 0), false);
3558 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
3560 static void
3561 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3563 internal_fn ifn = gimple_call_internal_fn (stmt);
3564 int rhs_index = internal_fn_stored_value_index (ifn);
3565 tree base = gimple_call_arg (stmt, 0);
3566 tree offset = gimple_call_arg (stmt, 1);
3567 tree scale = gimple_call_arg (stmt, 2);
3568 tree rhs = gimple_call_arg (stmt, rhs_index);
3570 rtx base_rtx = expand_normal (base);
3571 rtx offset_rtx = expand_normal (offset);
3572 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3573 rtx rhs_rtx = expand_normal (rhs);
3575 class expand_operand ops[8];
3576 int i = 0;
3577 create_address_operand (&ops[i++], base_rtx);
3578 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3579 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3580 create_integer_operand (&ops[i++], scale_int);
3581 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
3582 i = add_mask_and_len_args (ops, i, stmt);
3584 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
3585 TYPE_MODE (TREE_TYPE (offset)));
3586 expand_insn (icode, i, ops);
3589 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
3591 static void
3592 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3594 tree lhs = gimple_call_lhs (stmt);
3595 tree base = gimple_call_arg (stmt, 0);
3596 tree offset = gimple_call_arg (stmt, 1);
3597 tree scale = gimple_call_arg (stmt, 2);
3599 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3600 rtx base_rtx = expand_normal (base);
3601 rtx offset_rtx = expand_normal (offset);
3602 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3604 int i = 0;
3605 class expand_operand ops[8];
3606 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
3607 create_address_operand (&ops[i++], base_rtx);
3608 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3609 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3610 create_integer_operand (&ops[i++], scale_int);
3611 i = add_mask_and_len_args (ops, i, stmt);
3612 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
3613 TYPE_MODE (TREE_TYPE (offset)));
3614 expand_insn (icode, i, ops);
3615 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3616 emit_move_insn (lhs_rtx, ops[0].value);
3619 /* Helper for expand_DIVMOD. Return true if the sequence starting with
3620 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
3622 static bool
3623 contains_call_div_mod (rtx_insn *insn)
3625 subrtx_iterator::array_type array;
3626 for (; insn; insn = NEXT_INSN (insn))
3627 if (CALL_P (insn))
3628 return true;
3629 else if (INSN_P (insn))
3630 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3631 switch (GET_CODE (*iter))
3633 case CALL:
3634 case DIV:
3635 case UDIV:
3636 case MOD:
3637 case UMOD:
3638 return true;
3639 default:
3640 break;
3642 return false;
3645 /* Expand DIVMOD() using:
3646 a) optab handler for udivmod/sdivmod if it is available.
3647 b) If optab_handler doesn't exist, generate call to
3648 target-specific divmod libfunc. */
3650 static void
3651 expand_DIVMOD (internal_fn, gcall *call_stmt)
3653 tree lhs = gimple_call_lhs (call_stmt);
3654 tree arg0 = gimple_call_arg (call_stmt, 0);
3655 tree arg1 = gimple_call_arg (call_stmt, 1);
3657 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3658 tree type = TREE_TYPE (TREE_TYPE (lhs));
3659 machine_mode mode = TYPE_MODE (type);
3660 bool unsignedp = TYPE_UNSIGNED (type);
3661 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3663 rtx op0 = expand_normal (arg0);
3664 rtx op1 = expand_normal (arg1);
3665 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3667 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3668 rtx_insn *insns = NULL;
3670 if (TREE_CODE (arg1) == INTEGER_CST)
3672 /* For DIVMOD by integral constants, there could be efficient code
3673 expanded inline e.g. using shifts and plus/minus. Try to expand
3674 the division and modulo and if it emits any library calls or any
3675 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3676 divmod libcall. */
3677 scalar_int_mode int_mode;
3678 if (remainder == NULL_RTX
3679 && optimize
3680 && CONST_INT_P (op1)
3681 && !pow2p_hwi (INTVAL (op1))
3682 && is_int_mode (TYPE_MODE (type), &int_mode)
3683 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
3684 && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
3685 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
3686 && optimize_insn_for_speed_p ())
3688 rtx_insn *last = get_last_insn ();
3689 remainder = NULL_RTX;
3690 quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
3691 TYPE_UNSIGNED (type));
3692 if (quotient != NULL_RTX)
3694 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
3696 rtx_insn *move = emit_move_insn (quotient, quotient);
3697 set_dst_reg_note (move, REG_EQUAL,
3698 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3699 ? UDIV : DIV, int_mode,
3700 copy_rtx (op0), op1),
3701 quotient);
3702 move = emit_move_insn (remainder, remainder);
3703 set_dst_reg_note (move, REG_EQUAL,
3704 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3705 ? UMOD : MOD, int_mode,
3706 copy_rtx (op0), op1),
3707 quotient);
3710 else
3711 delete_insns_since (last);
3714 if (remainder == NULL_RTX)
3716 struct separate_ops ops;
3717 ops.code = TRUNC_DIV_EXPR;
3718 ops.type = type;
3719 ops.op0 = make_tree (ops.type, op0);
3720 ops.op1 = arg1;
3721 ops.op2 = NULL_TREE;
3722 ops.location = gimple_location (call_stmt);
3723 start_sequence ();
3724 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3725 if (contains_call_div_mod (get_insns ()))
3726 quotient = NULL_RTX;
3727 else
3729 ops.code = TRUNC_MOD_EXPR;
3730 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
3731 EXPAND_NORMAL);
3732 if (contains_call_div_mod (get_insns ()))
3733 remainder = NULL_RTX;
3735 if (remainder)
3736 insns = get_insns ();
3737 end_sequence ();
3741 if (remainder)
3742 emit_insn (insns);
3744 /* Check if optab_handler exists for divmod_optab for given mode. */
3745 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
3747 quotient = gen_reg_rtx (mode);
3748 remainder = gen_reg_rtx (mode);
3749 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3752 /* Generate call to divmod libfunc if it exists. */
3753 else if (rtx libfunc = optab_libfunc (tab, mode))
3754 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3755 &quotient, &remainder);
3757 else
3758 gcc_unreachable ();
3760 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3761 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3762 make_tree (TREE_TYPE (arg0), quotient),
3763 make_tree (TREE_TYPE (arg1), remainder)),
3764 target, VOIDmode, EXPAND_NORMAL);
3767 /* Expand a NOP. */
3769 static void
3770 expand_NOP (internal_fn, gcall *)
3772 /* Nothing. But it shouldn't really prevail. */
3775 /* Coroutines, all should have been processed at this stage. */
3777 static void
3778 expand_CO_FRAME (internal_fn, gcall *)
3780 gcc_unreachable ();
3783 static void
3784 expand_CO_YIELD (internal_fn, gcall *)
3786 gcc_unreachable ();
3789 static void
3790 expand_CO_SUSPN (internal_fn, gcall *)
3792 gcc_unreachable ();
3795 static void
3796 expand_CO_ACTOR (internal_fn, gcall *)
3798 gcc_unreachable ();
3801 /* Expand a call to FN using the operands in STMT. FN has a single
3802 output operand and NARGS input operands. */
3804 static void
3805 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3806 unsigned int nargs)
3808 tree_pair types = direct_internal_fn_types (fn, stmt);
3809 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3810 expand_fn_using_insn (stmt, icode, 1, nargs);
3813 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3815 static void
3816 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3818 expand_operand ops[4];
3819 tree rhs_type[2];
3821 tree lhs = gimple_call_lhs (stmt);
3822 tree lhs_type = TREE_TYPE (lhs);
3823 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3824 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3826 for (unsigned int i = 0; i < 2; ++i)
3828 tree rhs = gimple_call_arg (stmt, i);
3829 rhs_type[i] = TREE_TYPE (rhs);
3830 rtx rhs_rtx = expand_normal (rhs);
3831 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3834 int opcnt;
3835 if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
3837 /* When the mask is an integer mode the exact vector length may not
3838 be clear to the backend, so we pass it in operand[3].
3839 Use the vector in arg2 for the most reliable intended size. */
3840 tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
3841 create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
3842 opcnt = 4;
3844 else
3845 /* The mask has a vector type so the length operand is unnecessary. */
3846 opcnt = 3;
3848 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3849 TYPE_MODE (lhs_type));
3851 expand_insn (icode, opcnt, ops);
3852 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3853 emit_move_insn (lhs_rtx, ops[0].value);
3856 /* Expand a call to a convert-like optab using the operands in STMT.
3857 FN has a single output operand and NARGS input operands. */
3859 static void
3860 expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
3861 unsigned int nargs)
3863 tree_pair types = direct_internal_fn_types (fn, stmt);
3864 insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
3865 TYPE_MODE (types.second));
3866 expand_fn_using_insn (stmt, icode, 1, nargs);
3869 /* Expanders for optabs that can use expand_direct_optab_fn. */
3871 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3872 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3874 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3875 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3877 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3878 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3880 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3881 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3883 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3884 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3886 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3887 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3889 #define expand_cond_len_unary_optab_fn(FN, STMT, OPTAB) \
3890 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3892 #define expand_cond_len_binary_optab_fn(FN, STMT, OPTAB) \
3893 expand_direct_optab_fn (FN, STMT, OPTAB, 6)
3895 #define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
3896 expand_direct_optab_fn (FN, STMT, OPTAB, 7)
3898 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3899 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3901 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3902 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3904 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3905 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3907 #define expand_mask_len_fold_left_optab_fn(FN, STMT, OPTAB) \
3908 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3910 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3911 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3913 /* Expanders for optabs that can use expand_convert_optab_fn. */
3915 #define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
3916 expand_convert_optab_fn (FN, STMT, OPTAB, 1)
3918 /* RETURN_TYPE and ARGS are a return type and argument list that are
3919 in principle compatible with FN (which satisfies direct_internal_fn_p).
3920 Return the types that should be used to determine whether the
3921 target supports FN. */
3923 tree_pair
3924 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3926 const direct_internal_fn_info &info = direct_internal_fn (fn);
3927 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3928 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3929 return tree_pair (type0, type1);
3932 /* CALL is a call whose return type and arguments are in principle
3933 compatible with FN (which satisfies direct_internal_fn_p). Return the
3934 types that should be used to determine whether the target supports FN. */
3936 tree_pair
3937 direct_internal_fn_types (internal_fn fn, gcall *call)
3939 const direct_internal_fn_info &info = direct_internal_fn (fn);
3940 tree op0 = (info.type0 < 0
3941 ? gimple_call_lhs (call)
3942 : gimple_call_arg (call, info.type0));
3943 tree op1 = (info.type1 < 0
3944 ? gimple_call_lhs (call)
3945 : gimple_call_arg (call, info.type1));
3946 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3949 /* Return true if OPTAB is supported for TYPES (whose modes should be
3950 the same) when the optimization type is OPT_TYPE. Used for simple
3951 direct optabs. */
3953 static bool
3954 direct_optab_supported_p (direct_optab optab, tree_pair types,
3955 optimization_type opt_type)
3957 machine_mode mode = TYPE_MODE (types.first);
3958 gcc_checking_assert (mode == TYPE_MODE (types.second));
3959 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3962 /* Return true if OPTAB is supported for TYPES, where the first type
3963 is the destination and the second type is the source. Used for
3964 convert optabs. */
3966 static bool
3967 convert_optab_supported_p (convert_optab optab, tree_pair types,
3968 optimization_type opt_type)
3970 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3971 TYPE_MODE (types.second), opt_type)
3972 != CODE_FOR_nothing);
3975 /* Return true if load/store lanes optab OPTAB is supported for
3976 array type TYPES.first when the optimization type is OPT_TYPE. */
3978 static bool
3979 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3980 optimization_type opt_type)
3982 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3983 machine_mode imode = TYPE_MODE (types.first);
3984 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3985 return (convert_optab_handler (optab, imode, vmode, opt_type)
3986 != CODE_FOR_nothing);
3989 #define direct_unary_optab_supported_p direct_optab_supported_p
3990 #define direct_unary_convert_optab_supported_p convert_optab_supported_p
3991 #define direct_binary_optab_supported_p direct_optab_supported_p
3992 #define direct_ternary_optab_supported_p direct_optab_supported_p
3993 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3994 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3995 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
3996 #define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
3997 #define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
3998 #define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
3999 #define direct_mask_load_optab_supported_p convert_optab_supported_p
4000 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
4001 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
4002 #define direct_gather_load_optab_supported_p convert_optab_supported_p
4003 #define direct_len_load_optab_supported_p direct_optab_supported_p
4004 #define direct_mask_len_load_optab_supported_p convert_optab_supported_p
4005 #define direct_mask_store_optab_supported_p convert_optab_supported_p
4006 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
4007 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
4008 #define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
4009 #define direct_vec_cond_optab_supported_p convert_optab_supported_p
4010 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
4011 #define direct_len_store_optab_supported_p direct_optab_supported_p
4012 #define direct_mask_len_store_optab_supported_p convert_optab_supported_p
4013 #define direct_while_optab_supported_p convert_optab_supported_p
4014 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
4015 #define direct_fold_left_optab_supported_p direct_optab_supported_p
4016 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
4017 #define direct_mask_len_fold_left_optab_supported_p direct_optab_supported_p
4018 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
4019 #define direct_vec_set_optab_supported_p direct_optab_supported_p
4020 #define direct_vec_extract_optab_supported_p direct_optab_supported_p
4022 /* Return the optab used by internal function FN. */
4024 optab
4025 direct_internal_fn_optab (internal_fn fn, tree_pair types)
4027 switch (fn)
4029 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4030 case IFN_##CODE: break;
4031 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4032 case IFN_##CODE: return OPTAB##_optab;
4033 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4034 UNSIGNED_OPTAB, TYPE) \
4035 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
4036 ? UNSIGNED_OPTAB ## _optab \
4037 : SIGNED_OPTAB ## _optab);
4038 #include "internal-fn.def"
4040 case IFN_LAST:
4041 break;
4043 gcc_unreachable ();
4046 /* Return the optab used by internal function FN. */
4048 static optab
4049 direct_internal_fn_optab (internal_fn fn)
4051 switch (fn)
4053 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4054 case IFN_##CODE: break;
4055 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4056 case IFN_##CODE: return OPTAB##_optab;
4057 #include "internal-fn.def"
4059 case IFN_LAST:
4060 break;
4062 gcc_unreachable ();
4065 /* Return true if FN is supported for the types in TYPES when the
4066 optimization type is OPT_TYPE. The types are those associated with
4067 the "type0" and "type1" fields of FN's direct_internal_fn_info
4068 structure. */
4070 bool
4071 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
4072 optimization_type opt_type)
4074 switch (fn)
4076 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4077 case IFN_##CODE: break;
4078 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4079 case IFN_##CODE: \
4080 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
4081 opt_type);
4082 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4083 UNSIGNED_OPTAB, TYPE) \
4084 case IFN_##CODE: \
4086 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
4087 ? UNSIGNED_OPTAB ## _optab \
4088 : SIGNED_OPTAB ## _optab); \
4089 return direct_##TYPE##_optab_supported_p (which_optab, types, \
4090 opt_type); \
4092 #include "internal-fn.def"
4094 case IFN_LAST:
4095 break;
4097 gcc_unreachable ();
4100 /* Return true if FN is supported for type TYPE when the optimization
4101 type is OPT_TYPE. The caller knows that the "type0" and "type1"
4102 fields of FN's direct_internal_fn_info structure are the same. */
4104 bool
4105 direct_internal_fn_supported_p (internal_fn fn, tree type,
4106 optimization_type opt_type)
4108 const direct_internal_fn_info &info = direct_internal_fn (fn);
4109 gcc_checking_assert (info.type0 == info.type1);
4110 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
4113 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
4114 given that STMT is a call to a direct internal function. */
4116 bool
4117 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
4119 internal_fn fn = gimple_call_internal_fn (stmt);
4120 tree_pair types = direct_internal_fn_types (fn, stmt);
4121 return direct_internal_fn_supported_p (fn, types, opt_type);
4124 /* Return true if FN is a binary operation and if FN is commutative. */
4126 bool
4127 commutative_binary_fn_p (internal_fn fn)
4129 switch (fn)
4131 case IFN_AVG_FLOOR:
4132 case IFN_AVG_CEIL:
4133 case IFN_MULH:
4134 case IFN_MULHS:
4135 case IFN_MULHRS:
4136 case IFN_FMIN:
4137 case IFN_FMAX:
4138 case IFN_COMPLEX_MUL:
4139 case IFN_UBSAN_CHECK_ADD:
4140 case IFN_UBSAN_CHECK_MUL:
4141 case IFN_ADD_OVERFLOW:
4142 case IFN_MUL_OVERFLOW:
4143 case IFN_VEC_WIDEN_PLUS:
4144 case IFN_VEC_WIDEN_PLUS_LO:
4145 case IFN_VEC_WIDEN_PLUS_HI:
4146 case IFN_VEC_WIDEN_PLUS_EVEN:
4147 case IFN_VEC_WIDEN_PLUS_ODD:
4148 return true;
4150 default:
4151 return false;
4155 /* Return true if FN is a ternary operation and if its first two arguments
4156 are commutative. */
4158 bool
4159 commutative_ternary_fn_p (internal_fn fn)
4161 switch (fn)
4163 case IFN_FMA:
4164 case IFN_FMS:
4165 case IFN_FNMA:
4166 case IFN_FNMS:
4167 case IFN_UADDC:
4168 return true;
4170 default:
4171 return false;
4175 /* Return true if FN is an associative binary operation. */
4177 bool
4178 associative_binary_fn_p (internal_fn fn)
4180 switch (fn)
4182 case IFN_FMIN:
4183 case IFN_FMAX:
4184 return true;
4186 default:
4187 return false;
4191 /* If FN is commutative in two consecutive arguments, return the
4192 index of the first, otherwise return -1. */
4195 first_commutative_argument (internal_fn fn)
4197 switch (fn)
4199 case IFN_COND_ADD:
4200 case IFN_COND_MUL:
4201 case IFN_COND_MIN:
4202 case IFN_COND_MAX:
4203 case IFN_COND_FMIN:
4204 case IFN_COND_FMAX:
4205 case IFN_COND_AND:
4206 case IFN_COND_IOR:
4207 case IFN_COND_XOR:
4208 case IFN_COND_FMA:
4209 case IFN_COND_FMS:
4210 case IFN_COND_FNMA:
4211 case IFN_COND_FNMS:
4212 case IFN_COND_LEN_ADD:
4213 case IFN_COND_LEN_MUL:
4214 case IFN_COND_LEN_MIN:
4215 case IFN_COND_LEN_MAX:
4216 case IFN_COND_LEN_FMIN:
4217 case IFN_COND_LEN_FMAX:
4218 case IFN_COND_LEN_AND:
4219 case IFN_COND_LEN_IOR:
4220 case IFN_COND_LEN_XOR:
4221 case IFN_COND_LEN_FMA:
4222 case IFN_COND_LEN_FMS:
4223 case IFN_COND_LEN_FNMA:
4224 case IFN_COND_LEN_FNMS:
4225 return 1;
4227 default:
4228 if (commutative_binary_fn_p (fn)
4229 || commutative_ternary_fn_p (fn))
4230 return 0;
4231 return -1;
4235 /* Return true if this CODE describes an internal_fn that returns a vector with
4236 elements twice as wide as the element size of the input vectors. */
4238 bool
4239 widening_fn_p (code_helper code)
4241 if (!code.is_fn_code ())
4242 return false;
4244 if (!internal_fn_p ((combined_fn) code))
4245 return false;
4247 internal_fn fn = as_internal_fn ((combined_fn) code);
4248 switch (fn)
4250 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4251 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
4252 case IFN_##NAME: \
4253 case IFN_##NAME##_HI: \
4254 case IFN_##NAME##_LO: \
4255 case IFN_##NAME##_EVEN: \
4256 case IFN_##NAME##_ODD: \
4257 return true;
4258 #include "internal-fn.def"
4259 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4261 default:
4262 return false;
4266 /* Return true if IFN_SET_EDOM is supported. */
4268 bool
4269 set_edom_supported_p (void)
4271 #ifdef TARGET_EDOM
4272 return true;
4273 #else
4274 return false;
4275 #endif
4278 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4279 static void \
4280 expand_##CODE (internal_fn fn, gcall *stmt) \
4282 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
4284 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4285 UNSIGNED_OPTAB, TYPE) \
4286 static void \
4287 expand_##CODE (internal_fn fn, gcall *stmt) \
4289 tree_pair types = direct_internal_fn_types (fn, stmt); \
4290 optab which_optab = direct_internal_fn_optab (fn, types); \
4291 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
4293 #include "internal-fn.def"
4294 #undef DEF_INTERNAL_OPTAB_FN
4295 #undef DEF_INTERNAL_SIGNED_OPTAB_FN
4297 /* Routines to expand each internal function, indexed by function number.
4298 Each routine has the prototype:
4300 expand_<NAME> (gcall *stmt)
4302 where STMT is the statement that performs the call. */
4303 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
4305 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
4306 #include "internal-fn.def"
4310 /* Invoke T(CODE, SUFFIX) for each conditional function IFN_COND_##SUFFIX
4311 that maps to a tree code CODE. There is also an IFN_COND_LEN_##SUFFIX
4312 for each such IFN_COND_##SUFFIX. */
4313 #define FOR_EACH_CODE_MAPPING(T) \
4314 T (PLUS_EXPR, ADD) \
4315 T (MINUS_EXPR, SUB) \
4316 T (MULT_EXPR, MUL) \
4317 T (TRUNC_DIV_EXPR, DIV) \
4318 T (TRUNC_MOD_EXPR, MOD) \
4319 T (RDIV_EXPR, RDIV) \
4320 T (MIN_EXPR, MIN) \
4321 T (MAX_EXPR, MAX) \
4322 T (BIT_AND_EXPR, AND) \
4323 T (BIT_IOR_EXPR, IOR) \
4324 T (BIT_XOR_EXPR, XOR) \
4325 T (LSHIFT_EXPR, SHL) \
4326 T (RSHIFT_EXPR, SHR) \
4327 T (NEGATE_EXPR, NEG)
4329 /* Return a function that only performs CODE when a certain condition is met
4330 and that uses a given fallback value otherwise. For example, if CODE is
4331 a binary operation associated with conditional function FN:
4333 LHS = FN (COND, A, B, ELSE)
4335 is equivalent to the C expression:
4337 LHS = COND ? A CODE B : ELSE;
4339 operating elementwise if the operands are vectors.
4341 Return IFN_LAST if no such function exists. */
4343 internal_fn
4344 get_conditional_internal_fn (tree_code code)
4346 switch (code)
4348 #define CASE(CODE, IFN) case CODE: return IFN_COND_##IFN;
4349 FOR_EACH_CODE_MAPPING(CASE)
4350 #undef CASE
4351 default:
4352 return IFN_LAST;
4356 /* If IFN implements the conditional form of a tree code, return that
4357 tree code, otherwise return ERROR_MARK. */
4359 tree_code
4360 conditional_internal_fn_code (internal_fn ifn)
4362 switch (ifn)
4364 #define CASE(CODE, IFN) \
4365 case IFN_COND_##IFN: \
4366 case IFN_COND_LEN_##IFN: \
4367 return CODE;
4368 FOR_EACH_CODE_MAPPING (CASE)
4369 #undef CASE
4370 default:
4371 return ERROR_MARK;
4375 /* Like get_conditional_internal_fn, but return a function that
4376 additionally restricts the operation to the leading elements
4377 of a vector. The number of elements to process is given by a length
4378 and bias pair, as for IFN_LOAD_LEN. The values of the remaining
4379 elements are taken from the fallback ("else") argument.
4381 For example, if CODE is a binary operation associated with FN:
4383 LHS = FN (COND, A, B, ELSE, LEN, BIAS)
4385 is equivalent to the C code:
4387 for (int i = 0; i < NUNITS; i++)
4389 if (i < LEN + BIAS && COND[i])
4390 LHS[i] = A[i] CODE B[i];
4391 else
4392 LHS[i] = ELSE[i];
4396 internal_fn
4397 get_conditional_len_internal_fn (tree_code code)
4399 switch (code)
4401 #define CASE(CODE, IFN) case CODE: return IFN_COND_LEN_##IFN;
4402 FOR_EACH_CODE_MAPPING(CASE)
4403 #undef CASE
4404 default:
4405 return IFN_LAST;
4409 /* Invoke T(IFN) for each internal function IFN that also has an
4410 IFN_COND_* form. */
4411 #define FOR_EACH_COND_FN_PAIR(T) \
4412 T (FMAX) \
4413 T (FMIN) \
4414 T (FMA) \
4415 T (FMS) \
4416 T (FNMA) \
4417 T (FNMS)
4419 /* Return a function that only performs internal function FN when a
4420 certain condition is met and that uses a given fallback value otherwise.
4421 In other words, the returned function FN' is such that:
4423 LHS = FN' (COND, A1, ... An, ELSE)
4425 is equivalent to the C expression:
4427 LHS = COND ? FN (A1, ..., An) : ELSE;
4429 operating elementwise if the operands are vectors.
4431 Return IFN_LAST if no such function exists. */
4433 internal_fn
4434 get_conditional_internal_fn (internal_fn fn)
4436 switch (fn)
4438 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
4439 FOR_EACH_COND_FN_PAIR(CASE)
4440 #undef CASE
4441 default:
4442 return IFN_LAST;
4446 /* If IFN implements the conditional form of an unconditional internal
4447 function, return that unconditional function, otherwise return IFN_LAST. */
4449 internal_fn
4450 get_unconditional_internal_fn (internal_fn ifn)
4452 switch (ifn)
4454 #define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
4455 FOR_EACH_COND_FN_PAIR(CASE)
4456 #undef CASE
4457 default:
4458 return IFN_LAST;
4462 /* Return true if STMT can be interpreted as a conditional tree code
4463 operation of the form:
4465 LHS = COND ? OP (RHS1, ...) : ELSE;
4467 operating elementwise if the operands are vectors. This includes
4468 the case of an all-true COND, so that the operation always happens.
4470 There is an alternative approach to interpret the STMT when the operands
4471 are vectors which is the operation predicated by both conditional mask
4472 and loop control length, the equivalent C code:
4474 for (int i = 0; i < NUNTIS; i++)
4476 if (i < LEN + BIAS && COND[i])
4477 LHS[i] = A[i] CODE B[i];
4478 else
4479 LHS[i] = ELSE[i];
4482 When returning true, set:
4484 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
4485 is known to be all-true
4486 - *CODE_OUT to the tree code
4487 - OPS[I] to operand I of *CODE_OUT
4488 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
4489 condition is known to be all true.
4490 - *LEN to the len argument if it COND_LEN_* operations or to NULL_TREE.
4491 - *BIAS to the bias argument if it COND_LEN_* operations or to NULL_TREE. */
4493 bool
4494 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
4495 tree_code *code_out,
4496 tree (&ops)[3], tree *else_out,
4497 tree *len, tree *bias)
4499 *len = NULL_TREE;
4500 *bias = NULL_TREE;
4501 if (gassign *assign = dyn_cast <gassign *> (stmt))
4503 *cond_out = NULL_TREE;
4504 *code_out = gimple_assign_rhs_code (assign);
4505 ops[0] = gimple_assign_rhs1 (assign);
4506 ops[1] = gimple_assign_rhs2 (assign);
4507 ops[2] = gimple_assign_rhs3 (assign);
4508 *else_out = NULL_TREE;
4509 return true;
4511 if (gcall *call = dyn_cast <gcall *> (stmt))
4512 if (gimple_call_internal_p (call))
4514 internal_fn ifn = gimple_call_internal_fn (call);
4515 tree_code code = conditional_internal_fn_code (ifn);
4516 int len_index = internal_fn_len_index (ifn);
4517 int cond_nargs = len_index >= 0 ? 4 : 2;
4518 if (code != ERROR_MARK)
4520 *cond_out = gimple_call_arg (call, 0);
4521 *code_out = code;
4522 unsigned int nops = gimple_call_num_args (call) - cond_nargs;
4523 for (unsigned int i = 0; i < 3; ++i)
4524 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
4525 *else_out = gimple_call_arg (call, nops + 1);
4526 if (len_index < 0)
4528 if (integer_truep (*cond_out))
4530 *cond_out = NULL_TREE;
4531 *else_out = NULL_TREE;
4534 else
4536 *len = gimple_call_arg (call, len_index);
4537 *bias = gimple_call_arg (call, len_index + 1);
4539 return true;
4542 return false;
4545 /* Return true if IFN is some form of load from memory. */
4547 bool
4548 internal_load_fn_p (internal_fn fn)
4550 switch (fn)
4552 case IFN_MASK_LOAD:
4553 case IFN_LOAD_LANES:
4554 case IFN_MASK_LOAD_LANES:
4555 case IFN_GATHER_LOAD:
4556 case IFN_MASK_GATHER_LOAD:
4557 case IFN_MASK_LEN_GATHER_LOAD:
4558 case IFN_LEN_LOAD:
4559 case IFN_MASK_LEN_LOAD:
4560 return true;
4562 default:
4563 return false;
4567 /* Return true if IFN is some form of store to memory. */
4569 bool
4570 internal_store_fn_p (internal_fn fn)
4572 switch (fn)
4574 case IFN_MASK_STORE:
4575 case IFN_STORE_LANES:
4576 case IFN_MASK_STORE_LANES:
4577 case IFN_SCATTER_STORE:
4578 case IFN_MASK_SCATTER_STORE:
4579 case IFN_MASK_LEN_SCATTER_STORE:
4580 case IFN_LEN_STORE:
4581 case IFN_MASK_LEN_STORE:
4582 return true;
4584 default:
4585 return false;
4589 /* Return true if IFN is some form of gather load or scatter store. */
4591 bool
4592 internal_gather_scatter_fn_p (internal_fn fn)
4594 switch (fn)
4596 case IFN_GATHER_LOAD:
4597 case IFN_MASK_GATHER_LOAD:
4598 case IFN_MASK_LEN_GATHER_LOAD:
4599 case IFN_SCATTER_STORE:
4600 case IFN_MASK_SCATTER_STORE:
4601 case IFN_MASK_LEN_SCATTER_STORE:
4602 return true;
4604 default:
4605 return false;
4609 /* If FN takes a vector len argument, return the index of that argument,
4610 otherwise return -1. */
4613 internal_fn_len_index (internal_fn fn)
4615 switch (fn)
4617 case IFN_LEN_LOAD:
4618 case IFN_LEN_STORE:
4619 return 2;
4621 case IFN_MASK_LEN_GATHER_LOAD:
4622 case IFN_MASK_LEN_SCATTER_STORE:
4623 case IFN_COND_LEN_FMA:
4624 case IFN_COND_LEN_FMS:
4625 case IFN_COND_LEN_FNMA:
4626 case IFN_COND_LEN_FNMS:
4627 return 5;
4629 case IFN_COND_LEN_ADD:
4630 case IFN_COND_LEN_SUB:
4631 case IFN_COND_LEN_MUL:
4632 case IFN_COND_LEN_DIV:
4633 case IFN_COND_LEN_MOD:
4634 case IFN_COND_LEN_RDIV:
4635 case IFN_COND_LEN_MIN:
4636 case IFN_COND_LEN_MAX:
4637 case IFN_COND_LEN_FMIN:
4638 case IFN_COND_LEN_FMAX:
4639 case IFN_COND_LEN_AND:
4640 case IFN_COND_LEN_IOR:
4641 case IFN_COND_LEN_XOR:
4642 case IFN_COND_LEN_SHL:
4643 case IFN_COND_LEN_SHR:
4644 return 4;
4646 case IFN_COND_LEN_NEG:
4647 case IFN_MASK_LEN_LOAD:
4648 case IFN_MASK_LEN_STORE:
4649 return 3;
4651 default:
4652 return -1;
4656 /* If FN takes a vector mask argument, return the index of that argument,
4657 otherwise return -1. */
4660 internal_fn_mask_index (internal_fn fn)
4662 switch (fn)
4664 case IFN_MASK_LOAD:
4665 case IFN_MASK_LOAD_LANES:
4666 case IFN_MASK_STORE:
4667 case IFN_MASK_STORE_LANES:
4668 case IFN_MASK_LEN_LOAD:
4669 case IFN_MASK_LEN_STORE:
4670 return 2;
4672 case IFN_MASK_GATHER_LOAD:
4673 case IFN_MASK_SCATTER_STORE:
4674 case IFN_MASK_LEN_GATHER_LOAD:
4675 case IFN_MASK_LEN_SCATTER_STORE:
4676 return 4;
4678 default:
4679 return (conditional_internal_fn_code (fn) != ERROR_MARK
4680 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
4684 /* If FN takes a value that should be stored to memory, return the index
4685 of that argument, otherwise return -1. */
4688 internal_fn_stored_value_index (internal_fn fn)
4690 switch (fn)
4692 case IFN_MASK_STORE:
4693 case IFN_MASK_STORE_LANES:
4694 case IFN_SCATTER_STORE:
4695 case IFN_MASK_SCATTER_STORE:
4696 case IFN_MASK_LEN_SCATTER_STORE:
4697 return 3;
4699 case IFN_LEN_STORE:
4700 return 4;
4702 case IFN_MASK_LEN_STORE:
4703 return 5;
4705 default:
4706 return -1;
4710 /* Return true if the target supports gather load or scatter store function
4711 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
4712 while for stores it is the vector type of the stored data argument.
4713 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
4714 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
4715 offset from the shared base address of each loaded or stored element.
4716 SCALE is the amount by which these offsets should be multiplied
4717 *after* they have been extended to address width. */
4719 bool
4720 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
4721 tree memory_element_type,
4722 tree offset_vector_type, int scale)
4724 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
4725 TYPE_SIZE (memory_element_type)))
4726 return false;
4727 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
4728 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
4729 return false;
4730 optab optab = direct_internal_fn_optab (ifn);
4731 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
4732 TYPE_MODE (offset_vector_type));
4733 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
4734 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
4735 return (icode != CODE_FOR_nothing
4736 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
4737 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
4740 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
4741 for pointers of type TYPE when the accesses have LENGTH bytes and their
4742 common byte alignment is ALIGN. */
4744 bool
4745 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
4746 poly_uint64 length, unsigned int align)
4748 machine_mode mode = TYPE_MODE (type);
4749 optab optab = direct_internal_fn_optab (ifn);
4750 insn_code icode = direct_optab_handler (optab, mode);
4751 if (icode == CODE_FOR_nothing)
4752 return false;
4753 rtx length_rtx = immed_wide_int_const (length, mode);
4754 return (insn_operand_matches (icode, 3, length_rtx)
4755 && insn_operand_matches (icode, 4, GEN_INT (align)));
4758 /* Return the supported bias for IFN which is either IFN_{LEN_,MASK_LEN_,}LOAD
4759 or IFN_{LEN_,MASK_LEN_,}STORE. For now we only support the biases of 0 and
4760 -1 (in case 0 is not an allowable length for {len_,mask_len_}load or
4761 {len_,mask_len_}store). If none of the biases match what the backend
4762 provides, return VECT_PARTIAL_BIAS_UNSUPPORTED. */
4764 signed char
4765 internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
4767 optab optab = direct_internal_fn_optab (ifn);
4768 insn_code icode = direct_optab_handler (optab, mode);
4769 int bias_no = 3;
4771 if (icode == CODE_FOR_nothing)
4773 machine_mode mask_mode;
4774 if (!targetm.vectorize.get_mask_mode (mode).exists (&mask_mode))
4775 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4776 if (ifn == IFN_LEN_LOAD)
4778 /* Try MASK_LEN_LOAD. */
4779 optab = direct_internal_fn_optab (IFN_MASK_LEN_LOAD);
4781 else
4783 /* Try MASK_LEN_STORE. */
4784 optab = direct_internal_fn_optab (IFN_MASK_LEN_STORE);
4786 icode = convert_optab_handler (optab, mode, mask_mode);
4787 bias_no = 4;
4790 if (icode != CODE_FOR_nothing)
4792 /* For now we only support biases of 0 or -1. Try both of them. */
4793 if (insn_operand_matches (icode, bias_no, GEN_INT (0)))
4794 return 0;
4795 if (insn_operand_matches (icode, bias_no, GEN_INT (-1)))
4796 return -1;
4799 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4802 /* Expand STMT as though it were a call to internal function FN. */
4804 void
4805 expand_internal_call (internal_fn fn, gcall *stmt)
4807 internal_fn_expanders[fn] (fn, stmt);
4810 /* Expand STMT, which is a call to internal function FN. */
4812 void
4813 expand_internal_call (gcall *stmt)
4815 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
4818 /* If TYPE is a vector type, return true if IFN is a direct internal
4819 function that is supported for that type. If TYPE is a scalar type,
4820 return true if IFN is a direct internal function that is supported for
4821 the target's preferred vector version of TYPE. */
4823 bool
4824 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
4826 if (VECTOR_MODE_P (TYPE_MODE (type)))
4827 return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
4829 scalar_mode smode;
4830 if (VECTOR_TYPE_P (type)
4831 || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
4832 return false;
4834 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
4835 if (VECTOR_MODE_P (vmode))
4837 tree vectype = build_vector_type_for_mode (type, vmode);
4838 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4839 return true;
4842 auto_vector_modes vector_modes;
4843 targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
4844 for (machine_mode base_mode : vector_modes)
4845 if (related_vector_mode (base_mode, smode).exists (&vmode))
4847 tree vectype = build_vector_type_for_mode (type, vmode);
4848 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4849 return true;
4852 return false;
4855 void
4856 expand_SHUFFLEVECTOR (internal_fn, gcall *)
4858 gcc_unreachable ();
4861 void
4862 expand_PHI (internal_fn, gcall *)
4864 gcc_unreachable ();
4867 void
4868 expand_SPACESHIP (internal_fn, gcall *stmt)
4870 tree lhs = gimple_call_lhs (stmt);
4871 tree rhs1 = gimple_call_arg (stmt, 0);
4872 tree rhs2 = gimple_call_arg (stmt, 1);
4873 tree type = TREE_TYPE (rhs1);
4875 do_pending_stack_adjust ();
4877 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
4878 rtx op1 = expand_normal (rhs1);
4879 rtx op2 = expand_normal (rhs2);
4881 class expand_operand ops[3];
4882 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
4883 create_input_operand (&ops[1], op1, TYPE_MODE (type));
4884 create_input_operand (&ops[2], op2, TYPE_MODE (type));
4885 insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
4886 expand_insn (icode, 3, ops);
4887 if (!rtx_equal_p (target, ops[0].value))
4888 emit_move_insn (target, ops[0].value);
4891 void
4892 expand_ASSUME (internal_fn, gcall *)
4896 void
4897 expand_MASK_CALL (internal_fn, gcall *)
4899 /* This IFN should only exist between ifcvt and vect passes. */
4900 gcc_unreachable ();