c++: fix throwing cleanup with label
[official-gcc.git] / gcc / internal-fn.cc
blobda9b944dd5d95b002d57cf9b9a78e2612887f5f1
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_store_direct { 3, 2, false }
169 #define store_lanes_direct { 0, 0, false }
170 #define mask_store_lanes_direct { 0, 0, false }
171 #define vec_cond_mask_direct { 1, 0, false }
172 #define vec_cond_direct { 2, 0, false }
173 #define scatter_store_direct { 3, 1, false }
174 #define len_store_direct { 3, 3, false }
175 #define vec_set_direct { 3, 3, false }
176 #define unary_direct { 0, 0, true }
177 #define unary_convert_direct { -1, 0, true }
178 #define binary_direct { 0, 0, true }
179 #define ternary_direct { 0, 0, true }
180 #define cond_unary_direct { 1, 1, true }
181 #define cond_binary_direct { 1, 1, true }
182 #define cond_ternary_direct { 1, 1, true }
183 #define while_direct { 0, 2, false }
184 #define fold_extract_direct { 2, 2, false }
185 #define fold_left_direct { 1, 1, false }
186 #define mask_fold_left_direct { 1, 1, false }
187 #define check_ptrs_direct { 0, 0, false }
189 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
190 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
191 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
192 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
193 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
194 #include "internal-fn.def"
195 not_direct
198 /* Expand STMT using instruction ICODE. The instruction has NOUTPUTS
199 output operands and NINPUTS input operands, where NOUTPUTS is either
200 0 or 1. The output operand (if any) comes first, followed by the
201 NINPUTS input operands. */
203 static void
204 expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
205 unsigned int ninputs)
207 gcc_assert (icode != CODE_FOR_nothing);
209 expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
210 unsigned int opno = 0;
211 rtx lhs_rtx = NULL_RTX;
212 tree lhs = gimple_call_lhs (stmt);
214 if (noutputs)
216 gcc_assert (noutputs == 1);
217 if (lhs)
218 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
220 /* Do not assign directly to a promoted subreg, since there is no
221 guarantee that the instruction will leave the upper bits of the
222 register in the state required by SUBREG_PROMOTED_SIGN. */
223 rtx dest = lhs_rtx;
224 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
225 dest = NULL_RTX;
226 create_output_operand (&ops[opno], dest,
227 insn_data[icode].operand[opno].mode);
228 opno += 1;
230 else
231 gcc_assert (!lhs);
233 for (unsigned int i = 0; i < ninputs; ++i)
235 tree rhs = gimple_call_arg (stmt, i);
236 tree rhs_type = TREE_TYPE (rhs);
237 rtx rhs_rtx = expand_normal (rhs);
238 if (INTEGRAL_TYPE_P (rhs_type))
239 create_convert_operand_from (&ops[opno], rhs_rtx,
240 TYPE_MODE (rhs_type),
241 TYPE_UNSIGNED (rhs_type));
242 else
243 create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
244 opno += 1;
247 gcc_assert (opno == noutputs + ninputs);
248 expand_insn (icode, opno, ops);
249 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
251 /* If the return value has an integral type, convert the instruction
252 result to that type. This is useful for things that return an
253 int regardless of the size of the input. If the instruction result
254 is smaller than required, assume that it is signed.
256 If the return value has a nonintegral type, its mode must match
257 the instruction result. */
258 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
260 /* If this is a scalar in a register that is stored in a wider
261 mode than the declared mode, compute the result into its
262 declared mode and then convert to the wider mode. */
263 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
264 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
265 convert_move (SUBREG_REG (lhs_rtx), tmp,
266 SUBREG_PROMOTED_SIGN (lhs_rtx));
268 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
269 emit_move_insn (lhs_rtx, ops[0].value);
270 else
272 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
273 convert_move (lhs_rtx, ops[0].value, 0);
278 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
279 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
281 static enum insn_code
282 get_multi_vector_move (tree array_type, convert_optab optab)
284 machine_mode imode;
285 machine_mode vmode;
287 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
288 imode = TYPE_MODE (array_type);
289 vmode = TYPE_MODE (TREE_TYPE (array_type));
291 return convert_optab_handler (optab, imode, vmode);
294 /* Expand LOAD_LANES call STMT using optab OPTAB. */
296 static void
297 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
299 class expand_operand ops[2];
300 tree type, lhs, rhs;
301 rtx target, mem;
303 lhs = gimple_call_lhs (stmt);
304 rhs = gimple_call_arg (stmt, 0);
305 type = TREE_TYPE (lhs);
307 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
308 mem = expand_normal (rhs);
310 gcc_assert (MEM_P (mem));
311 PUT_MODE (mem, TYPE_MODE (type));
313 create_output_operand (&ops[0], target, TYPE_MODE (type));
314 create_fixed_operand (&ops[1], mem);
315 expand_insn (get_multi_vector_move (type, optab), 2, ops);
316 if (!rtx_equal_p (target, ops[0].value))
317 emit_move_insn (target, ops[0].value);
320 /* Expand STORE_LANES call STMT using optab OPTAB. */
322 static void
323 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
325 class expand_operand ops[2];
326 tree type, lhs, rhs;
327 rtx target, reg;
329 lhs = gimple_call_lhs (stmt);
330 rhs = gimple_call_arg (stmt, 0);
331 type = TREE_TYPE (rhs);
333 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
334 reg = expand_normal (rhs);
336 gcc_assert (MEM_P (target));
337 PUT_MODE (target, TYPE_MODE (type));
339 create_fixed_operand (&ops[0], target);
340 create_input_operand (&ops[1], reg, TYPE_MODE (type));
341 expand_insn (get_multi_vector_move (type, optab), 2, ops);
344 static void
345 expand_ANNOTATE (internal_fn, gcall *)
347 gcc_unreachable ();
350 /* This should get expanded in omp_device_lower pass. */
352 static void
353 expand_GOMP_USE_SIMT (internal_fn, gcall *)
355 gcc_unreachable ();
358 /* This should get expanded in omp_device_lower pass. */
360 static void
361 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
363 gcc_unreachable ();
366 /* Allocate per-lane storage and begin non-uniform execution region. */
368 static void
369 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
371 rtx target;
372 tree lhs = gimple_call_lhs (stmt);
373 if (lhs)
374 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
375 else
376 target = gen_reg_rtx (Pmode);
377 rtx size = expand_normal (gimple_call_arg (stmt, 0));
378 rtx align = expand_normal (gimple_call_arg (stmt, 1));
379 class expand_operand ops[3];
380 create_output_operand (&ops[0], target, Pmode);
381 create_input_operand (&ops[1], size, Pmode);
382 create_input_operand (&ops[2], align, Pmode);
383 gcc_assert (targetm.have_omp_simt_enter ());
384 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
385 if (!rtx_equal_p (target, ops[0].value))
386 emit_move_insn (target, ops[0].value);
389 /* Deallocate per-lane storage and leave non-uniform execution region. */
391 static void
392 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
394 gcc_checking_assert (!gimple_call_lhs (stmt));
395 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
396 class expand_operand ops[1];
397 create_input_operand (&ops[0], arg, Pmode);
398 gcc_assert (targetm.have_omp_simt_exit ());
399 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
402 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
403 without SIMT execution this should be expanded in omp_device_lower pass. */
405 static void
406 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
408 tree lhs = gimple_call_lhs (stmt);
409 if (!lhs)
410 return;
412 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
413 gcc_assert (targetm.have_omp_simt_lane ());
414 emit_insn (targetm.gen_omp_simt_lane (target));
417 /* This should get expanded in omp_device_lower pass. */
419 static void
420 expand_GOMP_SIMT_VF (internal_fn, gcall *)
422 gcc_unreachable ();
425 /* This should get expanded in omp_device_lower pass. */
427 static void
428 expand_GOMP_TARGET_REV (internal_fn, gcall *)
430 gcc_unreachable ();
433 /* Lane index of the first SIMT lane that supplies a non-zero argument.
434 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
435 lane that executed the last iteration for handling OpenMP lastprivate. */
437 static void
438 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
440 tree lhs = gimple_call_lhs (stmt);
441 if (!lhs)
442 return;
444 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
445 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
446 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
447 class expand_operand ops[2];
448 create_output_operand (&ops[0], target, mode);
449 create_input_operand (&ops[1], cond, mode);
450 gcc_assert (targetm.have_omp_simt_last_lane ());
451 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
452 if (!rtx_equal_p (target, ops[0].value))
453 emit_move_insn (target, ops[0].value);
456 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
458 static void
459 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
461 tree lhs = gimple_call_lhs (stmt);
462 if (!lhs)
463 return;
465 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
466 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
467 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
468 class expand_operand ops[2];
469 create_output_operand (&ops[0], target, mode);
470 create_input_operand (&ops[1], ctr, mode);
471 gcc_assert (targetm.have_omp_simt_ordered ());
472 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
473 if (!rtx_equal_p (target, ops[0].value))
474 emit_move_insn (target, ops[0].value);
477 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
478 any lane supplies a non-zero argument. */
480 static void
481 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
483 tree lhs = gimple_call_lhs (stmt);
484 if (!lhs)
485 return;
487 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
488 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
489 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
490 class expand_operand ops[2];
491 create_output_operand (&ops[0], target, mode);
492 create_input_operand (&ops[1], cond, mode);
493 gcc_assert (targetm.have_omp_simt_vote_any ());
494 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
495 if (!rtx_equal_p (target, ops[0].value))
496 emit_move_insn (target, ops[0].value);
499 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
500 is destination lane index XOR given offset. */
502 static void
503 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
505 tree lhs = gimple_call_lhs (stmt);
506 if (!lhs)
507 return;
509 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
510 rtx src = expand_normal (gimple_call_arg (stmt, 0));
511 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
512 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
513 class expand_operand ops[3];
514 create_output_operand (&ops[0], target, mode);
515 create_input_operand (&ops[1], src, mode);
516 create_input_operand (&ops[2], idx, SImode);
517 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
518 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
519 if (!rtx_equal_p (target, ops[0].value))
520 emit_move_insn (target, ops[0].value);
523 /* Exchange between SIMT lanes according to given source lane index. */
525 static void
526 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
528 tree lhs = gimple_call_lhs (stmt);
529 if (!lhs)
530 return;
532 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
533 rtx src = expand_normal (gimple_call_arg (stmt, 0));
534 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
535 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
536 class expand_operand ops[3];
537 create_output_operand (&ops[0], target, mode);
538 create_input_operand (&ops[1], src, mode);
539 create_input_operand (&ops[2], idx, SImode);
540 gcc_assert (targetm.have_omp_simt_xchg_idx ());
541 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
542 if (!rtx_equal_p (target, ops[0].value))
543 emit_move_insn (target, ops[0].value);
546 /* This should get expanded in adjust_simduid_builtins. */
548 static void
549 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
551 gcc_unreachable ();
554 /* This should get expanded in adjust_simduid_builtins. */
556 static void
557 expand_GOMP_SIMD_VF (internal_fn, gcall *)
559 gcc_unreachable ();
562 /* This should get expanded in adjust_simduid_builtins. */
564 static void
565 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
567 gcc_unreachable ();
570 /* This should get expanded in adjust_simduid_builtins. */
572 static void
573 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
575 gcc_unreachable ();
578 /* This should get expanded in adjust_simduid_builtins. */
580 static void
581 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
583 gcc_unreachable ();
586 /* This should get expanded in the sanopt pass. */
588 static void
589 expand_UBSAN_NULL (internal_fn, gcall *)
591 gcc_unreachable ();
594 /* This should get expanded in the sanopt pass. */
596 static void
597 expand_UBSAN_BOUNDS (internal_fn, gcall *)
599 gcc_unreachable ();
602 /* This should get expanded in the sanopt pass. */
604 static void
605 expand_UBSAN_VPTR (internal_fn, gcall *)
607 gcc_unreachable ();
610 /* This should get expanded in the sanopt pass. */
612 static void
613 expand_UBSAN_PTR (internal_fn, gcall *)
615 gcc_unreachable ();
618 /* This should get expanded in the sanopt pass. */
620 static void
621 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
623 gcc_unreachable ();
626 /* This should get expanded in the sanopt pass. */
628 static void
629 expand_HWASAN_CHECK (internal_fn, gcall *)
631 gcc_unreachable ();
634 /* For hwasan stack tagging:
635 Clear tags on the dynamically allocated space.
636 For use after an object dynamically allocated on the stack goes out of
637 scope. */
638 static void
639 expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
641 gcc_assert (Pmode == ptr_mode);
642 tree restored_position = gimple_call_arg (gc, 0);
643 rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
644 EXPAND_NORMAL);
645 rtx func = init_one_libfunc ("__hwasan_tag_memory");
646 rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
647 stack_pointer_rtx, NULL_RTX, 0,
648 OPTAB_WIDEN);
649 emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
650 virtual_stack_dynamic_rtx, Pmode,
651 HWASAN_STACK_BACKGROUND, QImode,
652 off, Pmode);
655 /* For hwasan stack tagging:
656 Return a tag to be used for a dynamic allocation. */
657 static void
658 expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
660 tree tag = gimple_call_lhs (gc);
661 rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
662 machine_mode mode = GET_MODE (target);
663 gcc_assert (mode == QImode);
665 rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
666 gcc_assert (base_tag);
667 rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
668 rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
669 target, /* unsignedp = */1,
670 OPTAB_WIDEN);
671 chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
673 /* Really need to put the tag into the `target` RTX. */
674 if (chosen_tag != target)
676 rtx temp = chosen_tag;
677 gcc_assert (GET_MODE (chosen_tag) == mode);
678 emit_move_insn (target, temp);
681 hwasan_increment_frame_tag ();
684 /* For hwasan stack tagging:
685 Tag a region of space in the shadow stack according to the base pointer of
686 an object on the stack. N.b. the length provided in the internal call is
687 required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
688 static void
689 expand_HWASAN_MARK (internal_fn, gcall *gc)
691 gcc_assert (ptr_mode == Pmode);
692 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
693 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
695 tree base = gimple_call_arg (gc, 1);
696 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
697 rtx base_rtx = expand_normal (base);
699 rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
700 : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
701 rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
703 tree len = gimple_call_arg (gc, 2);
704 rtx r_len = expand_normal (len);
706 rtx func = init_one_libfunc ("__hwasan_tag_memory");
707 emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
708 tag, QImode, r_len, Pmode);
711 /* For hwasan stack tagging:
712 Store a tag into a pointer. */
713 static void
714 expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
716 gcc_assert (ptr_mode == Pmode);
717 tree g_target = gimple_call_lhs (gc);
718 tree g_ptr = gimple_call_arg (gc, 0);
719 tree g_tag = gimple_call_arg (gc, 1);
721 rtx ptr = expand_normal (g_ptr);
722 rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
723 rtx target = expand_normal (g_target);
725 rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
726 rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
727 if (tagged_value != target)
728 emit_move_insn (target, tagged_value);
731 /* This should get expanded in the sanopt pass. */
733 static void
734 expand_ASAN_CHECK (internal_fn, gcall *)
736 gcc_unreachable ();
739 /* This should get expanded in the sanopt pass. */
741 static void
742 expand_ASAN_MARK (internal_fn, gcall *)
744 gcc_unreachable ();
747 /* This should get expanded in the sanopt pass. */
749 static void
750 expand_ASAN_POISON (internal_fn, gcall *)
752 gcc_unreachable ();
755 /* This should get expanded in the sanopt pass. */
757 static void
758 expand_ASAN_POISON_USE (internal_fn, gcall *)
760 gcc_unreachable ();
763 /* This should get expanded in the tsan pass. */
765 static void
766 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
768 gcc_unreachable ();
771 /* This should get expanded in the lower pass. */
773 static void
774 expand_FALLTHROUGH (internal_fn, gcall *call)
776 error_at (gimple_location (call),
777 "invalid use of attribute %<fallthrough%>");
780 /* Return minimum precision needed to represent all values
781 of ARG in SIGNed integral type. */
783 static int
784 get_min_precision (tree arg, signop sign)
786 int prec = TYPE_PRECISION (TREE_TYPE (arg));
787 int cnt = 0;
788 signop orig_sign = sign;
789 if (TREE_CODE (arg) == INTEGER_CST)
791 int p;
792 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
794 widest_int w = wi::to_widest (arg);
795 w = wi::ext (w, prec, sign);
796 p = wi::min_precision (w, sign);
798 else
799 p = wi::min_precision (wi::to_wide (arg), sign);
800 return MIN (p, prec);
802 while (CONVERT_EXPR_P (arg)
803 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
804 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
806 arg = TREE_OPERAND (arg, 0);
807 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
809 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
810 sign = UNSIGNED;
811 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
812 return prec + (orig_sign != sign);
813 prec = TYPE_PRECISION (TREE_TYPE (arg));
815 if (++cnt > 30)
816 return prec + (orig_sign != sign);
818 if (CONVERT_EXPR_P (arg)
819 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
820 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
822 /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
823 If y_2's min precision is smaller than prec, return that. */
824 int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
825 if (oprec < prec)
826 return oprec + (orig_sign != sign);
828 if (TREE_CODE (arg) != SSA_NAME)
829 return prec + (orig_sign != sign);
830 value_range r;
831 while (!get_global_range_query ()->range_of_expr (r, arg)
832 || r.varying_p ()
833 || r.undefined_p ())
835 gimple *g = SSA_NAME_DEF_STMT (arg);
836 if (is_gimple_assign (g)
837 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
839 tree t = gimple_assign_rhs1 (g);
840 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
841 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
843 arg = t;
844 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
846 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
847 sign = UNSIGNED;
848 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
849 return prec + (orig_sign != sign);
850 prec = TYPE_PRECISION (TREE_TYPE (arg));
852 if (++cnt > 30)
853 return prec + (orig_sign != sign);
854 continue;
857 return prec + (orig_sign != sign);
859 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
861 int p1 = wi::min_precision (r.lower_bound (), sign);
862 int p2 = wi::min_precision (r.upper_bound (), sign);
863 p1 = MAX (p1, p2);
864 prec = MIN (prec, p1);
866 else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
868 int p = wi::min_precision (r.upper_bound (), UNSIGNED);
869 prec = MIN (prec, p);
871 return prec + (orig_sign != sign);
874 /* Helper for expand_*_overflow. Set the __imag__ part to true
875 (1 except for signed:1 type, in which case store -1). */
877 static void
878 expand_arith_set_overflow (tree lhs, rtx target)
880 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
881 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
882 write_complex_part (target, constm1_rtx, true, false);
883 else
884 write_complex_part (target, const1_rtx, true, false);
887 /* Helper for expand_*_overflow. Store RES into the __real__ part
888 of TARGET. If RES has larger MODE than __real__ part of TARGET,
889 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
890 if LHS has smaller precision than its mode. */
892 static void
893 expand_arith_overflow_result_store (tree lhs, rtx target,
894 scalar_int_mode mode, rtx res)
896 scalar_int_mode tgtmode
897 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
898 rtx lres = res;
899 if (tgtmode != mode)
901 rtx_code_label *done_label = gen_label_rtx ();
902 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
903 lres = convert_modes (tgtmode, mode, res, uns);
904 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
905 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
906 EQ, true, mode, NULL_RTX, NULL, done_label,
907 profile_probability::very_likely ());
908 expand_arith_set_overflow (lhs, target);
909 emit_label (done_label);
911 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
912 int tgtprec = GET_MODE_PRECISION (tgtmode);
913 if (prec < tgtprec)
915 rtx_code_label *done_label = gen_label_rtx ();
916 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
917 res = lres;
918 if (uns)
920 rtx mask
921 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
922 tgtmode);
923 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
924 true, OPTAB_LIB_WIDEN);
926 else
928 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
929 NULL_RTX, 1);
930 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
931 NULL_RTX, 0);
933 do_compare_rtx_and_jump (res, lres,
934 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
935 profile_probability::very_likely ());
936 expand_arith_set_overflow (lhs, target);
937 emit_label (done_label);
939 write_complex_part (target, lres, false, false);
942 /* Helper for expand_*_overflow. Store RES into TARGET. */
944 static void
945 expand_ubsan_result_store (rtx target, rtx res)
947 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
948 /* If this is a scalar in a register that is stored in a wider mode
949 than the declared mode, compute the result into its declared mode
950 and then convert to the wider mode. Our value is the computed
951 expression. */
952 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
953 else
954 emit_move_insn (target, res);
957 /* Add sub/add overflow checking to the statement STMT.
958 CODE says whether the operation is +, or -. */
960 void
961 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
962 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
963 bool uns1_p, bool is_ubsan, tree *datap)
965 rtx res, target = NULL_RTX;
966 tree fn;
967 rtx_code_label *done_label = gen_label_rtx ();
968 rtx_code_label *do_error = gen_label_rtx ();
969 do_pending_stack_adjust ();
970 rtx op0 = expand_normal (arg0);
971 rtx op1 = expand_normal (arg1);
972 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
973 int prec = GET_MODE_PRECISION (mode);
974 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
975 bool do_xor = false;
977 if (is_ubsan)
978 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
980 if (lhs)
982 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
983 if (!is_ubsan)
984 write_complex_part (target, const0_rtx, true, false);
987 /* We assume both operands and result have the same precision
988 here (GET_MODE_BITSIZE (mode)), S stands for signed type
989 with that precision, U for unsigned type with that precision,
990 sgn for unsigned most significant bit in that precision.
991 s1 is signed first operand, u1 is unsigned first operand,
992 s2 is signed second operand, u2 is unsigned second operand,
993 sr is signed result, ur is unsigned result and the following
994 rules say how to compute result (which is always result of
995 the operands as if both were unsigned, cast to the right
996 signedness) and how to compute whether operation overflowed.
998 s1 + s2 -> sr
999 res = (S) ((U) s1 + (U) s2)
1000 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
1001 s1 - s2 -> sr
1002 res = (S) ((U) s1 - (U) s2)
1003 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
1004 u1 + u2 -> ur
1005 res = u1 + u2
1006 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
1007 u1 - u2 -> ur
1008 res = u1 - u2
1009 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
1010 s1 + u2 -> sr
1011 res = (S) ((U) s1 + u2)
1012 ovf = ((U) res ^ sgn) < u2
1013 s1 + u2 -> ur
1014 t1 = (S) (u2 ^ sgn)
1015 t2 = s1 + t1
1016 res = (U) t2 ^ sgn
1017 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
1018 s1 - u2 -> sr
1019 res = (S) ((U) s1 - u2)
1020 ovf = u2 > ((U) s1 ^ sgn)
1021 s1 - u2 -> ur
1022 res = (U) s1 - u2
1023 ovf = s1 < 0 || u2 > (U) s1
1024 u1 - s2 -> sr
1025 res = u1 - (U) s2
1026 ovf = u1 >= ((U) s2 ^ sgn)
1027 u1 - s2 -> ur
1028 t1 = u1 ^ sgn
1029 t2 = t1 - (U) s2
1030 res = t2 ^ sgn
1031 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
1032 s1 + s2 -> ur
1033 res = (U) s1 + (U) s2
1034 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
1035 u1 + u2 -> sr
1036 res = (S) (u1 + u2)
1037 ovf = (U) res < u2 || res < 0
1038 u1 - u2 -> sr
1039 res = (S) (u1 - u2)
1040 ovf = u1 >= u2 ? res < 0 : res >= 0
1041 s1 - s2 -> ur
1042 res = (U) s1 - (U) s2
1043 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
1045 if (code == PLUS_EXPR && uns0_p && !uns1_p)
1047 /* PLUS_EXPR is commutative, if operand signedness differs,
1048 canonicalize to the first operand being signed and second
1049 unsigned to simplify following code. */
1050 std::swap (op0, op1);
1051 std::swap (arg0, arg1);
1052 uns0_p = false;
1053 uns1_p = true;
1056 /* u1 +- u2 -> ur */
1057 if (uns0_p && uns1_p && unsr_p)
1059 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
1060 : usubv4_optab, mode);
1061 if (icode != CODE_FOR_nothing)
1063 class expand_operand ops[4];
1064 rtx_insn *last = get_last_insn ();
1066 res = gen_reg_rtx (mode);
1067 create_output_operand (&ops[0], res, mode);
1068 create_input_operand (&ops[1], op0, mode);
1069 create_input_operand (&ops[2], op1, mode);
1070 create_fixed_operand (&ops[3], do_error);
1071 if (maybe_expand_insn (icode, 4, ops))
1073 last = get_last_insn ();
1074 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1075 && JUMP_P (last)
1076 && any_condjump_p (last)
1077 && !find_reg_note (last, REG_BR_PROB, 0))
1078 add_reg_br_prob_note (last,
1079 profile_probability::very_unlikely ());
1080 emit_jump (done_label);
1081 goto do_error_label;
1084 delete_insns_since (last);
1087 /* Compute the operation. On RTL level, the addition is always
1088 unsigned. */
1089 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1090 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1091 rtx tem = op0;
1092 /* For PLUS_EXPR, the operation is commutative, so we can pick
1093 operand to compare against. For prec <= BITS_PER_WORD, I think
1094 preferring REG operand is better over CONST_INT, because
1095 the CONST_INT might enlarge the instruction or CSE would need
1096 to figure out we'd already loaded it into a register before.
1097 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
1098 as then the multi-word comparison can be perhaps simplified. */
1099 if (code == PLUS_EXPR
1100 && (prec <= BITS_PER_WORD
1101 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
1102 : CONST_SCALAR_INT_P (op1)))
1103 tem = op1;
1104 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1105 true, mode, NULL_RTX, NULL, done_label,
1106 profile_probability::very_likely ());
1107 goto do_error_label;
1110 /* s1 +- u2 -> sr */
1111 if (!uns0_p && uns1_p && !unsr_p)
1113 /* Compute the operation. On RTL level, the addition is always
1114 unsigned. */
1115 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1116 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1117 rtx tem = expand_binop (mode, add_optab,
1118 code == PLUS_EXPR ? res : op0, sgn,
1119 NULL_RTX, false, OPTAB_LIB_WIDEN);
1120 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1121 done_label, profile_probability::very_likely ());
1122 goto do_error_label;
1125 /* s1 + u2 -> ur */
1126 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
1128 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1129 OPTAB_LIB_WIDEN);
1130 /* As we've changed op1, we have to avoid using the value range
1131 for the original argument. */
1132 arg1 = error_mark_node;
1133 do_xor = true;
1134 goto do_signed;
1137 /* u1 - s2 -> ur */
1138 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
1140 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
1141 OPTAB_LIB_WIDEN);
1142 /* As we've changed op0, we have to avoid using the value range
1143 for the original argument. */
1144 arg0 = error_mark_node;
1145 do_xor = true;
1146 goto do_signed;
1149 /* s1 - u2 -> ur */
1150 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
1152 /* Compute the operation. On RTL level, the addition is always
1153 unsigned. */
1154 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1155 OPTAB_LIB_WIDEN);
1156 int pos_neg = get_range_pos_neg (arg0);
1157 if (pos_neg == 2)
1158 /* If ARG0 is known to be always negative, this is always overflow. */
1159 emit_jump (do_error);
1160 else if (pos_neg == 3)
1161 /* If ARG0 is not known to be always positive, check at runtime. */
1162 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1163 NULL, do_error, profile_probability::very_unlikely ());
1164 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1165 done_label, profile_probability::very_likely ());
1166 goto do_error_label;
1169 /* u1 - s2 -> sr */
1170 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
1172 /* Compute the operation. On RTL level, the addition is always
1173 unsigned. */
1174 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1175 OPTAB_LIB_WIDEN);
1176 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1177 OPTAB_LIB_WIDEN);
1178 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1179 done_label, profile_probability::very_likely ());
1180 goto do_error_label;
1183 /* u1 + u2 -> sr */
1184 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
1186 /* Compute the operation. On RTL level, the addition is always
1187 unsigned. */
1188 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
1189 OPTAB_LIB_WIDEN);
1190 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1191 NULL, do_error, profile_probability::very_unlikely ());
1192 rtx tem = op1;
1193 /* The operation is commutative, so we can pick operand to compare
1194 against. For prec <= BITS_PER_WORD, I think preferring REG operand
1195 is better over CONST_INT, because the CONST_INT might enlarge the
1196 instruction or CSE would need to figure out we'd already loaded it
1197 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
1198 might be more beneficial, as then the multi-word comparison can be
1199 perhaps simplified. */
1200 if (prec <= BITS_PER_WORD
1201 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
1202 : CONST_SCALAR_INT_P (op0))
1203 tem = op0;
1204 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1205 done_label, profile_probability::very_likely ());
1206 goto do_error_label;
1209 /* s1 +- s2 -> ur */
1210 if (!uns0_p && !uns1_p && unsr_p)
1212 /* Compute the operation. On RTL level, the addition is always
1213 unsigned. */
1214 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1215 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1216 int pos_neg = get_range_pos_neg (arg1);
1217 if (code == PLUS_EXPR)
1219 int pos_neg0 = get_range_pos_neg (arg0);
1220 if (pos_neg0 != 3 && pos_neg == 3)
1222 std::swap (op0, op1);
1223 pos_neg = pos_neg0;
1226 rtx tem;
1227 if (pos_neg != 3)
1229 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
1230 ? and_optab : ior_optab,
1231 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1232 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
1233 NULL, done_label, profile_probability::very_likely ());
1235 else
1237 rtx_code_label *do_ior_label = gen_label_rtx ();
1238 do_compare_rtx_and_jump (op1, const0_rtx,
1239 code == MINUS_EXPR ? GE : LT, false, mode,
1240 NULL_RTX, NULL, do_ior_label,
1241 profile_probability::even ());
1242 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
1243 OPTAB_LIB_WIDEN);
1244 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1245 NULL, done_label, profile_probability::very_likely ());
1246 emit_jump (do_error);
1247 emit_label (do_ior_label);
1248 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
1249 OPTAB_LIB_WIDEN);
1250 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1251 NULL, done_label, profile_probability::very_likely ());
1253 goto do_error_label;
1256 /* u1 - u2 -> sr */
1257 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
1259 /* Compute the operation. On RTL level, the addition is always
1260 unsigned. */
1261 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1262 OPTAB_LIB_WIDEN);
1263 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1264 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1265 op0_geu_op1, profile_probability::even ());
1266 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1267 NULL, done_label, profile_probability::very_likely ());
1268 emit_jump (do_error);
1269 emit_label (op0_geu_op1);
1270 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1271 NULL, done_label, profile_probability::very_likely ());
1272 goto do_error_label;
1275 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1277 /* s1 +- s2 -> sr */
1278 do_signed:
1280 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1281 : subv4_optab, mode);
1282 if (icode != CODE_FOR_nothing)
1284 class expand_operand ops[4];
1285 rtx_insn *last = get_last_insn ();
1287 res = gen_reg_rtx (mode);
1288 create_output_operand (&ops[0], res, mode);
1289 create_input_operand (&ops[1], op0, mode);
1290 create_input_operand (&ops[2], op1, mode);
1291 create_fixed_operand (&ops[3], do_error);
1292 if (maybe_expand_insn (icode, 4, ops))
1294 last = get_last_insn ();
1295 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1296 && JUMP_P (last)
1297 && any_condjump_p (last)
1298 && !find_reg_note (last, REG_BR_PROB, 0))
1299 add_reg_br_prob_note (last,
1300 profile_probability::very_unlikely ());
1301 emit_jump (done_label);
1302 goto do_error_label;
1305 delete_insns_since (last);
1308 /* Compute the operation. On RTL level, the addition is always
1309 unsigned. */
1310 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1311 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1313 /* If we can prove that one of the arguments (for MINUS_EXPR only
1314 the second operand, as subtraction is not commutative) is always
1315 non-negative or always negative, we can do just one comparison
1316 and conditional jump. */
1317 int pos_neg = get_range_pos_neg (arg1);
1318 if (code == PLUS_EXPR)
1320 int pos_neg0 = get_range_pos_neg (arg0);
1321 if (pos_neg0 != 3 && pos_neg == 3)
1323 std::swap (op0, op1);
1324 pos_neg = pos_neg0;
1328 /* Addition overflows if and only if the two operands have the same sign,
1329 and the result has the opposite sign. Subtraction overflows if and
1330 only if the two operands have opposite sign, and the subtrahend has
1331 the same sign as the result. Here 0 is counted as positive. */
1332 if (pos_neg == 3)
1334 /* Compute op0 ^ op1 (operands have opposite sign). */
1335 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1336 OPTAB_LIB_WIDEN);
1338 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1339 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1340 OPTAB_LIB_WIDEN);
1342 rtx tem;
1343 if (code == PLUS_EXPR)
1345 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1346 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1347 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1348 OPTAB_LIB_WIDEN);
1350 else
1352 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1353 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1354 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1355 OPTAB_LIB_WIDEN);
1358 /* No overflow if the result has bit sign cleared. */
1359 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1360 NULL, done_label, profile_probability::very_likely ());
1363 /* Compare the result of the operation with the first operand.
1364 No overflow for addition if second operand is positive and result
1365 is larger or second operand is negative and result is smaller.
1366 Likewise for subtraction with sign of second operand flipped. */
1367 else
1368 do_compare_rtx_and_jump (res, op0,
1369 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1370 false, mode, NULL_RTX, NULL, done_label,
1371 profile_probability::very_likely ());
1374 do_error_label:
1375 emit_label (do_error);
1376 if (is_ubsan)
1378 /* Expand the ubsan builtin call. */
1379 push_temp_slots ();
1380 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1381 arg0, arg1, datap);
1382 expand_normal (fn);
1383 pop_temp_slots ();
1384 do_pending_stack_adjust ();
1386 else if (lhs)
1387 expand_arith_set_overflow (lhs, target);
1389 /* We're done. */
1390 emit_label (done_label);
1392 if (lhs)
1394 if (is_ubsan)
1395 expand_ubsan_result_store (target, res);
1396 else
1398 if (do_xor)
1399 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1400 OPTAB_LIB_WIDEN);
1402 expand_arith_overflow_result_store (lhs, target, mode, res);
1407 /* Add negate overflow checking to the statement STMT. */
1409 static void
1410 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1411 tree *datap)
1413 rtx res, op1;
1414 tree fn;
1415 rtx_code_label *done_label, *do_error;
1416 rtx target = NULL_RTX;
1418 done_label = gen_label_rtx ();
1419 do_error = gen_label_rtx ();
1421 do_pending_stack_adjust ();
1422 op1 = expand_normal (arg1);
1424 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1425 if (lhs)
1427 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1428 if (!is_ubsan)
1429 write_complex_part (target, const0_rtx, true, false);
1432 enum insn_code icode = optab_handler (negv3_optab, mode);
1433 if (icode != CODE_FOR_nothing)
1435 class expand_operand ops[3];
1436 rtx_insn *last = get_last_insn ();
1438 res = gen_reg_rtx (mode);
1439 create_output_operand (&ops[0], res, mode);
1440 create_input_operand (&ops[1], op1, mode);
1441 create_fixed_operand (&ops[2], do_error);
1442 if (maybe_expand_insn (icode, 3, ops))
1444 last = get_last_insn ();
1445 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1446 && JUMP_P (last)
1447 && any_condjump_p (last)
1448 && !find_reg_note (last, REG_BR_PROB, 0))
1449 add_reg_br_prob_note (last,
1450 profile_probability::very_unlikely ());
1451 emit_jump (done_label);
1453 else
1455 delete_insns_since (last);
1456 icode = CODE_FOR_nothing;
1460 if (icode == CODE_FOR_nothing)
1462 /* Compute the operation. On RTL level, the addition is always
1463 unsigned. */
1464 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1466 /* Compare the operand with the most negative value. */
1467 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1468 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1469 done_label, profile_probability::very_likely ());
1472 emit_label (do_error);
1473 if (is_ubsan)
1475 /* Expand the ubsan builtin call. */
1476 push_temp_slots ();
1477 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1478 arg1, NULL_TREE, datap);
1479 expand_normal (fn);
1480 pop_temp_slots ();
1481 do_pending_stack_adjust ();
1483 else if (lhs)
1484 expand_arith_set_overflow (lhs, target);
1486 /* We're done. */
1487 emit_label (done_label);
1489 if (lhs)
1491 if (is_ubsan)
1492 expand_ubsan_result_store (target, res);
1493 else
1494 expand_arith_overflow_result_store (lhs, target, mode, res);
1498 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1499 mode MODE can be expanded without using a libcall. */
1501 static bool
1502 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1503 rtx op0, rtx op1, bool uns)
1505 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1506 != CODE_FOR_nothing)
1507 return true;
1509 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1510 != CODE_FOR_nothing)
1511 return true;
1513 rtx_insn *last = get_last_insn ();
1514 if (CONSTANT_P (op0))
1515 op0 = convert_modes (wmode, mode, op0, uns);
1516 else
1517 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1518 if (CONSTANT_P (op1))
1519 op1 = convert_modes (wmode, mode, op1, uns);
1520 else
1521 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1522 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1523 delete_insns_since (last);
1524 return ret != NULL_RTX;
1527 /* Add mul overflow checking to the statement STMT. */
1529 static void
1530 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1531 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1532 tree *datap)
1534 rtx res, op0, op1;
1535 tree fn, type;
1536 rtx_code_label *done_label, *do_error;
1537 rtx target = NULL_RTX;
1538 signop sign;
1539 enum insn_code icode;
1541 done_label = gen_label_rtx ();
1542 do_error = gen_label_rtx ();
1544 do_pending_stack_adjust ();
1545 op0 = expand_normal (arg0);
1546 op1 = expand_normal (arg1);
1548 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1549 bool uns = unsr_p;
1550 if (lhs)
1552 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1553 if (!is_ubsan)
1554 write_complex_part (target, const0_rtx, true, false);
1557 if (is_ubsan)
1558 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1560 /* We assume both operands and result have the same precision
1561 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1562 with that precision, U for unsigned type with that precision,
1563 sgn for unsigned most significant bit in that precision.
1564 s1 is signed first operand, u1 is unsigned first operand,
1565 s2 is signed second operand, u2 is unsigned second operand,
1566 sr is signed result, ur is unsigned result and the following
1567 rules say how to compute result (which is always result of
1568 the operands as if both were unsigned, cast to the right
1569 signedness) and how to compute whether operation overflowed.
1570 main_ovf (false) stands for jump on signed multiplication
1571 overflow or the main algorithm with uns == false.
1572 main_ovf (true) stands for jump on unsigned multiplication
1573 overflow or the main algorithm with uns == true.
1575 s1 * s2 -> sr
1576 res = (S) ((U) s1 * (U) s2)
1577 ovf = main_ovf (false)
1578 u1 * u2 -> ur
1579 res = u1 * u2
1580 ovf = main_ovf (true)
1581 s1 * u2 -> ur
1582 res = (U) s1 * u2
1583 ovf = (s1 < 0 && u2) || main_ovf (true)
1584 u1 * u2 -> sr
1585 res = (S) (u1 * u2)
1586 ovf = res < 0 || main_ovf (true)
1587 s1 * u2 -> sr
1588 res = (S) ((U) s1 * u2)
1589 ovf = (S) u2 >= 0 ? main_ovf (false)
1590 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1591 s1 * s2 -> ur
1592 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1593 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1594 res = t1 * t2
1595 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1597 if (uns0_p && !uns1_p)
1599 /* Multiplication is commutative, if operand signedness differs,
1600 canonicalize to the first operand being signed and second
1601 unsigned to simplify following code. */
1602 std::swap (op0, op1);
1603 std::swap (arg0, arg1);
1604 uns0_p = false;
1605 uns1_p = true;
1608 int pos_neg0 = get_range_pos_neg (arg0);
1609 int pos_neg1 = get_range_pos_neg (arg1);
1611 /* s1 * u2 -> ur */
1612 if (!uns0_p && uns1_p && unsr_p)
1614 switch (pos_neg0)
1616 case 1:
1617 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1618 goto do_main;
1619 case 2:
1620 /* If s1 is negative, avoid the main code, just multiply and
1621 signal overflow if op1 is not 0. */
1622 struct separate_ops ops;
1623 ops.code = MULT_EXPR;
1624 ops.type = TREE_TYPE (arg1);
1625 ops.op0 = make_tree (ops.type, op0);
1626 ops.op1 = make_tree (ops.type, op1);
1627 ops.op2 = NULL_TREE;
1628 ops.location = loc;
1629 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1630 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1631 NULL, done_label, profile_probability::very_likely ());
1632 goto do_error_label;
1633 case 3:
1634 if (get_min_precision (arg1, UNSIGNED)
1635 + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
1637 /* If the first operand is sign extended from narrower type, the
1638 second operand is zero extended from narrower type and
1639 the sum of the two precisions is smaller or equal to the
1640 result precision: if the first argument is at runtime
1641 non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
1642 and there will be no overflow, if the first argument is
1643 negative and the second argument zero, the result will be
1644 0 and there will be no overflow, if the first argument is
1645 negative and the second argument positive, the result when
1646 treated as signed will be negative (minimum -0x7f80 or
1647 -0x7f..f80..0) there will be always overflow. So, do
1648 res = (U) (s1 * u2)
1649 ovf = (S) res < 0 */
1650 struct separate_ops ops;
1651 ops.code = MULT_EXPR;
1652 ops.type
1653 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1655 ops.op0 = make_tree (ops.type, op0);
1656 ops.op1 = make_tree (ops.type, op1);
1657 ops.op2 = NULL_TREE;
1658 ops.location = loc;
1659 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1660 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1661 mode, NULL_RTX, NULL, done_label,
1662 profile_probability::very_likely ());
1663 goto do_error_label;
1665 rtx_code_label *do_main_label;
1666 do_main_label = gen_label_rtx ();
1667 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1668 NULL, do_main_label, profile_probability::very_likely ());
1669 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1670 NULL, do_main_label, profile_probability::very_likely ());
1671 expand_arith_set_overflow (lhs, target);
1672 emit_label (do_main_label);
1673 goto do_main;
1674 default:
1675 gcc_unreachable ();
1679 /* u1 * u2 -> sr */
1680 if (uns0_p && uns1_p && !unsr_p)
1682 if ((pos_neg0 | pos_neg1) == 1)
1684 /* If both arguments are zero extended from narrower types,
1685 the MSB will be clear on both and so we can pretend it is
1686 a normal s1 * s2 -> sr multiplication. */
1687 uns0_p = false;
1688 uns1_p = false;
1690 else
1691 uns = true;
1692 /* Rest of handling of this case after res is computed. */
1693 goto do_main;
1696 /* s1 * u2 -> sr */
1697 if (!uns0_p && uns1_p && !unsr_p)
1699 switch (pos_neg1)
1701 case 1:
1702 goto do_main;
1703 case 2:
1704 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1705 avoid the main code, just multiply and signal overflow
1706 unless 0 * u2 or -1 * ((U) Smin). */
1707 struct separate_ops ops;
1708 ops.code = MULT_EXPR;
1709 ops.type = TREE_TYPE (arg1);
1710 ops.op0 = make_tree (ops.type, op0);
1711 ops.op1 = make_tree (ops.type, op1);
1712 ops.op2 = NULL_TREE;
1713 ops.location = loc;
1714 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1715 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1716 NULL, done_label, profile_probability::very_likely ());
1717 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1718 NULL, do_error, profile_probability::very_unlikely ());
1719 int prec;
1720 prec = GET_MODE_PRECISION (mode);
1721 rtx sgn;
1722 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1723 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1724 NULL, done_label, profile_probability::very_likely ());
1725 goto do_error_label;
1726 case 3:
1727 /* Rest of handling of this case after res is computed. */
1728 goto do_main;
1729 default:
1730 gcc_unreachable ();
1734 /* s1 * s2 -> ur */
1735 if (!uns0_p && !uns1_p && unsr_p)
1737 rtx tem;
1738 switch (pos_neg0 | pos_neg1)
1740 case 1: /* Both operands known to be non-negative. */
1741 goto do_main;
1742 case 2: /* Both operands known to be negative. */
1743 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1744 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1745 /* Avoid looking at arg0/arg1 ranges, as we've changed
1746 the arguments. */
1747 arg0 = error_mark_node;
1748 arg1 = error_mark_node;
1749 goto do_main;
1750 case 3:
1751 if ((pos_neg0 ^ pos_neg1) == 3)
1753 /* If one operand is known to be negative and the other
1754 non-negative, this overflows always, unless the non-negative
1755 one is 0. Just do normal multiply and set overflow
1756 unless one of the operands is 0. */
1757 struct separate_ops ops;
1758 ops.code = MULT_EXPR;
1759 ops.type
1760 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1762 ops.op0 = make_tree (ops.type, op0);
1763 ops.op1 = make_tree (ops.type, op1);
1764 ops.op2 = NULL_TREE;
1765 ops.location = loc;
1766 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1767 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1768 true, mode, NULL_RTX, NULL, done_label,
1769 profile_probability::very_likely ());
1770 goto do_error_label;
1772 if (get_min_precision (arg0, SIGNED)
1773 + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
1775 /* If both operands are sign extended from narrower types and
1776 the sum of the two precisions is smaller or equal to the
1777 result precision: if both arguments are at runtime
1778 non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
1779 and there will be no overflow, if both arguments are negative,
1780 maximum result will be 0x40..00 and there will be no overflow
1781 either, if one argument is positive and the other argument
1782 negative, the result when treated as signed will be negative
1783 and there will be always overflow, and if one argument is
1784 zero and the other negative the result will be zero and no
1785 overflow. So, do
1786 res = (U) (s1 * s2)
1787 ovf = (S) res < 0 */
1788 struct separate_ops ops;
1789 ops.code = MULT_EXPR;
1790 ops.type
1791 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1793 ops.op0 = make_tree (ops.type, op0);
1794 ops.op1 = make_tree (ops.type, op1);
1795 ops.op2 = NULL_TREE;
1796 ops.location = loc;
1797 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1798 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1799 mode, NULL_RTX, NULL, done_label,
1800 profile_probability::very_likely ());
1801 goto do_error_label;
1803 /* The general case, do all the needed comparisons at runtime. */
1804 rtx_code_label *do_main_label, *after_negate_label;
1805 rtx rop0, rop1;
1806 rop0 = gen_reg_rtx (mode);
1807 rop1 = gen_reg_rtx (mode);
1808 emit_move_insn (rop0, op0);
1809 emit_move_insn (rop1, op1);
1810 op0 = rop0;
1811 op1 = rop1;
1812 do_main_label = gen_label_rtx ();
1813 after_negate_label = gen_label_rtx ();
1814 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1815 OPTAB_LIB_WIDEN);
1816 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1817 NULL, after_negate_label, profile_probability::very_likely ());
1818 /* Both arguments negative here, negate them and continue with
1819 normal unsigned overflow checking multiplication. */
1820 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1821 NULL_RTX, false));
1822 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1823 NULL_RTX, false));
1824 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1825 the arguments. */
1826 arg0 = error_mark_node;
1827 arg1 = error_mark_node;
1828 emit_jump (do_main_label);
1829 emit_label (after_negate_label);
1830 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1831 OPTAB_LIB_WIDEN);
1832 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1833 NULL, do_main_label,
1834 profile_probability::very_likely ());
1835 /* One argument is negative here, the other positive. This
1836 overflows always, unless one of the arguments is 0. But
1837 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1838 is, thus we can keep do_main code oring in overflow as is. */
1839 if (pos_neg0 != 2)
1840 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1841 NULL, do_main_label,
1842 profile_probability::very_unlikely ());
1843 if (pos_neg1 != 2)
1844 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1845 NULL, do_main_label,
1846 profile_probability::very_unlikely ());
1847 expand_arith_set_overflow (lhs, target);
1848 emit_label (do_main_label);
1849 goto do_main;
1850 default:
1851 gcc_unreachable ();
1855 do_main:
1856 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1857 sign = uns ? UNSIGNED : SIGNED;
1858 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1859 if (uns
1860 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1861 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1863 /* Optimize unsigned multiplication by power of 2 constant
1864 using 2 shifts, one for result, one to extract the shifted
1865 out bits to see if they are all zero.
1866 Don't do this if optimizing for size and we have umulv4_optab,
1867 in that case assume multiplication will be shorter.
1868 This is heuristics based on the single target that provides
1869 umulv4 right now (i?86/x86_64), if further targets add it, this
1870 might need to be revisited.
1871 Cases where both operands are constant should be folded already
1872 during GIMPLE, and cases where one operand is constant but not
1873 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1874 below can be done without multiplication, just by shifts and adds,
1875 or we'd need to divide the result (and hope it actually doesn't
1876 really divide nor multiply) and compare the result of the division
1877 with the original operand. */
1878 rtx opn0 = op0;
1879 rtx opn1 = op1;
1880 tree argn0 = arg0;
1881 tree argn1 = arg1;
1882 if (integer_pow2p (arg0))
1884 std::swap (opn0, opn1);
1885 std::swap (argn0, argn1);
1887 int cnt = tree_log2 (argn1);
1888 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1890 rtx upper = const0_rtx;
1891 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1892 if (cnt != 0)
1893 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1894 GET_MODE_PRECISION (mode) - cnt,
1895 NULL_RTX, uns);
1896 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1897 NULL_RTX, NULL, done_label,
1898 profile_probability::very_likely ());
1899 goto do_error_label;
1902 if (icode != CODE_FOR_nothing)
1904 class expand_operand ops[4];
1905 rtx_insn *last = get_last_insn ();
1907 res = gen_reg_rtx (mode);
1908 create_output_operand (&ops[0], res, mode);
1909 create_input_operand (&ops[1], op0, mode);
1910 create_input_operand (&ops[2], op1, mode);
1911 create_fixed_operand (&ops[3], do_error);
1912 if (maybe_expand_insn (icode, 4, ops))
1914 last = get_last_insn ();
1915 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1916 && JUMP_P (last)
1917 && any_condjump_p (last)
1918 && !find_reg_note (last, REG_BR_PROB, 0))
1919 add_reg_br_prob_note (last,
1920 profile_probability::very_unlikely ());
1921 emit_jump (done_label);
1923 else
1925 delete_insns_since (last);
1926 icode = CODE_FOR_nothing;
1930 if (icode == CODE_FOR_nothing)
1932 struct separate_ops ops;
1933 int prec = GET_MODE_PRECISION (mode);
1934 scalar_int_mode hmode, wmode;
1935 ops.op0 = make_tree (type, op0);
1936 ops.op1 = make_tree (type, op1);
1937 ops.op2 = NULL_TREE;
1938 ops.location = loc;
1940 /* Optimize unsigned overflow check where we don't use the
1941 multiplication result, just whether overflow happened.
1942 If we can do MULT_HIGHPART_EXPR, that followed by
1943 comparison of the result against zero is cheapest.
1944 We'll still compute res, but it should be DCEd later. */
1945 use_operand_p use;
1946 gimple *use_stmt;
1947 if (!is_ubsan
1948 && lhs
1949 && uns
1950 && !(uns0_p && uns1_p && !unsr_p)
1951 && can_mult_highpart_p (mode, uns) == 1
1952 && single_imm_use (lhs, &use, &use_stmt)
1953 && is_gimple_assign (use_stmt)
1954 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1955 goto highpart;
1957 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1958 && targetm.scalar_mode_supported_p (wmode)
1959 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1961 twoxwider:
1962 ops.code = WIDEN_MULT_EXPR;
1963 ops.type
1964 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1966 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1967 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1968 NULL_RTX, uns);
1969 hipart = convert_modes (mode, wmode, hipart, uns);
1970 res = convert_modes (mode, wmode, res, uns);
1971 if (uns)
1972 /* For the unsigned multiplication, there was overflow if
1973 HIPART is non-zero. */
1974 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1975 NULL_RTX, NULL, done_label,
1976 profile_probability::very_likely ());
1977 else
1979 /* RES is used more than once, place it in a pseudo. */
1980 res = force_reg (mode, res);
1982 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1983 NULL_RTX, 0);
1984 /* RES is low half of the double width result, HIPART
1985 the high half. There was overflow if
1986 HIPART is different from RES < 0 ? -1 : 0. */
1987 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1988 NULL_RTX, NULL, done_label,
1989 profile_probability::very_likely ());
1992 else if (can_mult_highpart_p (mode, uns) == 1)
1994 highpart:
1995 ops.code = MULT_HIGHPART_EXPR;
1996 ops.type = type;
1998 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1999 EXPAND_NORMAL);
2000 ops.code = MULT_EXPR;
2001 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2002 if (uns)
2003 /* For the unsigned multiplication, there was overflow if
2004 HIPART is non-zero. */
2005 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2006 NULL_RTX, NULL, done_label,
2007 profile_probability::very_likely ());
2008 else
2010 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2011 NULL_RTX, 0);
2012 /* RES is low half of the double width result, HIPART
2013 the high half. There was overflow if
2014 HIPART is different from RES < 0 ? -1 : 0. */
2015 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2016 NULL_RTX, NULL, done_label,
2017 profile_probability::very_likely ());
2021 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
2022 && 2 * GET_MODE_PRECISION (hmode) == prec)
2024 rtx_code_label *large_op0 = gen_label_rtx ();
2025 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
2026 rtx_code_label *one_small_one_large = gen_label_rtx ();
2027 rtx_code_label *both_ops_large = gen_label_rtx ();
2028 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
2029 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
2030 rtx_code_label *do_overflow = gen_label_rtx ();
2031 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
2033 unsigned int hprec = GET_MODE_PRECISION (hmode);
2034 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
2035 NULL_RTX, uns);
2036 hipart0 = convert_modes (hmode, mode, hipart0, uns);
2037 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
2038 rtx signbit0 = const0_rtx;
2039 if (!uns)
2040 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
2041 NULL_RTX, 0);
2042 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
2043 NULL_RTX, uns);
2044 hipart1 = convert_modes (hmode, mode, hipart1, uns);
2045 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
2046 rtx signbit1 = const0_rtx;
2047 if (!uns)
2048 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
2049 NULL_RTX, 0);
2051 res = gen_reg_rtx (mode);
2053 /* True if op0 resp. op1 are known to be in the range of
2054 halfstype. */
2055 bool op0_small_p = false;
2056 bool op1_small_p = false;
2057 /* True if op0 resp. op1 are known to have all zeros or all ones
2058 in the upper half of bits, but are not known to be
2059 op{0,1}_small_p. */
2060 bool op0_medium_p = false;
2061 bool op1_medium_p = false;
2062 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
2063 nonnegative, 1 if unknown. */
2064 int op0_sign = 1;
2065 int op1_sign = 1;
2067 if (pos_neg0 == 1)
2068 op0_sign = 0;
2069 else if (pos_neg0 == 2)
2070 op0_sign = -1;
2071 if (pos_neg1 == 1)
2072 op1_sign = 0;
2073 else if (pos_neg1 == 2)
2074 op1_sign = -1;
2076 unsigned int mprec0 = prec;
2077 if (arg0 != error_mark_node)
2078 mprec0 = get_min_precision (arg0, sign);
2079 if (mprec0 <= hprec)
2080 op0_small_p = true;
2081 else if (!uns && mprec0 <= hprec + 1)
2082 op0_medium_p = true;
2083 unsigned int mprec1 = prec;
2084 if (arg1 != error_mark_node)
2085 mprec1 = get_min_precision (arg1, sign);
2086 if (mprec1 <= hprec)
2087 op1_small_p = true;
2088 else if (!uns && mprec1 <= hprec + 1)
2089 op1_medium_p = true;
2091 int smaller_sign = 1;
2092 int larger_sign = 1;
2093 if (op0_small_p)
2095 smaller_sign = op0_sign;
2096 larger_sign = op1_sign;
2098 else if (op1_small_p)
2100 smaller_sign = op1_sign;
2101 larger_sign = op0_sign;
2103 else if (op0_sign == op1_sign)
2105 smaller_sign = op0_sign;
2106 larger_sign = op0_sign;
2109 if (!op0_small_p)
2110 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
2111 NULL_RTX, NULL, large_op0,
2112 profile_probability::unlikely ());
2114 if (!op1_small_p)
2115 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2116 NULL_RTX, NULL, small_op0_large_op1,
2117 profile_probability::unlikely ());
2119 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
2120 hmode to mode, the multiplication will never overflow. We can
2121 do just one hmode x hmode => mode widening multiplication. */
2122 tree halfstype = build_nonstandard_integer_type (hprec, uns);
2123 ops.op0 = make_tree (halfstype, lopart0);
2124 ops.op1 = make_tree (halfstype, lopart1);
2125 ops.code = WIDEN_MULT_EXPR;
2126 ops.type = type;
2127 rtx thisres
2128 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2129 emit_move_insn (res, thisres);
2130 emit_jump (done_label);
2132 emit_label (small_op0_large_op1);
2134 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
2135 but op1 is not, just swap the arguments and handle it as op1
2136 sign/zero extended, op0 not. */
2137 rtx larger = gen_reg_rtx (mode);
2138 rtx hipart = gen_reg_rtx (hmode);
2139 rtx lopart = gen_reg_rtx (hmode);
2140 emit_move_insn (larger, op1);
2141 emit_move_insn (hipart, hipart1);
2142 emit_move_insn (lopart, lopart0);
2143 emit_jump (one_small_one_large);
2145 emit_label (large_op0);
2147 if (!op1_small_p)
2148 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2149 NULL_RTX, NULL, both_ops_large,
2150 profile_probability::unlikely ());
2152 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
2153 but op0 is not, prepare larger, hipart and lopart pseudos and
2154 handle it together with small_op0_large_op1. */
2155 emit_move_insn (larger, op0);
2156 emit_move_insn (hipart, hipart0);
2157 emit_move_insn (lopart, lopart1);
2159 emit_label (one_small_one_large);
2161 /* lopart is the low part of the operand that is sign extended
2162 to mode, larger is the other operand, hipart is the
2163 high part of larger and lopart0 and lopart1 are the low parts
2164 of both operands.
2165 We perform lopart0 * lopart1 and lopart * hipart widening
2166 multiplications. */
2167 tree halfutype = build_nonstandard_integer_type (hprec, 1);
2168 ops.op0 = make_tree (halfutype, lopart0);
2169 ops.op1 = make_tree (halfutype, lopart1);
2170 rtx lo0xlo1
2171 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2173 ops.op0 = make_tree (halfutype, lopart);
2174 ops.op1 = make_tree (halfutype, hipart);
2175 rtx loxhi = gen_reg_rtx (mode);
2176 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2177 emit_move_insn (loxhi, tem);
2179 if (!uns)
2181 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
2182 if (larger_sign == 0)
2183 emit_jump (after_hipart_neg);
2184 else if (larger_sign != -1)
2185 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
2186 NULL_RTX, NULL, after_hipart_neg,
2187 profile_probability::even ());
2189 tem = convert_modes (mode, hmode, lopart, 1);
2190 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
2191 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
2192 1, OPTAB_WIDEN);
2193 emit_move_insn (loxhi, tem);
2195 emit_label (after_hipart_neg);
2197 /* if (lopart < 0) loxhi -= larger; */
2198 if (smaller_sign == 0)
2199 emit_jump (after_lopart_neg);
2200 else if (smaller_sign != -1)
2201 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
2202 NULL_RTX, NULL, after_lopart_neg,
2203 profile_probability::even ());
2205 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
2206 1, OPTAB_WIDEN);
2207 emit_move_insn (loxhi, tem);
2209 emit_label (after_lopart_neg);
2212 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
2213 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
2214 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
2215 1, OPTAB_WIDEN);
2216 emit_move_insn (loxhi, tem);
2218 /* if (loxhi >> (bitsize / 2)
2219 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
2220 if (loxhi >> (bitsize / 2) == 0 (if uns). */
2221 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
2222 NULL_RTX, 0);
2223 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
2224 rtx signbitloxhi = const0_rtx;
2225 if (!uns)
2226 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
2227 convert_modes (hmode, mode,
2228 loxhi, 0),
2229 hprec - 1, NULL_RTX, 0);
2231 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
2232 NULL_RTX, NULL, do_overflow,
2233 profile_probability::very_unlikely ());
2235 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
2236 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
2237 NULL_RTX, 1);
2238 tem = convert_modes (mode, hmode,
2239 convert_modes (hmode, mode, lo0xlo1, 1), 1);
2241 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
2242 1, OPTAB_WIDEN);
2243 if (tem != res)
2244 emit_move_insn (res, tem);
2245 emit_jump (done_label);
2247 emit_label (both_ops_large);
2249 /* If both operands are large (not sign (!uns) or zero (uns)
2250 extended from hmode), then perform the full multiplication
2251 which will be the result of the operation.
2252 The only cases which don't overflow are for signed multiplication
2253 some cases where both hipart0 and highpart1 are 0 or -1.
2254 For unsigned multiplication when high parts are both non-zero
2255 this overflows always. */
2256 ops.code = MULT_EXPR;
2257 ops.op0 = make_tree (type, op0);
2258 ops.op1 = make_tree (type, op1);
2259 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2260 emit_move_insn (res, tem);
2262 if (!uns)
2264 if (!op0_medium_p)
2266 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
2267 NULL_RTX, 1, OPTAB_WIDEN);
2268 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2269 NULL_RTX, NULL, do_error,
2270 profile_probability::very_unlikely ());
2273 if (!op1_medium_p)
2275 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
2276 NULL_RTX, 1, OPTAB_WIDEN);
2277 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2278 NULL_RTX, NULL, do_error,
2279 profile_probability::very_unlikely ());
2282 /* At this point hipart{0,1} are both in [-1, 0]. If they are
2283 the same, overflow happened if res is non-positive, if they
2284 are different, overflow happened if res is positive. */
2285 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
2286 emit_jump (hipart_different);
2287 else if (op0_sign == 1 || op1_sign == 1)
2288 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
2289 NULL_RTX, NULL, hipart_different,
2290 profile_probability::even ());
2292 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
2293 NULL_RTX, NULL, do_error,
2294 profile_probability::very_unlikely ());
2295 emit_jump (done_label);
2297 emit_label (hipart_different);
2299 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
2300 NULL_RTX, NULL, do_error,
2301 profile_probability::very_unlikely ());
2302 emit_jump (done_label);
2305 emit_label (do_overflow);
2307 /* Overflow, do full multiplication and fallthru into do_error. */
2308 ops.op0 = make_tree (type, op0);
2309 ops.op1 = make_tree (type, op1);
2310 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2311 emit_move_insn (res, tem);
2313 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2314 && targetm.scalar_mode_supported_p (wmode))
2315 /* Even emitting a libcall is better than not detecting overflow
2316 at all. */
2317 goto twoxwider;
2318 else
2320 gcc_assert (!is_ubsan);
2321 ops.code = MULT_EXPR;
2322 ops.type = type;
2323 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2324 emit_jump (done_label);
2328 do_error_label:
2329 emit_label (do_error);
2330 if (is_ubsan)
2332 /* Expand the ubsan builtin call. */
2333 push_temp_slots ();
2334 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
2335 arg0, arg1, datap);
2336 expand_normal (fn);
2337 pop_temp_slots ();
2338 do_pending_stack_adjust ();
2340 else if (lhs)
2341 expand_arith_set_overflow (lhs, target);
2343 /* We're done. */
2344 emit_label (done_label);
2346 /* u1 * u2 -> sr */
2347 if (uns0_p && uns1_p && !unsr_p)
2349 rtx_code_label *all_done_label = gen_label_rtx ();
2350 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2351 NULL, all_done_label, profile_probability::very_likely ());
2352 expand_arith_set_overflow (lhs, target);
2353 emit_label (all_done_label);
2356 /* s1 * u2 -> sr */
2357 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2359 rtx_code_label *all_done_label = gen_label_rtx ();
2360 rtx_code_label *set_noovf = gen_label_rtx ();
2361 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2362 NULL, all_done_label, profile_probability::very_likely ());
2363 expand_arith_set_overflow (lhs, target);
2364 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2365 NULL, set_noovf, profile_probability::very_likely ());
2366 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2367 NULL, all_done_label, profile_probability::very_unlikely ());
2368 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2369 all_done_label, profile_probability::very_unlikely ());
2370 emit_label (set_noovf);
2371 write_complex_part (target, const0_rtx, true, false);
2372 emit_label (all_done_label);
2375 if (lhs)
2377 if (is_ubsan)
2378 expand_ubsan_result_store (target, res);
2379 else
2380 expand_arith_overflow_result_store (lhs, target, mode, res);
2384 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2386 static void
2387 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2388 tree arg0, tree arg1)
2390 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2391 rtx_code_label *loop_lab = NULL;
2392 rtx cntvar = NULL_RTX;
2393 tree cntv = NULL_TREE;
2394 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2395 tree sz = TYPE_SIZE (eltype);
2396 tree data = NULL_TREE;
2397 tree resv = NULL_TREE;
2398 rtx lhsr = NULL_RTX;
2399 rtx resvr = NULL_RTX;
2400 unsigned HOST_WIDE_INT const_cnt = 0;
2401 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2403 if (lhs)
2405 optab op;
2406 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2407 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2408 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2409 optab_default)) == unknown_optab
2410 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2411 == CODE_FOR_nothing))
2413 if (MEM_P (lhsr))
2414 resv = make_tree (TREE_TYPE (lhs), lhsr);
2415 else
2417 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2418 resv = make_tree (TREE_TYPE (lhs), resvr);
2422 if (use_loop_p)
2424 do_pending_stack_adjust ();
2425 loop_lab = gen_label_rtx ();
2426 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2427 cntv = make_tree (sizetype, cntvar);
2428 emit_move_insn (cntvar, const0_rtx);
2429 emit_label (loop_lab);
2431 if (TREE_CODE (arg0) != VECTOR_CST)
2433 rtx arg0r = expand_normal (arg0);
2434 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2436 if (TREE_CODE (arg1) != VECTOR_CST)
2438 rtx arg1r = expand_normal (arg1);
2439 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2441 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2443 tree op0, op1, res = NULL_TREE;
2444 if (use_loop_p)
2446 tree atype = build_array_type_nelts (eltype, cnt);
2447 op0 = uniform_vector_p (arg0);
2448 if (op0 == NULL_TREE)
2450 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2451 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2452 NULL_TREE, NULL_TREE);
2454 op1 = uniform_vector_p (arg1);
2455 if (op1 == NULL_TREE)
2457 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2458 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2459 NULL_TREE, NULL_TREE);
2461 if (resv)
2463 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2464 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2465 NULL_TREE, NULL_TREE);
2468 else
2470 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2471 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2472 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2473 if (resv)
2474 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2475 bitpos);
2477 switch (code)
2479 case PLUS_EXPR:
2480 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2481 false, false, false, true, &data);
2482 break;
2483 case MINUS_EXPR:
2484 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2485 expand_neg_overflow (loc, res, op1, true, &data);
2486 else
2487 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2488 false, false, false, true, &data);
2489 break;
2490 case MULT_EXPR:
2491 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2492 true, &data);
2493 break;
2494 default:
2495 gcc_unreachable ();
2498 if (use_loop_p)
2500 struct separate_ops ops;
2501 ops.code = PLUS_EXPR;
2502 ops.type = TREE_TYPE (cntv);
2503 ops.op0 = cntv;
2504 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2505 ops.op2 = NULL_TREE;
2506 ops.location = loc;
2507 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2508 EXPAND_NORMAL);
2509 if (ret != cntvar)
2510 emit_move_insn (cntvar, ret);
2511 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2512 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2513 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2514 profile_probability::very_likely ());
2516 if (lhs && resv == NULL_TREE)
2518 struct separate_ops ops;
2519 ops.code = code;
2520 ops.type = TREE_TYPE (arg0);
2521 ops.op0 = arg0;
2522 ops.op1 = arg1;
2523 ops.op2 = NULL_TREE;
2524 ops.location = loc;
2525 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2526 EXPAND_NORMAL);
2527 if (ret != lhsr)
2528 emit_move_insn (lhsr, ret);
2530 else if (resvr)
2531 emit_move_insn (lhsr, resvr);
2534 /* Expand UBSAN_CHECK_ADD call STMT. */
2536 static void
2537 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2539 location_t loc = gimple_location (stmt);
2540 tree lhs = gimple_call_lhs (stmt);
2541 tree arg0 = gimple_call_arg (stmt, 0);
2542 tree arg1 = gimple_call_arg (stmt, 1);
2543 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2544 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2545 else
2546 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2547 false, false, false, true, NULL);
2550 /* Expand UBSAN_CHECK_SUB call STMT. */
2552 static void
2553 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2555 location_t loc = gimple_location (stmt);
2556 tree lhs = gimple_call_lhs (stmt);
2557 tree arg0 = gimple_call_arg (stmt, 0);
2558 tree arg1 = gimple_call_arg (stmt, 1);
2559 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2560 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2561 else if (integer_zerop (arg0))
2562 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2563 else
2564 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2565 false, false, false, true, NULL);
2568 /* Expand UBSAN_CHECK_MUL call STMT. */
2570 static void
2571 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2573 location_t loc = gimple_location (stmt);
2574 tree lhs = gimple_call_lhs (stmt);
2575 tree arg0 = gimple_call_arg (stmt, 0);
2576 tree arg1 = gimple_call_arg (stmt, 1);
2577 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2578 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2579 else
2580 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2581 NULL);
2584 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2586 static void
2587 expand_arith_overflow (enum tree_code code, gimple *stmt)
2589 tree lhs = gimple_call_lhs (stmt);
2590 if (lhs == NULL_TREE)
2591 return;
2592 tree arg0 = gimple_call_arg (stmt, 0);
2593 tree arg1 = gimple_call_arg (stmt, 1);
2594 tree type = TREE_TYPE (TREE_TYPE (lhs));
2595 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2596 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2597 int unsr_p = TYPE_UNSIGNED (type);
2598 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2599 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2600 int precres = TYPE_PRECISION (type);
2601 location_t loc = gimple_location (stmt);
2602 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2603 uns0_p = true;
2604 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2605 uns1_p = true;
2606 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2607 prec0 = MIN (prec0, pr);
2608 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2609 prec1 = MIN (prec1, pr);
2611 /* If uns0_p && uns1_p, precop is minimum needed precision
2612 of unsigned type to hold the exact result, otherwise
2613 precop is minimum needed precision of signed type to
2614 hold the exact result. */
2615 int precop;
2616 if (code == MULT_EXPR)
2617 precop = prec0 + prec1 + (uns0_p != uns1_p);
2618 else
2620 if (uns0_p == uns1_p)
2621 precop = MAX (prec0, prec1) + 1;
2622 else if (uns0_p)
2623 precop = MAX (prec0 + 1, prec1) + 1;
2624 else
2625 precop = MAX (prec0, prec1 + 1) + 1;
2627 int orig_precres = precres;
2631 if ((uns0_p && uns1_p)
2632 ? ((precop + !unsr_p) <= precres
2633 /* u1 - u2 -> ur can overflow, no matter what precision
2634 the result has. */
2635 && (code != MINUS_EXPR || !unsr_p))
2636 : (!unsr_p && precop <= precres))
2638 /* The infinity precision result will always fit into result. */
2639 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2640 write_complex_part (target, const0_rtx, true, false);
2641 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2642 struct separate_ops ops;
2643 ops.code = code;
2644 ops.type = type;
2645 ops.op0 = fold_convert_loc (loc, type, arg0);
2646 ops.op1 = fold_convert_loc (loc, type, arg1);
2647 ops.op2 = NULL_TREE;
2648 ops.location = loc;
2649 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2650 expand_arith_overflow_result_store (lhs, target, mode, tem);
2651 return;
2654 /* For operations with low precision, if target doesn't have them, start
2655 with precres widening right away, otherwise do it only if the most
2656 simple cases can't be used. */
2657 const int min_precision = targetm.min_arithmetic_precision ();
2658 if (orig_precres == precres && precres < min_precision)
2660 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2661 && prec1 <= precres)
2662 || ((!uns0_p || !uns1_p) && !unsr_p
2663 && prec0 + uns0_p <= precres
2664 && prec1 + uns1_p <= precres))
2666 arg0 = fold_convert_loc (loc, type, arg0);
2667 arg1 = fold_convert_loc (loc, type, arg1);
2668 switch (code)
2670 case MINUS_EXPR:
2671 if (integer_zerop (arg0) && !unsr_p)
2673 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2674 return;
2676 /* FALLTHRU */
2677 case PLUS_EXPR:
2678 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2679 unsr_p, unsr_p, false, NULL);
2680 return;
2681 case MULT_EXPR:
2682 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2683 unsr_p, unsr_p, false, NULL);
2684 return;
2685 default:
2686 gcc_unreachable ();
2690 /* For sub-word operations, retry with a wider type first. */
2691 if (orig_precres == precres && precop <= BITS_PER_WORD)
2693 int p = MAX (min_precision, precop);
2694 scalar_int_mode m = smallest_int_mode_for_size (p);
2695 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2696 uns0_p && uns1_p
2697 && unsr_p);
2698 p = TYPE_PRECISION (optype);
2699 if (p > precres)
2701 precres = p;
2702 unsr_p = TYPE_UNSIGNED (optype);
2703 type = optype;
2704 continue;
2708 if (prec0 <= precres && prec1 <= precres)
2710 tree types[2];
2711 if (unsr_p)
2713 types[0] = build_nonstandard_integer_type (precres, 0);
2714 types[1] = type;
2716 else
2718 types[0] = type;
2719 types[1] = build_nonstandard_integer_type (precres, 1);
2721 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2722 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2723 if (code != MULT_EXPR)
2724 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2725 uns0_p, uns1_p, false, NULL);
2726 else
2727 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2728 uns0_p, uns1_p, false, NULL);
2729 return;
2732 /* Retry with a wider type. */
2733 if (orig_precres == precres)
2735 int p = MAX (prec0, prec1);
2736 scalar_int_mode m = smallest_int_mode_for_size (p);
2737 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2738 uns0_p && uns1_p
2739 && unsr_p);
2740 p = TYPE_PRECISION (optype);
2741 if (p > precres)
2743 precres = p;
2744 unsr_p = TYPE_UNSIGNED (optype);
2745 type = optype;
2746 continue;
2750 gcc_unreachable ();
2752 while (1);
2755 /* Expand ADD_OVERFLOW STMT. */
2757 static void
2758 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2760 expand_arith_overflow (PLUS_EXPR, stmt);
2763 /* Expand SUB_OVERFLOW STMT. */
2765 static void
2766 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2768 expand_arith_overflow (MINUS_EXPR, stmt);
2771 /* Expand MUL_OVERFLOW STMT. */
2773 static void
2774 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2776 expand_arith_overflow (MULT_EXPR, stmt);
2779 /* This should get folded in tree-vectorizer.cc. */
2781 static void
2782 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2784 gcc_unreachable ();
2787 /* This should get folded in tree-vectorizer.cc. */
2789 static void
2790 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2792 gcc_unreachable ();
2795 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2796 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2798 static tree
2799 expand_call_mem_ref (tree type, gcall *stmt, int index)
2801 tree addr = gimple_call_arg (stmt, index);
2802 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2803 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2804 if (TYPE_ALIGN (type) != align)
2805 type = build_aligned_type (type, align);
2807 tree tmp = addr;
2808 if (TREE_CODE (tmp) == SSA_NAME)
2810 gimple *def = SSA_NAME_DEF_STMT (tmp);
2811 if (gimple_assign_single_p (def))
2812 tmp = gimple_assign_rhs1 (def);
2815 if (TREE_CODE (tmp) == ADDR_EXPR)
2817 tree mem = TREE_OPERAND (tmp, 0);
2818 if (TREE_CODE (mem) == TARGET_MEM_REF
2819 && types_compatible_p (TREE_TYPE (mem), type))
2821 tree offset = TMR_OFFSET (mem);
2822 if (type != TREE_TYPE (mem)
2823 || alias_ptr_type != TREE_TYPE (offset)
2824 || !integer_zerop (offset))
2826 mem = copy_node (mem);
2827 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2828 wi::to_poly_wide (offset));
2829 TREE_TYPE (mem) = type;
2831 return mem;
2835 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2838 /* Expand MASK_LOAD{,_LANES} or LEN_LOAD call STMT using optab OPTAB. */
2840 static void
2841 expand_partial_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2843 class expand_operand ops[4];
2844 tree type, lhs, rhs, maskt, biast;
2845 rtx mem, target, mask, bias;
2846 insn_code icode;
2848 maskt = gimple_call_arg (stmt, 2);
2849 lhs = gimple_call_lhs (stmt);
2850 if (lhs == NULL_TREE)
2851 return;
2852 type = TREE_TYPE (lhs);
2853 rhs = expand_call_mem_ref (type, stmt, 0);
2855 if (optab == vec_mask_load_lanes_optab)
2856 icode = get_multi_vector_move (type, optab);
2857 else if (optab == len_load_optab)
2858 icode = direct_optab_handler (optab, TYPE_MODE (type));
2859 else
2860 icode = convert_optab_handler (optab, TYPE_MODE (type),
2861 TYPE_MODE (TREE_TYPE (maskt)));
2863 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2864 gcc_assert (MEM_P (mem));
2865 mask = expand_normal (maskt);
2866 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2867 create_output_operand (&ops[0], target, TYPE_MODE (type));
2868 create_fixed_operand (&ops[1], mem);
2869 if (optab == len_load_optab)
2871 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2872 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2873 biast = gimple_call_arg (stmt, 3);
2874 bias = expand_normal (biast);
2875 create_input_operand (&ops[3], bias, QImode);
2876 expand_insn (icode, 4, ops);
2878 else
2880 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2881 expand_insn (icode, 3, ops);
2884 if (!rtx_equal_p (target, ops[0].value))
2885 emit_move_insn (target, ops[0].value);
2888 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
2889 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2890 #define expand_len_load_optab_fn expand_partial_load_optab_fn
2892 /* Expand MASK_STORE{,_LANES} or LEN_STORE call STMT using optab OPTAB. */
2894 static void
2895 expand_partial_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2897 class expand_operand ops[4];
2898 tree type, lhs, rhs, maskt, biast;
2899 rtx mem, reg, mask, bias;
2900 insn_code icode;
2902 maskt = gimple_call_arg (stmt, 2);
2903 rhs = gimple_call_arg (stmt, 3);
2904 type = TREE_TYPE (rhs);
2905 lhs = expand_call_mem_ref (type, stmt, 0);
2907 if (optab == vec_mask_store_lanes_optab)
2908 icode = get_multi_vector_move (type, optab);
2909 else if (optab == len_store_optab)
2910 icode = direct_optab_handler (optab, TYPE_MODE (type));
2911 else
2912 icode = convert_optab_handler (optab, TYPE_MODE (type),
2913 TYPE_MODE (TREE_TYPE (maskt)));
2915 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2916 gcc_assert (MEM_P (mem));
2917 mask = expand_normal (maskt);
2918 reg = expand_normal (rhs);
2919 create_fixed_operand (&ops[0], mem);
2920 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2921 if (optab == len_store_optab)
2923 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2924 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2925 biast = gimple_call_arg (stmt, 4);
2926 bias = expand_normal (biast);
2927 create_input_operand (&ops[3], bias, QImode);
2928 expand_insn (icode, 4, ops);
2930 else
2932 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2933 expand_insn (icode, 3, ops);
2937 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
2938 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2939 #define expand_len_store_optab_fn expand_partial_store_optab_fn
2941 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
2942 The expansion of STMT happens based on OPTAB table associated. */
2944 static void
2945 expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2947 class expand_operand ops[6];
2948 insn_code icode;
2949 tree lhs = gimple_call_lhs (stmt);
2950 tree op0a = gimple_call_arg (stmt, 0);
2951 tree op0b = gimple_call_arg (stmt, 1);
2952 tree op1 = gimple_call_arg (stmt, 2);
2953 tree op2 = gimple_call_arg (stmt, 3);
2954 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
2956 tree vec_cond_type = TREE_TYPE (lhs);
2957 tree op_mode = TREE_TYPE (op0a);
2958 bool unsignedp = TYPE_UNSIGNED (op_mode);
2960 machine_mode mode = TYPE_MODE (vec_cond_type);
2961 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
2963 icode = convert_optab_handler (optab, mode, cmp_op_mode);
2964 rtx comparison
2965 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
2966 rtx rtx_op1 = expand_normal (op1);
2967 rtx rtx_op2 = expand_normal (op2);
2969 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2970 create_output_operand (&ops[0], target, mode);
2971 create_input_operand (&ops[1], rtx_op1, mode);
2972 create_input_operand (&ops[2], rtx_op2, mode);
2973 create_fixed_operand (&ops[3], comparison);
2974 create_fixed_operand (&ops[4], XEXP (comparison, 0));
2975 create_fixed_operand (&ops[5], XEXP (comparison, 1));
2976 expand_insn (icode, 6, ops);
2977 if (!rtx_equal_p (ops[0].value, target))
2978 emit_move_insn (target, ops[0].value);
2981 /* Expand VCOND_MASK optab internal function.
2982 The expansion of STMT happens based on OPTAB table associated. */
2984 static void
2985 expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2987 class expand_operand ops[4];
2989 tree lhs = gimple_call_lhs (stmt);
2990 tree op0 = gimple_call_arg (stmt, 0);
2991 tree op1 = gimple_call_arg (stmt, 1);
2992 tree op2 = gimple_call_arg (stmt, 2);
2993 tree vec_cond_type = TREE_TYPE (lhs);
2995 machine_mode mode = TYPE_MODE (vec_cond_type);
2996 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
2997 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
2998 rtx mask, rtx_op1, rtx_op2;
3000 gcc_assert (icode != CODE_FOR_nothing);
3002 mask = expand_normal (op0);
3003 rtx_op1 = expand_normal (op1);
3004 rtx_op2 = expand_normal (op2);
3006 mask = force_reg (mask_mode, mask);
3007 rtx_op1 = force_reg (mode, rtx_op1);
3009 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3010 create_output_operand (&ops[0], target, mode);
3011 create_input_operand (&ops[1], rtx_op1, mode);
3012 create_input_operand (&ops[2], rtx_op2, mode);
3013 create_input_operand (&ops[3], mask, mask_mode);
3014 expand_insn (icode, 4, ops);
3015 if (!rtx_equal_p (ops[0].value, target))
3016 emit_move_insn (target, ops[0].value);
3019 /* Expand VEC_SET internal functions. */
3021 static void
3022 expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3024 tree lhs = gimple_call_lhs (stmt);
3025 tree op0 = gimple_call_arg (stmt, 0);
3026 tree op1 = gimple_call_arg (stmt, 1);
3027 tree op2 = gimple_call_arg (stmt, 2);
3028 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3029 rtx src = expand_normal (op0);
3031 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3032 scalar_mode innermode = GET_MODE_INNER (outermode);
3034 rtx value = expand_normal (op1);
3035 rtx pos = expand_normal (op2);
3037 class expand_operand ops[3];
3038 enum insn_code icode = optab_handler (optab, outermode);
3040 if (icode != CODE_FOR_nothing)
3042 rtx temp = gen_reg_rtx (outermode);
3043 emit_move_insn (temp, src);
3045 create_fixed_operand (&ops[0], temp);
3046 create_input_operand (&ops[1], value, innermode);
3047 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
3048 true);
3049 if (maybe_expand_insn (icode, 3, ops))
3051 emit_move_insn (target, temp);
3052 return;
3055 gcc_unreachable ();
3058 static void
3059 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
3063 static void
3064 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
3066 /* When guessing was done, the hints should be already stripped away. */
3067 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
3069 rtx target;
3070 tree lhs = gimple_call_lhs (stmt);
3071 if (lhs)
3072 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3073 else
3074 target = const0_rtx;
3075 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
3076 if (lhs && val != target)
3077 emit_move_insn (target, val);
3080 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
3081 should never be called. */
3083 static void
3084 expand_VA_ARG (internal_fn, gcall *)
3086 gcc_unreachable ();
3089 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
3090 dummy function should never be called. */
3092 static void
3093 expand_VEC_CONVERT (internal_fn, gcall *)
3095 gcc_unreachable ();
3098 /* Expand IFN_RAWMEMCHAR internal function. */
3100 void
3101 expand_RAWMEMCHR (internal_fn, gcall *stmt)
3103 expand_operand ops[3];
3105 tree lhs = gimple_call_lhs (stmt);
3106 if (!lhs)
3107 return;
3108 machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
3109 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3110 create_output_operand (&ops[0], lhs_rtx, lhs_mode);
3112 tree mem = gimple_call_arg (stmt, 0);
3113 rtx mem_rtx = get_memory_rtx (mem, NULL);
3114 create_fixed_operand (&ops[1], mem_rtx);
3116 tree pattern = gimple_call_arg (stmt, 1);
3117 machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
3118 rtx pattern_rtx = expand_normal (pattern);
3119 create_input_operand (&ops[2], pattern_rtx, mode);
3121 insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
3123 expand_insn (icode, 3, ops);
3124 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3125 emit_move_insn (lhs_rtx, ops[0].value);
3128 /* Expand the IFN_UNIQUE function according to its first argument. */
3130 static void
3131 expand_UNIQUE (internal_fn, gcall *stmt)
3133 rtx pattern = NULL_RTX;
3134 enum ifn_unique_kind kind
3135 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
3137 switch (kind)
3139 default:
3140 gcc_unreachable ();
3142 case IFN_UNIQUE_UNSPEC:
3143 if (targetm.have_unique ())
3144 pattern = targetm.gen_unique ();
3145 break;
3147 case IFN_UNIQUE_OACC_FORK:
3148 case IFN_UNIQUE_OACC_JOIN:
3149 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
3151 tree lhs = gimple_call_lhs (stmt);
3152 rtx target = const0_rtx;
3154 if (lhs)
3155 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3157 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
3158 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
3160 if (kind == IFN_UNIQUE_OACC_FORK)
3161 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
3162 else
3163 pattern = targetm.gen_oacc_join (target, data_dep, axis);
3165 else
3166 gcc_unreachable ();
3167 break;
3170 if (pattern)
3171 emit_insn (pattern);
3174 /* Expand the IFN_DEFERRED_INIT function:
3175 LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
3177 Initialize the LHS with zero/pattern according to its second argument
3178 INIT_TYPE:
3179 if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
3180 if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
3181 to initialize;
3182 The LHS variable is initialized including paddings.
3183 The reasons to choose 0xFE for pattern initialization are:
3184 1. It is a non-canonical virtual address on x86_64, and at the
3185 high end of the i386 kernel address space.
3186 2. It is a very large float value (-1.694739530317379e+38).
3187 3. It is also an unusual number for integers. */
3188 #define INIT_PATTERN_VALUE 0xFE
3189 static void
3190 expand_DEFERRED_INIT (internal_fn, gcall *stmt)
3192 tree lhs = gimple_call_lhs (stmt);
3193 tree var_size = gimple_call_arg (stmt, 0);
3194 enum auto_init_type init_type
3195 = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
3196 bool reg_lhs = true;
3198 tree var_type = TREE_TYPE (lhs);
3199 gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
3201 if (TREE_CODE (lhs) == SSA_NAME)
3202 reg_lhs = true;
3203 else
3205 tree lhs_base = lhs;
3206 while (handled_component_p (lhs_base))
3207 lhs_base = TREE_OPERAND (lhs_base, 0);
3208 reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
3209 || non_mem_decl_p (lhs_base));
3210 /* If this expands to a register and the underlying decl is wrapped in
3211 a MEM_REF that just serves as an access type change expose the decl
3212 if it is of correct size. This avoids a situation as in PR103271
3213 if the target does not support a direct move to the registers mode. */
3214 if (reg_lhs
3215 && TREE_CODE (lhs_base) == MEM_REF
3216 && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
3217 && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
3218 && integer_zerop (TREE_OPERAND (lhs_base, 1))
3219 && tree_fits_uhwi_p (var_size)
3220 && tree_int_cst_equal
3221 (var_size,
3222 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
3224 lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
3225 var_type = TREE_TYPE (lhs);
3229 if (!reg_lhs)
3231 /* If the variable is not in register, expand to a memset
3232 to initialize it. */
3233 mark_addressable (lhs);
3234 tree var_addr = build_fold_addr_expr (lhs);
3236 tree value = (init_type == AUTO_INIT_PATTERN)
3237 ? build_int_cst (integer_type_node,
3238 INIT_PATTERN_VALUE)
3239 : integer_zero_node;
3240 tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
3241 3, var_addr, value, var_size);
3242 /* Expand this memset call. */
3243 expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
3245 else
3247 /* If this variable is in a register use expand_assignment.
3248 For boolean scalars force zero-init. */
3249 tree init;
3250 scalar_int_mode var_mode;
3251 if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
3252 && tree_fits_uhwi_p (var_size)
3253 && (init_type == AUTO_INIT_PATTERN
3254 || !is_gimple_reg_type (var_type))
3255 && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
3256 0).exists (&var_mode)
3257 && have_insn_for (SET, var_mode))
3259 unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
3260 unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
3261 memset (buf, (init_type == AUTO_INIT_PATTERN
3262 ? INIT_PATTERN_VALUE : 0), total_bytes);
3263 tree itype = build_nonstandard_integer_type
3264 (total_bytes * BITS_PER_UNIT, 1);
3265 wide_int w = wi::from_buffer (buf, total_bytes);
3266 init = wide_int_to_tree (itype, w);
3267 /* Pun the LHS to make sure its type has constant size
3268 unless it is an SSA name where that's already known. */
3269 if (TREE_CODE (lhs) != SSA_NAME)
3270 lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
3271 else
3272 init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
3274 else
3275 /* Use zero-init also for variable-length sizes. */
3276 init = build_zero_cst (var_type);
3278 expand_assignment (lhs, init, false);
3282 /* The size of an OpenACC compute dimension. */
3284 static void
3285 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
3287 tree lhs = gimple_call_lhs (stmt);
3289 if (!lhs)
3290 return;
3292 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3293 if (targetm.have_oacc_dim_size ())
3295 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3296 VOIDmode, EXPAND_NORMAL);
3297 emit_insn (targetm.gen_oacc_dim_size (target, dim));
3299 else
3300 emit_move_insn (target, GEN_INT (1));
3303 /* The position of an OpenACC execution engine along one compute axis. */
3305 static void
3306 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
3308 tree lhs = gimple_call_lhs (stmt);
3310 if (!lhs)
3311 return;
3313 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3314 if (targetm.have_oacc_dim_pos ())
3316 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3317 VOIDmode, EXPAND_NORMAL);
3318 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
3320 else
3321 emit_move_insn (target, const0_rtx);
3324 /* This is expanded by oacc_device_lower pass. */
3326 static void
3327 expand_GOACC_LOOP (internal_fn, gcall *)
3329 gcc_unreachable ();
3332 /* This is expanded by oacc_device_lower pass. */
3334 static void
3335 expand_GOACC_REDUCTION (internal_fn, gcall *)
3337 gcc_unreachable ();
3340 /* This is expanded by oacc_device_lower pass. */
3342 static void
3343 expand_GOACC_TILE (internal_fn, gcall *)
3345 gcc_unreachable ();
3348 /* Set errno to EDOM. */
3350 static void
3351 expand_SET_EDOM (internal_fn, gcall *)
3353 #ifdef TARGET_EDOM
3354 #ifdef GEN_ERRNO_RTX
3355 rtx errno_rtx = GEN_ERRNO_RTX;
3356 #else
3357 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
3358 #endif
3359 emit_move_insn (errno_rtx,
3360 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
3361 #else
3362 gcc_unreachable ();
3363 #endif
3366 /* Expand atomic bit test and set. */
3368 static void
3369 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
3371 expand_ifn_atomic_bit_test_and (call);
3374 /* Expand atomic bit test and complement. */
3376 static void
3377 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
3379 expand_ifn_atomic_bit_test_and (call);
3382 /* Expand atomic bit test and reset. */
3384 static void
3385 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
3387 expand_ifn_atomic_bit_test_and (call);
3390 /* Expand atomic bit test and set. */
3392 static void
3393 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
3395 expand_ifn_atomic_compare_exchange (call);
3398 /* Expand atomic add fetch and cmp with 0. */
3400 static void
3401 expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
3403 expand_ifn_atomic_op_fetch_cmp_0 (call);
3406 /* Expand atomic sub fetch and cmp with 0. */
3408 static void
3409 expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
3411 expand_ifn_atomic_op_fetch_cmp_0 (call);
3414 /* Expand atomic and fetch and cmp with 0. */
3416 static void
3417 expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
3419 expand_ifn_atomic_op_fetch_cmp_0 (call);
3422 /* Expand atomic or fetch and cmp with 0. */
3424 static void
3425 expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
3427 expand_ifn_atomic_op_fetch_cmp_0 (call);
3430 /* Expand atomic xor fetch and cmp with 0. */
3432 static void
3433 expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
3435 expand_ifn_atomic_op_fetch_cmp_0 (call);
3438 /* Expand LAUNDER to assignment, lhs = arg0. */
3440 static void
3441 expand_LAUNDER (internal_fn, gcall *call)
3443 tree lhs = gimple_call_lhs (call);
3445 if (!lhs)
3446 return;
3448 expand_assignment (lhs, gimple_call_arg (call, 0), false);
3451 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
3453 static void
3454 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3456 internal_fn ifn = gimple_call_internal_fn (stmt);
3457 int rhs_index = internal_fn_stored_value_index (ifn);
3458 int mask_index = internal_fn_mask_index (ifn);
3459 tree base = gimple_call_arg (stmt, 0);
3460 tree offset = gimple_call_arg (stmt, 1);
3461 tree scale = gimple_call_arg (stmt, 2);
3462 tree rhs = gimple_call_arg (stmt, rhs_index);
3464 rtx base_rtx = expand_normal (base);
3465 rtx offset_rtx = expand_normal (offset);
3466 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3467 rtx rhs_rtx = expand_normal (rhs);
3469 class expand_operand ops[6];
3470 int i = 0;
3471 create_address_operand (&ops[i++], base_rtx);
3472 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3473 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3474 create_integer_operand (&ops[i++], scale_int);
3475 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
3476 if (mask_index >= 0)
3478 tree mask = gimple_call_arg (stmt, mask_index);
3479 rtx mask_rtx = expand_normal (mask);
3480 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
3483 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
3484 TYPE_MODE (TREE_TYPE (offset)));
3485 expand_insn (icode, i, ops);
3488 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
3490 static void
3491 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3493 tree lhs = gimple_call_lhs (stmt);
3494 tree base = gimple_call_arg (stmt, 0);
3495 tree offset = gimple_call_arg (stmt, 1);
3496 tree scale = gimple_call_arg (stmt, 2);
3498 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3499 rtx base_rtx = expand_normal (base);
3500 rtx offset_rtx = expand_normal (offset);
3501 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3503 int i = 0;
3504 class expand_operand ops[6];
3505 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
3506 create_address_operand (&ops[i++], base_rtx);
3507 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3508 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3509 create_integer_operand (&ops[i++], scale_int);
3510 if (optab == mask_gather_load_optab)
3512 tree mask = gimple_call_arg (stmt, 4);
3513 rtx mask_rtx = expand_normal (mask);
3514 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
3516 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
3517 TYPE_MODE (TREE_TYPE (offset)));
3518 expand_insn (icode, i, ops);
3519 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3520 emit_move_insn (lhs_rtx, ops[0].value);
3523 /* Helper for expand_DIVMOD. Return true if the sequence starting with
3524 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
3526 static bool
3527 contains_call_div_mod (rtx_insn *insn)
3529 subrtx_iterator::array_type array;
3530 for (; insn; insn = NEXT_INSN (insn))
3531 if (CALL_P (insn))
3532 return true;
3533 else if (INSN_P (insn))
3534 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3535 switch (GET_CODE (*iter))
3537 case CALL:
3538 case DIV:
3539 case UDIV:
3540 case MOD:
3541 case UMOD:
3542 return true;
3543 default:
3544 break;
3546 return false;
3549 /* Expand DIVMOD() using:
3550 a) optab handler for udivmod/sdivmod if it is available.
3551 b) If optab_handler doesn't exist, generate call to
3552 target-specific divmod libfunc. */
3554 static void
3555 expand_DIVMOD (internal_fn, gcall *call_stmt)
3557 tree lhs = gimple_call_lhs (call_stmt);
3558 tree arg0 = gimple_call_arg (call_stmt, 0);
3559 tree arg1 = gimple_call_arg (call_stmt, 1);
3561 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3562 tree type = TREE_TYPE (TREE_TYPE (lhs));
3563 machine_mode mode = TYPE_MODE (type);
3564 bool unsignedp = TYPE_UNSIGNED (type);
3565 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3567 rtx op0 = expand_normal (arg0);
3568 rtx op1 = expand_normal (arg1);
3569 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3571 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3572 rtx_insn *insns = NULL;
3574 if (TREE_CODE (arg1) == INTEGER_CST)
3576 /* For DIVMOD by integral constants, there could be efficient code
3577 expanded inline e.g. using shifts and plus/minus. Try to expand
3578 the division and modulo and if it emits any library calls or any
3579 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3580 divmod libcall. */
3581 scalar_int_mode int_mode;
3582 if (remainder == NULL_RTX
3583 && optimize
3584 && CONST_INT_P (op1)
3585 && !pow2p_hwi (INTVAL (op1))
3586 && is_int_mode (TYPE_MODE (type), &int_mode)
3587 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
3588 && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
3589 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
3590 && optimize_insn_for_speed_p ())
3592 rtx_insn *last = get_last_insn ();
3593 remainder = NULL_RTX;
3594 quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
3595 TYPE_UNSIGNED (type));
3596 if (quotient != NULL_RTX)
3598 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
3600 rtx_insn *move = emit_move_insn (quotient, quotient);
3601 set_dst_reg_note (move, REG_EQUAL,
3602 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3603 ? UDIV : DIV, int_mode,
3604 copy_rtx (op0), op1),
3605 quotient);
3606 move = emit_move_insn (remainder, remainder);
3607 set_dst_reg_note (move, REG_EQUAL,
3608 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3609 ? UMOD : MOD, int_mode,
3610 copy_rtx (op0), op1),
3611 quotient);
3614 else
3615 delete_insns_since (last);
3618 if (remainder == NULL_RTX)
3620 struct separate_ops ops;
3621 ops.code = TRUNC_DIV_EXPR;
3622 ops.type = type;
3623 ops.op0 = make_tree (ops.type, op0);
3624 ops.op1 = arg1;
3625 ops.op2 = NULL_TREE;
3626 ops.location = gimple_location (call_stmt);
3627 start_sequence ();
3628 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3629 if (contains_call_div_mod (get_insns ()))
3630 quotient = NULL_RTX;
3631 else
3633 ops.code = TRUNC_MOD_EXPR;
3634 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
3635 EXPAND_NORMAL);
3636 if (contains_call_div_mod (get_insns ()))
3637 remainder = NULL_RTX;
3639 if (remainder)
3640 insns = get_insns ();
3641 end_sequence ();
3645 if (remainder)
3646 emit_insn (insns);
3648 /* Check if optab_handler exists for divmod_optab for given mode. */
3649 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
3651 quotient = gen_reg_rtx (mode);
3652 remainder = gen_reg_rtx (mode);
3653 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3656 /* Generate call to divmod libfunc if it exists. */
3657 else if (rtx libfunc = optab_libfunc (tab, mode))
3658 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3659 &quotient, &remainder);
3661 else
3662 gcc_unreachable ();
3664 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3665 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3666 make_tree (TREE_TYPE (arg0), quotient),
3667 make_tree (TREE_TYPE (arg1), remainder)),
3668 target, VOIDmode, EXPAND_NORMAL);
3671 /* Expand a NOP. */
3673 static void
3674 expand_NOP (internal_fn, gcall *)
3676 /* Nothing. But it shouldn't really prevail. */
3679 /* Coroutines, all should have been processed at this stage. */
3681 static void
3682 expand_CO_FRAME (internal_fn, gcall *)
3684 gcc_unreachable ();
3687 static void
3688 expand_CO_YIELD (internal_fn, gcall *)
3690 gcc_unreachable ();
3693 static void
3694 expand_CO_SUSPN (internal_fn, gcall *)
3696 gcc_unreachable ();
3699 static void
3700 expand_CO_ACTOR (internal_fn, gcall *)
3702 gcc_unreachable ();
3705 /* Expand a call to FN using the operands in STMT. FN has a single
3706 output operand and NARGS input operands. */
3708 static void
3709 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3710 unsigned int nargs)
3712 tree_pair types = direct_internal_fn_types (fn, stmt);
3713 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3714 expand_fn_using_insn (stmt, icode, 1, nargs);
3717 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3719 static void
3720 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3722 expand_operand ops[4];
3723 tree rhs_type[2];
3725 tree lhs = gimple_call_lhs (stmt);
3726 tree lhs_type = TREE_TYPE (lhs);
3727 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3728 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3730 for (unsigned int i = 0; i < 2; ++i)
3732 tree rhs = gimple_call_arg (stmt, i);
3733 rhs_type[i] = TREE_TYPE (rhs);
3734 rtx rhs_rtx = expand_normal (rhs);
3735 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3738 int opcnt;
3739 if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
3741 /* When the mask is an integer mode the exact vector length may not
3742 be clear to the backend, so we pass it in operand[3].
3743 Use the vector in arg2 for the most reliable intended size. */
3744 tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
3745 create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
3746 opcnt = 4;
3748 else
3749 /* The mask has a vector type so the length operand is unnecessary. */
3750 opcnt = 3;
3752 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3753 TYPE_MODE (lhs_type));
3755 expand_insn (icode, opcnt, ops);
3756 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3757 emit_move_insn (lhs_rtx, ops[0].value);
3760 /* Expand a call to a convert-like optab using the operands in STMT.
3761 FN has a single output operand and NARGS input operands. */
3763 static void
3764 expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
3765 unsigned int nargs)
3767 tree_pair types = direct_internal_fn_types (fn, stmt);
3768 insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
3769 TYPE_MODE (types.second));
3770 expand_fn_using_insn (stmt, icode, 1, nargs);
3773 /* Expanders for optabs that can use expand_direct_optab_fn. */
3775 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3776 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3778 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3779 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3781 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3782 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3784 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3785 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3787 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3788 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3790 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3791 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3793 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3794 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3796 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3797 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3799 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3800 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3802 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3803 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3805 /* Expanders for optabs that can use expand_convert_optab_fn. */
3807 #define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
3808 expand_convert_optab_fn (FN, STMT, OPTAB, 1)
3810 /* RETURN_TYPE and ARGS are a return type and argument list that are
3811 in principle compatible with FN (which satisfies direct_internal_fn_p).
3812 Return the types that should be used to determine whether the
3813 target supports FN. */
3815 tree_pair
3816 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3818 const direct_internal_fn_info &info = direct_internal_fn (fn);
3819 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3820 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3821 return tree_pair (type0, type1);
3824 /* CALL is a call whose return type and arguments are in principle
3825 compatible with FN (which satisfies direct_internal_fn_p). Return the
3826 types that should be used to determine whether the target supports FN. */
3828 tree_pair
3829 direct_internal_fn_types (internal_fn fn, gcall *call)
3831 const direct_internal_fn_info &info = direct_internal_fn (fn);
3832 tree op0 = (info.type0 < 0
3833 ? gimple_call_lhs (call)
3834 : gimple_call_arg (call, info.type0));
3835 tree op1 = (info.type1 < 0
3836 ? gimple_call_lhs (call)
3837 : gimple_call_arg (call, info.type1));
3838 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3841 /* Return true if OPTAB is supported for TYPES (whose modes should be
3842 the same) when the optimization type is OPT_TYPE. Used for simple
3843 direct optabs. */
3845 static bool
3846 direct_optab_supported_p (direct_optab optab, tree_pair types,
3847 optimization_type opt_type)
3849 machine_mode mode = TYPE_MODE (types.first);
3850 gcc_checking_assert (mode == TYPE_MODE (types.second));
3851 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3854 /* Return true if OPTAB is supported for TYPES, where the first type
3855 is the destination and the second type is the source. Used for
3856 convert optabs. */
3858 static bool
3859 convert_optab_supported_p (convert_optab optab, tree_pair types,
3860 optimization_type opt_type)
3862 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3863 TYPE_MODE (types.second), opt_type)
3864 != CODE_FOR_nothing);
3867 /* Return true if load/store lanes optab OPTAB is supported for
3868 array type TYPES.first when the optimization type is OPT_TYPE. */
3870 static bool
3871 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3872 optimization_type opt_type)
3874 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3875 machine_mode imode = TYPE_MODE (types.first);
3876 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3877 return (convert_optab_handler (optab, imode, vmode, opt_type)
3878 != CODE_FOR_nothing);
3881 #define direct_unary_optab_supported_p direct_optab_supported_p
3882 #define direct_unary_convert_optab_supported_p convert_optab_supported_p
3883 #define direct_binary_optab_supported_p direct_optab_supported_p
3884 #define direct_ternary_optab_supported_p direct_optab_supported_p
3885 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3886 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3887 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
3888 #define direct_mask_load_optab_supported_p convert_optab_supported_p
3889 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
3890 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
3891 #define direct_gather_load_optab_supported_p convert_optab_supported_p
3892 #define direct_len_load_optab_supported_p direct_optab_supported_p
3893 #define direct_mask_store_optab_supported_p convert_optab_supported_p
3894 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
3895 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
3896 #define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
3897 #define direct_vec_cond_optab_supported_p convert_optab_supported_p
3898 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
3899 #define direct_len_store_optab_supported_p direct_optab_supported_p
3900 #define direct_while_optab_supported_p convert_optab_supported_p
3901 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
3902 #define direct_fold_left_optab_supported_p direct_optab_supported_p
3903 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
3904 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
3905 #define direct_vec_set_optab_supported_p direct_optab_supported_p
3907 /* Return the optab used by internal function FN. */
3909 optab
3910 direct_internal_fn_optab (internal_fn fn, tree_pair types)
3912 switch (fn)
3914 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3915 case IFN_##CODE: break;
3916 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3917 case IFN_##CODE: return OPTAB##_optab;
3918 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3919 UNSIGNED_OPTAB, TYPE) \
3920 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
3921 ? UNSIGNED_OPTAB ## _optab \
3922 : SIGNED_OPTAB ## _optab);
3923 #include "internal-fn.def"
3925 case IFN_LAST:
3926 break;
3928 gcc_unreachable ();
3931 /* Return the optab used by internal function FN. */
3933 static optab
3934 direct_internal_fn_optab (internal_fn fn)
3936 switch (fn)
3938 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3939 case IFN_##CODE: break;
3940 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3941 case IFN_##CODE: return OPTAB##_optab;
3942 #include "internal-fn.def"
3944 case IFN_LAST:
3945 break;
3947 gcc_unreachable ();
3950 /* Return true if FN is supported for the types in TYPES when the
3951 optimization type is OPT_TYPE. The types are those associated with
3952 the "type0" and "type1" fields of FN's direct_internal_fn_info
3953 structure. */
3955 bool
3956 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
3957 optimization_type opt_type)
3959 switch (fn)
3961 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3962 case IFN_##CODE: break;
3963 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3964 case IFN_##CODE: \
3965 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
3966 opt_type);
3967 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3968 UNSIGNED_OPTAB, TYPE) \
3969 case IFN_##CODE: \
3971 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
3972 ? UNSIGNED_OPTAB ## _optab \
3973 : SIGNED_OPTAB ## _optab); \
3974 return direct_##TYPE##_optab_supported_p (which_optab, types, \
3975 opt_type); \
3977 #include "internal-fn.def"
3979 case IFN_LAST:
3980 break;
3982 gcc_unreachable ();
3985 /* Return true if FN is supported for type TYPE when the optimization
3986 type is OPT_TYPE. The caller knows that the "type0" and "type1"
3987 fields of FN's direct_internal_fn_info structure are the same. */
3989 bool
3990 direct_internal_fn_supported_p (internal_fn fn, tree type,
3991 optimization_type opt_type)
3993 const direct_internal_fn_info &info = direct_internal_fn (fn);
3994 gcc_checking_assert (info.type0 == info.type1);
3995 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
3998 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
3999 given that STMT is a call to a direct internal function. */
4001 bool
4002 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
4004 internal_fn fn = gimple_call_internal_fn (stmt);
4005 tree_pair types = direct_internal_fn_types (fn, stmt);
4006 return direct_internal_fn_supported_p (fn, types, opt_type);
4009 /* Return true if FN is a binary operation and if FN is commutative. */
4011 bool
4012 commutative_binary_fn_p (internal_fn fn)
4014 switch (fn)
4016 case IFN_AVG_FLOOR:
4017 case IFN_AVG_CEIL:
4018 case IFN_MULH:
4019 case IFN_MULHS:
4020 case IFN_MULHRS:
4021 case IFN_FMIN:
4022 case IFN_FMAX:
4023 case IFN_COMPLEX_MUL:
4024 case IFN_UBSAN_CHECK_ADD:
4025 case IFN_UBSAN_CHECK_MUL:
4026 case IFN_ADD_OVERFLOW:
4027 case IFN_MUL_OVERFLOW:
4028 case IFN_VEC_WIDEN_PLUS:
4029 case IFN_VEC_WIDEN_PLUS_LO:
4030 case IFN_VEC_WIDEN_PLUS_HI:
4031 case IFN_VEC_WIDEN_PLUS_EVEN:
4032 case IFN_VEC_WIDEN_PLUS_ODD:
4033 return true;
4035 default:
4036 return false;
4040 /* Return true if FN is a ternary operation and if its first two arguments
4041 are commutative. */
4043 bool
4044 commutative_ternary_fn_p (internal_fn fn)
4046 switch (fn)
4048 case IFN_FMA:
4049 case IFN_FMS:
4050 case IFN_FNMA:
4051 case IFN_FNMS:
4052 return true;
4054 default:
4055 return false;
4059 /* Return true if FN is an associative binary operation. */
4061 bool
4062 associative_binary_fn_p (internal_fn fn)
4064 switch (fn)
4066 case IFN_FMIN:
4067 case IFN_FMAX:
4068 return true;
4070 default:
4071 return false;
4075 /* If FN is commutative in two consecutive arguments, return the
4076 index of the first, otherwise return -1. */
4079 first_commutative_argument (internal_fn fn)
4081 switch (fn)
4083 case IFN_COND_ADD:
4084 case IFN_COND_MUL:
4085 case IFN_COND_MIN:
4086 case IFN_COND_MAX:
4087 case IFN_COND_FMIN:
4088 case IFN_COND_FMAX:
4089 case IFN_COND_AND:
4090 case IFN_COND_IOR:
4091 case IFN_COND_XOR:
4092 case IFN_COND_FMA:
4093 case IFN_COND_FMS:
4094 case IFN_COND_FNMA:
4095 case IFN_COND_FNMS:
4096 return 1;
4098 default:
4099 if (commutative_binary_fn_p (fn)
4100 || commutative_ternary_fn_p (fn))
4101 return 0;
4102 return -1;
4106 /* Return true if this CODE describes an internal_fn that returns a vector with
4107 elements twice as wide as the element size of the input vectors. */
4109 bool
4110 widening_fn_p (code_helper code)
4112 if (!code.is_fn_code ())
4113 return false;
4115 if (!internal_fn_p ((combined_fn) code))
4116 return false;
4118 internal_fn fn = as_internal_fn ((combined_fn) code);
4119 switch (fn)
4121 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4122 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
4123 case IFN_##NAME: \
4124 case IFN_##NAME##_HI: \
4125 case IFN_##NAME##_LO: \
4126 case IFN_##NAME##_EVEN: \
4127 case IFN_##NAME##_ODD: \
4128 return true;
4129 #include "internal-fn.def"
4130 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4132 default:
4133 return false;
4137 /* Return true if IFN_SET_EDOM is supported. */
4139 bool
4140 set_edom_supported_p (void)
4142 #ifdef TARGET_EDOM
4143 return true;
4144 #else
4145 return false;
4146 #endif
4149 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4150 static void \
4151 expand_##CODE (internal_fn fn, gcall *stmt) \
4153 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
4155 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4156 UNSIGNED_OPTAB, TYPE) \
4157 static void \
4158 expand_##CODE (internal_fn fn, gcall *stmt) \
4160 tree_pair types = direct_internal_fn_types (fn, stmt); \
4161 optab which_optab = direct_internal_fn_optab (fn, types); \
4162 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
4164 #include "internal-fn.def"
4165 #undef DEF_INTERNAL_OPTAB_FN
4166 #undef DEF_INTERNAL_SIGNED_OPTAB_FN
4168 /* Routines to expand each internal function, indexed by function number.
4169 Each routine has the prototype:
4171 expand_<NAME> (gcall *stmt)
4173 where STMT is the statement that performs the call. */
4174 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
4176 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
4177 #include "internal-fn.def"
4181 /* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
4182 tree code CODE. */
4183 #define FOR_EACH_CODE_MAPPING(T) \
4184 T (PLUS_EXPR, IFN_COND_ADD) \
4185 T (MINUS_EXPR, IFN_COND_SUB) \
4186 T (MULT_EXPR, IFN_COND_MUL) \
4187 T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
4188 T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
4189 T (RDIV_EXPR, IFN_COND_RDIV) \
4190 T (MIN_EXPR, IFN_COND_MIN) \
4191 T (MAX_EXPR, IFN_COND_MAX) \
4192 T (BIT_AND_EXPR, IFN_COND_AND) \
4193 T (BIT_IOR_EXPR, IFN_COND_IOR) \
4194 T (BIT_XOR_EXPR, IFN_COND_XOR) \
4195 T (LSHIFT_EXPR, IFN_COND_SHL) \
4196 T (RSHIFT_EXPR, IFN_COND_SHR) \
4197 T (NEGATE_EXPR, IFN_COND_NEG)
4199 /* Return a function that only performs CODE when a certain condition is met
4200 and that uses a given fallback value otherwise. For example, if CODE is
4201 a binary operation associated with conditional function FN:
4203 LHS = FN (COND, A, B, ELSE)
4205 is equivalent to the C expression:
4207 LHS = COND ? A CODE B : ELSE;
4209 operating elementwise if the operands are vectors.
4211 Return IFN_LAST if no such function exists. */
4213 internal_fn
4214 get_conditional_internal_fn (tree_code code)
4216 switch (code)
4218 #define CASE(CODE, IFN) case CODE: return IFN;
4219 FOR_EACH_CODE_MAPPING(CASE)
4220 #undef CASE
4221 default:
4222 return IFN_LAST;
4226 /* If IFN implements the conditional form of a tree code, return that
4227 tree code, otherwise return ERROR_MARK. */
4229 tree_code
4230 conditional_internal_fn_code (internal_fn ifn)
4232 switch (ifn)
4234 #define CASE(CODE, IFN) case IFN: return CODE;
4235 FOR_EACH_CODE_MAPPING(CASE)
4236 #undef CASE
4237 default:
4238 return ERROR_MARK;
4242 /* Invoke T(IFN) for each internal function IFN that also has an
4243 IFN_COND_* form. */
4244 #define FOR_EACH_COND_FN_PAIR(T) \
4245 T (FMAX) \
4246 T (FMIN) \
4247 T (FMA) \
4248 T (FMS) \
4249 T (FNMA) \
4250 T (FNMS)
4252 /* Return a function that only performs internal function FN when a
4253 certain condition is met and that uses a given fallback value otherwise.
4254 In other words, the returned function FN' is such that:
4256 LHS = FN' (COND, A1, ... An, ELSE)
4258 is equivalent to the C expression:
4260 LHS = COND ? FN (A1, ..., An) : ELSE;
4262 operating elementwise if the operands are vectors.
4264 Return IFN_LAST if no such function exists. */
4266 internal_fn
4267 get_conditional_internal_fn (internal_fn fn)
4269 switch (fn)
4271 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
4272 FOR_EACH_COND_FN_PAIR(CASE)
4273 #undef CASE
4274 default:
4275 return IFN_LAST;
4279 /* If IFN implements the conditional form of an unconditional internal
4280 function, return that unconditional function, otherwise return IFN_LAST. */
4282 internal_fn
4283 get_unconditional_internal_fn (internal_fn ifn)
4285 switch (ifn)
4287 #define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
4288 FOR_EACH_COND_FN_PAIR(CASE)
4289 #undef CASE
4290 default:
4291 return IFN_LAST;
4295 /* Return true if STMT can be interpreted as a conditional tree code
4296 operation of the form:
4298 LHS = COND ? OP (RHS1, ...) : ELSE;
4300 operating elementwise if the operands are vectors. This includes
4301 the case of an all-true COND, so that the operation always happens.
4303 When returning true, set:
4305 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
4306 is known to be all-true
4307 - *CODE_OUT to the tree code
4308 - OPS[I] to operand I of *CODE_OUT
4309 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
4310 condition is known to be all true. */
4312 bool
4313 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
4314 tree_code *code_out,
4315 tree (&ops)[3], tree *else_out)
4317 if (gassign *assign = dyn_cast <gassign *> (stmt))
4319 *cond_out = NULL_TREE;
4320 *code_out = gimple_assign_rhs_code (assign);
4321 ops[0] = gimple_assign_rhs1 (assign);
4322 ops[1] = gimple_assign_rhs2 (assign);
4323 ops[2] = gimple_assign_rhs3 (assign);
4324 *else_out = NULL_TREE;
4325 return true;
4327 if (gcall *call = dyn_cast <gcall *> (stmt))
4328 if (gimple_call_internal_p (call))
4330 internal_fn ifn = gimple_call_internal_fn (call);
4331 tree_code code = conditional_internal_fn_code (ifn);
4332 if (code != ERROR_MARK)
4334 *cond_out = gimple_call_arg (call, 0);
4335 *code_out = code;
4336 unsigned int nops = gimple_call_num_args (call) - 2;
4337 for (unsigned int i = 0; i < 3; ++i)
4338 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
4339 *else_out = gimple_call_arg (call, nops + 1);
4340 if (integer_truep (*cond_out))
4342 *cond_out = NULL_TREE;
4343 *else_out = NULL_TREE;
4345 return true;
4348 return false;
4351 /* Return true if IFN is some form of load from memory. */
4353 bool
4354 internal_load_fn_p (internal_fn fn)
4356 switch (fn)
4358 case IFN_MASK_LOAD:
4359 case IFN_LOAD_LANES:
4360 case IFN_MASK_LOAD_LANES:
4361 case IFN_GATHER_LOAD:
4362 case IFN_MASK_GATHER_LOAD:
4363 case IFN_LEN_LOAD:
4364 return true;
4366 default:
4367 return false;
4371 /* Return true if IFN is some form of store to memory. */
4373 bool
4374 internal_store_fn_p (internal_fn fn)
4376 switch (fn)
4378 case IFN_MASK_STORE:
4379 case IFN_STORE_LANES:
4380 case IFN_MASK_STORE_LANES:
4381 case IFN_SCATTER_STORE:
4382 case IFN_MASK_SCATTER_STORE:
4383 case IFN_LEN_STORE:
4384 return true;
4386 default:
4387 return false;
4391 /* Return true if IFN is some form of gather load or scatter store. */
4393 bool
4394 internal_gather_scatter_fn_p (internal_fn fn)
4396 switch (fn)
4398 case IFN_GATHER_LOAD:
4399 case IFN_MASK_GATHER_LOAD:
4400 case IFN_SCATTER_STORE:
4401 case IFN_MASK_SCATTER_STORE:
4402 return true;
4404 default:
4405 return false;
4409 /* If FN takes a vector mask argument, return the index of that argument,
4410 otherwise return -1. */
4413 internal_fn_mask_index (internal_fn fn)
4415 switch (fn)
4417 case IFN_MASK_LOAD:
4418 case IFN_MASK_LOAD_LANES:
4419 case IFN_MASK_STORE:
4420 case IFN_MASK_STORE_LANES:
4421 return 2;
4423 case IFN_MASK_GATHER_LOAD:
4424 case IFN_MASK_SCATTER_STORE:
4425 return 4;
4427 default:
4428 return (conditional_internal_fn_code (fn) != ERROR_MARK
4429 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
4433 /* If FN takes a value that should be stored to memory, return the index
4434 of that argument, otherwise return -1. */
4437 internal_fn_stored_value_index (internal_fn fn)
4439 switch (fn)
4441 case IFN_MASK_STORE:
4442 case IFN_MASK_STORE_LANES:
4443 case IFN_SCATTER_STORE:
4444 case IFN_MASK_SCATTER_STORE:
4445 case IFN_LEN_STORE:
4446 return 3;
4448 default:
4449 return -1;
4453 /* Return true if the target supports gather load or scatter store function
4454 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
4455 while for stores it is the vector type of the stored data argument.
4456 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
4457 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
4458 offset from the shared base address of each loaded or stored element.
4459 SCALE is the amount by which these offsets should be multiplied
4460 *after* they have been extended to address width. */
4462 bool
4463 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
4464 tree memory_element_type,
4465 tree offset_vector_type, int scale)
4467 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
4468 TYPE_SIZE (memory_element_type)))
4469 return false;
4470 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
4471 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
4472 return false;
4473 optab optab = direct_internal_fn_optab (ifn);
4474 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
4475 TYPE_MODE (offset_vector_type));
4476 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
4477 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
4478 return (icode != CODE_FOR_nothing
4479 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
4480 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
4483 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
4484 for pointers of type TYPE when the accesses have LENGTH bytes and their
4485 common byte alignment is ALIGN. */
4487 bool
4488 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
4489 poly_uint64 length, unsigned int align)
4491 machine_mode mode = TYPE_MODE (type);
4492 optab optab = direct_internal_fn_optab (ifn);
4493 insn_code icode = direct_optab_handler (optab, mode);
4494 if (icode == CODE_FOR_nothing)
4495 return false;
4496 rtx length_rtx = immed_wide_int_const (length, mode);
4497 return (insn_operand_matches (icode, 3, length_rtx)
4498 && insn_operand_matches (icode, 4, GEN_INT (align)));
4501 /* Return the supported bias for IFN which is either IFN_LEN_LOAD
4502 or IFN_LEN_STORE. For now we only support the biases of 0 and -1
4503 (in case 0 is not an allowable length for len_load or len_store).
4504 If none of the biases match what the backend provides, return
4505 VECT_PARTIAL_BIAS_UNSUPPORTED. */
4507 signed char
4508 internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
4510 optab optab = direct_internal_fn_optab (ifn);
4511 insn_code icode = direct_optab_handler (optab, mode);
4513 if (icode != CODE_FOR_nothing)
4515 /* For now we only support biases of 0 or -1. Try both of them. */
4516 if (insn_operand_matches (icode, 3, GEN_INT (0)))
4517 return 0;
4518 if (insn_operand_matches (icode, 3, GEN_INT (-1)))
4519 return -1;
4522 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4525 /* Expand STMT as though it were a call to internal function FN. */
4527 void
4528 expand_internal_call (internal_fn fn, gcall *stmt)
4530 internal_fn_expanders[fn] (fn, stmt);
4533 /* Expand STMT, which is a call to internal function FN. */
4535 void
4536 expand_internal_call (gcall *stmt)
4538 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
4541 /* If TYPE is a vector type, return true if IFN is a direct internal
4542 function that is supported for that type. If TYPE is a scalar type,
4543 return true if IFN is a direct internal function that is supported for
4544 the target's preferred vector version of TYPE. */
4546 bool
4547 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
4549 if (VECTOR_MODE_P (TYPE_MODE (type)))
4550 return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
4552 scalar_mode smode;
4553 if (VECTOR_TYPE_P (type)
4554 || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
4555 return false;
4557 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
4558 if (VECTOR_MODE_P (vmode))
4560 tree vectype = build_vector_type_for_mode (type, vmode);
4561 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4562 return true;
4565 auto_vector_modes vector_modes;
4566 targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
4567 for (machine_mode base_mode : vector_modes)
4568 if (related_vector_mode (base_mode, smode).exists (&vmode))
4570 tree vectype = build_vector_type_for_mode (type, vmode);
4571 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4572 return true;
4575 return false;
4578 void
4579 expand_SHUFFLEVECTOR (internal_fn, gcall *)
4581 gcc_unreachable ();
4584 void
4585 expand_PHI (internal_fn, gcall *)
4587 gcc_unreachable ();
4590 void
4591 expand_SPACESHIP (internal_fn, gcall *stmt)
4593 tree lhs = gimple_call_lhs (stmt);
4594 tree rhs1 = gimple_call_arg (stmt, 0);
4595 tree rhs2 = gimple_call_arg (stmt, 1);
4596 tree type = TREE_TYPE (rhs1);
4598 do_pending_stack_adjust ();
4600 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
4601 rtx op1 = expand_normal (rhs1);
4602 rtx op2 = expand_normal (rhs2);
4604 class expand_operand ops[3];
4605 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
4606 create_input_operand (&ops[1], op1, TYPE_MODE (type));
4607 create_input_operand (&ops[2], op2, TYPE_MODE (type));
4608 insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
4609 expand_insn (icode, 3, ops);
4610 if (!rtx_equal_p (target, ops[0].value))
4611 emit_move_insn (target, ops[0].value);
4614 void
4615 expand_ASSUME (internal_fn, gcall *)
4619 void
4620 expand_MASK_CALL (internal_fn, gcall *)
4622 /* This IFN should only exist between ifcvt and vect passes. */
4623 gcc_unreachable ();