gccrs: Add another test case for passing associated type-bounds
[official-gcc.git] / gcc / internal-fn.cc
blob6e81dc05e0e0714256759b0594816df451415a2d
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 /* Fnspec of each internal function, indexed by function number. */
94 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
96 void
97 init_internal_fns ()
99 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
100 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
101 build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
102 #include "internal-fn.def"
103 internal_fn_fnspec_array[IFN_LAST] = 0;
106 /* Create static initializers for the information returned by
107 direct_internal_fn. */
108 #define not_direct { -2, -2, false }
109 #define mask_load_direct { -1, 2, false }
110 #define load_lanes_direct { -1, -1, false }
111 #define mask_load_lanes_direct { -1, -1, false }
112 #define gather_load_direct { 3, 1, false }
113 #define len_load_direct { -1, -1, false }
114 #define mask_store_direct { 3, 2, false }
115 #define store_lanes_direct { 0, 0, false }
116 #define mask_store_lanes_direct { 0, 0, false }
117 #define vec_cond_mask_direct { 1, 0, false }
118 #define vec_cond_direct { 2, 0, false }
119 #define scatter_store_direct { 3, 1, false }
120 #define len_store_direct { 3, 3, false }
121 #define vec_set_direct { 3, 3, false }
122 #define unary_direct { 0, 0, true }
123 #define unary_convert_direct { -1, 0, true }
124 #define binary_direct { 0, 0, true }
125 #define ternary_direct { 0, 0, true }
126 #define cond_unary_direct { 1, 1, true }
127 #define cond_binary_direct { 1, 1, true }
128 #define cond_ternary_direct { 1, 1, true }
129 #define while_direct { 0, 2, false }
130 #define fold_extract_direct { 2, 2, false }
131 #define fold_left_direct { 1, 1, false }
132 #define mask_fold_left_direct { 1, 1, false }
133 #define check_ptrs_direct { 0, 0, false }
135 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
136 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
137 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
138 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
139 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
140 #include "internal-fn.def"
141 not_direct
144 /* Expand STMT using instruction ICODE. The instruction has NOUTPUTS
145 output operands and NINPUTS input operands, where NOUTPUTS is either
146 0 or 1. The output operand (if any) comes first, followed by the
147 NINPUTS input operands. */
149 static void
150 expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
151 unsigned int ninputs)
153 gcc_assert (icode != CODE_FOR_nothing);
155 expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
156 unsigned int opno = 0;
157 rtx lhs_rtx = NULL_RTX;
158 tree lhs = gimple_call_lhs (stmt);
160 if (noutputs)
162 gcc_assert (noutputs == 1);
163 if (lhs)
164 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
166 /* Do not assign directly to a promoted subreg, since there is no
167 guarantee that the instruction will leave the upper bits of the
168 register in the state required by SUBREG_PROMOTED_SIGN. */
169 rtx dest = lhs_rtx;
170 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
171 dest = NULL_RTX;
172 create_output_operand (&ops[opno], dest,
173 insn_data[icode].operand[opno].mode);
174 opno += 1;
176 else
177 gcc_assert (!lhs);
179 for (unsigned int i = 0; i < ninputs; ++i)
181 tree rhs = gimple_call_arg (stmt, i);
182 tree rhs_type = TREE_TYPE (rhs);
183 rtx rhs_rtx = expand_normal (rhs);
184 if (INTEGRAL_TYPE_P (rhs_type))
185 create_convert_operand_from (&ops[opno], rhs_rtx,
186 TYPE_MODE (rhs_type),
187 TYPE_UNSIGNED (rhs_type));
188 else
189 create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
190 opno += 1;
193 gcc_assert (opno == noutputs + ninputs);
194 expand_insn (icode, opno, ops);
195 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
197 /* If the return value has an integral type, convert the instruction
198 result to that type. This is useful for things that return an
199 int regardless of the size of the input. If the instruction result
200 is smaller than required, assume that it is signed.
202 If the return value has a nonintegral type, its mode must match
203 the instruction result. */
204 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
206 /* If this is a scalar in a register that is stored in a wider
207 mode than the declared mode, compute the result into its
208 declared mode and then convert to the wider mode. */
209 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
210 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
211 convert_move (SUBREG_REG (lhs_rtx), tmp,
212 SUBREG_PROMOTED_SIGN (lhs_rtx));
214 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
215 emit_move_insn (lhs_rtx, ops[0].value);
216 else
218 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
219 convert_move (lhs_rtx, ops[0].value, 0);
224 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
225 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
227 static enum insn_code
228 get_multi_vector_move (tree array_type, convert_optab optab)
230 machine_mode imode;
231 machine_mode vmode;
233 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
234 imode = TYPE_MODE (array_type);
235 vmode = TYPE_MODE (TREE_TYPE (array_type));
237 return convert_optab_handler (optab, imode, vmode);
240 /* Expand LOAD_LANES call STMT using optab OPTAB. */
242 static void
243 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
245 class expand_operand ops[2];
246 tree type, lhs, rhs;
247 rtx target, mem;
249 lhs = gimple_call_lhs (stmt);
250 rhs = gimple_call_arg (stmt, 0);
251 type = TREE_TYPE (lhs);
253 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
254 mem = expand_normal (rhs);
256 gcc_assert (MEM_P (mem));
257 PUT_MODE (mem, TYPE_MODE (type));
259 create_output_operand (&ops[0], target, TYPE_MODE (type));
260 create_fixed_operand (&ops[1], mem);
261 expand_insn (get_multi_vector_move (type, optab), 2, ops);
262 if (!rtx_equal_p (target, ops[0].value))
263 emit_move_insn (target, ops[0].value);
266 /* Expand STORE_LANES call STMT using optab OPTAB. */
268 static void
269 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
271 class expand_operand ops[2];
272 tree type, lhs, rhs;
273 rtx target, reg;
275 lhs = gimple_call_lhs (stmt);
276 rhs = gimple_call_arg (stmt, 0);
277 type = TREE_TYPE (rhs);
279 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
280 reg = expand_normal (rhs);
282 gcc_assert (MEM_P (target));
283 PUT_MODE (target, TYPE_MODE (type));
285 create_fixed_operand (&ops[0], target);
286 create_input_operand (&ops[1], reg, TYPE_MODE (type));
287 expand_insn (get_multi_vector_move (type, optab), 2, ops);
290 static void
291 expand_ANNOTATE (internal_fn, gcall *)
293 gcc_unreachable ();
296 /* This should get expanded in omp_device_lower pass. */
298 static void
299 expand_GOMP_USE_SIMT (internal_fn, gcall *)
301 gcc_unreachable ();
304 /* This should get expanded in omp_device_lower pass. */
306 static void
307 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
309 gcc_unreachable ();
312 /* Allocate per-lane storage and begin non-uniform execution region. */
314 static void
315 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
317 rtx target;
318 tree lhs = gimple_call_lhs (stmt);
319 if (lhs)
320 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
321 else
322 target = gen_reg_rtx (Pmode);
323 rtx size = expand_normal (gimple_call_arg (stmt, 0));
324 rtx align = expand_normal (gimple_call_arg (stmt, 1));
325 class expand_operand ops[3];
326 create_output_operand (&ops[0], target, Pmode);
327 create_input_operand (&ops[1], size, Pmode);
328 create_input_operand (&ops[2], align, Pmode);
329 gcc_assert (targetm.have_omp_simt_enter ());
330 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
331 if (!rtx_equal_p (target, ops[0].value))
332 emit_move_insn (target, ops[0].value);
335 /* Deallocate per-lane storage and leave non-uniform execution region. */
337 static void
338 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
340 gcc_checking_assert (!gimple_call_lhs (stmt));
341 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
342 class expand_operand ops[1];
343 create_input_operand (&ops[0], arg, Pmode);
344 gcc_assert (targetm.have_omp_simt_exit ());
345 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
348 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
349 without SIMT execution this should be expanded in omp_device_lower pass. */
351 static void
352 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
354 tree lhs = gimple_call_lhs (stmt);
355 if (!lhs)
356 return;
358 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
359 gcc_assert (targetm.have_omp_simt_lane ());
360 emit_insn (targetm.gen_omp_simt_lane (target));
363 /* This should get expanded in omp_device_lower pass. */
365 static void
366 expand_GOMP_SIMT_VF (internal_fn, gcall *)
368 gcc_unreachable ();
371 /* This should get expanded in omp_device_lower pass. */
373 static void
374 expand_GOMP_TARGET_REV (internal_fn, gcall *)
376 gcc_unreachable ();
379 /* Lane index of the first SIMT lane that supplies a non-zero argument.
380 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
381 lane that executed the last iteration for handling OpenMP lastprivate. */
383 static void
384 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
386 tree lhs = gimple_call_lhs (stmt);
387 if (!lhs)
388 return;
390 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
391 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
392 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
393 class expand_operand ops[2];
394 create_output_operand (&ops[0], target, mode);
395 create_input_operand (&ops[1], cond, mode);
396 gcc_assert (targetm.have_omp_simt_last_lane ());
397 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
398 if (!rtx_equal_p (target, ops[0].value))
399 emit_move_insn (target, ops[0].value);
402 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
404 static void
405 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
407 tree lhs = gimple_call_lhs (stmt);
408 if (!lhs)
409 return;
411 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
412 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
413 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
414 class expand_operand ops[2];
415 create_output_operand (&ops[0], target, mode);
416 create_input_operand (&ops[1], ctr, mode);
417 gcc_assert (targetm.have_omp_simt_ordered ());
418 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
419 if (!rtx_equal_p (target, ops[0].value))
420 emit_move_insn (target, ops[0].value);
423 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
424 any lane supplies a non-zero argument. */
426 static void
427 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
429 tree lhs = gimple_call_lhs (stmt);
430 if (!lhs)
431 return;
433 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
434 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
435 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
436 class expand_operand ops[2];
437 create_output_operand (&ops[0], target, mode);
438 create_input_operand (&ops[1], cond, mode);
439 gcc_assert (targetm.have_omp_simt_vote_any ());
440 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
441 if (!rtx_equal_p (target, ops[0].value))
442 emit_move_insn (target, ops[0].value);
445 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
446 is destination lane index XOR given offset. */
448 static void
449 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
451 tree lhs = gimple_call_lhs (stmt);
452 if (!lhs)
453 return;
455 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
456 rtx src = expand_normal (gimple_call_arg (stmt, 0));
457 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
458 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
459 class expand_operand ops[3];
460 create_output_operand (&ops[0], target, mode);
461 create_input_operand (&ops[1], src, mode);
462 create_input_operand (&ops[2], idx, SImode);
463 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
464 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
465 if (!rtx_equal_p (target, ops[0].value))
466 emit_move_insn (target, ops[0].value);
469 /* Exchange between SIMT lanes according to given source lane index. */
471 static void
472 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
474 tree lhs = gimple_call_lhs (stmt);
475 if (!lhs)
476 return;
478 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
479 rtx src = expand_normal (gimple_call_arg (stmt, 0));
480 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
481 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
482 class expand_operand ops[3];
483 create_output_operand (&ops[0], target, mode);
484 create_input_operand (&ops[1], src, mode);
485 create_input_operand (&ops[2], idx, SImode);
486 gcc_assert (targetm.have_omp_simt_xchg_idx ());
487 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
488 if (!rtx_equal_p (target, ops[0].value))
489 emit_move_insn (target, ops[0].value);
492 /* This should get expanded in adjust_simduid_builtins. */
494 static void
495 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
497 gcc_unreachable ();
500 /* This should get expanded in adjust_simduid_builtins. */
502 static void
503 expand_GOMP_SIMD_VF (internal_fn, gcall *)
505 gcc_unreachable ();
508 /* This should get expanded in adjust_simduid_builtins. */
510 static void
511 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
513 gcc_unreachable ();
516 /* This should get expanded in adjust_simduid_builtins. */
518 static void
519 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
521 gcc_unreachable ();
524 /* This should get expanded in adjust_simduid_builtins. */
526 static void
527 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
529 gcc_unreachable ();
532 /* This should get expanded in the sanopt pass. */
534 static void
535 expand_UBSAN_NULL (internal_fn, gcall *)
537 gcc_unreachable ();
540 /* This should get expanded in the sanopt pass. */
542 static void
543 expand_UBSAN_BOUNDS (internal_fn, gcall *)
545 gcc_unreachable ();
548 /* This should get expanded in the sanopt pass. */
550 static void
551 expand_UBSAN_VPTR (internal_fn, gcall *)
553 gcc_unreachable ();
556 /* This should get expanded in the sanopt pass. */
558 static void
559 expand_UBSAN_PTR (internal_fn, gcall *)
561 gcc_unreachable ();
564 /* This should get expanded in the sanopt pass. */
566 static void
567 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
569 gcc_unreachable ();
572 /* This should get expanded in the sanopt pass. */
574 static void
575 expand_HWASAN_CHECK (internal_fn, gcall *)
577 gcc_unreachable ();
580 /* For hwasan stack tagging:
581 Clear tags on the dynamically allocated space.
582 For use after an object dynamically allocated on the stack goes out of
583 scope. */
584 static void
585 expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
587 gcc_assert (Pmode == ptr_mode);
588 tree restored_position = gimple_call_arg (gc, 0);
589 rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
590 EXPAND_NORMAL);
591 rtx func = init_one_libfunc ("__hwasan_tag_memory");
592 rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
593 stack_pointer_rtx, NULL_RTX, 0,
594 OPTAB_WIDEN);
595 emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
596 virtual_stack_dynamic_rtx, Pmode,
597 HWASAN_STACK_BACKGROUND, QImode,
598 off, Pmode);
601 /* For hwasan stack tagging:
602 Return a tag to be used for a dynamic allocation. */
603 static void
604 expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
606 tree tag = gimple_call_lhs (gc);
607 rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
608 machine_mode mode = GET_MODE (target);
609 gcc_assert (mode == QImode);
611 rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
612 gcc_assert (base_tag);
613 rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
614 rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
615 target, /* unsignedp = */1,
616 OPTAB_WIDEN);
617 chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
619 /* Really need to put the tag into the `target` RTX. */
620 if (chosen_tag != target)
622 rtx temp = chosen_tag;
623 gcc_assert (GET_MODE (chosen_tag) == mode);
624 emit_move_insn (target, temp);
627 hwasan_increment_frame_tag ();
630 /* For hwasan stack tagging:
631 Tag a region of space in the shadow stack according to the base pointer of
632 an object on the stack. N.b. the length provided in the internal call is
633 required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
634 static void
635 expand_HWASAN_MARK (internal_fn, gcall *gc)
637 gcc_assert (ptr_mode == Pmode);
638 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
639 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
641 tree base = gimple_call_arg (gc, 1);
642 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
643 rtx base_rtx = expand_normal (base);
645 rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
646 : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
647 rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
649 tree len = gimple_call_arg (gc, 2);
650 rtx r_len = expand_normal (len);
652 rtx func = init_one_libfunc ("__hwasan_tag_memory");
653 emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
654 tag, QImode, r_len, Pmode);
657 /* For hwasan stack tagging:
658 Store a tag into a pointer. */
659 static void
660 expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
662 gcc_assert (ptr_mode == Pmode);
663 tree g_target = gimple_call_lhs (gc);
664 tree g_ptr = gimple_call_arg (gc, 0);
665 tree g_tag = gimple_call_arg (gc, 1);
667 rtx ptr = expand_normal (g_ptr);
668 rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
669 rtx target = expand_normal (g_target);
671 rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
672 rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
673 if (tagged_value != target)
674 emit_move_insn (target, tagged_value);
677 /* This should get expanded in the sanopt pass. */
679 static void
680 expand_ASAN_CHECK (internal_fn, gcall *)
682 gcc_unreachable ();
685 /* This should get expanded in the sanopt pass. */
687 static void
688 expand_ASAN_MARK (internal_fn, gcall *)
690 gcc_unreachable ();
693 /* This should get expanded in the sanopt pass. */
695 static void
696 expand_ASAN_POISON (internal_fn, gcall *)
698 gcc_unreachable ();
701 /* This should get expanded in the sanopt pass. */
703 static void
704 expand_ASAN_POISON_USE (internal_fn, gcall *)
706 gcc_unreachable ();
709 /* This should get expanded in the tsan pass. */
711 static void
712 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
714 gcc_unreachable ();
717 /* This should get expanded in the lower pass. */
719 static void
720 expand_FALLTHROUGH (internal_fn, gcall *call)
722 error_at (gimple_location (call),
723 "invalid use of attribute %<fallthrough%>");
726 /* Return minimum precision needed to represent all values
727 of ARG in SIGNed integral type. */
729 static int
730 get_min_precision (tree arg, signop sign)
732 int prec = TYPE_PRECISION (TREE_TYPE (arg));
733 int cnt = 0;
734 signop orig_sign = sign;
735 if (TREE_CODE (arg) == INTEGER_CST)
737 int p;
738 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
740 widest_int w = wi::to_widest (arg);
741 w = wi::ext (w, prec, sign);
742 p = wi::min_precision (w, sign);
744 else
745 p = wi::min_precision (wi::to_wide (arg), sign);
746 return MIN (p, prec);
748 while (CONVERT_EXPR_P (arg)
749 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
750 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
752 arg = TREE_OPERAND (arg, 0);
753 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
755 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
756 sign = UNSIGNED;
757 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
758 return prec + (orig_sign != sign);
759 prec = TYPE_PRECISION (TREE_TYPE (arg));
761 if (++cnt > 30)
762 return prec + (orig_sign != sign);
764 if (CONVERT_EXPR_P (arg)
765 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
766 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
768 /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
769 If y_2's min precision is smaller than prec, return that. */
770 int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
771 if (oprec < prec)
772 return oprec + (orig_sign != sign);
774 if (TREE_CODE (arg) != SSA_NAME)
775 return prec + (orig_sign != sign);
776 value_range r;
777 while (!get_global_range_query ()->range_of_expr (r, arg)
778 || r.kind () != VR_RANGE)
780 gimple *g = SSA_NAME_DEF_STMT (arg);
781 if (is_gimple_assign (g)
782 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
784 tree t = gimple_assign_rhs1 (g);
785 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
786 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
788 arg = t;
789 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
791 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
792 sign = UNSIGNED;
793 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
794 return prec + (orig_sign != sign);
795 prec = TYPE_PRECISION (TREE_TYPE (arg));
797 if (++cnt > 30)
798 return prec + (orig_sign != sign);
799 continue;
802 return prec + (orig_sign != sign);
804 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
806 int p1 = wi::min_precision (r.lower_bound (), sign);
807 int p2 = wi::min_precision (r.upper_bound (), sign);
808 p1 = MAX (p1, p2);
809 prec = MIN (prec, p1);
811 else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
813 int p = wi::min_precision (r.upper_bound (), UNSIGNED);
814 prec = MIN (prec, p);
816 return prec + (orig_sign != sign);
819 /* Helper for expand_*_overflow. Set the __imag__ part to true
820 (1 except for signed:1 type, in which case store -1). */
822 static void
823 expand_arith_set_overflow (tree lhs, rtx target)
825 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
826 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
827 write_complex_part (target, constm1_rtx, true, false);
828 else
829 write_complex_part (target, const1_rtx, true, false);
832 /* Helper for expand_*_overflow. Store RES into the __real__ part
833 of TARGET. If RES has larger MODE than __real__ part of TARGET,
834 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
835 if LHS has smaller precision than its mode. */
837 static void
838 expand_arith_overflow_result_store (tree lhs, rtx target,
839 scalar_int_mode mode, rtx res)
841 scalar_int_mode tgtmode
842 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
843 rtx lres = res;
844 if (tgtmode != mode)
846 rtx_code_label *done_label = gen_label_rtx ();
847 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
848 lres = convert_modes (tgtmode, mode, res, uns);
849 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
850 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
851 EQ, true, mode, NULL_RTX, NULL, done_label,
852 profile_probability::very_likely ());
853 expand_arith_set_overflow (lhs, target);
854 emit_label (done_label);
856 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
857 int tgtprec = GET_MODE_PRECISION (tgtmode);
858 if (prec < tgtprec)
860 rtx_code_label *done_label = gen_label_rtx ();
861 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
862 res = lres;
863 if (uns)
865 rtx mask
866 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
867 tgtmode);
868 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
869 true, OPTAB_LIB_WIDEN);
871 else
873 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
874 NULL_RTX, 1);
875 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
876 NULL_RTX, 0);
878 do_compare_rtx_and_jump (res, lres,
879 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
880 profile_probability::very_likely ());
881 expand_arith_set_overflow (lhs, target);
882 emit_label (done_label);
884 write_complex_part (target, lres, false, false);
887 /* Helper for expand_*_overflow. Store RES into TARGET. */
889 static void
890 expand_ubsan_result_store (rtx target, rtx res)
892 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
893 /* If this is a scalar in a register that is stored in a wider mode
894 than the declared mode, compute the result into its declared mode
895 and then convert to the wider mode. Our value is the computed
896 expression. */
897 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
898 else
899 emit_move_insn (target, res);
902 /* Add sub/add overflow checking to the statement STMT.
903 CODE says whether the operation is +, or -. */
905 void
906 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
907 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
908 bool uns1_p, bool is_ubsan, tree *datap)
910 rtx res, target = NULL_RTX;
911 tree fn;
912 rtx_code_label *done_label = gen_label_rtx ();
913 rtx_code_label *do_error = gen_label_rtx ();
914 do_pending_stack_adjust ();
915 rtx op0 = expand_normal (arg0);
916 rtx op1 = expand_normal (arg1);
917 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
918 int prec = GET_MODE_PRECISION (mode);
919 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
920 bool do_xor = false;
922 if (is_ubsan)
923 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
925 if (lhs)
927 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
928 if (!is_ubsan)
929 write_complex_part (target, const0_rtx, true, false);
932 /* We assume both operands and result have the same precision
933 here (GET_MODE_BITSIZE (mode)), S stands for signed type
934 with that precision, U for unsigned type with that precision,
935 sgn for unsigned most significant bit in that precision.
936 s1 is signed first operand, u1 is unsigned first operand,
937 s2 is signed second operand, u2 is unsigned second operand,
938 sr is signed result, ur is unsigned result and the following
939 rules say how to compute result (which is always result of
940 the operands as if both were unsigned, cast to the right
941 signedness) and how to compute whether operation overflowed.
943 s1 + s2 -> sr
944 res = (S) ((U) s1 + (U) s2)
945 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
946 s1 - s2 -> sr
947 res = (S) ((U) s1 - (U) s2)
948 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
949 u1 + u2 -> ur
950 res = u1 + u2
951 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
952 u1 - u2 -> ur
953 res = u1 - u2
954 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
955 s1 + u2 -> sr
956 res = (S) ((U) s1 + u2)
957 ovf = ((U) res ^ sgn) < u2
958 s1 + u2 -> ur
959 t1 = (S) (u2 ^ sgn)
960 t2 = s1 + t1
961 res = (U) t2 ^ sgn
962 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
963 s1 - u2 -> sr
964 res = (S) ((U) s1 - u2)
965 ovf = u2 > ((U) s1 ^ sgn)
966 s1 - u2 -> ur
967 res = (U) s1 - u2
968 ovf = s1 < 0 || u2 > (U) s1
969 u1 - s2 -> sr
970 res = u1 - (U) s2
971 ovf = u1 >= ((U) s2 ^ sgn)
972 u1 - s2 -> ur
973 t1 = u1 ^ sgn
974 t2 = t1 - (U) s2
975 res = t2 ^ sgn
976 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
977 s1 + s2 -> ur
978 res = (U) s1 + (U) s2
979 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
980 u1 + u2 -> sr
981 res = (S) (u1 + u2)
982 ovf = (U) res < u2 || res < 0
983 u1 - u2 -> sr
984 res = (S) (u1 - u2)
985 ovf = u1 >= u2 ? res < 0 : res >= 0
986 s1 - s2 -> ur
987 res = (U) s1 - (U) s2
988 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
990 if (code == PLUS_EXPR && uns0_p && !uns1_p)
992 /* PLUS_EXPR is commutative, if operand signedness differs,
993 canonicalize to the first operand being signed and second
994 unsigned to simplify following code. */
995 std::swap (op0, op1);
996 std::swap (arg0, arg1);
997 uns0_p = false;
998 uns1_p = true;
1001 /* u1 +- u2 -> ur */
1002 if (uns0_p && uns1_p && unsr_p)
1004 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
1005 : usubv4_optab, mode);
1006 if (icode != CODE_FOR_nothing)
1008 class expand_operand ops[4];
1009 rtx_insn *last = get_last_insn ();
1011 res = gen_reg_rtx (mode);
1012 create_output_operand (&ops[0], res, mode);
1013 create_input_operand (&ops[1], op0, mode);
1014 create_input_operand (&ops[2], op1, mode);
1015 create_fixed_operand (&ops[3], do_error);
1016 if (maybe_expand_insn (icode, 4, ops))
1018 last = get_last_insn ();
1019 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1020 && JUMP_P (last)
1021 && any_condjump_p (last)
1022 && !find_reg_note (last, REG_BR_PROB, 0))
1023 add_reg_br_prob_note (last,
1024 profile_probability::very_unlikely ());
1025 emit_jump (done_label);
1026 goto do_error_label;
1029 delete_insns_since (last);
1032 /* Compute the operation. On RTL level, the addition is always
1033 unsigned. */
1034 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1035 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1036 rtx tem = op0;
1037 /* For PLUS_EXPR, the operation is commutative, so we can pick
1038 operand to compare against. For prec <= BITS_PER_WORD, I think
1039 preferring REG operand is better over CONST_INT, because
1040 the CONST_INT might enlarge the instruction or CSE would need
1041 to figure out we'd already loaded it into a register before.
1042 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
1043 as then the multi-word comparison can be perhaps simplified. */
1044 if (code == PLUS_EXPR
1045 && (prec <= BITS_PER_WORD
1046 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
1047 : CONST_SCALAR_INT_P (op1)))
1048 tem = op1;
1049 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1050 true, mode, NULL_RTX, NULL, done_label,
1051 profile_probability::very_likely ());
1052 goto do_error_label;
1055 /* s1 +- u2 -> sr */
1056 if (!uns0_p && uns1_p && !unsr_p)
1058 /* Compute the operation. On RTL level, the addition is always
1059 unsigned. */
1060 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1061 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1062 rtx tem = expand_binop (mode, add_optab,
1063 code == PLUS_EXPR ? res : op0, sgn,
1064 NULL_RTX, false, OPTAB_LIB_WIDEN);
1065 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1066 done_label, profile_probability::very_likely ());
1067 goto do_error_label;
1070 /* s1 + u2 -> ur */
1071 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
1073 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1074 OPTAB_LIB_WIDEN);
1075 /* As we've changed op1, we have to avoid using the value range
1076 for the original argument. */
1077 arg1 = error_mark_node;
1078 do_xor = true;
1079 goto do_signed;
1082 /* u1 - s2 -> ur */
1083 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
1085 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
1086 OPTAB_LIB_WIDEN);
1087 /* As we've changed op0, we have to avoid using the value range
1088 for the original argument. */
1089 arg0 = error_mark_node;
1090 do_xor = true;
1091 goto do_signed;
1094 /* s1 - u2 -> ur */
1095 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
1097 /* Compute the operation. On RTL level, the addition is always
1098 unsigned. */
1099 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1100 OPTAB_LIB_WIDEN);
1101 int pos_neg = get_range_pos_neg (arg0);
1102 if (pos_neg == 2)
1103 /* If ARG0 is known to be always negative, this is always overflow. */
1104 emit_jump (do_error);
1105 else if (pos_neg == 3)
1106 /* If ARG0 is not known to be always positive, check at runtime. */
1107 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1108 NULL, do_error, profile_probability::very_unlikely ());
1109 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1110 done_label, profile_probability::very_likely ());
1111 goto do_error_label;
1114 /* u1 - s2 -> sr */
1115 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
1117 /* Compute the operation. On RTL level, the addition is always
1118 unsigned. */
1119 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1120 OPTAB_LIB_WIDEN);
1121 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1122 OPTAB_LIB_WIDEN);
1123 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1124 done_label, profile_probability::very_likely ());
1125 goto do_error_label;
1128 /* u1 + u2 -> sr */
1129 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
1131 /* Compute the operation. On RTL level, the addition is always
1132 unsigned. */
1133 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
1134 OPTAB_LIB_WIDEN);
1135 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1136 NULL, do_error, profile_probability::very_unlikely ());
1137 rtx tem = op1;
1138 /* The operation is commutative, so we can pick operand to compare
1139 against. For prec <= BITS_PER_WORD, I think preferring REG operand
1140 is better over CONST_INT, because the CONST_INT might enlarge the
1141 instruction or CSE would need to figure out we'd already loaded it
1142 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
1143 might be more beneficial, as then the multi-word comparison can be
1144 perhaps simplified. */
1145 if (prec <= BITS_PER_WORD
1146 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
1147 : CONST_SCALAR_INT_P (op0))
1148 tem = op0;
1149 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1150 done_label, profile_probability::very_likely ());
1151 goto do_error_label;
1154 /* s1 +- s2 -> ur */
1155 if (!uns0_p && !uns1_p && unsr_p)
1157 /* Compute the operation. On RTL level, the addition is always
1158 unsigned. */
1159 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1160 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1161 int pos_neg = get_range_pos_neg (arg1);
1162 if (code == PLUS_EXPR)
1164 int pos_neg0 = get_range_pos_neg (arg0);
1165 if (pos_neg0 != 3 && pos_neg == 3)
1167 std::swap (op0, op1);
1168 pos_neg = pos_neg0;
1171 rtx tem;
1172 if (pos_neg != 3)
1174 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
1175 ? and_optab : ior_optab,
1176 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1177 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
1178 NULL, done_label, profile_probability::very_likely ());
1180 else
1182 rtx_code_label *do_ior_label = gen_label_rtx ();
1183 do_compare_rtx_and_jump (op1, const0_rtx,
1184 code == MINUS_EXPR ? GE : LT, false, mode,
1185 NULL_RTX, NULL, do_ior_label,
1186 profile_probability::even ());
1187 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
1188 OPTAB_LIB_WIDEN);
1189 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1190 NULL, done_label, profile_probability::very_likely ());
1191 emit_jump (do_error);
1192 emit_label (do_ior_label);
1193 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
1194 OPTAB_LIB_WIDEN);
1195 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1196 NULL, done_label, profile_probability::very_likely ());
1198 goto do_error_label;
1201 /* u1 - u2 -> sr */
1202 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
1204 /* Compute the operation. On RTL level, the addition is always
1205 unsigned. */
1206 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1207 OPTAB_LIB_WIDEN);
1208 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1209 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1210 op0_geu_op1, profile_probability::even ());
1211 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1212 NULL, done_label, profile_probability::very_likely ());
1213 emit_jump (do_error);
1214 emit_label (op0_geu_op1);
1215 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1216 NULL, done_label, profile_probability::very_likely ());
1217 goto do_error_label;
1220 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1222 /* s1 +- s2 -> sr */
1223 do_signed:
1225 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1226 : subv4_optab, mode);
1227 if (icode != CODE_FOR_nothing)
1229 class expand_operand ops[4];
1230 rtx_insn *last = get_last_insn ();
1232 res = gen_reg_rtx (mode);
1233 create_output_operand (&ops[0], res, mode);
1234 create_input_operand (&ops[1], op0, mode);
1235 create_input_operand (&ops[2], op1, mode);
1236 create_fixed_operand (&ops[3], do_error);
1237 if (maybe_expand_insn (icode, 4, ops))
1239 last = get_last_insn ();
1240 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1241 && JUMP_P (last)
1242 && any_condjump_p (last)
1243 && !find_reg_note (last, REG_BR_PROB, 0))
1244 add_reg_br_prob_note (last,
1245 profile_probability::very_unlikely ());
1246 emit_jump (done_label);
1247 goto do_error_label;
1250 delete_insns_since (last);
1253 /* Compute the operation. On RTL level, the addition is always
1254 unsigned. */
1255 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1256 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1258 /* If we can prove that one of the arguments (for MINUS_EXPR only
1259 the second operand, as subtraction is not commutative) is always
1260 non-negative or always negative, we can do just one comparison
1261 and conditional jump. */
1262 int pos_neg = get_range_pos_neg (arg1);
1263 if (code == PLUS_EXPR)
1265 int pos_neg0 = get_range_pos_neg (arg0);
1266 if (pos_neg0 != 3 && pos_neg == 3)
1268 std::swap (op0, op1);
1269 pos_neg = pos_neg0;
1273 /* Addition overflows if and only if the two operands have the same sign,
1274 and the result has the opposite sign. Subtraction overflows if and
1275 only if the two operands have opposite sign, and the subtrahend has
1276 the same sign as the result. Here 0 is counted as positive. */
1277 if (pos_neg == 3)
1279 /* Compute op0 ^ op1 (operands have opposite sign). */
1280 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1281 OPTAB_LIB_WIDEN);
1283 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1284 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1285 OPTAB_LIB_WIDEN);
1287 rtx tem;
1288 if (code == PLUS_EXPR)
1290 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1291 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1292 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1293 OPTAB_LIB_WIDEN);
1295 else
1297 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1298 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1299 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1300 OPTAB_LIB_WIDEN);
1303 /* No overflow if the result has bit sign cleared. */
1304 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1305 NULL, done_label, profile_probability::very_likely ());
1308 /* Compare the result of the operation with the first operand.
1309 No overflow for addition if second operand is positive and result
1310 is larger or second operand is negative and result is smaller.
1311 Likewise for subtraction with sign of second operand flipped. */
1312 else
1313 do_compare_rtx_and_jump (res, op0,
1314 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1315 false, mode, NULL_RTX, NULL, done_label,
1316 profile_probability::very_likely ());
1319 do_error_label:
1320 emit_label (do_error);
1321 if (is_ubsan)
1323 /* Expand the ubsan builtin call. */
1324 push_temp_slots ();
1325 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1326 arg0, arg1, datap);
1327 expand_normal (fn);
1328 pop_temp_slots ();
1329 do_pending_stack_adjust ();
1331 else if (lhs)
1332 expand_arith_set_overflow (lhs, target);
1334 /* We're done. */
1335 emit_label (done_label);
1337 if (lhs)
1339 if (is_ubsan)
1340 expand_ubsan_result_store (target, res);
1341 else
1343 if (do_xor)
1344 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1345 OPTAB_LIB_WIDEN);
1347 expand_arith_overflow_result_store (lhs, target, mode, res);
1352 /* Add negate overflow checking to the statement STMT. */
1354 static void
1355 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1356 tree *datap)
1358 rtx res, op1;
1359 tree fn;
1360 rtx_code_label *done_label, *do_error;
1361 rtx target = NULL_RTX;
1363 done_label = gen_label_rtx ();
1364 do_error = gen_label_rtx ();
1366 do_pending_stack_adjust ();
1367 op1 = expand_normal (arg1);
1369 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1370 if (lhs)
1372 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1373 if (!is_ubsan)
1374 write_complex_part (target, const0_rtx, true, false);
1377 enum insn_code icode = optab_handler (negv3_optab, mode);
1378 if (icode != CODE_FOR_nothing)
1380 class expand_operand ops[3];
1381 rtx_insn *last = get_last_insn ();
1383 res = gen_reg_rtx (mode);
1384 create_output_operand (&ops[0], res, mode);
1385 create_input_operand (&ops[1], op1, mode);
1386 create_fixed_operand (&ops[2], do_error);
1387 if (maybe_expand_insn (icode, 3, ops))
1389 last = get_last_insn ();
1390 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1391 && JUMP_P (last)
1392 && any_condjump_p (last)
1393 && !find_reg_note (last, REG_BR_PROB, 0))
1394 add_reg_br_prob_note (last,
1395 profile_probability::very_unlikely ());
1396 emit_jump (done_label);
1398 else
1400 delete_insns_since (last);
1401 icode = CODE_FOR_nothing;
1405 if (icode == CODE_FOR_nothing)
1407 /* Compute the operation. On RTL level, the addition is always
1408 unsigned. */
1409 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1411 /* Compare the operand with the most negative value. */
1412 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1413 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1414 done_label, profile_probability::very_likely ());
1417 emit_label (do_error);
1418 if (is_ubsan)
1420 /* Expand the ubsan builtin call. */
1421 push_temp_slots ();
1422 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1423 arg1, NULL_TREE, datap);
1424 expand_normal (fn);
1425 pop_temp_slots ();
1426 do_pending_stack_adjust ();
1428 else if (lhs)
1429 expand_arith_set_overflow (lhs, target);
1431 /* We're done. */
1432 emit_label (done_label);
1434 if (lhs)
1436 if (is_ubsan)
1437 expand_ubsan_result_store (target, res);
1438 else
1439 expand_arith_overflow_result_store (lhs, target, mode, res);
1443 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1444 mode MODE can be expanded without using a libcall. */
1446 static bool
1447 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1448 rtx op0, rtx op1, bool uns)
1450 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1451 != CODE_FOR_nothing)
1452 return true;
1454 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1455 != CODE_FOR_nothing)
1456 return true;
1458 rtx_insn *last = get_last_insn ();
1459 if (CONSTANT_P (op0))
1460 op0 = convert_modes (wmode, mode, op0, uns);
1461 else
1462 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1463 if (CONSTANT_P (op1))
1464 op1 = convert_modes (wmode, mode, op1, uns);
1465 else
1466 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1467 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1468 delete_insns_since (last);
1469 return ret != NULL_RTX;
1472 /* Add mul overflow checking to the statement STMT. */
1474 static void
1475 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1476 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1477 tree *datap)
1479 rtx res, op0, op1;
1480 tree fn, type;
1481 rtx_code_label *done_label, *do_error;
1482 rtx target = NULL_RTX;
1483 signop sign;
1484 enum insn_code icode;
1486 done_label = gen_label_rtx ();
1487 do_error = gen_label_rtx ();
1489 do_pending_stack_adjust ();
1490 op0 = expand_normal (arg0);
1491 op1 = expand_normal (arg1);
1493 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1494 bool uns = unsr_p;
1495 if (lhs)
1497 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1498 if (!is_ubsan)
1499 write_complex_part (target, const0_rtx, true, false);
1502 if (is_ubsan)
1503 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1505 /* We assume both operands and result have the same precision
1506 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1507 with that precision, U for unsigned type with that precision,
1508 sgn for unsigned most significant bit in that precision.
1509 s1 is signed first operand, u1 is unsigned first operand,
1510 s2 is signed second operand, u2 is unsigned second operand,
1511 sr is signed result, ur is unsigned result and the following
1512 rules say how to compute result (which is always result of
1513 the operands as if both were unsigned, cast to the right
1514 signedness) and how to compute whether operation overflowed.
1515 main_ovf (false) stands for jump on signed multiplication
1516 overflow or the main algorithm with uns == false.
1517 main_ovf (true) stands for jump on unsigned multiplication
1518 overflow or the main algorithm with uns == true.
1520 s1 * s2 -> sr
1521 res = (S) ((U) s1 * (U) s2)
1522 ovf = main_ovf (false)
1523 u1 * u2 -> ur
1524 res = u1 * u2
1525 ovf = main_ovf (true)
1526 s1 * u2 -> ur
1527 res = (U) s1 * u2
1528 ovf = (s1 < 0 && u2) || main_ovf (true)
1529 u1 * u2 -> sr
1530 res = (S) (u1 * u2)
1531 ovf = res < 0 || main_ovf (true)
1532 s1 * u2 -> sr
1533 res = (S) ((U) s1 * u2)
1534 ovf = (S) u2 >= 0 ? main_ovf (false)
1535 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1536 s1 * s2 -> ur
1537 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1538 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1539 res = t1 * t2
1540 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1542 if (uns0_p && !uns1_p)
1544 /* Multiplication is commutative, if operand signedness differs,
1545 canonicalize to the first operand being signed and second
1546 unsigned to simplify following code. */
1547 std::swap (op0, op1);
1548 std::swap (arg0, arg1);
1549 uns0_p = false;
1550 uns1_p = true;
1553 int pos_neg0 = get_range_pos_neg (arg0);
1554 int pos_neg1 = get_range_pos_neg (arg1);
1556 /* s1 * u2 -> ur */
1557 if (!uns0_p && uns1_p && unsr_p)
1559 switch (pos_neg0)
1561 case 1:
1562 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1563 goto do_main;
1564 case 2:
1565 /* If s1 is negative, avoid the main code, just multiply and
1566 signal overflow if op1 is not 0. */
1567 struct separate_ops ops;
1568 ops.code = MULT_EXPR;
1569 ops.type = TREE_TYPE (arg1);
1570 ops.op0 = make_tree (ops.type, op0);
1571 ops.op1 = make_tree (ops.type, op1);
1572 ops.op2 = NULL_TREE;
1573 ops.location = loc;
1574 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1575 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1576 NULL, done_label, profile_probability::very_likely ());
1577 goto do_error_label;
1578 case 3:
1579 if (get_min_precision (arg1, UNSIGNED)
1580 + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
1582 /* If the first operand is sign extended from narrower type, the
1583 second operand is zero extended from narrower type and
1584 the sum of the two precisions is smaller or equal to the
1585 result precision: if the first argument is at runtime
1586 non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
1587 and there will be no overflow, if the first argument is
1588 negative and the second argument zero, the result will be
1589 0 and there will be no overflow, if the first argument is
1590 negative and the second argument positive, the result when
1591 treated as signed will be negative (minimum -0x7f80 or
1592 -0x7f..f80..0) there will be always overflow. So, do
1593 res = (U) (s1 * u2)
1594 ovf = (S) res < 0 */
1595 struct separate_ops ops;
1596 ops.code = MULT_EXPR;
1597 ops.type
1598 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1600 ops.op0 = make_tree (ops.type, op0);
1601 ops.op1 = make_tree (ops.type, op1);
1602 ops.op2 = NULL_TREE;
1603 ops.location = loc;
1604 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1605 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1606 mode, NULL_RTX, NULL, done_label,
1607 profile_probability::very_likely ());
1608 goto do_error_label;
1610 rtx_code_label *do_main_label;
1611 do_main_label = gen_label_rtx ();
1612 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1613 NULL, do_main_label, profile_probability::very_likely ());
1614 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1615 NULL, do_main_label, profile_probability::very_likely ());
1616 expand_arith_set_overflow (lhs, target);
1617 emit_label (do_main_label);
1618 goto do_main;
1619 default:
1620 gcc_unreachable ();
1624 /* u1 * u2 -> sr */
1625 if (uns0_p && uns1_p && !unsr_p)
1627 if ((pos_neg0 | pos_neg1) == 1)
1629 /* If both arguments are zero extended from narrower types,
1630 the MSB will be clear on both and so we can pretend it is
1631 a normal s1 * s2 -> sr multiplication. */
1632 uns0_p = false;
1633 uns1_p = false;
1635 else
1636 uns = true;
1637 /* Rest of handling of this case after res is computed. */
1638 goto do_main;
1641 /* s1 * u2 -> sr */
1642 if (!uns0_p && uns1_p && !unsr_p)
1644 switch (pos_neg1)
1646 case 1:
1647 goto do_main;
1648 case 2:
1649 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1650 avoid the main code, just multiply and signal overflow
1651 unless 0 * u2 or -1 * ((U) Smin). */
1652 struct separate_ops ops;
1653 ops.code = MULT_EXPR;
1654 ops.type = TREE_TYPE (arg1);
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 (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1661 NULL, done_label, profile_probability::very_likely ());
1662 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1663 NULL, do_error, profile_probability::very_unlikely ());
1664 int prec;
1665 prec = GET_MODE_PRECISION (mode);
1666 rtx sgn;
1667 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1668 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1669 NULL, done_label, profile_probability::very_likely ());
1670 goto do_error_label;
1671 case 3:
1672 /* Rest of handling of this case after res is computed. */
1673 goto do_main;
1674 default:
1675 gcc_unreachable ();
1679 /* s1 * s2 -> ur */
1680 if (!uns0_p && !uns1_p && unsr_p)
1682 rtx tem;
1683 switch (pos_neg0 | pos_neg1)
1685 case 1: /* Both operands known to be non-negative. */
1686 goto do_main;
1687 case 2: /* Both operands known to be negative. */
1688 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1689 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1690 /* Avoid looking at arg0/arg1 ranges, as we've changed
1691 the arguments. */
1692 arg0 = error_mark_node;
1693 arg1 = error_mark_node;
1694 goto do_main;
1695 case 3:
1696 if ((pos_neg0 ^ pos_neg1) == 3)
1698 /* If one operand is known to be negative and the other
1699 non-negative, this overflows always, unless the non-negative
1700 one is 0. Just do normal multiply and set overflow
1701 unless one of the operands is 0. */
1702 struct separate_ops ops;
1703 ops.code = MULT_EXPR;
1704 ops.type
1705 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1707 ops.op0 = make_tree (ops.type, op0);
1708 ops.op1 = make_tree (ops.type, op1);
1709 ops.op2 = NULL_TREE;
1710 ops.location = loc;
1711 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1712 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1713 true, mode, NULL_RTX, NULL, done_label,
1714 profile_probability::very_likely ());
1715 goto do_error_label;
1717 if (get_min_precision (arg0, SIGNED)
1718 + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
1720 /* If both operands are sign extended from narrower types and
1721 the sum of the two precisions is smaller or equal to the
1722 result precision: if both arguments are at runtime
1723 non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
1724 and there will be no overflow, if both arguments are negative,
1725 maximum result will be 0x40..00 and there will be no overflow
1726 either, if one argument is positive and the other argument
1727 negative, the result when treated as signed will be negative
1728 and there will be always overflow, and if one argument is
1729 zero and the other negative the result will be zero and no
1730 overflow. So, do
1731 res = (U) (s1 * s2)
1732 ovf = (S) res < 0 */
1733 struct separate_ops ops;
1734 ops.code = MULT_EXPR;
1735 ops.type
1736 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1738 ops.op0 = make_tree (ops.type, op0);
1739 ops.op1 = make_tree (ops.type, op1);
1740 ops.op2 = NULL_TREE;
1741 ops.location = loc;
1742 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1743 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1744 mode, NULL_RTX, NULL, done_label,
1745 profile_probability::very_likely ());
1746 goto do_error_label;
1748 /* The general case, do all the needed comparisons at runtime. */
1749 rtx_code_label *do_main_label, *after_negate_label;
1750 rtx rop0, rop1;
1751 rop0 = gen_reg_rtx (mode);
1752 rop1 = gen_reg_rtx (mode);
1753 emit_move_insn (rop0, op0);
1754 emit_move_insn (rop1, op1);
1755 op0 = rop0;
1756 op1 = rop1;
1757 do_main_label = gen_label_rtx ();
1758 after_negate_label = gen_label_rtx ();
1759 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1760 OPTAB_LIB_WIDEN);
1761 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1762 NULL, after_negate_label, profile_probability::very_likely ());
1763 /* Both arguments negative here, negate them and continue with
1764 normal unsigned overflow checking multiplication. */
1765 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1766 NULL_RTX, false));
1767 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1768 NULL_RTX, false));
1769 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1770 the arguments. */
1771 arg0 = error_mark_node;
1772 arg1 = error_mark_node;
1773 emit_jump (do_main_label);
1774 emit_label (after_negate_label);
1775 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1776 OPTAB_LIB_WIDEN);
1777 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1778 NULL, do_main_label,
1779 profile_probability::very_likely ());
1780 /* One argument is negative here, the other positive. This
1781 overflows always, unless one of the arguments is 0. But
1782 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1783 is, thus we can keep do_main code oring in overflow as is. */
1784 if (pos_neg0 != 2)
1785 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1786 NULL, do_main_label,
1787 profile_probability::very_unlikely ());
1788 if (pos_neg1 != 2)
1789 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1790 NULL, do_main_label,
1791 profile_probability::very_unlikely ());
1792 expand_arith_set_overflow (lhs, target);
1793 emit_label (do_main_label);
1794 goto do_main;
1795 default:
1796 gcc_unreachable ();
1800 do_main:
1801 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1802 sign = uns ? UNSIGNED : SIGNED;
1803 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1804 if (uns
1805 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1806 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1808 /* Optimize unsigned multiplication by power of 2 constant
1809 using 2 shifts, one for result, one to extract the shifted
1810 out bits to see if they are all zero.
1811 Don't do this if optimizing for size and we have umulv4_optab,
1812 in that case assume multiplication will be shorter.
1813 This is heuristics based on the single target that provides
1814 umulv4 right now (i?86/x86_64), if further targets add it, this
1815 might need to be revisited.
1816 Cases where both operands are constant should be folded already
1817 during GIMPLE, and cases where one operand is constant but not
1818 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1819 below can be done without multiplication, just by shifts and adds,
1820 or we'd need to divide the result (and hope it actually doesn't
1821 really divide nor multiply) and compare the result of the division
1822 with the original operand. */
1823 rtx opn0 = op0;
1824 rtx opn1 = op1;
1825 tree argn0 = arg0;
1826 tree argn1 = arg1;
1827 if (integer_pow2p (arg0))
1829 std::swap (opn0, opn1);
1830 std::swap (argn0, argn1);
1832 int cnt = tree_log2 (argn1);
1833 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1835 rtx upper = const0_rtx;
1836 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1837 if (cnt != 0)
1838 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1839 GET_MODE_PRECISION (mode) - cnt,
1840 NULL_RTX, uns);
1841 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1842 NULL_RTX, NULL, done_label,
1843 profile_probability::very_likely ());
1844 goto do_error_label;
1847 if (icode != CODE_FOR_nothing)
1849 class expand_operand ops[4];
1850 rtx_insn *last = get_last_insn ();
1852 res = gen_reg_rtx (mode);
1853 create_output_operand (&ops[0], res, mode);
1854 create_input_operand (&ops[1], op0, mode);
1855 create_input_operand (&ops[2], op1, mode);
1856 create_fixed_operand (&ops[3], do_error);
1857 if (maybe_expand_insn (icode, 4, ops))
1859 last = get_last_insn ();
1860 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1861 && JUMP_P (last)
1862 && any_condjump_p (last)
1863 && !find_reg_note (last, REG_BR_PROB, 0))
1864 add_reg_br_prob_note (last,
1865 profile_probability::very_unlikely ());
1866 emit_jump (done_label);
1868 else
1870 delete_insns_since (last);
1871 icode = CODE_FOR_nothing;
1875 if (icode == CODE_FOR_nothing)
1877 struct separate_ops ops;
1878 int prec = GET_MODE_PRECISION (mode);
1879 scalar_int_mode hmode, wmode;
1880 ops.op0 = make_tree (type, op0);
1881 ops.op1 = make_tree (type, op1);
1882 ops.op2 = NULL_TREE;
1883 ops.location = loc;
1885 /* Optimize unsigned overflow check where we don't use the
1886 multiplication result, just whether overflow happened.
1887 If we can do MULT_HIGHPART_EXPR, that followed by
1888 comparison of the result against zero is cheapest.
1889 We'll still compute res, but it should be DCEd later. */
1890 use_operand_p use;
1891 gimple *use_stmt;
1892 if (!is_ubsan
1893 && lhs
1894 && uns
1895 && !(uns0_p && uns1_p && !unsr_p)
1896 && can_mult_highpart_p (mode, uns) == 1
1897 && single_imm_use (lhs, &use, &use_stmt)
1898 && is_gimple_assign (use_stmt)
1899 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1900 goto highpart;
1902 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
1903 && targetm.scalar_mode_supported_p (wmode)
1904 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
1906 twoxwider:
1907 ops.code = WIDEN_MULT_EXPR;
1908 ops.type
1909 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
1911 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1912 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1913 NULL_RTX, uns);
1914 hipart = convert_modes (mode, wmode, hipart, uns);
1915 res = convert_modes (mode, wmode, res, uns);
1916 if (uns)
1917 /* For the unsigned multiplication, there was overflow if
1918 HIPART is non-zero. */
1919 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1920 NULL_RTX, NULL, done_label,
1921 profile_probability::very_likely ());
1922 else
1924 /* RES is used more than once, place it in a pseudo. */
1925 res = force_reg (mode, res);
1927 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1928 NULL_RTX, 0);
1929 /* RES is low half of the double width result, HIPART
1930 the high half. There was overflow if
1931 HIPART is different from RES < 0 ? -1 : 0. */
1932 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1933 NULL_RTX, NULL, done_label,
1934 profile_probability::very_likely ());
1937 else if (can_mult_highpart_p (mode, uns) == 1)
1939 highpart:
1940 ops.code = MULT_HIGHPART_EXPR;
1941 ops.type = type;
1943 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
1944 EXPAND_NORMAL);
1945 ops.code = MULT_EXPR;
1946 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1947 if (uns)
1948 /* For the unsigned multiplication, there was overflow if
1949 HIPART is non-zero. */
1950 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1951 NULL_RTX, NULL, done_label,
1952 profile_probability::very_likely ());
1953 else
1955 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1956 NULL_RTX, 0);
1957 /* RES is low half of the double width result, HIPART
1958 the high half. There was overflow if
1959 HIPART is different from RES < 0 ? -1 : 0. */
1960 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1961 NULL_RTX, NULL, done_label,
1962 profile_probability::very_likely ());
1966 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
1967 && 2 * GET_MODE_PRECISION (hmode) == prec)
1969 rtx_code_label *large_op0 = gen_label_rtx ();
1970 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1971 rtx_code_label *one_small_one_large = gen_label_rtx ();
1972 rtx_code_label *both_ops_large = gen_label_rtx ();
1973 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1974 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
1975 rtx_code_label *do_overflow = gen_label_rtx ();
1976 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
1978 unsigned int hprec = GET_MODE_PRECISION (hmode);
1979 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1980 NULL_RTX, uns);
1981 hipart0 = convert_modes (hmode, mode, hipart0, uns);
1982 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1983 rtx signbit0 = const0_rtx;
1984 if (!uns)
1985 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1986 NULL_RTX, 0);
1987 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1988 NULL_RTX, uns);
1989 hipart1 = convert_modes (hmode, mode, hipart1, uns);
1990 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1991 rtx signbit1 = const0_rtx;
1992 if (!uns)
1993 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1994 NULL_RTX, 0);
1996 res = gen_reg_rtx (mode);
1998 /* True if op0 resp. op1 are known to be in the range of
1999 halfstype. */
2000 bool op0_small_p = false;
2001 bool op1_small_p = false;
2002 /* True if op0 resp. op1 are known to have all zeros or all ones
2003 in the upper half of bits, but are not known to be
2004 op{0,1}_small_p. */
2005 bool op0_medium_p = false;
2006 bool op1_medium_p = false;
2007 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
2008 nonnegative, 1 if unknown. */
2009 int op0_sign = 1;
2010 int op1_sign = 1;
2012 if (pos_neg0 == 1)
2013 op0_sign = 0;
2014 else if (pos_neg0 == 2)
2015 op0_sign = -1;
2016 if (pos_neg1 == 1)
2017 op1_sign = 0;
2018 else if (pos_neg1 == 2)
2019 op1_sign = -1;
2021 unsigned int mprec0 = prec;
2022 if (arg0 != error_mark_node)
2023 mprec0 = get_min_precision (arg0, sign);
2024 if (mprec0 <= hprec)
2025 op0_small_p = true;
2026 else if (!uns && mprec0 <= hprec + 1)
2027 op0_medium_p = true;
2028 unsigned int mprec1 = prec;
2029 if (arg1 != error_mark_node)
2030 mprec1 = get_min_precision (arg1, sign);
2031 if (mprec1 <= hprec)
2032 op1_small_p = true;
2033 else if (!uns && mprec1 <= hprec + 1)
2034 op1_medium_p = true;
2036 int smaller_sign = 1;
2037 int larger_sign = 1;
2038 if (op0_small_p)
2040 smaller_sign = op0_sign;
2041 larger_sign = op1_sign;
2043 else if (op1_small_p)
2045 smaller_sign = op1_sign;
2046 larger_sign = op0_sign;
2048 else if (op0_sign == op1_sign)
2050 smaller_sign = op0_sign;
2051 larger_sign = op0_sign;
2054 if (!op0_small_p)
2055 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
2056 NULL_RTX, NULL, large_op0,
2057 profile_probability::unlikely ());
2059 if (!op1_small_p)
2060 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2061 NULL_RTX, NULL, small_op0_large_op1,
2062 profile_probability::unlikely ());
2064 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
2065 hmode to mode, the multiplication will never overflow. We can
2066 do just one hmode x hmode => mode widening multiplication. */
2067 tree halfstype = build_nonstandard_integer_type (hprec, uns);
2068 ops.op0 = make_tree (halfstype, lopart0);
2069 ops.op1 = make_tree (halfstype, lopart1);
2070 ops.code = WIDEN_MULT_EXPR;
2071 ops.type = type;
2072 rtx thisres
2073 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2074 emit_move_insn (res, thisres);
2075 emit_jump (done_label);
2077 emit_label (small_op0_large_op1);
2079 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
2080 but op1 is not, just swap the arguments and handle it as op1
2081 sign/zero extended, op0 not. */
2082 rtx larger = gen_reg_rtx (mode);
2083 rtx hipart = gen_reg_rtx (hmode);
2084 rtx lopart = gen_reg_rtx (hmode);
2085 emit_move_insn (larger, op1);
2086 emit_move_insn (hipart, hipart1);
2087 emit_move_insn (lopart, lopart0);
2088 emit_jump (one_small_one_large);
2090 emit_label (large_op0);
2092 if (!op1_small_p)
2093 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2094 NULL_RTX, NULL, both_ops_large,
2095 profile_probability::unlikely ());
2097 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
2098 but op0 is not, prepare larger, hipart and lopart pseudos and
2099 handle it together with small_op0_large_op1. */
2100 emit_move_insn (larger, op0);
2101 emit_move_insn (hipart, hipart0);
2102 emit_move_insn (lopart, lopart1);
2104 emit_label (one_small_one_large);
2106 /* lopart is the low part of the operand that is sign extended
2107 to mode, larger is the other operand, hipart is the
2108 high part of larger and lopart0 and lopart1 are the low parts
2109 of both operands.
2110 We perform lopart0 * lopart1 and lopart * hipart widening
2111 multiplications. */
2112 tree halfutype = build_nonstandard_integer_type (hprec, 1);
2113 ops.op0 = make_tree (halfutype, lopart0);
2114 ops.op1 = make_tree (halfutype, lopart1);
2115 rtx lo0xlo1
2116 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2118 ops.op0 = make_tree (halfutype, lopart);
2119 ops.op1 = make_tree (halfutype, hipart);
2120 rtx loxhi = gen_reg_rtx (mode);
2121 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2122 emit_move_insn (loxhi, tem);
2124 if (!uns)
2126 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
2127 if (larger_sign == 0)
2128 emit_jump (after_hipart_neg);
2129 else if (larger_sign != -1)
2130 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
2131 NULL_RTX, NULL, after_hipart_neg,
2132 profile_probability::even ());
2134 tem = convert_modes (mode, hmode, lopart, 1);
2135 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
2136 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
2137 1, OPTAB_WIDEN);
2138 emit_move_insn (loxhi, tem);
2140 emit_label (after_hipart_neg);
2142 /* if (lopart < 0) loxhi -= larger; */
2143 if (smaller_sign == 0)
2144 emit_jump (after_lopart_neg);
2145 else if (smaller_sign != -1)
2146 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
2147 NULL_RTX, NULL, after_lopart_neg,
2148 profile_probability::even ());
2150 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
2151 1, OPTAB_WIDEN);
2152 emit_move_insn (loxhi, tem);
2154 emit_label (after_lopart_neg);
2157 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
2158 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
2159 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
2160 1, OPTAB_WIDEN);
2161 emit_move_insn (loxhi, tem);
2163 /* if (loxhi >> (bitsize / 2)
2164 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
2165 if (loxhi >> (bitsize / 2) == 0 (if uns). */
2166 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
2167 NULL_RTX, 0);
2168 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
2169 rtx signbitloxhi = const0_rtx;
2170 if (!uns)
2171 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
2172 convert_modes (hmode, mode,
2173 loxhi, 0),
2174 hprec - 1, NULL_RTX, 0);
2176 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
2177 NULL_RTX, NULL, do_overflow,
2178 profile_probability::very_unlikely ());
2180 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
2181 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
2182 NULL_RTX, 1);
2183 tem = convert_modes (mode, hmode,
2184 convert_modes (hmode, mode, lo0xlo1, 1), 1);
2186 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
2187 1, OPTAB_WIDEN);
2188 if (tem != res)
2189 emit_move_insn (res, tem);
2190 emit_jump (done_label);
2192 emit_label (both_ops_large);
2194 /* If both operands are large (not sign (!uns) or zero (uns)
2195 extended from hmode), then perform the full multiplication
2196 which will be the result of the operation.
2197 The only cases which don't overflow are for signed multiplication
2198 some cases where both hipart0 and highpart1 are 0 or -1.
2199 For unsigned multiplication when high parts are both non-zero
2200 this overflows always. */
2201 ops.code = MULT_EXPR;
2202 ops.op0 = make_tree (type, op0);
2203 ops.op1 = make_tree (type, op1);
2204 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2205 emit_move_insn (res, tem);
2207 if (!uns)
2209 if (!op0_medium_p)
2211 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
2212 NULL_RTX, 1, OPTAB_WIDEN);
2213 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2214 NULL_RTX, NULL, do_error,
2215 profile_probability::very_unlikely ());
2218 if (!op1_medium_p)
2220 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
2221 NULL_RTX, 1, OPTAB_WIDEN);
2222 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2223 NULL_RTX, NULL, do_error,
2224 profile_probability::very_unlikely ());
2227 /* At this point hipart{0,1} are both in [-1, 0]. If they are
2228 the same, overflow happened if res is non-positive, if they
2229 are different, overflow happened if res is positive. */
2230 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
2231 emit_jump (hipart_different);
2232 else if (op0_sign == 1 || op1_sign == 1)
2233 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
2234 NULL_RTX, NULL, hipart_different,
2235 profile_probability::even ());
2237 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
2238 NULL_RTX, NULL, do_error,
2239 profile_probability::very_unlikely ());
2240 emit_jump (done_label);
2242 emit_label (hipart_different);
2244 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
2245 NULL_RTX, NULL, do_error,
2246 profile_probability::very_unlikely ());
2247 emit_jump (done_label);
2250 emit_label (do_overflow);
2252 /* Overflow, do full multiplication and fallthru into do_error. */
2253 ops.op0 = make_tree (type, op0);
2254 ops.op1 = make_tree (type, op1);
2255 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2256 emit_move_insn (res, tem);
2258 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2259 && targetm.scalar_mode_supported_p (wmode))
2260 /* Even emitting a libcall is better than not detecting overflow
2261 at all. */
2262 goto twoxwider;
2263 else
2265 gcc_assert (!is_ubsan);
2266 ops.code = MULT_EXPR;
2267 ops.type = type;
2268 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2269 emit_jump (done_label);
2273 do_error_label:
2274 emit_label (do_error);
2275 if (is_ubsan)
2277 /* Expand the ubsan builtin call. */
2278 push_temp_slots ();
2279 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
2280 arg0, arg1, datap);
2281 expand_normal (fn);
2282 pop_temp_slots ();
2283 do_pending_stack_adjust ();
2285 else if (lhs)
2286 expand_arith_set_overflow (lhs, target);
2288 /* We're done. */
2289 emit_label (done_label);
2291 /* u1 * u2 -> sr */
2292 if (uns0_p && uns1_p && !unsr_p)
2294 rtx_code_label *all_done_label = gen_label_rtx ();
2295 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2296 NULL, all_done_label, profile_probability::very_likely ());
2297 expand_arith_set_overflow (lhs, target);
2298 emit_label (all_done_label);
2301 /* s1 * u2 -> sr */
2302 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2304 rtx_code_label *all_done_label = gen_label_rtx ();
2305 rtx_code_label *set_noovf = gen_label_rtx ();
2306 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2307 NULL, all_done_label, profile_probability::very_likely ());
2308 expand_arith_set_overflow (lhs, target);
2309 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2310 NULL, set_noovf, profile_probability::very_likely ());
2311 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2312 NULL, all_done_label, profile_probability::very_unlikely ());
2313 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2314 all_done_label, profile_probability::very_unlikely ());
2315 emit_label (set_noovf);
2316 write_complex_part (target, const0_rtx, true, false);
2317 emit_label (all_done_label);
2320 if (lhs)
2322 if (is_ubsan)
2323 expand_ubsan_result_store (target, res);
2324 else
2325 expand_arith_overflow_result_store (lhs, target, mode, res);
2329 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2331 static void
2332 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2333 tree arg0, tree arg1)
2335 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2336 rtx_code_label *loop_lab = NULL;
2337 rtx cntvar = NULL_RTX;
2338 tree cntv = NULL_TREE;
2339 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2340 tree sz = TYPE_SIZE (eltype);
2341 tree data = NULL_TREE;
2342 tree resv = NULL_TREE;
2343 rtx lhsr = NULL_RTX;
2344 rtx resvr = NULL_RTX;
2345 unsigned HOST_WIDE_INT const_cnt = 0;
2346 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2348 if (lhs)
2350 optab op;
2351 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2352 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2353 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2354 optab_default)) == unknown_optab
2355 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2356 == CODE_FOR_nothing))
2358 if (MEM_P (lhsr))
2359 resv = make_tree (TREE_TYPE (lhs), lhsr);
2360 else
2362 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2363 resv = make_tree (TREE_TYPE (lhs), resvr);
2367 if (use_loop_p)
2369 do_pending_stack_adjust ();
2370 loop_lab = gen_label_rtx ();
2371 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2372 cntv = make_tree (sizetype, cntvar);
2373 emit_move_insn (cntvar, const0_rtx);
2374 emit_label (loop_lab);
2376 if (TREE_CODE (arg0) != VECTOR_CST)
2378 rtx arg0r = expand_normal (arg0);
2379 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2381 if (TREE_CODE (arg1) != VECTOR_CST)
2383 rtx arg1r = expand_normal (arg1);
2384 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2386 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2388 tree op0, op1, res = NULL_TREE;
2389 if (use_loop_p)
2391 tree atype = build_array_type_nelts (eltype, cnt);
2392 op0 = uniform_vector_p (arg0);
2393 if (op0 == NULL_TREE)
2395 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2396 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2397 NULL_TREE, NULL_TREE);
2399 op1 = uniform_vector_p (arg1);
2400 if (op1 == NULL_TREE)
2402 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2403 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2404 NULL_TREE, NULL_TREE);
2406 if (resv)
2408 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2409 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2410 NULL_TREE, NULL_TREE);
2413 else
2415 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2416 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2417 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2418 if (resv)
2419 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2420 bitpos);
2422 switch (code)
2424 case PLUS_EXPR:
2425 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2426 false, false, false, true, &data);
2427 break;
2428 case MINUS_EXPR:
2429 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2430 expand_neg_overflow (loc, res, op1, true, &data);
2431 else
2432 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2433 false, false, false, true, &data);
2434 break;
2435 case MULT_EXPR:
2436 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2437 true, &data);
2438 break;
2439 default:
2440 gcc_unreachable ();
2443 if (use_loop_p)
2445 struct separate_ops ops;
2446 ops.code = PLUS_EXPR;
2447 ops.type = TREE_TYPE (cntv);
2448 ops.op0 = cntv;
2449 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2450 ops.op2 = NULL_TREE;
2451 ops.location = loc;
2452 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2453 EXPAND_NORMAL);
2454 if (ret != cntvar)
2455 emit_move_insn (cntvar, ret);
2456 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2457 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2458 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2459 profile_probability::very_likely ());
2461 if (lhs && resv == NULL_TREE)
2463 struct separate_ops ops;
2464 ops.code = code;
2465 ops.type = TREE_TYPE (arg0);
2466 ops.op0 = arg0;
2467 ops.op1 = arg1;
2468 ops.op2 = NULL_TREE;
2469 ops.location = loc;
2470 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2471 EXPAND_NORMAL);
2472 if (ret != lhsr)
2473 emit_move_insn (lhsr, ret);
2475 else if (resvr)
2476 emit_move_insn (lhsr, resvr);
2479 /* Expand UBSAN_CHECK_ADD call STMT. */
2481 static void
2482 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2484 location_t loc = gimple_location (stmt);
2485 tree lhs = gimple_call_lhs (stmt);
2486 tree arg0 = gimple_call_arg (stmt, 0);
2487 tree arg1 = gimple_call_arg (stmt, 1);
2488 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2489 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2490 else
2491 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2492 false, false, false, true, NULL);
2495 /* Expand UBSAN_CHECK_SUB call STMT. */
2497 static void
2498 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2500 location_t loc = gimple_location (stmt);
2501 tree lhs = gimple_call_lhs (stmt);
2502 tree arg0 = gimple_call_arg (stmt, 0);
2503 tree arg1 = gimple_call_arg (stmt, 1);
2504 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2505 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2506 else if (integer_zerop (arg0))
2507 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2508 else
2509 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2510 false, false, false, true, NULL);
2513 /* Expand UBSAN_CHECK_MUL call STMT. */
2515 static void
2516 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2518 location_t loc = gimple_location (stmt);
2519 tree lhs = gimple_call_lhs (stmt);
2520 tree arg0 = gimple_call_arg (stmt, 0);
2521 tree arg1 = gimple_call_arg (stmt, 1);
2522 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2523 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2524 else
2525 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2526 NULL);
2529 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2531 static void
2532 expand_arith_overflow (enum tree_code code, gimple *stmt)
2534 tree lhs = gimple_call_lhs (stmt);
2535 if (lhs == NULL_TREE)
2536 return;
2537 tree arg0 = gimple_call_arg (stmt, 0);
2538 tree arg1 = gimple_call_arg (stmt, 1);
2539 tree type = TREE_TYPE (TREE_TYPE (lhs));
2540 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2541 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2542 int unsr_p = TYPE_UNSIGNED (type);
2543 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2544 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2545 int precres = TYPE_PRECISION (type);
2546 location_t loc = gimple_location (stmt);
2547 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2548 uns0_p = true;
2549 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2550 uns1_p = true;
2551 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2552 prec0 = MIN (prec0, pr);
2553 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2554 prec1 = MIN (prec1, pr);
2556 /* If uns0_p && uns1_p, precop is minimum needed precision
2557 of unsigned type to hold the exact result, otherwise
2558 precop is minimum needed precision of signed type to
2559 hold the exact result. */
2560 int precop;
2561 if (code == MULT_EXPR)
2562 precop = prec0 + prec1 + (uns0_p != uns1_p);
2563 else
2565 if (uns0_p == uns1_p)
2566 precop = MAX (prec0, prec1) + 1;
2567 else if (uns0_p)
2568 precop = MAX (prec0 + 1, prec1) + 1;
2569 else
2570 precop = MAX (prec0, prec1 + 1) + 1;
2572 int orig_precres = precres;
2576 if ((uns0_p && uns1_p)
2577 ? ((precop + !unsr_p) <= precres
2578 /* u1 - u2 -> ur can overflow, no matter what precision
2579 the result has. */
2580 && (code != MINUS_EXPR || !unsr_p))
2581 : (!unsr_p && precop <= precres))
2583 /* The infinity precision result will always fit into result. */
2584 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2585 write_complex_part (target, const0_rtx, true, false);
2586 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2587 struct separate_ops ops;
2588 ops.code = code;
2589 ops.type = type;
2590 ops.op0 = fold_convert_loc (loc, type, arg0);
2591 ops.op1 = fold_convert_loc (loc, type, arg1);
2592 ops.op2 = NULL_TREE;
2593 ops.location = loc;
2594 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2595 expand_arith_overflow_result_store (lhs, target, mode, tem);
2596 return;
2599 /* For operations with low precision, if target doesn't have them, start
2600 with precres widening right away, otherwise do it only if the most
2601 simple cases can't be used. */
2602 const int min_precision = targetm.min_arithmetic_precision ();
2603 if (orig_precres == precres && precres < min_precision)
2605 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2606 && prec1 <= precres)
2607 || ((!uns0_p || !uns1_p) && !unsr_p
2608 && prec0 + uns0_p <= precres
2609 && prec1 + uns1_p <= precres))
2611 arg0 = fold_convert_loc (loc, type, arg0);
2612 arg1 = fold_convert_loc (loc, type, arg1);
2613 switch (code)
2615 case MINUS_EXPR:
2616 if (integer_zerop (arg0) && !unsr_p)
2618 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2619 return;
2621 /* FALLTHRU */
2622 case PLUS_EXPR:
2623 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2624 unsr_p, unsr_p, false, NULL);
2625 return;
2626 case MULT_EXPR:
2627 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2628 unsr_p, unsr_p, false, NULL);
2629 return;
2630 default:
2631 gcc_unreachable ();
2635 /* For sub-word operations, retry with a wider type first. */
2636 if (orig_precres == precres && precop <= BITS_PER_WORD)
2638 int p = MAX (min_precision, precop);
2639 scalar_int_mode m = smallest_int_mode_for_size (p);
2640 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2641 uns0_p && uns1_p
2642 && unsr_p);
2643 p = TYPE_PRECISION (optype);
2644 if (p > precres)
2646 precres = p;
2647 unsr_p = TYPE_UNSIGNED (optype);
2648 type = optype;
2649 continue;
2653 if (prec0 <= precres && prec1 <= precres)
2655 tree types[2];
2656 if (unsr_p)
2658 types[0] = build_nonstandard_integer_type (precres, 0);
2659 types[1] = type;
2661 else
2663 types[0] = type;
2664 types[1] = build_nonstandard_integer_type (precres, 1);
2666 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2667 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2668 if (code != MULT_EXPR)
2669 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2670 uns0_p, uns1_p, false, NULL);
2671 else
2672 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2673 uns0_p, uns1_p, false, NULL);
2674 return;
2677 /* Retry with a wider type. */
2678 if (orig_precres == precres)
2680 int p = MAX (prec0, prec1);
2681 scalar_int_mode m = smallest_int_mode_for_size (p);
2682 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2683 uns0_p && uns1_p
2684 && unsr_p);
2685 p = TYPE_PRECISION (optype);
2686 if (p > precres)
2688 precres = p;
2689 unsr_p = TYPE_UNSIGNED (optype);
2690 type = optype;
2691 continue;
2695 gcc_unreachable ();
2697 while (1);
2700 /* Expand ADD_OVERFLOW STMT. */
2702 static void
2703 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2705 expand_arith_overflow (PLUS_EXPR, stmt);
2708 /* Expand SUB_OVERFLOW STMT. */
2710 static void
2711 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2713 expand_arith_overflow (MINUS_EXPR, stmt);
2716 /* Expand MUL_OVERFLOW STMT. */
2718 static void
2719 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2721 expand_arith_overflow (MULT_EXPR, stmt);
2724 /* This should get folded in tree-vectorizer.cc. */
2726 static void
2727 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2729 gcc_unreachable ();
2732 /* This should get folded in tree-vectorizer.cc. */
2734 static void
2735 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2737 gcc_unreachable ();
2740 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2741 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2743 static tree
2744 expand_call_mem_ref (tree type, gcall *stmt, int index)
2746 tree addr = gimple_call_arg (stmt, index);
2747 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2748 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2749 if (TYPE_ALIGN (type) != align)
2750 type = build_aligned_type (type, align);
2752 tree tmp = addr;
2753 if (TREE_CODE (tmp) == SSA_NAME)
2755 gimple *def = SSA_NAME_DEF_STMT (tmp);
2756 if (gimple_assign_single_p (def))
2757 tmp = gimple_assign_rhs1 (def);
2760 if (TREE_CODE (tmp) == ADDR_EXPR)
2762 tree mem = TREE_OPERAND (tmp, 0);
2763 if (TREE_CODE (mem) == TARGET_MEM_REF
2764 && types_compatible_p (TREE_TYPE (mem), type))
2766 tree offset = TMR_OFFSET (mem);
2767 if (type != TREE_TYPE (mem)
2768 || alias_ptr_type != TREE_TYPE (offset)
2769 || !integer_zerop (offset))
2771 mem = copy_node (mem);
2772 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2773 wi::to_poly_wide (offset));
2774 TREE_TYPE (mem) = type;
2776 return mem;
2780 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2783 /* Expand MASK_LOAD{,_LANES} or LEN_LOAD call STMT using optab OPTAB. */
2785 static void
2786 expand_partial_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2788 class expand_operand ops[4];
2789 tree type, lhs, rhs, maskt, biast;
2790 rtx mem, target, mask, bias;
2791 insn_code icode;
2793 maskt = gimple_call_arg (stmt, 2);
2794 lhs = gimple_call_lhs (stmt);
2795 if (lhs == NULL_TREE)
2796 return;
2797 type = TREE_TYPE (lhs);
2798 rhs = expand_call_mem_ref (type, stmt, 0);
2800 if (optab == vec_mask_load_lanes_optab)
2801 icode = get_multi_vector_move (type, optab);
2802 else if (optab == len_load_optab)
2803 icode = direct_optab_handler (optab, TYPE_MODE (type));
2804 else
2805 icode = convert_optab_handler (optab, TYPE_MODE (type),
2806 TYPE_MODE (TREE_TYPE (maskt)));
2808 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2809 gcc_assert (MEM_P (mem));
2810 mask = expand_normal (maskt);
2811 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2812 create_output_operand (&ops[0], target, TYPE_MODE (type));
2813 create_fixed_operand (&ops[1], mem);
2814 if (optab == len_load_optab)
2816 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2817 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2818 biast = gimple_call_arg (stmt, 3);
2819 bias = expand_normal (biast);
2820 create_input_operand (&ops[3], bias, QImode);
2821 expand_insn (icode, 4, ops);
2823 else
2825 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2826 expand_insn (icode, 3, ops);
2829 if (!rtx_equal_p (target, ops[0].value))
2830 emit_move_insn (target, ops[0].value);
2833 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
2834 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2835 #define expand_len_load_optab_fn expand_partial_load_optab_fn
2837 /* Expand MASK_STORE{,_LANES} or LEN_STORE call STMT using optab OPTAB. */
2839 static void
2840 expand_partial_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2842 class expand_operand ops[4];
2843 tree type, lhs, rhs, maskt, biast;
2844 rtx mem, reg, mask, bias;
2845 insn_code icode;
2847 maskt = gimple_call_arg (stmt, 2);
2848 rhs = gimple_call_arg (stmt, 3);
2849 type = TREE_TYPE (rhs);
2850 lhs = expand_call_mem_ref (type, stmt, 0);
2852 if (optab == vec_mask_store_lanes_optab)
2853 icode = get_multi_vector_move (type, optab);
2854 else if (optab == len_store_optab)
2855 icode = direct_optab_handler (optab, TYPE_MODE (type));
2856 else
2857 icode = convert_optab_handler (optab, TYPE_MODE (type),
2858 TYPE_MODE (TREE_TYPE (maskt)));
2860 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2861 gcc_assert (MEM_P (mem));
2862 mask = expand_normal (maskt);
2863 reg = expand_normal (rhs);
2864 create_fixed_operand (&ops[0], mem);
2865 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2866 if (optab == len_store_optab)
2868 create_convert_operand_from (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)),
2869 TYPE_UNSIGNED (TREE_TYPE (maskt)));
2870 biast = gimple_call_arg (stmt, 4);
2871 bias = expand_normal (biast);
2872 create_input_operand (&ops[3], bias, QImode);
2873 expand_insn (icode, 4, ops);
2875 else
2877 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
2878 expand_insn (icode, 3, ops);
2882 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
2883 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
2884 #define expand_len_store_optab_fn expand_partial_store_optab_fn
2886 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
2887 The expansion of STMT happens based on OPTAB table associated. */
2889 static void
2890 expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2892 class expand_operand ops[6];
2893 insn_code icode;
2894 tree lhs = gimple_call_lhs (stmt);
2895 tree op0a = gimple_call_arg (stmt, 0);
2896 tree op0b = gimple_call_arg (stmt, 1);
2897 tree op1 = gimple_call_arg (stmt, 2);
2898 tree op2 = gimple_call_arg (stmt, 3);
2899 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
2901 tree vec_cond_type = TREE_TYPE (lhs);
2902 tree op_mode = TREE_TYPE (op0a);
2903 bool unsignedp = TYPE_UNSIGNED (op_mode);
2905 machine_mode mode = TYPE_MODE (vec_cond_type);
2906 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
2908 icode = convert_optab_handler (optab, mode, cmp_op_mode);
2909 rtx comparison
2910 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
2911 rtx rtx_op1 = expand_normal (op1);
2912 rtx rtx_op2 = expand_normal (op2);
2914 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2915 create_output_operand (&ops[0], target, mode);
2916 create_input_operand (&ops[1], rtx_op1, mode);
2917 create_input_operand (&ops[2], rtx_op2, mode);
2918 create_fixed_operand (&ops[3], comparison);
2919 create_fixed_operand (&ops[4], XEXP (comparison, 0));
2920 create_fixed_operand (&ops[5], XEXP (comparison, 1));
2921 expand_insn (icode, 6, ops);
2922 if (!rtx_equal_p (ops[0].value, target))
2923 emit_move_insn (target, ops[0].value);
2926 /* Expand VCOND_MASK optab internal function.
2927 The expansion of STMT happens based on OPTAB table associated. */
2929 static void
2930 expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2932 class expand_operand ops[4];
2934 tree lhs = gimple_call_lhs (stmt);
2935 tree op0 = gimple_call_arg (stmt, 0);
2936 tree op1 = gimple_call_arg (stmt, 1);
2937 tree op2 = gimple_call_arg (stmt, 2);
2938 tree vec_cond_type = TREE_TYPE (lhs);
2940 machine_mode mode = TYPE_MODE (vec_cond_type);
2941 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
2942 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
2943 rtx mask, rtx_op1, rtx_op2;
2945 gcc_assert (icode != CODE_FOR_nothing);
2947 mask = expand_normal (op0);
2948 rtx_op1 = expand_normal (op1);
2949 rtx_op2 = expand_normal (op2);
2951 mask = force_reg (mask_mode, mask);
2952 rtx_op1 = force_reg (mode, rtx_op1);
2954 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2955 create_output_operand (&ops[0], target, mode);
2956 create_input_operand (&ops[1], rtx_op1, mode);
2957 create_input_operand (&ops[2], rtx_op2, mode);
2958 create_input_operand (&ops[3], mask, mask_mode);
2959 expand_insn (icode, 4, ops);
2960 if (!rtx_equal_p (ops[0].value, target))
2961 emit_move_insn (target, ops[0].value);
2964 /* Expand VEC_SET internal functions. */
2966 static void
2967 expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
2969 tree lhs = gimple_call_lhs (stmt);
2970 tree op0 = gimple_call_arg (stmt, 0);
2971 tree op1 = gimple_call_arg (stmt, 1);
2972 tree op2 = gimple_call_arg (stmt, 2);
2973 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2974 rtx src = expand_normal (op0);
2976 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
2977 scalar_mode innermode = GET_MODE_INNER (outermode);
2979 rtx value = expand_normal (op1);
2980 rtx pos = expand_normal (op2);
2982 class expand_operand ops[3];
2983 enum insn_code icode = optab_handler (optab, outermode);
2985 if (icode != CODE_FOR_nothing)
2987 rtx temp = gen_reg_rtx (outermode);
2988 emit_move_insn (temp, src);
2990 create_fixed_operand (&ops[0], temp);
2991 create_input_operand (&ops[1], value, innermode);
2992 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
2993 true);
2994 if (maybe_expand_insn (icode, 3, ops))
2996 emit_move_insn (target, temp);
2997 return;
3000 gcc_unreachable ();
3003 static void
3004 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
3008 static void
3009 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
3011 /* When guessing was done, the hints should be already stripped away. */
3012 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
3014 rtx target;
3015 tree lhs = gimple_call_lhs (stmt);
3016 if (lhs)
3017 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3018 else
3019 target = const0_rtx;
3020 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
3021 if (lhs && val != target)
3022 emit_move_insn (target, val);
3025 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
3026 should never be called. */
3028 static void
3029 expand_VA_ARG (internal_fn, gcall *)
3031 gcc_unreachable ();
3034 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
3035 dummy function should never be called. */
3037 static void
3038 expand_VEC_CONVERT (internal_fn, gcall *)
3040 gcc_unreachable ();
3043 /* Expand IFN_RAWMEMCHAR internal function. */
3045 void
3046 expand_RAWMEMCHR (internal_fn, gcall *stmt)
3048 expand_operand ops[3];
3050 tree lhs = gimple_call_lhs (stmt);
3051 if (!lhs)
3052 return;
3053 machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
3054 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3055 create_output_operand (&ops[0], lhs_rtx, lhs_mode);
3057 tree mem = gimple_call_arg (stmt, 0);
3058 rtx mem_rtx = get_memory_rtx (mem, NULL);
3059 create_fixed_operand (&ops[1], mem_rtx);
3061 tree pattern = gimple_call_arg (stmt, 1);
3062 machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
3063 rtx pattern_rtx = expand_normal (pattern);
3064 create_input_operand (&ops[2], pattern_rtx, mode);
3066 insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
3068 expand_insn (icode, 3, ops);
3069 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3070 emit_move_insn (lhs_rtx, ops[0].value);
3073 /* Expand the IFN_UNIQUE function according to its first argument. */
3075 static void
3076 expand_UNIQUE (internal_fn, gcall *stmt)
3078 rtx pattern = NULL_RTX;
3079 enum ifn_unique_kind kind
3080 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
3082 switch (kind)
3084 default:
3085 gcc_unreachable ();
3087 case IFN_UNIQUE_UNSPEC:
3088 if (targetm.have_unique ())
3089 pattern = targetm.gen_unique ();
3090 break;
3092 case IFN_UNIQUE_OACC_FORK:
3093 case IFN_UNIQUE_OACC_JOIN:
3094 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
3096 tree lhs = gimple_call_lhs (stmt);
3097 rtx target = const0_rtx;
3099 if (lhs)
3100 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3102 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
3103 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
3105 if (kind == IFN_UNIQUE_OACC_FORK)
3106 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
3107 else
3108 pattern = targetm.gen_oacc_join (target, data_dep, axis);
3110 else
3111 gcc_unreachable ();
3112 break;
3115 if (pattern)
3116 emit_insn (pattern);
3119 /* Expand the IFN_DEFERRED_INIT function:
3120 LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
3122 Initialize the LHS with zero/pattern according to its second argument
3123 INIT_TYPE:
3124 if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
3125 if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
3126 to initialize;
3127 The LHS variable is initialized including paddings.
3128 The reasons to choose 0xFE for pattern initialization are:
3129 1. It is a non-canonical virtual address on x86_64, and at the
3130 high end of the i386 kernel address space.
3131 2. It is a very large float value (-1.694739530317379e+38).
3132 3. It is also an unusual number for integers. */
3133 #define INIT_PATTERN_VALUE 0xFE
3134 static void
3135 expand_DEFERRED_INIT (internal_fn, gcall *stmt)
3137 tree lhs = gimple_call_lhs (stmt);
3138 tree var_size = gimple_call_arg (stmt, 0);
3139 enum auto_init_type init_type
3140 = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
3141 bool reg_lhs = true;
3143 tree var_type = TREE_TYPE (lhs);
3144 gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
3146 if (TREE_CODE (lhs) == SSA_NAME)
3147 reg_lhs = true;
3148 else
3150 tree lhs_base = lhs;
3151 while (handled_component_p (lhs_base))
3152 lhs_base = TREE_OPERAND (lhs_base, 0);
3153 reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
3154 || non_mem_decl_p (lhs_base));
3155 /* If this expands to a register and the underlying decl is wrapped in
3156 a MEM_REF that just serves as an access type change expose the decl
3157 if it is of correct size. This avoids a situation as in PR103271
3158 if the target does not support a direct move to the registers mode. */
3159 if (reg_lhs
3160 && TREE_CODE (lhs_base) == MEM_REF
3161 && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
3162 && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
3163 && integer_zerop (TREE_OPERAND (lhs_base, 1))
3164 && tree_fits_uhwi_p (var_size)
3165 && tree_int_cst_equal
3166 (var_size,
3167 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
3169 lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
3170 var_type = TREE_TYPE (lhs);
3174 if (!reg_lhs)
3176 /* If the variable is not in register, expand to a memset
3177 to initialize it. */
3178 mark_addressable (lhs);
3179 tree var_addr = build_fold_addr_expr (lhs);
3181 tree value = (init_type == AUTO_INIT_PATTERN)
3182 ? build_int_cst (integer_type_node,
3183 INIT_PATTERN_VALUE)
3184 : integer_zero_node;
3185 tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
3186 3, var_addr, value, var_size);
3187 /* Expand this memset call. */
3188 expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
3190 else
3192 /* If this variable is in a register use expand_assignment.
3193 For boolean scalars force zero-init. */
3194 tree init;
3195 scalar_int_mode var_mode;
3196 if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
3197 && tree_fits_uhwi_p (var_size)
3198 && (init_type == AUTO_INIT_PATTERN
3199 || !is_gimple_reg_type (var_type))
3200 && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
3201 0).exists (&var_mode)
3202 && have_insn_for (SET, var_mode))
3204 unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
3205 unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
3206 memset (buf, (init_type == AUTO_INIT_PATTERN
3207 ? INIT_PATTERN_VALUE : 0), total_bytes);
3208 tree itype = build_nonstandard_integer_type
3209 (total_bytes * BITS_PER_UNIT, 1);
3210 wide_int w = wi::from_buffer (buf, total_bytes);
3211 init = wide_int_to_tree (itype, w);
3212 /* Pun the LHS to make sure its type has constant size
3213 unless it is an SSA name where that's already known. */
3214 if (TREE_CODE (lhs) != SSA_NAME)
3215 lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
3216 else
3217 init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
3219 else
3220 /* Use zero-init also for variable-length sizes. */
3221 init = build_zero_cst (var_type);
3223 expand_assignment (lhs, init, false);
3227 /* The size of an OpenACC compute dimension. */
3229 static void
3230 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
3232 tree lhs = gimple_call_lhs (stmt);
3234 if (!lhs)
3235 return;
3237 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3238 if (targetm.have_oacc_dim_size ())
3240 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3241 VOIDmode, EXPAND_NORMAL);
3242 emit_insn (targetm.gen_oacc_dim_size (target, dim));
3244 else
3245 emit_move_insn (target, GEN_INT (1));
3248 /* The position of an OpenACC execution engine along one compute axis. */
3250 static void
3251 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
3253 tree lhs = gimple_call_lhs (stmt);
3255 if (!lhs)
3256 return;
3258 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3259 if (targetm.have_oacc_dim_pos ())
3261 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3262 VOIDmode, EXPAND_NORMAL);
3263 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
3265 else
3266 emit_move_insn (target, const0_rtx);
3269 /* This is expanded by oacc_device_lower pass. */
3271 static void
3272 expand_GOACC_LOOP (internal_fn, gcall *)
3274 gcc_unreachable ();
3277 /* This is expanded by oacc_device_lower pass. */
3279 static void
3280 expand_GOACC_REDUCTION (internal_fn, gcall *)
3282 gcc_unreachable ();
3285 /* This is expanded by oacc_device_lower pass. */
3287 static void
3288 expand_GOACC_TILE (internal_fn, gcall *)
3290 gcc_unreachable ();
3293 /* Set errno to EDOM. */
3295 static void
3296 expand_SET_EDOM (internal_fn, gcall *)
3298 #ifdef TARGET_EDOM
3299 #ifdef GEN_ERRNO_RTX
3300 rtx errno_rtx = GEN_ERRNO_RTX;
3301 #else
3302 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
3303 #endif
3304 emit_move_insn (errno_rtx,
3305 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
3306 #else
3307 gcc_unreachable ();
3308 #endif
3311 /* Expand atomic bit test and set. */
3313 static void
3314 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
3316 expand_ifn_atomic_bit_test_and (call);
3319 /* Expand atomic bit test and complement. */
3321 static void
3322 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
3324 expand_ifn_atomic_bit_test_and (call);
3327 /* Expand atomic bit test and reset. */
3329 static void
3330 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
3332 expand_ifn_atomic_bit_test_and (call);
3335 /* Expand atomic bit test and set. */
3337 static void
3338 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
3340 expand_ifn_atomic_compare_exchange (call);
3343 /* Expand atomic add fetch and cmp with 0. */
3345 static void
3346 expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
3348 expand_ifn_atomic_op_fetch_cmp_0 (call);
3351 /* Expand atomic sub fetch and cmp with 0. */
3353 static void
3354 expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
3356 expand_ifn_atomic_op_fetch_cmp_0 (call);
3359 /* Expand atomic and fetch and cmp with 0. */
3361 static void
3362 expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
3364 expand_ifn_atomic_op_fetch_cmp_0 (call);
3367 /* Expand atomic or fetch and cmp with 0. */
3369 static void
3370 expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
3372 expand_ifn_atomic_op_fetch_cmp_0 (call);
3375 /* Expand atomic xor fetch and cmp with 0. */
3377 static void
3378 expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
3380 expand_ifn_atomic_op_fetch_cmp_0 (call);
3383 /* Expand LAUNDER to assignment, lhs = arg0. */
3385 static void
3386 expand_LAUNDER (internal_fn, gcall *call)
3388 tree lhs = gimple_call_lhs (call);
3390 if (!lhs)
3391 return;
3393 expand_assignment (lhs, gimple_call_arg (call, 0), false);
3396 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
3398 static void
3399 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3401 internal_fn ifn = gimple_call_internal_fn (stmt);
3402 int rhs_index = internal_fn_stored_value_index (ifn);
3403 int mask_index = internal_fn_mask_index (ifn);
3404 tree base = gimple_call_arg (stmt, 0);
3405 tree offset = gimple_call_arg (stmt, 1);
3406 tree scale = gimple_call_arg (stmt, 2);
3407 tree rhs = gimple_call_arg (stmt, rhs_index);
3409 rtx base_rtx = expand_normal (base);
3410 rtx offset_rtx = expand_normal (offset);
3411 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3412 rtx rhs_rtx = expand_normal (rhs);
3414 class expand_operand ops[6];
3415 int i = 0;
3416 create_address_operand (&ops[i++], base_rtx);
3417 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3418 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3419 create_integer_operand (&ops[i++], scale_int);
3420 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
3421 if (mask_index >= 0)
3423 tree mask = gimple_call_arg (stmt, mask_index);
3424 rtx mask_rtx = expand_normal (mask);
3425 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
3428 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
3429 TYPE_MODE (TREE_TYPE (offset)));
3430 expand_insn (icode, i, ops);
3433 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
3435 static void
3436 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3438 tree lhs = gimple_call_lhs (stmt);
3439 tree base = gimple_call_arg (stmt, 0);
3440 tree offset = gimple_call_arg (stmt, 1);
3441 tree scale = gimple_call_arg (stmt, 2);
3443 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3444 rtx base_rtx = expand_normal (base);
3445 rtx offset_rtx = expand_normal (offset);
3446 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3448 int i = 0;
3449 class expand_operand ops[6];
3450 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
3451 create_address_operand (&ops[i++], base_rtx);
3452 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3453 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3454 create_integer_operand (&ops[i++], scale_int);
3455 if (optab == mask_gather_load_optab)
3457 tree mask = gimple_call_arg (stmt, 4);
3458 rtx mask_rtx = expand_normal (mask);
3459 create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
3461 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
3462 TYPE_MODE (TREE_TYPE (offset)));
3463 expand_insn (icode, i, ops);
3464 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3465 emit_move_insn (lhs_rtx, ops[0].value);
3468 /* Helper for expand_DIVMOD. Return true if the sequence starting with
3469 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
3471 static bool
3472 contains_call_div_mod (rtx_insn *insn)
3474 subrtx_iterator::array_type array;
3475 for (; insn; insn = NEXT_INSN (insn))
3476 if (CALL_P (insn))
3477 return true;
3478 else if (INSN_P (insn))
3479 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3480 switch (GET_CODE (*iter))
3482 case CALL:
3483 case DIV:
3484 case UDIV:
3485 case MOD:
3486 case UMOD:
3487 return true;
3488 default:
3489 break;
3491 return false;
3494 /* Expand DIVMOD() using:
3495 a) optab handler for udivmod/sdivmod if it is available.
3496 b) If optab_handler doesn't exist, generate call to
3497 target-specific divmod libfunc. */
3499 static void
3500 expand_DIVMOD (internal_fn, gcall *call_stmt)
3502 tree lhs = gimple_call_lhs (call_stmt);
3503 tree arg0 = gimple_call_arg (call_stmt, 0);
3504 tree arg1 = gimple_call_arg (call_stmt, 1);
3506 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3507 tree type = TREE_TYPE (TREE_TYPE (lhs));
3508 machine_mode mode = TYPE_MODE (type);
3509 bool unsignedp = TYPE_UNSIGNED (type);
3510 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3512 rtx op0 = expand_normal (arg0);
3513 rtx op1 = expand_normal (arg1);
3514 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3516 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3517 rtx_insn *insns = NULL;
3519 if (TREE_CODE (arg1) == INTEGER_CST)
3521 /* For DIVMOD by integral constants, there could be efficient code
3522 expanded inline e.g. using shifts and plus/minus. Try to expand
3523 the division and modulo and if it emits any library calls or any
3524 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3525 divmod libcall. */
3526 scalar_int_mode int_mode;
3527 if (remainder == NULL_RTX
3528 && optimize
3529 && CONST_INT_P (op1)
3530 && !pow2p_hwi (INTVAL (op1))
3531 && is_int_mode (TYPE_MODE (type), &int_mode)
3532 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
3533 && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
3534 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
3535 && optimize_insn_for_speed_p ())
3537 rtx_insn *last = get_last_insn ();
3538 remainder = NULL_RTX;
3539 quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
3540 TYPE_UNSIGNED (type));
3541 if (quotient != NULL_RTX)
3543 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
3545 rtx_insn *move = emit_move_insn (quotient, quotient);
3546 set_dst_reg_note (move, REG_EQUAL,
3547 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3548 ? UDIV : DIV, int_mode,
3549 copy_rtx (op0), op1),
3550 quotient);
3551 move = emit_move_insn (remainder, remainder);
3552 set_dst_reg_note (move, REG_EQUAL,
3553 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3554 ? UMOD : MOD, int_mode,
3555 copy_rtx (op0), op1),
3556 quotient);
3559 else
3560 delete_insns_since (last);
3563 if (remainder == NULL_RTX)
3565 struct separate_ops ops;
3566 ops.code = TRUNC_DIV_EXPR;
3567 ops.type = type;
3568 ops.op0 = make_tree (ops.type, op0);
3569 ops.op1 = arg1;
3570 ops.op2 = NULL_TREE;
3571 ops.location = gimple_location (call_stmt);
3572 start_sequence ();
3573 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3574 if (contains_call_div_mod (get_insns ()))
3575 quotient = NULL_RTX;
3576 else
3578 ops.code = TRUNC_MOD_EXPR;
3579 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
3580 EXPAND_NORMAL);
3581 if (contains_call_div_mod (get_insns ()))
3582 remainder = NULL_RTX;
3584 if (remainder)
3585 insns = get_insns ();
3586 end_sequence ();
3590 if (remainder)
3591 emit_insn (insns);
3593 /* Check if optab_handler exists for divmod_optab for given mode. */
3594 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
3596 quotient = gen_reg_rtx (mode);
3597 remainder = gen_reg_rtx (mode);
3598 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3601 /* Generate call to divmod libfunc if it exists. */
3602 else if (rtx libfunc = optab_libfunc (tab, mode))
3603 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3604 &quotient, &remainder);
3606 else
3607 gcc_unreachable ();
3609 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3610 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3611 make_tree (TREE_TYPE (arg0), quotient),
3612 make_tree (TREE_TYPE (arg1), remainder)),
3613 target, VOIDmode, EXPAND_NORMAL);
3616 /* Expand a NOP. */
3618 static void
3619 expand_NOP (internal_fn, gcall *)
3621 /* Nothing. But it shouldn't really prevail. */
3624 /* Coroutines, all should have been processed at this stage. */
3626 static void
3627 expand_CO_FRAME (internal_fn, gcall *)
3629 gcc_unreachable ();
3632 static void
3633 expand_CO_YIELD (internal_fn, gcall *)
3635 gcc_unreachable ();
3638 static void
3639 expand_CO_SUSPN (internal_fn, gcall *)
3641 gcc_unreachable ();
3644 static void
3645 expand_CO_ACTOR (internal_fn, gcall *)
3647 gcc_unreachable ();
3650 /* Expand a call to FN using the operands in STMT. FN has a single
3651 output operand and NARGS input operands. */
3653 static void
3654 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3655 unsigned int nargs)
3657 tree_pair types = direct_internal_fn_types (fn, stmt);
3658 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3659 expand_fn_using_insn (stmt, icode, 1, nargs);
3662 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3664 static void
3665 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3667 expand_operand ops[4];
3668 tree rhs_type[2];
3670 tree lhs = gimple_call_lhs (stmt);
3671 tree lhs_type = TREE_TYPE (lhs);
3672 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3673 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3675 for (unsigned int i = 0; i < 2; ++i)
3677 tree rhs = gimple_call_arg (stmt, i);
3678 rhs_type[i] = TREE_TYPE (rhs);
3679 rtx rhs_rtx = expand_normal (rhs);
3680 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3683 int opcnt;
3684 if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
3686 /* When the mask is an integer mode the exact vector length may not
3687 be clear to the backend, so we pass it in operand[3].
3688 Use the vector in arg2 for the most reliable intended size. */
3689 tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
3690 create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
3691 opcnt = 4;
3693 else
3694 /* The mask has a vector type so the length operand is unnecessary. */
3695 opcnt = 3;
3697 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3698 TYPE_MODE (lhs_type));
3700 expand_insn (icode, opcnt, ops);
3701 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3702 emit_move_insn (lhs_rtx, ops[0].value);
3705 /* Expand a call to a convert-like optab using the operands in STMT.
3706 FN has a single output operand and NARGS input operands. */
3708 static void
3709 expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
3710 unsigned int nargs)
3712 tree_pair types = direct_internal_fn_types (fn, stmt);
3713 insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
3714 TYPE_MODE (types.second));
3715 expand_fn_using_insn (stmt, icode, 1, nargs);
3718 /* Expanders for optabs that can use expand_direct_optab_fn. */
3720 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3721 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3723 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3724 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3726 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3727 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3729 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3730 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3732 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3733 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3735 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3736 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3738 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3739 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3741 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3742 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3744 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3745 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3747 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3748 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3750 /* Expanders for optabs that can use expand_convert_optab_fn. */
3752 #define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
3753 expand_convert_optab_fn (FN, STMT, OPTAB, 1)
3755 /* RETURN_TYPE and ARGS are a return type and argument list that are
3756 in principle compatible with FN (which satisfies direct_internal_fn_p).
3757 Return the types that should be used to determine whether the
3758 target supports FN. */
3760 tree_pair
3761 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3763 const direct_internal_fn_info &info = direct_internal_fn (fn);
3764 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3765 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3766 return tree_pair (type0, type1);
3769 /* CALL is a call whose return type and arguments are in principle
3770 compatible with FN (which satisfies direct_internal_fn_p). Return the
3771 types that should be used to determine whether the target supports FN. */
3773 tree_pair
3774 direct_internal_fn_types (internal_fn fn, gcall *call)
3776 const direct_internal_fn_info &info = direct_internal_fn (fn);
3777 tree op0 = (info.type0 < 0
3778 ? gimple_call_lhs (call)
3779 : gimple_call_arg (call, info.type0));
3780 tree op1 = (info.type1 < 0
3781 ? gimple_call_lhs (call)
3782 : gimple_call_arg (call, info.type1));
3783 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3786 /* Return true if OPTAB is supported for TYPES (whose modes should be
3787 the same) when the optimization type is OPT_TYPE. Used for simple
3788 direct optabs. */
3790 static bool
3791 direct_optab_supported_p (direct_optab optab, tree_pair types,
3792 optimization_type opt_type)
3794 machine_mode mode = TYPE_MODE (types.first);
3795 gcc_checking_assert (mode == TYPE_MODE (types.second));
3796 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3799 /* Return true if OPTAB is supported for TYPES, where the first type
3800 is the destination and the second type is the source. Used for
3801 convert optabs. */
3803 static bool
3804 convert_optab_supported_p (convert_optab optab, tree_pair types,
3805 optimization_type opt_type)
3807 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3808 TYPE_MODE (types.second), opt_type)
3809 != CODE_FOR_nothing);
3812 /* Return true if load/store lanes optab OPTAB is supported for
3813 array type TYPES.first when the optimization type is OPT_TYPE. */
3815 static bool
3816 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3817 optimization_type opt_type)
3819 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3820 machine_mode imode = TYPE_MODE (types.first);
3821 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3822 return (convert_optab_handler (optab, imode, vmode, opt_type)
3823 != CODE_FOR_nothing);
3826 #define direct_unary_optab_supported_p direct_optab_supported_p
3827 #define direct_unary_convert_optab_supported_p convert_optab_supported_p
3828 #define direct_binary_optab_supported_p direct_optab_supported_p
3829 #define direct_ternary_optab_supported_p direct_optab_supported_p
3830 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
3831 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
3832 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
3833 #define direct_mask_load_optab_supported_p convert_optab_supported_p
3834 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
3835 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
3836 #define direct_gather_load_optab_supported_p convert_optab_supported_p
3837 #define direct_len_load_optab_supported_p direct_optab_supported_p
3838 #define direct_mask_store_optab_supported_p convert_optab_supported_p
3839 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
3840 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
3841 #define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
3842 #define direct_vec_cond_optab_supported_p convert_optab_supported_p
3843 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
3844 #define direct_len_store_optab_supported_p direct_optab_supported_p
3845 #define direct_while_optab_supported_p convert_optab_supported_p
3846 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
3847 #define direct_fold_left_optab_supported_p direct_optab_supported_p
3848 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
3849 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
3850 #define direct_vec_set_optab_supported_p direct_optab_supported_p
3852 /* Return the optab used by internal function FN. */
3854 static optab
3855 direct_internal_fn_optab (internal_fn fn, tree_pair types)
3857 switch (fn)
3859 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3860 case IFN_##CODE: break;
3861 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3862 case IFN_##CODE: return OPTAB##_optab;
3863 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3864 UNSIGNED_OPTAB, TYPE) \
3865 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
3866 ? UNSIGNED_OPTAB ## _optab \
3867 : SIGNED_OPTAB ## _optab);
3868 #include "internal-fn.def"
3870 case IFN_LAST:
3871 break;
3873 gcc_unreachable ();
3876 /* Return the optab used by internal function FN. */
3878 static optab
3879 direct_internal_fn_optab (internal_fn fn)
3881 switch (fn)
3883 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3884 case IFN_##CODE: break;
3885 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3886 case IFN_##CODE: return OPTAB##_optab;
3887 #include "internal-fn.def"
3889 case IFN_LAST:
3890 break;
3892 gcc_unreachable ();
3895 /* Return true if FN is supported for the types in TYPES when the
3896 optimization type is OPT_TYPE. The types are those associated with
3897 the "type0" and "type1" fields of FN's direct_internal_fn_info
3898 structure. */
3900 bool
3901 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
3902 optimization_type opt_type)
3904 switch (fn)
3906 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
3907 case IFN_##CODE: break;
3908 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
3909 case IFN_##CODE: \
3910 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
3911 opt_type);
3912 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
3913 UNSIGNED_OPTAB, TYPE) \
3914 case IFN_##CODE: \
3916 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
3917 ? UNSIGNED_OPTAB ## _optab \
3918 : SIGNED_OPTAB ## _optab); \
3919 return direct_##TYPE##_optab_supported_p (which_optab, types, \
3920 opt_type); \
3922 #include "internal-fn.def"
3924 case IFN_LAST:
3925 break;
3927 gcc_unreachable ();
3930 /* Return true if FN is supported for type TYPE when the optimization
3931 type is OPT_TYPE. The caller knows that the "type0" and "type1"
3932 fields of FN's direct_internal_fn_info structure are the same. */
3934 bool
3935 direct_internal_fn_supported_p (internal_fn fn, tree type,
3936 optimization_type opt_type)
3938 const direct_internal_fn_info &info = direct_internal_fn (fn);
3939 gcc_checking_assert (info.type0 == info.type1);
3940 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
3943 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
3944 given that STMT is a call to a direct internal function. */
3946 bool
3947 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
3949 internal_fn fn = gimple_call_internal_fn (stmt);
3950 tree_pair types = direct_internal_fn_types (fn, stmt);
3951 return direct_internal_fn_supported_p (fn, types, opt_type);
3954 /* Return true if FN is a binary operation and if FN is commutative. */
3956 bool
3957 commutative_binary_fn_p (internal_fn fn)
3959 switch (fn)
3961 case IFN_AVG_FLOOR:
3962 case IFN_AVG_CEIL:
3963 case IFN_MULH:
3964 case IFN_MULHS:
3965 case IFN_MULHRS:
3966 case IFN_FMIN:
3967 case IFN_FMAX:
3968 case IFN_COMPLEX_MUL:
3969 case IFN_UBSAN_CHECK_ADD:
3970 case IFN_UBSAN_CHECK_MUL:
3971 case IFN_ADD_OVERFLOW:
3972 case IFN_MUL_OVERFLOW:
3973 return true;
3975 default:
3976 return false;
3980 /* Return true if FN is a ternary operation and if its first two arguments
3981 are commutative. */
3983 bool
3984 commutative_ternary_fn_p (internal_fn fn)
3986 switch (fn)
3988 case IFN_FMA:
3989 case IFN_FMS:
3990 case IFN_FNMA:
3991 case IFN_FNMS:
3992 return true;
3994 default:
3995 return false;
3999 /* Return true if FN is an associative binary operation. */
4001 bool
4002 associative_binary_fn_p (internal_fn fn)
4004 switch (fn)
4006 case IFN_FMIN:
4007 case IFN_FMAX:
4008 return true;
4010 default:
4011 return false;
4015 /* If FN is commutative in two consecutive arguments, return the
4016 index of the first, otherwise return -1. */
4019 first_commutative_argument (internal_fn fn)
4021 switch (fn)
4023 case IFN_COND_ADD:
4024 case IFN_COND_MUL:
4025 case IFN_COND_MIN:
4026 case IFN_COND_MAX:
4027 case IFN_COND_FMIN:
4028 case IFN_COND_FMAX:
4029 case IFN_COND_AND:
4030 case IFN_COND_IOR:
4031 case IFN_COND_XOR:
4032 case IFN_COND_FMA:
4033 case IFN_COND_FMS:
4034 case IFN_COND_FNMA:
4035 case IFN_COND_FNMS:
4036 return 1;
4038 default:
4039 if (commutative_binary_fn_p (fn)
4040 || commutative_ternary_fn_p (fn))
4041 return 0;
4042 return -1;
4046 /* Return true if IFN_SET_EDOM is supported. */
4048 bool
4049 set_edom_supported_p (void)
4051 #ifdef TARGET_EDOM
4052 return true;
4053 #else
4054 return false;
4055 #endif
4058 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4059 static void \
4060 expand_##CODE (internal_fn fn, gcall *stmt) \
4062 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
4064 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4065 UNSIGNED_OPTAB, TYPE) \
4066 static void \
4067 expand_##CODE (internal_fn fn, gcall *stmt) \
4069 tree_pair types = direct_internal_fn_types (fn, stmt); \
4070 optab which_optab = direct_internal_fn_optab (fn, types); \
4071 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
4073 #include "internal-fn.def"
4075 /* Routines to expand each internal function, indexed by function number.
4076 Each routine has the prototype:
4078 expand_<NAME> (gcall *stmt)
4080 where STMT is the statement that performs the call. */
4081 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
4082 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
4083 #include "internal-fn.def"
4087 /* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
4088 tree code CODE. */
4089 #define FOR_EACH_CODE_MAPPING(T) \
4090 T (PLUS_EXPR, IFN_COND_ADD) \
4091 T (MINUS_EXPR, IFN_COND_SUB) \
4092 T (MULT_EXPR, IFN_COND_MUL) \
4093 T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
4094 T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
4095 T (RDIV_EXPR, IFN_COND_RDIV) \
4096 T (MIN_EXPR, IFN_COND_MIN) \
4097 T (MAX_EXPR, IFN_COND_MAX) \
4098 T (BIT_AND_EXPR, IFN_COND_AND) \
4099 T (BIT_IOR_EXPR, IFN_COND_IOR) \
4100 T (BIT_XOR_EXPR, IFN_COND_XOR) \
4101 T (LSHIFT_EXPR, IFN_COND_SHL) \
4102 T (RSHIFT_EXPR, IFN_COND_SHR) \
4103 T (NEGATE_EXPR, IFN_COND_NEG)
4105 /* Return a function that only performs CODE when a certain condition is met
4106 and that uses a given fallback value otherwise. For example, if CODE is
4107 a binary operation associated with conditional function FN:
4109 LHS = FN (COND, A, B, ELSE)
4111 is equivalent to the C expression:
4113 LHS = COND ? A CODE B : ELSE;
4115 operating elementwise if the operands are vectors.
4117 Return IFN_LAST if no such function exists. */
4119 internal_fn
4120 get_conditional_internal_fn (tree_code code)
4122 switch (code)
4124 #define CASE(CODE, IFN) case CODE: return IFN;
4125 FOR_EACH_CODE_MAPPING(CASE)
4126 #undef CASE
4127 default:
4128 return IFN_LAST;
4132 /* If IFN implements the conditional form of a tree code, return that
4133 tree code, otherwise return ERROR_MARK. */
4135 tree_code
4136 conditional_internal_fn_code (internal_fn ifn)
4138 switch (ifn)
4140 #define CASE(CODE, IFN) case IFN: return CODE;
4141 FOR_EACH_CODE_MAPPING(CASE)
4142 #undef CASE
4143 default:
4144 return ERROR_MARK;
4148 /* Invoke T(IFN) for each internal function IFN that also has an
4149 IFN_COND_* form. */
4150 #define FOR_EACH_COND_FN_PAIR(T) \
4151 T (FMAX) \
4152 T (FMIN) \
4153 T (FMA) \
4154 T (FMS) \
4155 T (FNMA) \
4156 T (FNMS)
4158 /* Return a function that only performs internal function FN when a
4159 certain condition is met and that uses a given fallback value otherwise.
4160 In other words, the returned function FN' is such that:
4162 LHS = FN' (COND, A1, ... An, ELSE)
4164 is equivalent to the C expression:
4166 LHS = COND ? FN (A1, ..., An) : ELSE;
4168 operating elementwise if the operands are vectors.
4170 Return IFN_LAST if no such function exists. */
4172 internal_fn
4173 get_conditional_internal_fn (internal_fn fn)
4175 switch (fn)
4177 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
4178 FOR_EACH_COND_FN_PAIR(CASE)
4179 #undef CASE
4180 default:
4181 return IFN_LAST;
4185 /* If IFN implements the conditional form of an unconditional internal
4186 function, return that unconditional function, otherwise return IFN_LAST. */
4188 internal_fn
4189 get_unconditional_internal_fn (internal_fn ifn)
4191 switch (ifn)
4193 #define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
4194 FOR_EACH_COND_FN_PAIR(CASE)
4195 #undef CASE
4196 default:
4197 return IFN_LAST;
4201 /* Return true if STMT can be interpreted as a conditional tree code
4202 operation of the form:
4204 LHS = COND ? OP (RHS1, ...) : ELSE;
4206 operating elementwise if the operands are vectors. This includes
4207 the case of an all-true COND, so that the operation always happens.
4209 When returning true, set:
4211 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
4212 is known to be all-true
4213 - *CODE_OUT to the tree code
4214 - OPS[I] to operand I of *CODE_OUT
4215 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
4216 condition is known to be all true. */
4218 bool
4219 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
4220 tree_code *code_out,
4221 tree (&ops)[3], tree *else_out)
4223 if (gassign *assign = dyn_cast <gassign *> (stmt))
4225 *cond_out = NULL_TREE;
4226 *code_out = gimple_assign_rhs_code (assign);
4227 ops[0] = gimple_assign_rhs1 (assign);
4228 ops[1] = gimple_assign_rhs2 (assign);
4229 ops[2] = gimple_assign_rhs3 (assign);
4230 *else_out = NULL_TREE;
4231 return true;
4233 if (gcall *call = dyn_cast <gcall *> (stmt))
4234 if (gimple_call_internal_p (call))
4236 internal_fn ifn = gimple_call_internal_fn (call);
4237 tree_code code = conditional_internal_fn_code (ifn);
4238 if (code != ERROR_MARK)
4240 *cond_out = gimple_call_arg (call, 0);
4241 *code_out = code;
4242 unsigned int nops = gimple_call_num_args (call) - 2;
4243 for (unsigned int i = 0; i < 3; ++i)
4244 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
4245 *else_out = gimple_call_arg (call, nops + 1);
4246 if (integer_truep (*cond_out))
4248 *cond_out = NULL_TREE;
4249 *else_out = NULL_TREE;
4251 return true;
4254 return false;
4257 /* Return true if IFN is some form of load from memory. */
4259 bool
4260 internal_load_fn_p (internal_fn fn)
4262 switch (fn)
4264 case IFN_MASK_LOAD:
4265 case IFN_LOAD_LANES:
4266 case IFN_MASK_LOAD_LANES:
4267 case IFN_GATHER_LOAD:
4268 case IFN_MASK_GATHER_LOAD:
4269 case IFN_LEN_LOAD:
4270 return true;
4272 default:
4273 return false;
4277 /* Return true if IFN is some form of store to memory. */
4279 bool
4280 internal_store_fn_p (internal_fn fn)
4282 switch (fn)
4284 case IFN_MASK_STORE:
4285 case IFN_STORE_LANES:
4286 case IFN_MASK_STORE_LANES:
4287 case IFN_SCATTER_STORE:
4288 case IFN_MASK_SCATTER_STORE:
4289 case IFN_LEN_STORE:
4290 return true;
4292 default:
4293 return false;
4297 /* Return true if IFN is some form of gather load or scatter store. */
4299 bool
4300 internal_gather_scatter_fn_p (internal_fn fn)
4302 switch (fn)
4304 case IFN_GATHER_LOAD:
4305 case IFN_MASK_GATHER_LOAD:
4306 case IFN_SCATTER_STORE:
4307 case IFN_MASK_SCATTER_STORE:
4308 return true;
4310 default:
4311 return false;
4315 /* If FN takes a vector mask argument, return the index of that argument,
4316 otherwise return -1. */
4319 internal_fn_mask_index (internal_fn fn)
4321 switch (fn)
4323 case IFN_MASK_LOAD:
4324 case IFN_MASK_LOAD_LANES:
4325 case IFN_MASK_STORE:
4326 case IFN_MASK_STORE_LANES:
4327 return 2;
4329 case IFN_MASK_GATHER_LOAD:
4330 case IFN_MASK_SCATTER_STORE:
4331 return 4;
4333 default:
4334 return (conditional_internal_fn_code (fn) != ERROR_MARK
4335 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
4339 /* If FN takes a value that should be stored to memory, return the index
4340 of that argument, otherwise return -1. */
4343 internal_fn_stored_value_index (internal_fn fn)
4345 switch (fn)
4347 case IFN_MASK_STORE:
4348 case IFN_MASK_STORE_LANES:
4349 case IFN_SCATTER_STORE:
4350 case IFN_MASK_SCATTER_STORE:
4351 case IFN_LEN_STORE:
4352 return 3;
4354 default:
4355 return -1;
4359 /* Return true if the target supports gather load or scatter store function
4360 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
4361 while for stores it is the vector type of the stored data argument.
4362 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
4363 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
4364 offset from the shared base address of each loaded or stored element.
4365 SCALE is the amount by which these offsets should be multiplied
4366 *after* they have been extended to address width. */
4368 bool
4369 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
4370 tree memory_element_type,
4371 tree offset_vector_type, int scale)
4373 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
4374 TYPE_SIZE (memory_element_type)))
4375 return false;
4376 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
4377 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
4378 return false;
4379 optab optab = direct_internal_fn_optab (ifn);
4380 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
4381 TYPE_MODE (offset_vector_type));
4382 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
4383 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
4384 return (icode != CODE_FOR_nothing
4385 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
4386 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
4389 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
4390 for pointers of type TYPE when the accesses have LENGTH bytes and their
4391 common byte alignment is ALIGN. */
4393 bool
4394 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
4395 poly_uint64 length, unsigned int align)
4397 machine_mode mode = TYPE_MODE (type);
4398 optab optab = direct_internal_fn_optab (ifn);
4399 insn_code icode = direct_optab_handler (optab, mode);
4400 if (icode == CODE_FOR_nothing)
4401 return false;
4402 rtx length_rtx = immed_wide_int_const (length, mode);
4403 return (insn_operand_matches (icode, 3, length_rtx)
4404 && insn_operand_matches (icode, 4, GEN_INT (align)));
4407 /* Return the supported bias for IFN which is either IFN_LEN_LOAD
4408 or IFN_LEN_STORE. For now we only support the biases of 0 and -1
4409 (in case 0 is not an allowable length for len_load or len_store).
4410 If none of the biases match what the backend provides, return
4411 VECT_PARTIAL_BIAS_UNSUPPORTED. */
4413 signed char
4414 internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
4416 optab optab = direct_internal_fn_optab (ifn);
4417 insn_code icode = direct_optab_handler (optab, mode);
4419 if (icode != CODE_FOR_nothing)
4421 /* For now we only support biases of 0 or -1. Try both of them. */
4422 if (insn_operand_matches (icode, 3, GEN_INT (0)))
4423 return 0;
4424 if (insn_operand_matches (icode, 3, GEN_INT (-1)))
4425 return -1;
4428 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4431 /* Expand STMT as though it were a call to internal function FN. */
4433 void
4434 expand_internal_call (internal_fn fn, gcall *stmt)
4436 internal_fn_expanders[fn] (fn, stmt);
4439 /* Expand STMT, which is a call to internal function FN. */
4441 void
4442 expand_internal_call (gcall *stmt)
4444 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
4447 /* If TYPE is a vector type, return true if IFN is a direct internal
4448 function that is supported for that type. If TYPE is a scalar type,
4449 return true if IFN is a direct internal function that is supported for
4450 the target's preferred vector version of TYPE. */
4452 bool
4453 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
4455 if (VECTOR_MODE_P (TYPE_MODE (type)))
4456 return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
4458 scalar_mode smode;
4459 if (VECTOR_TYPE_P (type)
4460 || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
4461 return false;
4463 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
4464 if (VECTOR_MODE_P (vmode))
4466 tree vectype = build_vector_type_for_mode (type, vmode);
4467 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4468 return true;
4471 auto_vector_modes vector_modes;
4472 targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
4473 for (machine_mode base_mode : vector_modes)
4474 if (related_vector_mode (base_mode, smode).exists (&vmode))
4476 tree vectype = build_vector_type_for_mode (type, vmode);
4477 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4478 return true;
4481 return false;
4484 void
4485 expand_SHUFFLEVECTOR (internal_fn, gcall *)
4487 gcc_unreachable ();
4490 void
4491 expand_PHI (internal_fn, gcall *)
4493 gcc_unreachable ();
4496 void
4497 expand_SPACESHIP (internal_fn, gcall *stmt)
4499 tree lhs = gimple_call_lhs (stmt);
4500 tree rhs1 = gimple_call_arg (stmt, 0);
4501 tree rhs2 = gimple_call_arg (stmt, 1);
4502 tree type = TREE_TYPE (rhs1);
4504 do_pending_stack_adjust ();
4506 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
4507 rtx op1 = expand_normal (rhs1);
4508 rtx op2 = expand_normal (rhs2);
4510 class expand_operand ops[3];
4511 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
4512 create_input_operand (&ops[1], op1, TYPE_MODE (type));
4513 create_input_operand (&ops[2], op2, TYPE_MODE (type));
4514 insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
4515 expand_insn (icode, 3, ops);
4516 if (!rtx_equal_p (target, ops[0].value))
4517 emit_move_insn (target, ops[0].value);
4520 void
4521 expand_ASSUME (internal_fn, gcall *)
4525 void
4526 expand_MASK_CALL (internal_fn, gcall *)
4528 /* This IFN should only exist between ifcvt and vect passes. */
4529 gcc_unreachable ();