ada: Fix minor glitch in finish_record_type
[official-gcc.git] / gcc / internal-fn.cc
blob0fd343592474bdad79b78366fb14f54dee213c06
1 /* Internal functions.
2 Copyright (C) 2011-2023 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "backend.h"
24 #include "target.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "predict.h"
29 #include "stringpool.h"
30 #include "tree-vrp.h"
31 #include "tree-ssanames.h"
32 #include "expmed.h"
33 #include "memmodel.h"
34 #include "optabs.h"
35 #include "emit-rtl.h"
36 #include "diagnostic-core.h"
37 #include "fold-const.h"
38 #include "internal-fn.h"
39 #include "stor-layout.h"
40 #include "dojump.h"
41 #include "expr.h"
42 #include "stringpool.h"
43 #include "attribs.h"
44 #include "asan.h"
45 #include "ubsan.h"
46 #include "recog.h"
47 #include "builtins.h"
48 #include "optabs-tree.h"
49 #include "gimple-ssa.h"
50 #include "tree-phinodes.h"
51 #include "ssa-iterators.h"
52 #include "explow.h"
53 #include "rtl-iter.h"
54 #include "gimple-range.h"
56 /* For lang_hooks.types.type_for_mode. */
57 #include "langhooks.h"
59 /* The names of each internal function, indexed by function number. */
60 const char *const internal_fn_name_array[] = {
61 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
62 #include "internal-fn.def"
63 "<invalid-fn>"
66 /* The ECF_* flags of each internal function, indexed by function number. */
67 const int internal_fn_flags_array[] = {
68 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
69 #include "internal-fn.def"
73 /* Return the internal function called NAME, or IFN_LAST if there's
74 no such function. */
76 internal_fn
77 lookup_internal_fn (const char *name)
79 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
80 static name_to_fn_map_type *name_to_fn_map;
82 if (!name_to_fn_map)
84 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
85 for (unsigned int i = 0; i < IFN_LAST; ++i)
86 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
87 internal_fn (i));
89 internal_fn *entry = name_to_fn_map->get (name);
90 return entry ? *entry : IFN_LAST;
93 /* Geven an internal_fn IFN that is a widening function, return its
94 corresponding LO and HI internal_fns. */
96 extern void
97 lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi)
99 gcc_assert (widening_fn_p (ifn));
101 switch (ifn)
103 default:
104 gcc_unreachable ();
105 #undef DEF_INTERNAL_FN
106 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
107 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
108 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
109 case IFN_##NAME: \
110 *lo = internal_fn (IFN_##NAME##_LO); \
111 *hi = internal_fn (IFN_##NAME##_HI); \
112 break;
113 #include "internal-fn.def"
114 #undef DEF_INTERNAL_FN
115 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
119 /* Given an internal_fn IFN that is a widening function, return its
120 corresponding _EVEN and _ODD internal_fns in *EVEN and *ODD. */
122 extern void
123 lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even,
124 internal_fn *odd)
126 gcc_assert (widening_fn_p (ifn));
128 switch (ifn)
130 default:
131 gcc_unreachable ();
132 #undef DEF_INTERNAL_FN
133 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
134 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
135 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
136 case IFN_##NAME: \
137 *even = internal_fn (IFN_##NAME##_EVEN); \
138 *odd = internal_fn (IFN_##NAME##_ODD); \
139 break;
140 #include "internal-fn.def"
141 #undef DEF_INTERNAL_FN
142 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
147 /* Fnspec of each internal function, indexed by function number. */
148 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
150 void
151 init_internal_fns ()
153 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
154 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
155 build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
156 #include "internal-fn.def"
157 internal_fn_fnspec_array[IFN_LAST] = 0;
160 /* Create static initializers for the information returned by
161 direct_internal_fn. */
162 #define not_direct { -2, -2, false }
163 #define mask_load_direct { -1, 2, false }
164 #define load_lanes_direct { -1, -1, false }
165 #define mask_load_lanes_direct { -1, -1, false }
166 #define gather_load_direct { 3, 1, false }
167 #define len_load_direct { -1, -1, false }
168 #define mask_len_load_direct { -1, 4, false }
169 #define mask_store_direct { 3, 2, false }
170 #define store_lanes_direct { 0, 0, false }
171 #define mask_store_lanes_direct { 0, 0, false }
172 #define vec_cond_mask_direct { 1, 0, false }
173 #define vec_cond_direct { 2, 0, false }
174 #define scatter_store_direct { 3, 1, false }
175 #define len_store_direct { 3, 3, false }
176 #define mask_len_store_direct { 4, 5, false }
177 #define vec_set_direct { 3, 3, false }
178 #define vec_extract_direct { 0, -1, false }
179 #define unary_direct { 0, 0, true }
180 #define unary_convert_direct { -1, 0, true }
181 #define binary_direct { 0, 0, true }
182 #define ternary_direct { 0, 0, true }
183 #define cond_unary_direct { 1, 1, true }
184 #define cond_binary_direct { 1, 1, true }
185 #define cond_ternary_direct { 1, 1, true }
186 #define cond_len_unary_direct { 1, 1, true }
187 #define cond_len_binary_direct { 1, 1, true }
188 #define cond_len_ternary_direct { 1, 1, true }
189 #define while_direct { 0, 2, false }
190 #define fold_extract_direct { 2, 2, false }
191 #define fold_len_extract_direct { 2, 2, false }
192 #define fold_left_direct { 1, 1, false }
193 #define mask_fold_left_direct { 1, 1, false }
194 #define mask_len_fold_left_direct { 1, 1, false }
195 #define check_ptrs_direct { 0, 0, false }
197 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
198 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
199 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
200 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
201 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
202 #include "internal-fn.def"
203 not_direct
206 /* Expand STMT using instruction ICODE. The instruction has NOUTPUTS
207 output operands and NINPUTS input operands, where NOUTPUTS is either
208 0 or 1. The output operand (if any) comes first, followed by the
209 NINPUTS input operands. */
211 static void
212 expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
213 unsigned int ninputs)
215 gcc_assert (icode != CODE_FOR_nothing);
217 expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
218 unsigned int opno = 0;
219 rtx lhs_rtx = NULL_RTX;
220 tree lhs = gimple_call_lhs (stmt);
222 if (noutputs)
224 gcc_assert (noutputs == 1);
225 if (lhs)
226 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
228 /* Do not assign directly to a promoted subreg, since there is no
229 guarantee that the instruction will leave the upper bits of the
230 register in the state required by SUBREG_PROMOTED_SIGN. */
231 rtx dest = lhs_rtx;
232 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
233 dest = NULL_RTX;
234 create_output_operand (&ops[opno], dest,
235 insn_data[icode].operand[opno].mode);
236 opno += 1;
238 else
239 gcc_assert (!lhs);
241 for (unsigned int i = 0; i < ninputs; ++i)
243 tree rhs = gimple_call_arg (stmt, i);
244 tree rhs_type = TREE_TYPE (rhs);
245 rtx rhs_rtx = expand_normal (rhs);
246 if (INTEGRAL_TYPE_P (rhs_type))
247 create_convert_operand_from (&ops[opno], rhs_rtx,
248 TYPE_MODE (rhs_type),
249 TYPE_UNSIGNED (rhs_type));
250 else
251 create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
252 opno += 1;
255 gcc_assert (opno == noutputs + ninputs);
256 expand_insn (icode, opno, ops);
257 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
259 /* If the return value has an integral type, convert the instruction
260 result to that type. This is useful for things that return an
261 int regardless of the size of the input. If the instruction result
262 is smaller than required, assume that it is signed.
264 If the return value has a nonintegral type, its mode must match
265 the instruction result. */
266 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
268 /* If this is a scalar in a register that is stored in a wider
269 mode than the declared mode, compute the result into its
270 declared mode and then convert to the wider mode. */
271 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
272 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
273 convert_move (SUBREG_REG (lhs_rtx), tmp,
274 SUBREG_PROMOTED_SIGN (lhs_rtx));
276 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
277 emit_move_insn (lhs_rtx, ops[0].value);
278 else
280 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
281 convert_move (lhs_rtx, ops[0].value, 0);
286 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
287 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
289 static enum insn_code
290 get_multi_vector_move (tree array_type, convert_optab optab)
292 machine_mode imode;
293 machine_mode vmode;
295 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
296 imode = TYPE_MODE (array_type);
297 vmode = TYPE_MODE (TREE_TYPE (array_type));
299 return convert_optab_handler (optab, imode, vmode);
302 /* Add mask and len arguments according to the STMT. */
304 static unsigned int
305 add_mask_and_len_args (expand_operand *ops, unsigned int opno, gcall *stmt)
307 internal_fn ifn = gimple_call_internal_fn (stmt);
308 int len_index = internal_fn_len_index (ifn);
309 /* BIAS is always consecutive next of LEN. */
310 int bias_index = len_index + 1;
311 int mask_index = internal_fn_mask_index (ifn);
312 /* The order of arguments are always {len,bias,mask}. */
313 if (mask_index >= 0)
315 tree mask = gimple_call_arg (stmt, mask_index);
316 rtx mask_rtx = expand_normal (mask);
317 create_input_operand (&ops[opno++], mask_rtx,
318 TYPE_MODE (TREE_TYPE (mask)));
320 if (len_index >= 0)
322 tree len = gimple_call_arg (stmt, len_index);
323 rtx len_rtx = expand_normal (len);
324 create_convert_operand_from (&ops[opno++], len_rtx,
325 TYPE_MODE (TREE_TYPE (len)),
326 TYPE_UNSIGNED (TREE_TYPE (len)));
327 tree biast = gimple_call_arg (stmt, bias_index);
328 rtx bias = expand_normal (biast);
329 create_input_operand (&ops[opno++], bias, QImode);
331 return opno;
334 /* Expand LOAD_LANES call STMT using optab OPTAB. */
336 static void
337 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
339 class expand_operand ops[2];
340 tree type, lhs, rhs;
341 rtx target, mem;
343 lhs = gimple_call_lhs (stmt);
344 rhs = gimple_call_arg (stmt, 0);
345 type = TREE_TYPE (lhs);
347 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
348 mem = expand_normal (rhs);
350 gcc_assert (MEM_P (mem));
351 PUT_MODE (mem, TYPE_MODE (type));
353 create_output_operand (&ops[0], target, TYPE_MODE (type));
354 create_fixed_operand (&ops[1], mem);
355 expand_insn (get_multi_vector_move (type, optab), 2, ops);
356 if (!rtx_equal_p (target, ops[0].value))
357 emit_move_insn (target, ops[0].value);
360 /* Expand STORE_LANES call STMT using optab OPTAB. */
362 static void
363 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
365 class expand_operand ops[2];
366 tree type, lhs, rhs;
367 rtx target, reg;
369 lhs = gimple_call_lhs (stmt);
370 rhs = gimple_call_arg (stmt, 0);
371 type = TREE_TYPE (rhs);
373 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
374 reg = expand_normal (rhs);
376 gcc_assert (MEM_P (target));
377 PUT_MODE (target, TYPE_MODE (type));
379 create_fixed_operand (&ops[0], target);
380 create_input_operand (&ops[1], reg, TYPE_MODE (type));
381 expand_insn (get_multi_vector_move (type, optab), 2, ops);
384 static void
385 expand_ANNOTATE (internal_fn, gcall *)
387 gcc_unreachable ();
390 /* This should get expanded in omp_device_lower pass. */
392 static void
393 expand_GOMP_USE_SIMT (internal_fn, gcall *)
395 gcc_unreachable ();
398 /* This should get expanded in omp_device_lower pass. */
400 static void
401 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
403 gcc_unreachable ();
406 /* Allocate per-lane storage and begin non-uniform execution region. */
408 static void
409 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
411 rtx target;
412 tree lhs = gimple_call_lhs (stmt);
413 if (lhs)
414 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
415 else
416 target = gen_reg_rtx (Pmode);
417 rtx size = expand_normal (gimple_call_arg (stmt, 0));
418 rtx align = expand_normal (gimple_call_arg (stmt, 1));
419 class expand_operand ops[3];
420 create_output_operand (&ops[0], target, Pmode);
421 create_input_operand (&ops[1], size, Pmode);
422 create_input_operand (&ops[2], align, Pmode);
423 gcc_assert (targetm.have_omp_simt_enter ());
424 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
425 if (!rtx_equal_p (target, ops[0].value))
426 emit_move_insn (target, ops[0].value);
429 /* Deallocate per-lane storage and leave non-uniform execution region. */
431 static void
432 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
434 gcc_checking_assert (!gimple_call_lhs (stmt));
435 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
436 class expand_operand ops[1];
437 create_input_operand (&ops[0], arg, Pmode);
438 gcc_assert (targetm.have_omp_simt_exit ());
439 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
442 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
443 without SIMT execution this should be expanded in omp_device_lower pass. */
445 static void
446 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
448 tree lhs = gimple_call_lhs (stmt);
449 if (!lhs)
450 return;
452 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
453 gcc_assert (targetm.have_omp_simt_lane ());
454 emit_insn (targetm.gen_omp_simt_lane (target));
457 /* This should get expanded in omp_device_lower pass. */
459 static void
460 expand_GOMP_SIMT_VF (internal_fn, gcall *)
462 gcc_unreachable ();
465 /* This should get expanded in omp_device_lower pass. */
467 static void
468 expand_GOMP_TARGET_REV (internal_fn, gcall *)
470 gcc_unreachable ();
473 /* Lane index of the first SIMT lane that supplies a non-zero argument.
474 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
475 lane that executed the last iteration for handling OpenMP lastprivate. */
477 static void
478 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
480 tree lhs = gimple_call_lhs (stmt);
481 if (!lhs)
482 return;
484 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
485 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
486 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
487 class expand_operand ops[2];
488 create_output_operand (&ops[0], target, mode);
489 create_input_operand (&ops[1], cond, mode);
490 gcc_assert (targetm.have_omp_simt_last_lane ());
491 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
492 if (!rtx_equal_p (target, ops[0].value))
493 emit_move_insn (target, ops[0].value);
496 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
498 static void
499 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
501 tree lhs = gimple_call_lhs (stmt);
502 if (!lhs)
503 return;
505 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
506 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
507 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
508 class expand_operand ops[2];
509 create_output_operand (&ops[0], target, mode);
510 create_input_operand (&ops[1], ctr, mode);
511 gcc_assert (targetm.have_omp_simt_ordered ());
512 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
513 if (!rtx_equal_p (target, ops[0].value))
514 emit_move_insn (target, ops[0].value);
517 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
518 any lane supplies a non-zero argument. */
520 static void
521 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
523 tree lhs = gimple_call_lhs (stmt);
524 if (!lhs)
525 return;
527 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
528 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
529 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
530 class expand_operand ops[2];
531 create_output_operand (&ops[0], target, mode);
532 create_input_operand (&ops[1], cond, mode);
533 gcc_assert (targetm.have_omp_simt_vote_any ());
534 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
535 if (!rtx_equal_p (target, ops[0].value))
536 emit_move_insn (target, ops[0].value);
539 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
540 is destination lane index XOR given offset. */
542 static void
543 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
545 tree lhs = gimple_call_lhs (stmt);
546 if (!lhs)
547 return;
549 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
550 rtx src = expand_normal (gimple_call_arg (stmt, 0));
551 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
552 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
553 class expand_operand ops[3];
554 create_output_operand (&ops[0], target, mode);
555 create_input_operand (&ops[1], src, mode);
556 create_input_operand (&ops[2], idx, SImode);
557 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
558 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
559 if (!rtx_equal_p (target, ops[0].value))
560 emit_move_insn (target, ops[0].value);
563 /* Exchange between SIMT lanes according to given source lane index. */
565 static void
566 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
568 tree lhs = gimple_call_lhs (stmt);
569 if (!lhs)
570 return;
572 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
573 rtx src = expand_normal (gimple_call_arg (stmt, 0));
574 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
575 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
576 class expand_operand ops[3];
577 create_output_operand (&ops[0], target, mode);
578 create_input_operand (&ops[1], src, mode);
579 create_input_operand (&ops[2], idx, SImode);
580 gcc_assert (targetm.have_omp_simt_xchg_idx ());
581 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
582 if (!rtx_equal_p (target, ops[0].value))
583 emit_move_insn (target, ops[0].value);
586 /* This should get expanded in adjust_simduid_builtins. */
588 static void
589 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
591 gcc_unreachable ();
594 /* This should get expanded in adjust_simduid_builtins. */
596 static void
597 expand_GOMP_SIMD_VF (internal_fn, gcall *)
599 gcc_unreachable ();
602 /* This should get expanded in adjust_simduid_builtins. */
604 static void
605 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
607 gcc_unreachable ();
610 /* This should get expanded in adjust_simduid_builtins. */
612 static void
613 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
615 gcc_unreachable ();
618 /* This should get expanded in adjust_simduid_builtins. */
620 static void
621 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
623 gcc_unreachable ();
626 /* This should get expanded in the sanopt pass. */
628 static void
629 expand_UBSAN_NULL (internal_fn, gcall *)
631 gcc_unreachable ();
634 /* This should get expanded in the sanopt pass. */
636 static void
637 expand_UBSAN_BOUNDS (internal_fn, gcall *)
639 gcc_unreachable ();
642 /* This should get expanded in the sanopt pass. */
644 static void
645 expand_UBSAN_VPTR (internal_fn, gcall *)
647 gcc_unreachable ();
650 /* This should get expanded in the sanopt pass. */
652 static void
653 expand_UBSAN_PTR (internal_fn, gcall *)
655 gcc_unreachable ();
658 /* This should get expanded in the sanopt pass. */
660 static void
661 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
663 gcc_unreachable ();
666 /* This should get expanded in the sanopt pass. */
668 static void
669 expand_HWASAN_CHECK (internal_fn, gcall *)
671 gcc_unreachable ();
674 /* For hwasan stack tagging:
675 Clear tags on the dynamically allocated space.
676 For use after an object dynamically allocated on the stack goes out of
677 scope. */
678 static void
679 expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
681 gcc_assert (Pmode == ptr_mode);
682 tree restored_position = gimple_call_arg (gc, 0);
683 rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
684 EXPAND_NORMAL);
685 rtx func = init_one_libfunc ("__hwasan_tag_memory");
686 rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
687 stack_pointer_rtx, NULL_RTX, 0,
688 OPTAB_WIDEN);
689 emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
690 virtual_stack_dynamic_rtx, Pmode,
691 HWASAN_STACK_BACKGROUND, QImode,
692 off, Pmode);
695 /* For hwasan stack tagging:
696 Return a tag to be used for a dynamic allocation. */
697 static void
698 expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
700 tree tag = gimple_call_lhs (gc);
701 rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
702 machine_mode mode = GET_MODE (target);
703 gcc_assert (mode == QImode);
705 rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
706 gcc_assert (base_tag);
707 rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
708 rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
709 target, /* unsignedp = */1,
710 OPTAB_WIDEN);
711 chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
713 /* Really need to put the tag into the `target` RTX. */
714 if (chosen_tag != target)
716 rtx temp = chosen_tag;
717 gcc_assert (GET_MODE (chosen_tag) == mode);
718 emit_move_insn (target, temp);
721 hwasan_increment_frame_tag ();
724 /* For hwasan stack tagging:
725 Tag a region of space in the shadow stack according to the base pointer of
726 an object on the stack. N.b. the length provided in the internal call is
727 required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
728 static void
729 expand_HWASAN_MARK (internal_fn, gcall *gc)
731 gcc_assert (ptr_mode == Pmode);
732 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
733 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
735 tree base = gimple_call_arg (gc, 1);
736 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
737 rtx base_rtx = expand_normal (base);
739 rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
740 : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
741 rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
743 tree len = gimple_call_arg (gc, 2);
744 rtx r_len = expand_normal (len);
746 rtx func = init_one_libfunc ("__hwasan_tag_memory");
747 emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
748 tag, QImode, r_len, Pmode);
751 /* For hwasan stack tagging:
752 Store a tag into a pointer. */
753 static void
754 expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
756 gcc_assert (ptr_mode == Pmode);
757 tree g_target = gimple_call_lhs (gc);
758 tree g_ptr = gimple_call_arg (gc, 0);
759 tree g_tag = gimple_call_arg (gc, 1);
761 rtx ptr = expand_normal (g_ptr);
762 rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
763 rtx target = expand_normal (g_target);
765 rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
766 rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
767 if (tagged_value != target)
768 emit_move_insn (target, tagged_value);
771 /* This should get expanded in the sanopt pass. */
773 static void
774 expand_ASAN_CHECK (internal_fn, gcall *)
776 gcc_unreachable ();
779 /* This should get expanded in the sanopt pass. */
781 static void
782 expand_ASAN_MARK (internal_fn, gcall *)
784 gcc_unreachable ();
787 /* This should get expanded in the sanopt pass. */
789 static void
790 expand_ASAN_POISON (internal_fn, gcall *)
792 gcc_unreachable ();
795 /* This should get expanded in the sanopt pass. */
797 static void
798 expand_ASAN_POISON_USE (internal_fn, gcall *)
800 gcc_unreachable ();
803 /* This should get expanded in the tsan pass. */
805 static void
806 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
808 gcc_unreachable ();
811 /* This should get expanded in the lower pass. */
813 static void
814 expand_FALLTHROUGH (internal_fn, gcall *call)
816 error_at (gimple_location (call),
817 "invalid use of attribute %<fallthrough%>");
820 /* Return minimum precision needed to represent all values
821 of ARG in SIGNed integral type. */
823 static int
824 get_min_precision (tree arg, signop sign)
826 int prec = TYPE_PRECISION (TREE_TYPE (arg));
827 int cnt = 0;
828 signop orig_sign = sign;
829 if (TREE_CODE (arg) == INTEGER_CST)
831 int p;
832 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
834 widest_int w = wi::to_widest (arg);
835 w = wi::ext (w, prec, sign);
836 p = wi::min_precision (w, sign);
838 else
839 p = wi::min_precision (wi::to_wide (arg), sign);
840 return MIN (p, prec);
842 while (CONVERT_EXPR_P (arg)
843 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
844 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
846 arg = TREE_OPERAND (arg, 0);
847 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
849 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
850 sign = UNSIGNED;
851 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
852 return prec + (orig_sign != sign);
853 prec = TYPE_PRECISION (TREE_TYPE (arg));
855 if (++cnt > 30)
856 return prec + (orig_sign != sign);
858 if (CONVERT_EXPR_P (arg)
859 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
860 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
862 /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
863 If y_2's min precision is smaller than prec, return that. */
864 int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
865 if (oprec < prec)
866 return oprec + (orig_sign != sign);
868 if (TREE_CODE (arg) != SSA_NAME)
869 return prec + (orig_sign != sign);
870 value_range r;
871 while (!get_global_range_query ()->range_of_expr (r, arg)
872 || r.varying_p ()
873 || r.undefined_p ())
875 gimple *g = SSA_NAME_DEF_STMT (arg);
876 if (is_gimple_assign (g)
877 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
879 tree t = gimple_assign_rhs1 (g);
880 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
881 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
883 arg = t;
884 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
886 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
887 sign = UNSIGNED;
888 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
889 return prec + (orig_sign != sign);
890 prec = TYPE_PRECISION (TREE_TYPE (arg));
892 if (++cnt > 30)
893 return prec + (orig_sign != sign);
894 continue;
897 return prec + (orig_sign != sign);
899 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
901 int p1 = wi::min_precision (r.lower_bound (), sign);
902 int p2 = wi::min_precision (r.upper_bound (), sign);
903 p1 = MAX (p1, p2);
904 prec = MIN (prec, p1);
906 else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
908 int p = wi::min_precision (r.upper_bound (), UNSIGNED);
909 prec = MIN (prec, p);
911 return prec + (orig_sign != sign);
914 /* Helper for expand_*_overflow. Set the __imag__ part to true
915 (1 except for signed:1 type, in which case store -1). */
917 static void
918 expand_arith_set_overflow (tree lhs, rtx target)
920 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
921 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
922 write_complex_part (target, constm1_rtx, true, false);
923 else
924 write_complex_part (target, const1_rtx, true, false);
927 /* Helper for expand_*_overflow. Store RES into the __real__ part
928 of TARGET. If RES has larger MODE than __real__ part of TARGET,
929 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
930 if LHS has smaller precision than its mode. */
932 static void
933 expand_arith_overflow_result_store (tree lhs, rtx target,
934 scalar_int_mode mode, rtx res)
936 scalar_int_mode tgtmode
937 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
938 rtx lres = res;
939 if (tgtmode != mode)
941 rtx_code_label *done_label = gen_label_rtx ();
942 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
943 lres = convert_modes (tgtmode, mode, res, uns);
944 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
945 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
946 EQ, true, mode, NULL_RTX, NULL, done_label,
947 profile_probability::very_likely ());
948 expand_arith_set_overflow (lhs, target);
949 emit_label (done_label);
951 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
952 int tgtprec = GET_MODE_PRECISION (tgtmode);
953 if (prec < tgtprec)
955 rtx_code_label *done_label = gen_label_rtx ();
956 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
957 res = lres;
958 if (uns)
960 rtx mask
961 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
962 tgtmode);
963 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
964 true, OPTAB_LIB_WIDEN);
966 else
968 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
969 NULL_RTX, 1);
970 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
971 NULL_RTX, 0);
973 do_compare_rtx_and_jump (res, lres,
974 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
975 profile_probability::very_likely ());
976 expand_arith_set_overflow (lhs, target);
977 emit_label (done_label);
979 write_complex_part (target, lres, false, false);
982 /* Helper for expand_*_overflow. Store RES into TARGET. */
984 static void
985 expand_ubsan_result_store (tree lhs, rtx target, scalar_int_mode mode,
986 rtx res, rtx_code_label *do_error)
988 if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE
989 && TYPE_PRECISION (TREE_TYPE (lhs)) < GET_MODE_PRECISION (mode))
991 int uns = TYPE_UNSIGNED (TREE_TYPE (lhs));
992 int prec = TYPE_PRECISION (TREE_TYPE (lhs));
993 int tgtprec = GET_MODE_PRECISION (mode);
994 rtx resc = gen_reg_rtx (mode), lres;
995 emit_move_insn (resc, res);
996 if (uns)
998 rtx mask
999 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
1000 mode);
1001 lres = expand_simple_binop (mode, AND, res, mask, NULL_RTX,
1002 true, OPTAB_LIB_WIDEN);
1004 else
1006 lres = expand_shift (LSHIFT_EXPR, mode, res, tgtprec - prec,
1007 NULL_RTX, 1);
1008 lres = expand_shift (RSHIFT_EXPR, mode, lres, tgtprec - prec,
1009 NULL_RTX, 0);
1011 if (lres != res)
1012 emit_move_insn (res, lres);
1013 do_compare_rtx_and_jump (res, resc,
1014 NE, true, mode, NULL_RTX, NULL, do_error,
1015 profile_probability::very_unlikely ());
1017 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
1018 /* If this is a scalar in a register that is stored in a wider mode
1019 than the declared mode, compute the result into its declared mode
1020 and then convert to the wider mode. Our value is the computed
1021 expression. */
1022 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
1023 else
1024 emit_move_insn (target, res);
1027 /* Add sub/add overflow checking to the statement STMT.
1028 CODE says whether the operation is +, or -. */
1030 void
1031 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
1032 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
1033 bool uns1_p, bool is_ubsan, tree *datap)
1035 rtx res, target = NULL_RTX;
1036 tree fn;
1037 rtx_code_label *done_label = gen_label_rtx ();
1038 rtx_code_label *do_error = gen_label_rtx ();
1039 do_pending_stack_adjust ();
1040 rtx op0 = expand_normal (arg0);
1041 rtx op1 = expand_normal (arg1);
1042 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1043 int prec = GET_MODE_PRECISION (mode);
1044 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1045 bool do_xor = false;
1047 if (is_ubsan)
1048 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1050 if (lhs)
1052 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1053 if (!is_ubsan)
1054 write_complex_part (target, const0_rtx, true, false);
1057 /* We assume both operands and result have the same precision
1058 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1059 with that precision, U for unsigned type with that precision,
1060 sgn for unsigned most significant bit in that precision.
1061 s1 is signed first operand, u1 is unsigned first operand,
1062 s2 is signed second operand, u2 is unsigned second operand,
1063 sr is signed result, ur is unsigned result and the following
1064 rules say how to compute result (which is always result of
1065 the operands as if both were unsigned, cast to the right
1066 signedness) and how to compute whether operation overflowed.
1068 s1 + s2 -> sr
1069 res = (S) ((U) s1 + (U) s2)
1070 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
1071 s1 - s2 -> sr
1072 res = (S) ((U) s1 - (U) s2)
1073 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
1074 u1 + u2 -> ur
1075 res = u1 + u2
1076 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
1077 u1 - u2 -> ur
1078 res = u1 - u2
1079 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
1080 s1 + u2 -> sr
1081 res = (S) ((U) s1 + u2)
1082 ovf = ((U) res ^ sgn) < u2
1083 s1 + u2 -> ur
1084 t1 = (S) (u2 ^ sgn)
1085 t2 = s1 + t1
1086 res = (U) t2 ^ sgn
1087 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
1088 s1 - u2 -> sr
1089 res = (S) ((U) s1 - u2)
1090 ovf = u2 > ((U) s1 ^ sgn)
1091 s1 - u2 -> ur
1092 res = (U) s1 - u2
1093 ovf = s1 < 0 || u2 > (U) s1
1094 u1 - s2 -> sr
1095 res = u1 - (U) s2
1096 ovf = u1 >= ((U) s2 ^ sgn)
1097 u1 - s2 -> ur
1098 t1 = u1 ^ sgn
1099 t2 = t1 - (U) s2
1100 res = t2 ^ sgn
1101 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
1102 s1 + s2 -> ur
1103 res = (U) s1 + (U) s2
1104 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
1105 u1 + u2 -> sr
1106 res = (S) (u1 + u2)
1107 ovf = (U) res < u2 || res < 0
1108 u1 - u2 -> sr
1109 res = (S) (u1 - u2)
1110 ovf = u1 >= u2 ? res < 0 : res >= 0
1111 s1 - s2 -> ur
1112 res = (U) s1 - (U) s2
1113 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
1115 if (code == PLUS_EXPR && uns0_p && !uns1_p)
1117 /* PLUS_EXPR is commutative, if operand signedness differs,
1118 canonicalize to the first operand being signed and second
1119 unsigned to simplify following code. */
1120 std::swap (op0, op1);
1121 std::swap (arg0, arg1);
1122 uns0_p = false;
1123 uns1_p = true;
1126 /* u1 +- u2 -> ur */
1127 if (uns0_p && uns1_p && unsr_p)
1129 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
1130 : usubv4_optab, mode);
1131 if (icode != CODE_FOR_nothing)
1133 class expand_operand ops[4];
1134 rtx_insn *last = get_last_insn ();
1136 res = gen_reg_rtx (mode);
1137 create_output_operand (&ops[0], res, mode);
1138 create_input_operand (&ops[1], op0, mode);
1139 create_input_operand (&ops[2], op1, mode);
1140 create_fixed_operand (&ops[3], do_error);
1141 if (maybe_expand_insn (icode, 4, ops))
1143 last = get_last_insn ();
1144 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1145 && JUMP_P (last)
1146 && any_condjump_p (last)
1147 && !find_reg_note (last, REG_BR_PROB, 0))
1148 add_reg_br_prob_note (last,
1149 profile_probability::very_unlikely ());
1150 emit_jump (done_label);
1151 goto do_error_label;
1154 delete_insns_since (last);
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 rtx tem = op0;
1162 /* For PLUS_EXPR, the operation is commutative, so we can pick
1163 operand to compare against. For prec <= BITS_PER_WORD, I think
1164 preferring REG operand is better over CONST_INT, because
1165 the CONST_INT might enlarge the instruction or CSE would need
1166 to figure out we'd already loaded it into a register before.
1167 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
1168 as then the multi-word comparison can be perhaps simplified. */
1169 if (code == PLUS_EXPR
1170 && (prec <= BITS_PER_WORD
1171 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
1172 : CONST_SCALAR_INT_P (op1)))
1173 tem = op1;
1174 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1175 true, mode, NULL_RTX, NULL, done_label,
1176 profile_probability::very_likely ());
1177 goto do_error_label;
1180 /* s1 +- u2 -> sr */
1181 if (!uns0_p && uns1_p && !unsr_p)
1183 /* Compute the operation. On RTL level, the addition is always
1184 unsigned. */
1185 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1186 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1187 rtx tem = expand_binop (mode, add_optab,
1188 code == PLUS_EXPR ? res : op0, sgn,
1189 NULL_RTX, false, OPTAB_LIB_WIDEN);
1190 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1191 done_label, profile_probability::very_likely ());
1192 goto do_error_label;
1195 /* s1 + u2 -> ur */
1196 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
1198 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1199 OPTAB_LIB_WIDEN);
1200 /* As we've changed op1, we have to avoid using the value range
1201 for the original argument. */
1202 arg1 = error_mark_node;
1203 do_xor = true;
1204 goto do_signed;
1207 /* u1 - s2 -> ur */
1208 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
1210 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
1211 OPTAB_LIB_WIDEN);
1212 /* As we've changed op0, we have to avoid using the value range
1213 for the original argument. */
1214 arg0 = error_mark_node;
1215 do_xor = true;
1216 goto do_signed;
1219 /* s1 - u2 -> ur */
1220 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
1222 /* Compute the operation. On RTL level, the addition is always
1223 unsigned. */
1224 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1225 OPTAB_LIB_WIDEN);
1226 int pos_neg = get_range_pos_neg (arg0);
1227 if (pos_neg == 2)
1228 /* If ARG0 is known to be always negative, this is always overflow. */
1229 emit_jump (do_error);
1230 else if (pos_neg == 3)
1231 /* If ARG0 is not known to be always positive, check at runtime. */
1232 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1233 NULL, do_error, profile_probability::very_unlikely ());
1234 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1235 done_label, profile_probability::very_likely ());
1236 goto do_error_label;
1239 /* u1 - s2 -> sr */
1240 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
1242 /* Compute the operation. On RTL level, the addition is always
1243 unsigned. */
1244 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1245 OPTAB_LIB_WIDEN);
1246 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1247 OPTAB_LIB_WIDEN);
1248 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1249 done_label, profile_probability::very_likely ());
1250 goto do_error_label;
1253 /* u1 + u2 -> sr */
1254 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
1256 /* Compute the operation. On RTL level, the addition is always
1257 unsigned. */
1258 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
1259 OPTAB_LIB_WIDEN);
1260 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1261 NULL, do_error, profile_probability::very_unlikely ());
1262 rtx tem = op1;
1263 /* The operation is commutative, so we can pick operand to compare
1264 against. For prec <= BITS_PER_WORD, I think preferring REG operand
1265 is better over CONST_INT, because the CONST_INT might enlarge the
1266 instruction or CSE would need to figure out we'd already loaded it
1267 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
1268 might be more beneficial, as then the multi-word comparison can be
1269 perhaps simplified. */
1270 if (prec <= BITS_PER_WORD
1271 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
1272 : CONST_SCALAR_INT_P (op0))
1273 tem = op0;
1274 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1275 done_label, profile_probability::very_likely ());
1276 goto do_error_label;
1279 /* s1 +- s2 -> ur */
1280 if (!uns0_p && !uns1_p && unsr_p)
1282 /* Compute the operation. On RTL level, the addition is always
1283 unsigned. */
1284 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1285 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1286 int pos_neg = get_range_pos_neg (arg1);
1287 if (code == PLUS_EXPR)
1289 int pos_neg0 = get_range_pos_neg (arg0);
1290 if (pos_neg0 != 3 && pos_neg == 3)
1292 std::swap (op0, op1);
1293 pos_neg = pos_neg0;
1296 rtx tem;
1297 if (pos_neg != 3)
1299 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
1300 ? and_optab : ior_optab,
1301 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1302 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
1303 NULL, done_label, profile_probability::very_likely ());
1305 else
1307 rtx_code_label *do_ior_label = gen_label_rtx ();
1308 do_compare_rtx_and_jump (op1, const0_rtx,
1309 code == MINUS_EXPR ? GE : LT, false, mode,
1310 NULL_RTX, NULL, do_ior_label,
1311 profile_probability::even ());
1312 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
1313 OPTAB_LIB_WIDEN);
1314 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1315 NULL, done_label, profile_probability::very_likely ());
1316 emit_jump (do_error);
1317 emit_label (do_ior_label);
1318 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
1319 OPTAB_LIB_WIDEN);
1320 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1321 NULL, done_label, profile_probability::very_likely ());
1323 goto do_error_label;
1326 /* u1 - u2 -> sr */
1327 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
1329 /* Compute the operation. On RTL level, the addition is always
1330 unsigned. */
1331 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1332 OPTAB_LIB_WIDEN);
1333 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1334 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1335 op0_geu_op1, profile_probability::even ());
1336 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1337 NULL, done_label, profile_probability::very_likely ());
1338 emit_jump (do_error);
1339 emit_label (op0_geu_op1);
1340 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1341 NULL, done_label, profile_probability::very_likely ());
1342 goto do_error_label;
1345 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1347 /* s1 +- s2 -> sr */
1348 do_signed:
1350 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1351 : subv4_optab, mode);
1352 if (icode != CODE_FOR_nothing)
1354 class expand_operand ops[4];
1355 rtx_insn *last = get_last_insn ();
1357 res = gen_reg_rtx (mode);
1358 create_output_operand (&ops[0], res, mode);
1359 create_input_operand (&ops[1], op0, mode);
1360 create_input_operand (&ops[2], op1, mode);
1361 create_fixed_operand (&ops[3], do_error);
1362 if (maybe_expand_insn (icode, 4, ops))
1364 last = get_last_insn ();
1365 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1366 && JUMP_P (last)
1367 && any_condjump_p (last)
1368 && !find_reg_note (last, REG_BR_PROB, 0))
1369 add_reg_br_prob_note (last,
1370 profile_probability::very_unlikely ());
1371 emit_jump (done_label);
1372 goto do_error_label;
1375 delete_insns_since (last);
1378 /* Compute the operation. On RTL level, the addition is always
1379 unsigned. */
1380 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1381 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1383 /* If we can prove that one of the arguments (for MINUS_EXPR only
1384 the second operand, as subtraction is not commutative) is always
1385 non-negative or always negative, we can do just one comparison
1386 and conditional jump. */
1387 int pos_neg = get_range_pos_neg (arg1);
1388 if (code == PLUS_EXPR)
1390 int pos_neg0 = get_range_pos_neg (arg0);
1391 if (pos_neg0 != 3 && pos_neg == 3)
1393 std::swap (op0, op1);
1394 pos_neg = pos_neg0;
1398 /* Addition overflows if and only if the two operands have the same sign,
1399 and the result has the opposite sign. Subtraction overflows if and
1400 only if the two operands have opposite sign, and the subtrahend has
1401 the same sign as the result. Here 0 is counted as positive. */
1402 if (pos_neg == 3)
1404 /* Compute op0 ^ op1 (operands have opposite sign). */
1405 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1406 OPTAB_LIB_WIDEN);
1408 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1409 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1410 OPTAB_LIB_WIDEN);
1412 rtx tem;
1413 if (code == PLUS_EXPR)
1415 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1416 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1417 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1418 OPTAB_LIB_WIDEN);
1420 else
1422 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1423 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1424 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1425 OPTAB_LIB_WIDEN);
1428 /* No overflow if the result has bit sign cleared. */
1429 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1430 NULL, done_label, profile_probability::very_likely ());
1433 /* Compare the result of the operation with the first operand.
1434 No overflow for addition if second operand is positive and result
1435 is larger or second operand is negative and result is smaller.
1436 Likewise for subtraction with sign of second operand flipped. */
1437 else
1438 do_compare_rtx_and_jump (res, op0,
1439 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1440 false, mode, NULL_RTX, NULL, done_label,
1441 profile_probability::very_likely ());
1444 do_error_label:
1445 emit_label (do_error);
1446 if (is_ubsan)
1448 /* Expand the ubsan builtin call. */
1449 push_temp_slots ();
1450 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1451 arg0, arg1, datap);
1452 expand_normal (fn);
1453 pop_temp_slots ();
1454 do_pending_stack_adjust ();
1456 else if (lhs)
1457 expand_arith_set_overflow (lhs, target);
1459 /* We're done. */
1460 emit_label (done_label);
1462 if (lhs)
1464 if (is_ubsan)
1465 expand_ubsan_result_store (lhs, target, mode, res, do_error);
1466 else
1468 if (do_xor)
1469 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1470 OPTAB_LIB_WIDEN);
1472 expand_arith_overflow_result_store (lhs, target, mode, res);
1477 /* Add negate overflow checking to the statement STMT. */
1479 static void
1480 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1481 tree *datap)
1483 rtx res, op1;
1484 tree fn;
1485 rtx_code_label *done_label, *do_error;
1486 rtx target = NULL_RTX;
1488 done_label = gen_label_rtx ();
1489 do_error = gen_label_rtx ();
1491 do_pending_stack_adjust ();
1492 op1 = expand_normal (arg1);
1494 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
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 enum insn_code icode = optab_handler (negv3_optab, mode);
1503 if (icode != CODE_FOR_nothing)
1505 class expand_operand ops[3];
1506 rtx_insn *last = get_last_insn ();
1508 res = gen_reg_rtx (mode);
1509 create_output_operand (&ops[0], res, mode);
1510 create_input_operand (&ops[1], op1, mode);
1511 create_fixed_operand (&ops[2], do_error);
1512 if (maybe_expand_insn (icode, 3, ops))
1514 last = get_last_insn ();
1515 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1516 && JUMP_P (last)
1517 && any_condjump_p (last)
1518 && !find_reg_note (last, REG_BR_PROB, 0))
1519 add_reg_br_prob_note (last,
1520 profile_probability::very_unlikely ());
1521 emit_jump (done_label);
1523 else
1525 delete_insns_since (last);
1526 icode = CODE_FOR_nothing;
1530 if (icode == CODE_FOR_nothing)
1532 /* Compute the operation. On RTL level, the addition is always
1533 unsigned. */
1534 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1536 /* Compare the operand with the most negative value. */
1537 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1538 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1539 done_label, profile_probability::very_likely ());
1542 emit_label (do_error);
1543 if (is_ubsan)
1545 /* Expand the ubsan builtin call. */
1546 push_temp_slots ();
1547 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1548 arg1, NULL_TREE, datap);
1549 expand_normal (fn);
1550 pop_temp_slots ();
1551 do_pending_stack_adjust ();
1553 else if (lhs)
1554 expand_arith_set_overflow (lhs, target);
1556 /* We're done. */
1557 emit_label (done_label);
1559 if (lhs)
1561 if (is_ubsan)
1562 expand_ubsan_result_store (lhs, target, mode, res, do_error);
1563 else
1564 expand_arith_overflow_result_store (lhs, target, mode, res);
1568 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1569 mode MODE can be expanded without using a libcall. */
1571 static bool
1572 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1573 rtx op0, rtx op1, bool uns)
1575 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1576 != CODE_FOR_nothing)
1577 return true;
1579 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1580 != CODE_FOR_nothing)
1581 return true;
1583 rtx_insn *last = get_last_insn ();
1584 if (CONSTANT_P (op0))
1585 op0 = convert_modes (wmode, mode, op0, uns);
1586 else
1587 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1588 if (CONSTANT_P (op1))
1589 op1 = convert_modes (wmode, mode, op1, uns);
1590 else
1591 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1592 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1593 delete_insns_since (last);
1594 return ret != NULL_RTX;
1597 /* Add mul overflow checking to the statement STMT. */
1599 static void
1600 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1601 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1602 tree *datap)
1604 rtx res, op0, op1;
1605 tree fn, type;
1606 rtx_code_label *done_label, *do_error;
1607 rtx target = NULL_RTX;
1608 signop sign;
1609 enum insn_code icode;
1611 done_label = gen_label_rtx ();
1612 do_error = gen_label_rtx ();
1614 do_pending_stack_adjust ();
1615 op0 = expand_normal (arg0);
1616 op1 = expand_normal (arg1);
1618 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1619 bool uns = unsr_p;
1620 if (lhs)
1622 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1623 if (!is_ubsan)
1624 write_complex_part (target, const0_rtx, true, false);
1627 if (is_ubsan)
1628 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1630 /* We assume both operands and result have the same precision
1631 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1632 with that precision, U for unsigned type with that precision,
1633 sgn for unsigned most significant bit in that precision.
1634 s1 is signed first operand, u1 is unsigned first operand,
1635 s2 is signed second operand, u2 is unsigned second operand,
1636 sr is signed result, ur is unsigned result and the following
1637 rules say how to compute result (which is always result of
1638 the operands as if both were unsigned, cast to the right
1639 signedness) and how to compute whether operation overflowed.
1640 main_ovf (false) stands for jump on signed multiplication
1641 overflow or the main algorithm with uns == false.
1642 main_ovf (true) stands for jump on unsigned multiplication
1643 overflow or the main algorithm with uns == true.
1645 s1 * s2 -> sr
1646 res = (S) ((U) s1 * (U) s2)
1647 ovf = main_ovf (false)
1648 u1 * u2 -> ur
1649 res = u1 * u2
1650 ovf = main_ovf (true)
1651 s1 * u2 -> ur
1652 res = (U) s1 * u2
1653 ovf = (s1 < 0 && u2) || main_ovf (true)
1654 u1 * u2 -> sr
1655 res = (S) (u1 * u2)
1656 ovf = res < 0 || main_ovf (true)
1657 s1 * u2 -> sr
1658 res = (S) ((U) s1 * u2)
1659 ovf = (S) u2 >= 0 ? main_ovf (false)
1660 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1661 s1 * s2 -> ur
1662 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1663 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1664 res = t1 * t2
1665 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1667 if (uns0_p && !uns1_p)
1669 /* Multiplication is commutative, if operand signedness differs,
1670 canonicalize to the first operand being signed and second
1671 unsigned to simplify following code. */
1672 std::swap (op0, op1);
1673 std::swap (arg0, arg1);
1674 uns0_p = false;
1675 uns1_p = true;
1678 int pos_neg0 = get_range_pos_neg (arg0);
1679 int pos_neg1 = get_range_pos_neg (arg1);
1680 /* Unsigned types with smaller than mode precision, even if they have most
1681 significant bit set, are still zero-extended. */
1682 if (uns0_p && TYPE_PRECISION (TREE_TYPE (arg0)) < GET_MODE_PRECISION (mode))
1683 pos_neg0 = 1;
1684 if (uns1_p && TYPE_PRECISION (TREE_TYPE (arg1)) < GET_MODE_PRECISION (mode))
1685 pos_neg1 = 1;
1687 /* s1 * u2 -> ur */
1688 if (!uns0_p && uns1_p && unsr_p)
1690 switch (pos_neg0)
1692 case 1:
1693 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1694 goto do_main;
1695 case 2:
1696 /* If s1 is negative, avoid the main code, just multiply and
1697 signal overflow if op1 is not 0. */
1698 struct separate_ops ops;
1699 ops.code = MULT_EXPR;
1700 ops.type = TREE_TYPE (arg1);
1701 ops.op0 = make_tree (ops.type, op0);
1702 ops.op1 = make_tree (ops.type, op1);
1703 ops.op2 = NULL_TREE;
1704 ops.location = loc;
1705 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1706 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1707 NULL, done_label, profile_probability::very_likely ());
1708 goto do_error_label;
1709 case 3:
1710 if (get_min_precision (arg1, UNSIGNED)
1711 + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
1713 /* If the first operand is sign extended from narrower type, the
1714 second operand is zero extended from narrower type and
1715 the sum of the two precisions is smaller or equal to the
1716 result precision: if the first argument is at runtime
1717 non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
1718 and there will be no overflow, if the first argument is
1719 negative and the second argument zero, the result will be
1720 0 and there will be no overflow, if the first argument is
1721 negative and the second argument positive, the result when
1722 treated as signed will be negative (minimum -0x7f80 or
1723 -0x7f..f80..0) there will be always overflow. So, do
1724 res = (U) (s1 * u2)
1725 ovf = (S) res < 0 */
1726 struct separate_ops ops;
1727 ops.code = MULT_EXPR;
1728 ops.type
1729 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1731 ops.op0 = make_tree (ops.type, op0);
1732 ops.op1 = make_tree (ops.type, op1);
1733 ops.op2 = NULL_TREE;
1734 ops.location = loc;
1735 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1736 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1737 mode, NULL_RTX, NULL, done_label,
1738 profile_probability::very_likely ());
1739 goto do_error_label;
1741 rtx_code_label *do_main_label;
1742 do_main_label = gen_label_rtx ();
1743 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1744 NULL, do_main_label, profile_probability::very_likely ());
1745 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1746 NULL, do_main_label, profile_probability::very_likely ());
1747 expand_arith_set_overflow (lhs, target);
1748 emit_label (do_main_label);
1749 goto do_main;
1750 default:
1751 gcc_unreachable ();
1755 /* u1 * u2 -> sr */
1756 if (uns0_p && uns1_p && !unsr_p)
1758 if ((pos_neg0 | pos_neg1) == 1)
1760 /* If both arguments are zero extended from narrower types,
1761 the MSB will be clear on both and so we can pretend it is
1762 a normal s1 * s2 -> sr multiplication. */
1763 uns0_p = false;
1764 uns1_p = false;
1766 else
1767 uns = true;
1768 /* Rest of handling of this case after res is computed. */
1769 goto do_main;
1772 /* s1 * u2 -> sr */
1773 if (!uns0_p && uns1_p && !unsr_p)
1775 switch (pos_neg1)
1777 case 1:
1778 goto do_main;
1779 case 2:
1780 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1781 avoid the main code, just multiply and signal overflow
1782 unless 0 * u2 or -1 * ((U) Smin). */
1783 struct separate_ops ops;
1784 ops.code = MULT_EXPR;
1785 ops.type = TREE_TYPE (arg1);
1786 ops.op0 = make_tree (ops.type, op0);
1787 ops.op1 = make_tree (ops.type, op1);
1788 ops.op2 = NULL_TREE;
1789 ops.location = loc;
1790 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1791 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1792 NULL, done_label, profile_probability::very_likely ());
1793 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1794 NULL, do_error, profile_probability::very_unlikely ());
1795 int prec;
1796 prec = GET_MODE_PRECISION (mode);
1797 rtx sgn;
1798 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1799 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1800 NULL, done_label, profile_probability::very_likely ());
1801 goto do_error_label;
1802 case 3:
1803 /* Rest of handling of this case after res is computed. */
1804 goto do_main;
1805 default:
1806 gcc_unreachable ();
1810 /* s1 * s2 -> ur */
1811 if (!uns0_p && !uns1_p && unsr_p)
1813 rtx tem;
1814 switch (pos_neg0 | pos_neg1)
1816 case 1: /* Both operands known to be non-negative. */
1817 goto do_main;
1818 case 2: /* Both operands known to be negative. */
1819 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1820 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1821 /* Avoid looking at arg0/arg1 ranges, as we've changed
1822 the arguments. */
1823 arg0 = error_mark_node;
1824 arg1 = error_mark_node;
1825 goto do_main;
1826 case 3:
1827 if ((pos_neg0 ^ pos_neg1) == 3)
1829 /* If one operand is known to be negative and the other
1830 non-negative, this overflows always, unless the non-negative
1831 one is 0. Just do normal multiply and set overflow
1832 unless one of the operands is 0. */
1833 struct separate_ops ops;
1834 ops.code = MULT_EXPR;
1835 ops.type
1836 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1838 ops.op0 = make_tree (ops.type, op0);
1839 ops.op1 = make_tree (ops.type, op1);
1840 ops.op2 = NULL_TREE;
1841 ops.location = loc;
1842 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1843 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1844 true, mode, NULL_RTX, NULL, done_label,
1845 profile_probability::very_likely ());
1846 goto do_error_label;
1848 if (get_min_precision (arg0, SIGNED)
1849 + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
1851 /* If both operands are sign extended from narrower types and
1852 the sum of the two precisions is smaller or equal to the
1853 result precision: if both arguments are at runtime
1854 non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
1855 and there will be no overflow, if both arguments are negative,
1856 maximum result will be 0x40..00 and there will be no overflow
1857 either, if one argument is positive and the other argument
1858 negative, the result when treated as signed will be negative
1859 and there will be always overflow, and if one argument is
1860 zero and the other negative the result will be zero and no
1861 overflow. So, do
1862 res = (U) (s1 * s2)
1863 ovf = (S) res < 0 */
1864 struct separate_ops ops;
1865 ops.code = MULT_EXPR;
1866 ops.type
1867 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1869 ops.op0 = make_tree (ops.type, op0);
1870 ops.op1 = make_tree (ops.type, op1);
1871 ops.op2 = NULL_TREE;
1872 ops.location = loc;
1873 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1874 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1875 mode, NULL_RTX, NULL, done_label,
1876 profile_probability::very_likely ());
1877 goto do_error_label;
1879 /* The general case, do all the needed comparisons at runtime. */
1880 rtx_code_label *do_main_label, *after_negate_label;
1881 rtx rop0, rop1;
1882 rop0 = gen_reg_rtx (mode);
1883 rop1 = gen_reg_rtx (mode);
1884 emit_move_insn (rop0, op0);
1885 emit_move_insn (rop1, op1);
1886 op0 = rop0;
1887 op1 = rop1;
1888 do_main_label = gen_label_rtx ();
1889 after_negate_label = gen_label_rtx ();
1890 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1891 OPTAB_LIB_WIDEN);
1892 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1893 NULL, after_negate_label, profile_probability::very_likely ());
1894 /* Both arguments negative here, negate them and continue with
1895 normal unsigned overflow checking multiplication. */
1896 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1897 NULL_RTX, false));
1898 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1899 NULL_RTX, false));
1900 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1901 the arguments. */
1902 arg0 = error_mark_node;
1903 arg1 = error_mark_node;
1904 emit_jump (do_main_label);
1905 emit_label (after_negate_label);
1906 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1907 OPTAB_LIB_WIDEN);
1908 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1909 NULL, do_main_label,
1910 profile_probability::very_likely ());
1911 /* One argument is negative here, the other positive. This
1912 overflows always, unless one of the arguments is 0. But
1913 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1914 is, thus we can keep do_main code oring in overflow as is. */
1915 if (pos_neg0 != 2)
1916 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1917 NULL, do_main_label,
1918 profile_probability::very_unlikely ());
1919 if (pos_neg1 != 2)
1920 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1921 NULL, do_main_label,
1922 profile_probability::very_unlikely ());
1923 expand_arith_set_overflow (lhs, target);
1924 emit_label (do_main_label);
1925 goto do_main;
1926 default:
1927 gcc_unreachable ();
1931 do_main:
1932 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1933 sign = uns ? UNSIGNED : SIGNED;
1934 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1935 if (uns
1936 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1937 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1939 /* Optimize unsigned multiplication by power of 2 constant
1940 using 2 shifts, one for result, one to extract the shifted
1941 out bits to see if they are all zero.
1942 Don't do this if optimizing for size and we have umulv4_optab,
1943 in that case assume multiplication will be shorter.
1944 This is heuristics based on the single target that provides
1945 umulv4 right now (i?86/x86_64), if further targets add it, this
1946 might need to be revisited.
1947 Cases where both operands are constant should be folded already
1948 during GIMPLE, and cases where one operand is constant but not
1949 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1950 below can be done without multiplication, just by shifts and adds,
1951 or we'd need to divide the result (and hope it actually doesn't
1952 really divide nor multiply) and compare the result of the division
1953 with the original operand. */
1954 rtx opn0 = op0;
1955 rtx opn1 = op1;
1956 tree argn0 = arg0;
1957 tree argn1 = arg1;
1958 if (integer_pow2p (arg0))
1960 std::swap (opn0, opn1);
1961 std::swap (argn0, argn1);
1963 int cnt = tree_log2 (argn1);
1964 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1966 rtx upper = const0_rtx;
1967 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1968 if (cnt != 0)
1969 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1970 GET_MODE_PRECISION (mode) - cnt,
1971 NULL_RTX, uns);
1972 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1973 NULL_RTX, NULL, done_label,
1974 profile_probability::very_likely ());
1975 goto do_error_label;
1978 if (icode != CODE_FOR_nothing)
1980 class expand_operand ops[4];
1981 rtx_insn *last = get_last_insn ();
1983 res = gen_reg_rtx (mode);
1984 create_output_operand (&ops[0], res, mode);
1985 create_input_operand (&ops[1], op0, mode);
1986 create_input_operand (&ops[2], op1, mode);
1987 create_fixed_operand (&ops[3], do_error);
1988 if (maybe_expand_insn (icode, 4, ops))
1990 last = get_last_insn ();
1991 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1992 && JUMP_P (last)
1993 && any_condjump_p (last)
1994 && !find_reg_note (last, REG_BR_PROB, 0))
1995 add_reg_br_prob_note (last,
1996 profile_probability::very_unlikely ());
1997 emit_jump (done_label);
1999 else
2001 delete_insns_since (last);
2002 icode = CODE_FOR_nothing;
2006 if (icode == CODE_FOR_nothing)
2008 struct separate_ops ops;
2009 int prec = GET_MODE_PRECISION (mode);
2010 scalar_int_mode hmode, wmode;
2011 ops.op0 = make_tree (type, op0);
2012 ops.op1 = make_tree (type, op1);
2013 ops.op2 = NULL_TREE;
2014 ops.location = loc;
2016 /* Optimize unsigned overflow check where we don't use the
2017 multiplication result, just whether overflow happened.
2018 If we can do MULT_HIGHPART_EXPR, that followed by
2019 comparison of the result against zero is cheapest.
2020 We'll still compute res, but it should be DCEd later. */
2021 use_operand_p use;
2022 gimple *use_stmt;
2023 if (!is_ubsan
2024 && lhs
2025 && uns
2026 && !(uns0_p && uns1_p && !unsr_p)
2027 && can_mult_highpart_p (mode, uns) == 1
2028 && single_imm_use (lhs, &use, &use_stmt)
2029 && is_gimple_assign (use_stmt)
2030 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
2031 goto highpart;
2033 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2034 && targetm.scalar_mode_supported_p (wmode)
2035 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
2037 twoxwider:
2038 ops.code = WIDEN_MULT_EXPR;
2039 ops.type
2040 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
2042 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
2043 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
2044 NULL_RTX, uns);
2045 hipart = convert_modes (mode, wmode, hipart, uns);
2046 res = convert_modes (mode, wmode, res, uns);
2047 if (uns)
2048 /* For the unsigned multiplication, there was overflow if
2049 HIPART is non-zero. */
2050 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2051 NULL_RTX, NULL, done_label,
2052 profile_probability::very_likely ());
2053 else
2055 /* RES is used more than once, place it in a pseudo. */
2056 res = force_reg (mode, res);
2058 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2059 NULL_RTX, 0);
2060 /* RES is low half of the double width result, HIPART
2061 the high half. There was overflow if
2062 HIPART is different from RES < 0 ? -1 : 0. */
2063 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2064 NULL_RTX, NULL, done_label,
2065 profile_probability::very_likely ());
2068 else if (can_mult_highpart_p (mode, uns) == 1)
2070 highpart:
2071 ops.code = MULT_HIGHPART_EXPR;
2072 ops.type = type;
2074 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
2075 EXPAND_NORMAL);
2076 ops.code = MULT_EXPR;
2077 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2078 if (uns)
2079 /* For the unsigned multiplication, there was overflow if
2080 HIPART is non-zero. */
2081 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2082 NULL_RTX, NULL, done_label,
2083 profile_probability::very_likely ());
2084 else
2086 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2087 NULL_RTX, 0);
2088 /* RES is low half of the double width result, HIPART
2089 the high half. There was overflow if
2090 HIPART is different from RES < 0 ? -1 : 0. */
2091 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2092 NULL_RTX, NULL, done_label,
2093 profile_probability::very_likely ());
2097 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
2098 && 2 * GET_MODE_PRECISION (hmode) == prec)
2100 rtx_code_label *large_op0 = gen_label_rtx ();
2101 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
2102 rtx_code_label *one_small_one_large = gen_label_rtx ();
2103 rtx_code_label *both_ops_large = gen_label_rtx ();
2104 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
2105 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
2106 rtx_code_label *do_overflow = gen_label_rtx ();
2107 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
2109 unsigned int hprec = GET_MODE_PRECISION (hmode);
2110 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
2111 NULL_RTX, uns);
2112 hipart0 = convert_modes (hmode, mode, hipart0, uns);
2113 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
2114 rtx signbit0 = const0_rtx;
2115 if (!uns)
2116 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
2117 NULL_RTX, 0);
2118 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
2119 NULL_RTX, uns);
2120 hipart1 = convert_modes (hmode, mode, hipart1, uns);
2121 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
2122 rtx signbit1 = const0_rtx;
2123 if (!uns)
2124 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
2125 NULL_RTX, 0);
2127 res = gen_reg_rtx (mode);
2129 /* True if op0 resp. op1 are known to be in the range of
2130 halfstype. */
2131 bool op0_small_p = false;
2132 bool op1_small_p = false;
2133 /* True if op0 resp. op1 are known to have all zeros or all ones
2134 in the upper half of bits, but are not known to be
2135 op{0,1}_small_p. */
2136 bool op0_medium_p = false;
2137 bool op1_medium_p = false;
2138 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
2139 nonnegative, 1 if unknown. */
2140 int op0_sign = 1;
2141 int op1_sign = 1;
2143 if (pos_neg0 == 1)
2144 op0_sign = 0;
2145 else if (pos_neg0 == 2)
2146 op0_sign = -1;
2147 if (pos_neg1 == 1)
2148 op1_sign = 0;
2149 else if (pos_neg1 == 2)
2150 op1_sign = -1;
2152 unsigned int mprec0 = prec;
2153 if (arg0 != error_mark_node)
2154 mprec0 = get_min_precision (arg0, sign);
2155 if (mprec0 <= hprec)
2156 op0_small_p = true;
2157 else if (!uns && mprec0 <= hprec + 1)
2158 op0_medium_p = true;
2159 unsigned int mprec1 = prec;
2160 if (arg1 != error_mark_node)
2161 mprec1 = get_min_precision (arg1, sign);
2162 if (mprec1 <= hprec)
2163 op1_small_p = true;
2164 else if (!uns && mprec1 <= hprec + 1)
2165 op1_medium_p = true;
2167 int smaller_sign = 1;
2168 int larger_sign = 1;
2169 if (op0_small_p)
2171 smaller_sign = op0_sign;
2172 larger_sign = op1_sign;
2174 else if (op1_small_p)
2176 smaller_sign = op1_sign;
2177 larger_sign = op0_sign;
2179 else if (op0_sign == op1_sign)
2181 smaller_sign = op0_sign;
2182 larger_sign = op0_sign;
2185 if (!op0_small_p)
2186 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
2187 NULL_RTX, NULL, large_op0,
2188 profile_probability::unlikely ());
2190 if (!op1_small_p)
2191 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2192 NULL_RTX, NULL, small_op0_large_op1,
2193 profile_probability::unlikely ());
2195 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
2196 hmode to mode, the multiplication will never overflow. We can
2197 do just one hmode x hmode => mode widening multiplication. */
2198 tree halfstype = build_nonstandard_integer_type (hprec, uns);
2199 ops.op0 = make_tree (halfstype, lopart0);
2200 ops.op1 = make_tree (halfstype, lopart1);
2201 ops.code = WIDEN_MULT_EXPR;
2202 ops.type = type;
2203 rtx thisres
2204 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2205 emit_move_insn (res, thisres);
2206 emit_jump (done_label);
2208 emit_label (small_op0_large_op1);
2210 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
2211 but op1 is not, just swap the arguments and handle it as op1
2212 sign/zero extended, op0 not. */
2213 rtx larger = gen_reg_rtx (mode);
2214 rtx hipart = gen_reg_rtx (hmode);
2215 rtx lopart = gen_reg_rtx (hmode);
2216 emit_move_insn (larger, op1);
2217 emit_move_insn (hipart, hipart1);
2218 emit_move_insn (lopart, lopart0);
2219 emit_jump (one_small_one_large);
2221 emit_label (large_op0);
2223 if (!op1_small_p)
2224 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2225 NULL_RTX, NULL, both_ops_large,
2226 profile_probability::unlikely ());
2228 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
2229 but op0 is not, prepare larger, hipart and lopart pseudos and
2230 handle it together with small_op0_large_op1. */
2231 emit_move_insn (larger, op0);
2232 emit_move_insn (hipart, hipart0);
2233 emit_move_insn (lopart, lopart1);
2235 emit_label (one_small_one_large);
2237 /* lopart is the low part of the operand that is sign extended
2238 to mode, larger is the other operand, hipart is the
2239 high part of larger and lopart0 and lopart1 are the low parts
2240 of both operands.
2241 We perform lopart0 * lopart1 and lopart * hipart widening
2242 multiplications. */
2243 tree halfutype = build_nonstandard_integer_type (hprec, 1);
2244 ops.op0 = make_tree (halfutype, lopart0);
2245 ops.op1 = make_tree (halfutype, lopart1);
2246 rtx lo0xlo1
2247 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2249 ops.op0 = make_tree (halfutype, lopart);
2250 ops.op1 = make_tree (halfutype, hipart);
2251 rtx loxhi = gen_reg_rtx (mode);
2252 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2253 emit_move_insn (loxhi, tem);
2255 if (!uns)
2257 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
2258 if (larger_sign == 0)
2259 emit_jump (after_hipart_neg);
2260 else if (larger_sign != -1)
2261 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
2262 NULL_RTX, NULL, after_hipart_neg,
2263 profile_probability::even ());
2265 tem = convert_modes (mode, hmode, lopart, 1);
2266 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
2267 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
2268 1, OPTAB_WIDEN);
2269 emit_move_insn (loxhi, tem);
2271 emit_label (after_hipart_neg);
2273 /* if (lopart < 0) loxhi -= larger; */
2274 if (smaller_sign == 0)
2275 emit_jump (after_lopart_neg);
2276 else if (smaller_sign != -1)
2277 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
2278 NULL_RTX, NULL, after_lopart_neg,
2279 profile_probability::even ());
2281 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
2282 1, OPTAB_WIDEN);
2283 emit_move_insn (loxhi, tem);
2285 emit_label (after_lopart_neg);
2288 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
2289 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
2290 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
2291 1, OPTAB_WIDEN);
2292 emit_move_insn (loxhi, tem);
2294 /* if (loxhi >> (bitsize / 2)
2295 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
2296 if (loxhi >> (bitsize / 2) == 0 (if uns). */
2297 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
2298 NULL_RTX, 0);
2299 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
2300 rtx signbitloxhi = const0_rtx;
2301 if (!uns)
2302 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
2303 convert_modes (hmode, mode,
2304 loxhi, 0),
2305 hprec - 1, NULL_RTX, 0);
2307 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
2308 NULL_RTX, NULL, do_overflow,
2309 profile_probability::very_unlikely ());
2311 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
2312 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
2313 NULL_RTX, 1);
2314 tem = convert_modes (mode, hmode,
2315 convert_modes (hmode, mode, lo0xlo1, 1), 1);
2317 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
2318 1, OPTAB_WIDEN);
2319 if (tem != res)
2320 emit_move_insn (res, tem);
2321 emit_jump (done_label);
2323 emit_label (both_ops_large);
2325 /* If both operands are large (not sign (!uns) or zero (uns)
2326 extended from hmode), then perform the full multiplication
2327 which will be the result of the operation.
2328 The only cases which don't overflow are for signed multiplication
2329 some cases where both hipart0 and highpart1 are 0 or -1.
2330 For unsigned multiplication when high parts are both non-zero
2331 this overflows always. */
2332 ops.code = MULT_EXPR;
2333 ops.op0 = make_tree (type, op0);
2334 ops.op1 = make_tree (type, op1);
2335 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2336 emit_move_insn (res, tem);
2338 if (!uns)
2340 if (!op0_medium_p)
2342 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
2343 NULL_RTX, 1, OPTAB_WIDEN);
2344 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2345 NULL_RTX, NULL, do_error,
2346 profile_probability::very_unlikely ());
2349 if (!op1_medium_p)
2351 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
2352 NULL_RTX, 1, OPTAB_WIDEN);
2353 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2354 NULL_RTX, NULL, do_error,
2355 profile_probability::very_unlikely ());
2358 /* At this point hipart{0,1} are both in [-1, 0]. If they are
2359 the same, overflow happened if res is non-positive, if they
2360 are different, overflow happened if res is positive. */
2361 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
2362 emit_jump (hipart_different);
2363 else if (op0_sign == 1 || op1_sign == 1)
2364 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
2365 NULL_RTX, NULL, hipart_different,
2366 profile_probability::even ());
2368 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
2369 NULL_RTX, NULL, do_error,
2370 profile_probability::very_unlikely ());
2371 emit_jump (done_label);
2373 emit_label (hipart_different);
2375 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
2376 NULL_RTX, NULL, do_error,
2377 profile_probability::very_unlikely ());
2378 emit_jump (done_label);
2381 emit_label (do_overflow);
2383 /* Overflow, do full multiplication and fallthru into do_error. */
2384 ops.op0 = make_tree (type, op0);
2385 ops.op1 = make_tree (type, op1);
2386 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2387 emit_move_insn (res, tem);
2389 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2390 && targetm.scalar_mode_supported_p (wmode))
2391 /* Even emitting a libcall is better than not detecting overflow
2392 at all. */
2393 goto twoxwider;
2394 else
2396 gcc_assert (!is_ubsan);
2397 ops.code = MULT_EXPR;
2398 ops.type = type;
2399 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2400 emit_jump (done_label);
2404 do_error_label:
2405 emit_label (do_error);
2406 if (is_ubsan)
2408 /* Expand the ubsan builtin call. */
2409 push_temp_slots ();
2410 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
2411 arg0, arg1, datap);
2412 expand_normal (fn);
2413 pop_temp_slots ();
2414 do_pending_stack_adjust ();
2416 else if (lhs)
2417 expand_arith_set_overflow (lhs, target);
2419 /* We're done. */
2420 emit_label (done_label);
2422 /* u1 * u2 -> sr */
2423 if (uns0_p && uns1_p && !unsr_p)
2425 rtx_code_label *all_done_label = gen_label_rtx ();
2426 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2427 NULL, all_done_label, profile_probability::very_likely ());
2428 expand_arith_set_overflow (lhs, target);
2429 emit_label (all_done_label);
2432 /* s1 * u2 -> sr */
2433 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2435 rtx_code_label *all_done_label = gen_label_rtx ();
2436 rtx_code_label *set_noovf = gen_label_rtx ();
2437 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2438 NULL, all_done_label, profile_probability::very_likely ());
2439 expand_arith_set_overflow (lhs, target);
2440 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2441 NULL, set_noovf, profile_probability::very_likely ());
2442 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2443 NULL, all_done_label, profile_probability::very_unlikely ());
2444 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2445 all_done_label, profile_probability::very_unlikely ());
2446 emit_label (set_noovf);
2447 write_complex_part (target, const0_rtx, true, false);
2448 emit_label (all_done_label);
2451 if (lhs)
2453 if (is_ubsan)
2454 expand_ubsan_result_store (lhs, target, mode, res, do_error);
2455 else
2456 expand_arith_overflow_result_store (lhs, target, mode, res);
2460 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2462 static void
2463 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2464 tree arg0, tree arg1)
2466 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2467 rtx_code_label *loop_lab = NULL;
2468 rtx cntvar = NULL_RTX;
2469 tree cntv = NULL_TREE;
2470 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2471 tree sz = TYPE_SIZE (eltype);
2472 tree data = NULL_TREE;
2473 tree resv = NULL_TREE;
2474 rtx lhsr = NULL_RTX;
2475 rtx resvr = NULL_RTX;
2476 unsigned HOST_WIDE_INT const_cnt = 0;
2477 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2479 if (lhs)
2481 optab op;
2482 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2483 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2484 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2485 optab_default)) == unknown_optab
2486 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2487 == CODE_FOR_nothing))
2489 if (MEM_P (lhsr))
2490 resv = make_tree (TREE_TYPE (lhs), lhsr);
2491 else
2493 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2494 resv = make_tree (TREE_TYPE (lhs), resvr);
2498 if (use_loop_p)
2500 do_pending_stack_adjust ();
2501 loop_lab = gen_label_rtx ();
2502 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2503 cntv = make_tree (sizetype, cntvar);
2504 emit_move_insn (cntvar, const0_rtx);
2505 emit_label (loop_lab);
2507 if (TREE_CODE (arg0) != VECTOR_CST)
2509 rtx arg0r = expand_normal (arg0);
2510 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2512 if (TREE_CODE (arg1) != VECTOR_CST)
2514 rtx arg1r = expand_normal (arg1);
2515 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2517 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2519 tree op0, op1, res = NULL_TREE;
2520 if (use_loop_p)
2522 tree atype = build_array_type_nelts (eltype, cnt);
2523 op0 = uniform_vector_p (arg0);
2524 if (op0 == NULL_TREE)
2526 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2527 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2528 NULL_TREE, NULL_TREE);
2530 op1 = uniform_vector_p (arg1);
2531 if (op1 == NULL_TREE)
2533 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2534 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2535 NULL_TREE, NULL_TREE);
2537 if (resv)
2539 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2540 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2541 NULL_TREE, NULL_TREE);
2544 else
2546 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2547 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2548 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2549 if (resv)
2550 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2551 bitpos);
2553 switch (code)
2555 case PLUS_EXPR:
2556 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2557 false, false, false, true, &data);
2558 break;
2559 case MINUS_EXPR:
2560 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2561 expand_neg_overflow (loc, res, op1, true, &data);
2562 else
2563 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2564 false, false, false, true, &data);
2565 break;
2566 case MULT_EXPR:
2567 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2568 true, &data);
2569 break;
2570 default:
2571 gcc_unreachable ();
2574 if (use_loop_p)
2576 struct separate_ops ops;
2577 ops.code = PLUS_EXPR;
2578 ops.type = TREE_TYPE (cntv);
2579 ops.op0 = cntv;
2580 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2581 ops.op2 = NULL_TREE;
2582 ops.location = loc;
2583 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2584 EXPAND_NORMAL);
2585 if (ret != cntvar)
2586 emit_move_insn (cntvar, ret);
2587 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2588 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2589 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2590 profile_probability::very_likely ());
2592 if (lhs && resv == NULL_TREE)
2594 struct separate_ops ops;
2595 ops.code = code;
2596 ops.type = TREE_TYPE (arg0);
2597 ops.op0 = arg0;
2598 ops.op1 = arg1;
2599 ops.op2 = NULL_TREE;
2600 ops.location = loc;
2601 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2602 EXPAND_NORMAL);
2603 if (ret != lhsr)
2604 emit_move_insn (lhsr, ret);
2606 else if (resvr)
2607 emit_move_insn (lhsr, resvr);
2610 /* Expand UBSAN_CHECK_ADD call STMT. */
2612 static void
2613 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2615 location_t loc = gimple_location (stmt);
2616 tree lhs = gimple_call_lhs (stmt);
2617 tree arg0 = gimple_call_arg (stmt, 0);
2618 tree arg1 = gimple_call_arg (stmt, 1);
2619 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2620 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2621 else
2622 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2623 false, false, false, true, NULL);
2626 /* Expand UBSAN_CHECK_SUB call STMT. */
2628 static void
2629 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2631 location_t loc = gimple_location (stmt);
2632 tree lhs = gimple_call_lhs (stmt);
2633 tree arg0 = gimple_call_arg (stmt, 0);
2634 tree arg1 = gimple_call_arg (stmt, 1);
2635 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2636 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2637 else if (integer_zerop (arg0))
2638 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2639 else
2640 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2641 false, false, false, true, NULL);
2644 /* Expand UBSAN_CHECK_MUL call STMT. */
2646 static void
2647 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2649 location_t loc = gimple_location (stmt);
2650 tree lhs = gimple_call_lhs (stmt);
2651 tree arg0 = gimple_call_arg (stmt, 0);
2652 tree arg1 = gimple_call_arg (stmt, 1);
2653 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2654 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2655 else
2656 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2657 NULL);
2660 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2662 static void
2663 expand_arith_overflow (enum tree_code code, gimple *stmt)
2665 tree lhs = gimple_call_lhs (stmt);
2666 if (lhs == NULL_TREE)
2667 return;
2668 tree arg0 = gimple_call_arg (stmt, 0);
2669 tree arg1 = gimple_call_arg (stmt, 1);
2670 tree type = TREE_TYPE (TREE_TYPE (lhs));
2671 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2672 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2673 int unsr_p = TYPE_UNSIGNED (type);
2674 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2675 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2676 int precres = TYPE_PRECISION (type);
2677 location_t loc = gimple_location (stmt);
2678 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2679 uns0_p = true;
2680 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2681 uns1_p = true;
2682 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2683 prec0 = MIN (prec0, pr);
2684 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2685 prec1 = MIN (prec1, pr);
2687 /* If uns0_p && uns1_p, precop is minimum needed precision
2688 of unsigned type to hold the exact result, otherwise
2689 precop is minimum needed precision of signed type to
2690 hold the exact result. */
2691 int precop;
2692 if (code == MULT_EXPR)
2693 precop = prec0 + prec1 + (uns0_p != uns1_p);
2694 else
2696 if (uns0_p == uns1_p)
2697 precop = MAX (prec0, prec1) + 1;
2698 else if (uns0_p)
2699 precop = MAX (prec0 + 1, prec1) + 1;
2700 else
2701 precop = MAX (prec0, prec1 + 1) + 1;
2703 int orig_precres = precres;
2707 if ((uns0_p && uns1_p)
2708 ? ((precop + !unsr_p) <= precres
2709 /* u1 - u2 -> ur can overflow, no matter what precision
2710 the result has. */
2711 && (code != MINUS_EXPR || !unsr_p))
2712 : (!unsr_p && precop <= precres))
2714 /* The infinity precision result will always fit into result. */
2715 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2716 write_complex_part (target, const0_rtx, true, false);
2717 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2718 struct separate_ops ops;
2719 ops.code = code;
2720 ops.type = type;
2721 ops.op0 = fold_convert_loc (loc, type, arg0);
2722 ops.op1 = fold_convert_loc (loc, type, arg1);
2723 ops.op2 = NULL_TREE;
2724 ops.location = loc;
2725 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2726 expand_arith_overflow_result_store (lhs, target, mode, tem);
2727 return;
2730 /* For operations with low precision, if target doesn't have them, start
2731 with precres widening right away, otherwise do it only if the most
2732 simple cases can't be used. */
2733 const int min_precision = targetm.min_arithmetic_precision ();
2734 if (orig_precres == precres && precres < min_precision)
2736 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2737 && prec1 <= precres)
2738 || ((!uns0_p || !uns1_p) && !unsr_p
2739 && prec0 + uns0_p <= precres
2740 && prec1 + uns1_p <= precres))
2742 arg0 = fold_convert_loc (loc, type, arg0);
2743 arg1 = fold_convert_loc (loc, type, arg1);
2744 switch (code)
2746 case MINUS_EXPR:
2747 if (integer_zerop (arg0) && !unsr_p)
2749 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2750 return;
2752 /* FALLTHRU */
2753 case PLUS_EXPR:
2754 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2755 unsr_p, unsr_p, false, NULL);
2756 return;
2757 case MULT_EXPR:
2758 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2759 unsr_p, unsr_p, false, NULL);
2760 return;
2761 default:
2762 gcc_unreachable ();
2766 /* For sub-word operations, retry with a wider type first. */
2767 if (orig_precres == precres && precop <= BITS_PER_WORD)
2769 int p = MAX (min_precision, precop);
2770 scalar_int_mode m = smallest_int_mode_for_size (p);
2771 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2772 uns0_p && uns1_p
2773 && unsr_p);
2774 p = TYPE_PRECISION (optype);
2775 if (p > precres)
2777 precres = p;
2778 unsr_p = TYPE_UNSIGNED (optype);
2779 type = optype;
2780 continue;
2784 if (prec0 <= precres && prec1 <= precres)
2786 tree types[2];
2787 if (unsr_p)
2789 types[0] = build_nonstandard_integer_type (precres, 0);
2790 types[1] = type;
2792 else
2794 types[0] = type;
2795 types[1] = build_nonstandard_integer_type (precres, 1);
2797 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2798 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2799 if (code != MULT_EXPR)
2800 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2801 uns0_p, uns1_p, false, NULL);
2802 else
2803 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2804 uns0_p, uns1_p, false, NULL);
2805 return;
2808 /* Retry with a wider type. */
2809 if (orig_precres == precres)
2811 int p = MAX (prec0, prec1);
2812 scalar_int_mode m = smallest_int_mode_for_size (p);
2813 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2814 uns0_p && uns1_p
2815 && unsr_p);
2816 p = TYPE_PRECISION (optype);
2817 if (p > precres)
2819 precres = p;
2820 unsr_p = TYPE_UNSIGNED (optype);
2821 type = optype;
2822 continue;
2826 gcc_unreachable ();
2828 while (1);
2831 /* Expand ADD_OVERFLOW STMT. */
2833 static void
2834 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2836 expand_arith_overflow (PLUS_EXPR, stmt);
2839 /* Expand SUB_OVERFLOW STMT. */
2841 static void
2842 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2844 expand_arith_overflow (MINUS_EXPR, stmt);
2847 /* Expand MUL_OVERFLOW STMT. */
2849 static void
2850 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2852 expand_arith_overflow (MULT_EXPR, stmt);
2855 /* Expand UADDC STMT. */
2857 static void
2858 expand_UADDC (internal_fn ifn, gcall *stmt)
2860 tree lhs = gimple_call_lhs (stmt);
2861 tree arg1 = gimple_call_arg (stmt, 0);
2862 tree arg2 = gimple_call_arg (stmt, 1);
2863 tree arg3 = gimple_call_arg (stmt, 2);
2864 tree type = TREE_TYPE (arg1);
2865 machine_mode mode = TYPE_MODE (type);
2866 insn_code icode = optab_handler (ifn == IFN_UADDC
2867 ? uaddc5_optab : usubc5_optab, mode);
2868 rtx op1 = expand_normal (arg1);
2869 rtx op2 = expand_normal (arg2);
2870 rtx op3 = expand_normal (arg3);
2871 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2872 rtx re = gen_reg_rtx (mode);
2873 rtx im = gen_reg_rtx (mode);
2874 class expand_operand ops[5];
2875 create_output_operand (&ops[0], re, mode);
2876 create_output_operand (&ops[1], im, mode);
2877 create_input_operand (&ops[2], op1, mode);
2878 create_input_operand (&ops[3], op2, mode);
2879 create_input_operand (&ops[4], op3, mode);
2880 expand_insn (icode, 5, ops);
2881 write_complex_part (target, re, false, false);
2882 write_complex_part (target, im, true, false);
2885 /* Expand USUBC STMT. */
2887 static void
2888 expand_USUBC (internal_fn ifn, gcall *stmt)
2890 expand_UADDC (ifn, stmt);
2893 /* This should get folded in tree-vectorizer.cc. */
2895 static void
2896 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2898 gcc_unreachable ();
2901 /* This should get folded in tree-vectorizer.cc. */
2903 static void
2904 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2906 gcc_unreachable ();
2909 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2910 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2912 static tree
2913 expand_call_mem_ref (tree type, gcall *stmt, int index)
2915 tree addr = gimple_call_arg (stmt, index);
2916 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2917 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2918 if (TYPE_ALIGN (type) != align)
2919 type = build_aligned_type (type, align);
2921 tree tmp = addr;
2922 if (TREE_CODE (tmp) == SSA_NAME)
2924 gimple *def = SSA_NAME_DEF_STMT (tmp);
2925 if (gimple_assign_single_p (def))
2926 tmp = gimple_assign_rhs1 (def);
2929 if (TREE_CODE (tmp) == ADDR_EXPR)
2931 tree mem = TREE_OPERAND (tmp, 0);
2932 if (TREE_CODE (mem) == TARGET_MEM_REF
2933 && types_compatible_p (TREE_TYPE (mem), type))
2935 tree offset = TMR_OFFSET (mem);
2936 if (type != TREE_TYPE (mem)
2937 || alias_ptr_type != TREE_TYPE (offset)
2938 || !integer_zerop (offset))
2940 mem = copy_node (mem);
2941 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2942 wi::to_poly_wide (offset));
2943 TREE_TYPE (mem) = type;
2945 return mem;
2949 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2952 /* Expand MASK_LOAD{,_LANES}, MASK_LEN_LOAD or LEN_LOAD call STMT using optab
2953 * OPTAB. */
2955 static void
2956 expand_partial_load_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
2958 int i = 0;
2959 class expand_operand ops[5];
2960 tree type, lhs, rhs, maskt;
2961 rtx mem, target;
2962 insn_code icode;
2964 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
2965 lhs = gimple_call_lhs (stmt);
2966 if (lhs == NULL_TREE)
2967 return;
2968 type = TREE_TYPE (lhs);
2969 rhs = expand_call_mem_ref (type, stmt, 0);
2971 if (optab == vec_mask_load_lanes_optab
2972 || optab == vec_mask_len_load_lanes_optab)
2973 icode = get_multi_vector_move (type, optab);
2974 else if (optab == len_load_optab)
2975 icode = direct_optab_handler (optab, TYPE_MODE (type));
2976 else
2977 icode = convert_optab_handler (optab, TYPE_MODE (type),
2978 TYPE_MODE (TREE_TYPE (maskt)));
2980 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2981 gcc_assert (MEM_P (mem));
2982 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2983 create_output_operand (&ops[i++], target, TYPE_MODE (type));
2984 create_fixed_operand (&ops[i++], mem);
2985 i = add_mask_and_len_args (ops, i, stmt);
2986 expand_insn (icode, i, ops);
2988 if (!rtx_equal_p (target, ops[0].value))
2989 emit_move_insn (target, ops[0].value);
2992 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
2993 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
2994 #define expand_len_load_optab_fn expand_partial_load_optab_fn
2995 #define expand_mask_len_load_optab_fn expand_partial_load_optab_fn
2997 /* Expand MASK_STORE{,_LANES}, MASK_LEN_STORE or LEN_STORE call STMT using optab
2998 * OPTAB. */
3000 static void
3001 expand_partial_store_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
3003 int i = 0;
3004 class expand_operand ops[5];
3005 tree type, lhs, rhs, maskt;
3006 rtx mem, reg;
3007 insn_code icode;
3009 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
3010 rhs = gimple_call_arg (stmt, internal_fn_stored_value_index (ifn));
3011 type = TREE_TYPE (rhs);
3012 lhs = expand_call_mem_ref (type, stmt, 0);
3014 if (optab == vec_mask_store_lanes_optab
3015 || optab == vec_mask_len_store_lanes_optab)
3016 icode = get_multi_vector_move (type, optab);
3017 else if (optab == len_store_optab)
3018 icode = direct_optab_handler (optab, TYPE_MODE (type));
3019 else
3020 icode = convert_optab_handler (optab, TYPE_MODE (type),
3021 TYPE_MODE (TREE_TYPE (maskt)));
3023 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3024 gcc_assert (MEM_P (mem));
3025 reg = expand_normal (rhs);
3026 create_fixed_operand (&ops[i++], mem);
3027 create_input_operand (&ops[i++], reg, TYPE_MODE (type));
3028 i = add_mask_and_len_args (ops, i, stmt);
3029 expand_insn (icode, i, ops);
3032 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
3033 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
3034 #define expand_len_store_optab_fn expand_partial_store_optab_fn
3035 #define expand_mask_len_store_optab_fn expand_partial_store_optab_fn
3037 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
3038 The expansion of STMT happens based on OPTAB table associated. */
3040 static void
3041 expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3043 class expand_operand ops[6];
3044 insn_code icode;
3045 tree lhs = gimple_call_lhs (stmt);
3046 tree op0a = gimple_call_arg (stmt, 0);
3047 tree op0b = gimple_call_arg (stmt, 1);
3048 tree op1 = gimple_call_arg (stmt, 2);
3049 tree op2 = gimple_call_arg (stmt, 3);
3050 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
3052 tree vec_cond_type = TREE_TYPE (lhs);
3053 tree op_mode = TREE_TYPE (op0a);
3054 bool unsignedp = TYPE_UNSIGNED (op_mode);
3056 machine_mode mode = TYPE_MODE (vec_cond_type);
3057 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
3059 icode = convert_optab_handler (optab, mode, cmp_op_mode);
3060 rtx comparison
3061 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
3062 /* vector_compare_rtx legitimizes operands, preserve equality when
3063 expanding op1/op2. */
3064 rtx rtx_op1, rtx_op2;
3065 if (operand_equal_p (op1, op0a))
3066 rtx_op1 = XEXP (comparison, 0);
3067 else if (operand_equal_p (op1, op0b))
3068 rtx_op1 = XEXP (comparison, 1);
3069 else
3070 rtx_op1 = expand_normal (op1);
3071 if (operand_equal_p (op2, op0a))
3072 rtx_op2 = XEXP (comparison, 0);
3073 else if (operand_equal_p (op2, op0b))
3074 rtx_op2 = XEXP (comparison, 1);
3075 else
3076 rtx_op2 = expand_normal (op2);
3078 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3079 create_output_operand (&ops[0], target, mode);
3080 create_input_operand (&ops[1], rtx_op1, mode);
3081 create_input_operand (&ops[2], rtx_op2, mode);
3082 create_fixed_operand (&ops[3], comparison);
3083 create_fixed_operand (&ops[4], XEXP (comparison, 0));
3084 create_fixed_operand (&ops[5], XEXP (comparison, 1));
3085 expand_insn (icode, 6, ops);
3086 if (!rtx_equal_p (ops[0].value, target))
3087 emit_move_insn (target, ops[0].value);
3090 /* Expand VCOND_MASK optab internal function.
3091 The expansion of STMT happens based on OPTAB table associated. */
3093 static void
3094 expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3096 class expand_operand ops[4];
3098 tree lhs = gimple_call_lhs (stmt);
3099 tree op0 = gimple_call_arg (stmt, 0);
3100 tree op1 = gimple_call_arg (stmt, 1);
3101 tree op2 = gimple_call_arg (stmt, 2);
3102 tree vec_cond_type = TREE_TYPE (lhs);
3104 machine_mode mode = TYPE_MODE (vec_cond_type);
3105 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
3106 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
3107 rtx mask, rtx_op1, rtx_op2;
3109 gcc_assert (icode != CODE_FOR_nothing);
3111 mask = expand_normal (op0);
3112 rtx_op1 = expand_normal (op1);
3113 rtx_op2 = expand_normal (op2);
3115 mask = force_reg (mask_mode, mask);
3116 rtx_op1 = force_reg (mode, rtx_op1);
3118 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3119 create_output_operand (&ops[0], target, mode);
3120 create_input_operand (&ops[1], rtx_op1, mode);
3121 create_input_operand (&ops[2], rtx_op2, mode);
3122 create_input_operand (&ops[3], mask, mask_mode);
3123 expand_insn (icode, 4, ops);
3124 if (!rtx_equal_p (ops[0].value, target))
3125 emit_move_insn (target, ops[0].value);
3128 /* Expand VEC_SET internal functions. */
3130 static void
3131 expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3133 tree lhs = gimple_call_lhs (stmt);
3134 tree op0 = gimple_call_arg (stmt, 0);
3135 tree op1 = gimple_call_arg (stmt, 1);
3136 tree op2 = gimple_call_arg (stmt, 2);
3137 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3138 rtx src = expand_normal (op0);
3140 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3141 scalar_mode innermode = GET_MODE_INNER (outermode);
3143 rtx value = expand_normal (op1);
3144 rtx pos = expand_normal (op2);
3146 class expand_operand ops[3];
3147 enum insn_code icode = optab_handler (optab, outermode);
3149 if (icode != CODE_FOR_nothing)
3151 rtx temp = gen_reg_rtx (outermode);
3152 emit_move_insn (temp, src);
3154 create_fixed_operand (&ops[0], temp);
3155 create_input_operand (&ops[1], value, innermode);
3156 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
3157 true);
3158 if (maybe_expand_insn (icode, 3, ops))
3160 emit_move_insn (target, temp);
3161 return;
3164 gcc_unreachable ();
3167 static void
3168 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
3172 static void
3173 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
3175 /* When guessing was done, the hints should be already stripped away. */
3176 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
3178 rtx target;
3179 tree lhs = gimple_call_lhs (stmt);
3180 if (lhs)
3181 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3182 else
3183 target = const0_rtx;
3184 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
3185 if (lhs && val != target)
3186 emit_move_insn (target, val);
3189 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
3190 should never be called. */
3192 static void
3193 expand_VA_ARG (internal_fn, gcall *)
3195 gcc_unreachable ();
3198 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
3199 dummy function should never be called. */
3201 static void
3202 expand_VEC_CONVERT (internal_fn, gcall *)
3204 gcc_unreachable ();
3207 /* Expand IFN_RAWMEMCHAR internal function. */
3209 void
3210 expand_RAWMEMCHR (internal_fn, gcall *stmt)
3212 expand_operand ops[3];
3214 tree lhs = gimple_call_lhs (stmt);
3215 if (!lhs)
3216 return;
3217 machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
3218 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3219 create_output_operand (&ops[0], lhs_rtx, lhs_mode);
3221 tree mem = gimple_call_arg (stmt, 0);
3222 rtx mem_rtx = get_memory_rtx (mem, NULL);
3223 create_fixed_operand (&ops[1], mem_rtx);
3225 tree pattern = gimple_call_arg (stmt, 1);
3226 machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
3227 rtx pattern_rtx = expand_normal (pattern);
3228 create_input_operand (&ops[2], pattern_rtx, mode);
3230 insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
3232 expand_insn (icode, 3, ops);
3233 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3234 emit_move_insn (lhs_rtx, ops[0].value);
3237 /* Expand the IFN_UNIQUE function according to its first argument. */
3239 static void
3240 expand_UNIQUE (internal_fn, gcall *stmt)
3242 rtx pattern = NULL_RTX;
3243 enum ifn_unique_kind kind
3244 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
3246 switch (kind)
3248 default:
3249 gcc_unreachable ();
3251 case IFN_UNIQUE_UNSPEC:
3252 if (targetm.have_unique ())
3253 pattern = targetm.gen_unique ();
3254 break;
3256 case IFN_UNIQUE_OACC_FORK:
3257 case IFN_UNIQUE_OACC_JOIN:
3258 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
3260 tree lhs = gimple_call_lhs (stmt);
3261 rtx target = const0_rtx;
3263 if (lhs)
3264 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3266 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
3267 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
3269 if (kind == IFN_UNIQUE_OACC_FORK)
3270 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
3271 else
3272 pattern = targetm.gen_oacc_join (target, data_dep, axis);
3274 else
3275 gcc_unreachable ();
3276 break;
3279 if (pattern)
3280 emit_insn (pattern);
3283 /* Expand the IFN_DEFERRED_INIT function:
3284 LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
3286 Initialize the LHS with zero/pattern according to its second argument
3287 INIT_TYPE:
3288 if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
3289 if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
3290 to initialize;
3291 The LHS variable is initialized including paddings.
3292 The reasons to choose 0xFE for pattern initialization are:
3293 1. It is a non-canonical virtual address on x86_64, and at the
3294 high end of the i386 kernel address space.
3295 2. It is a very large float value (-1.694739530317379e+38).
3296 3. It is also an unusual number for integers. */
3297 #define INIT_PATTERN_VALUE 0xFE
3298 static void
3299 expand_DEFERRED_INIT (internal_fn, gcall *stmt)
3301 tree lhs = gimple_call_lhs (stmt);
3302 tree var_size = gimple_call_arg (stmt, 0);
3303 enum auto_init_type init_type
3304 = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
3305 bool reg_lhs = true;
3307 tree var_type = TREE_TYPE (lhs);
3308 gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
3310 if (TREE_CODE (lhs) == SSA_NAME)
3311 reg_lhs = true;
3312 else
3314 tree lhs_base = lhs;
3315 while (handled_component_p (lhs_base))
3316 lhs_base = TREE_OPERAND (lhs_base, 0);
3317 reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
3318 || non_mem_decl_p (lhs_base));
3319 /* If this expands to a register and the underlying decl is wrapped in
3320 a MEM_REF that just serves as an access type change expose the decl
3321 if it is of correct size. This avoids a situation as in PR103271
3322 if the target does not support a direct move to the registers mode. */
3323 if (reg_lhs
3324 && TREE_CODE (lhs_base) == MEM_REF
3325 && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
3326 && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
3327 && integer_zerop (TREE_OPERAND (lhs_base, 1))
3328 && tree_fits_uhwi_p (var_size)
3329 && tree_int_cst_equal
3330 (var_size,
3331 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
3333 lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
3334 var_type = TREE_TYPE (lhs);
3338 if (!reg_lhs)
3340 /* If the variable is not in register, expand to a memset
3341 to initialize it. */
3342 mark_addressable (lhs);
3343 tree var_addr = build_fold_addr_expr (lhs);
3345 tree value = (init_type == AUTO_INIT_PATTERN)
3346 ? build_int_cst (integer_type_node,
3347 INIT_PATTERN_VALUE)
3348 : integer_zero_node;
3349 tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
3350 3, var_addr, value, var_size);
3351 /* Expand this memset call. */
3352 expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
3354 else
3356 /* If this variable is in a register use expand_assignment.
3357 For boolean scalars force zero-init. */
3358 tree init;
3359 scalar_int_mode var_mode;
3360 if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
3361 && tree_fits_uhwi_p (var_size)
3362 && (init_type == AUTO_INIT_PATTERN
3363 || !is_gimple_reg_type (var_type))
3364 && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
3365 0).exists (&var_mode)
3366 && have_insn_for (SET, var_mode))
3368 unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
3369 unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
3370 memset (buf, (init_type == AUTO_INIT_PATTERN
3371 ? INIT_PATTERN_VALUE : 0), total_bytes);
3372 tree itype = build_nonstandard_integer_type
3373 (total_bytes * BITS_PER_UNIT, 1);
3374 wide_int w = wi::from_buffer (buf, total_bytes);
3375 init = wide_int_to_tree (itype, w);
3376 /* Pun the LHS to make sure its type has constant size
3377 unless it is an SSA name where that's already known. */
3378 if (TREE_CODE (lhs) != SSA_NAME)
3379 lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
3380 else
3381 init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
3383 else
3384 /* Use zero-init also for variable-length sizes. */
3385 init = build_zero_cst (var_type);
3387 expand_assignment (lhs, init, false);
3391 /* The size of an OpenACC compute dimension. */
3393 static void
3394 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
3396 tree lhs = gimple_call_lhs (stmt);
3398 if (!lhs)
3399 return;
3401 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3402 if (targetm.have_oacc_dim_size ())
3404 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3405 VOIDmode, EXPAND_NORMAL);
3406 emit_insn (targetm.gen_oacc_dim_size (target, dim));
3408 else
3409 emit_move_insn (target, GEN_INT (1));
3412 /* The position of an OpenACC execution engine along one compute axis. */
3414 static void
3415 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
3417 tree lhs = gimple_call_lhs (stmt);
3419 if (!lhs)
3420 return;
3422 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3423 if (targetm.have_oacc_dim_pos ())
3425 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3426 VOIDmode, EXPAND_NORMAL);
3427 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
3429 else
3430 emit_move_insn (target, const0_rtx);
3433 /* This is expanded by oacc_device_lower pass. */
3435 static void
3436 expand_GOACC_LOOP (internal_fn, gcall *)
3438 gcc_unreachable ();
3441 /* This is expanded by oacc_device_lower pass. */
3443 static void
3444 expand_GOACC_REDUCTION (internal_fn, gcall *)
3446 gcc_unreachable ();
3449 /* This is expanded by oacc_device_lower pass. */
3451 static void
3452 expand_GOACC_TILE (internal_fn, gcall *)
3454 gcc_unreachable ();
3457 /* Set errno to EDOM. */
3459 static void
3460 expand_SET_EDOM (internal_fn, gcall *)
3462 #ifdef TARGET_EDOM
3463 #ifdef GEN_ERRNO_RTX
3464 rtx errno_rtx = GEN_ERRNO_RTX;
3465 #else
3466 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
3467 #endif
3468 emit_move_insn (errno_rtx,
3469 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
3470 #else
3471 gcc_unreachable ();
3472 #endif
3475 /* Expand atomic bit test and set. */
3477 static void
3478 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
3480 expand_ifn_atomic_bit_test_and (call);
3483 /* Expand atomic bit test and complement. */
3485 static void
3486 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
3488 expand_ifn_atomic_bit_test_and (call);
3491 /* Expand atomic bit test and reset. */
3493 static void
3494 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
3496 expand_ifn_atomic_bit_test_and (call);
3499 /* Expand atomic bit test and set. */
3501 static void
3502 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
3504 expand_ifn_atomic_compare_exchange (call);
3507 /* Expand atomic add fetch and cmp with 0. */
3509 static void
3510 expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
3512 expand_ifn_atomic_op_fetch_cmp_0 (call);
3515 /* Expand atomic sub fetch and cmp with 0. */
3517 static void
3518 expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
3520 expand_ifn_atomic_op_fetch_cmp_0 (call);
3523 /* Expand atomic and fetch and cmp with 0. */
3525 static void
3526 expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
3528 expand_ifn_atomic_op_fetch_cmp_0 (call);
3531 /* Expand atomic or fetch and cmp with 0. */
3533 static void
3534 expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
3536 expand_ifn_atomic_op_fetch_cmp_0 (call);
3539 /* Expand atomic xor fetch and cmp with 0. */
3541 static void
3542 expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
3544 expand_ifn_atomic_op_fetch_cmp_0 (call);
3547 /* Expand LAUNDER to assignment, lhs = arg0. */
3549 static void
3550 expand_LAUNDER (internal_fn, gcall *call)
3552 tree lhs = gimple_call_lhs (call);
3554 if (!lhs)
3555 return;
3557 expand_assignment (lhs, gimple_call_arg (call, 0), false);
3560 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
3562 static void
3563 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3565 internal_fn ifn = gimple_call_internal_fn (stmt);
3566 int rhs_index = internal_fn_stored_value_index (ifn);
3567 tree base = gimple_call_arg (stmt, 0);
3568 tree offset = gimple_call_arg (stmt, 1);
3569 tree scale = gimple_call_arg (stmt, 2);
3570 tree rhs = gimple_call_arg (stmt, rhs_index);
3572 rtx base_rtx = expand_normal (base);
3573 rtx offset_rtx = expand_normal (offset);
3574 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3575 rtx rhs_rtx = expand_normal (rhs);
3577 class expand_operand ops[8];
3578 int i = 0;
3579 create_address_operand (&ops[i++], base_rtx);
3580 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3581 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3582 create_integer_operand (&ops[i++], scale_int);
3583 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
3584 i = add_mask_and_len_args (ops, i, stmt);
3586 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
3587 TYPE_MODE (TREE_TYPE (offset)));
3588 expand_insn (icode, i, ops);
3591 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
3593 static void
3594 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3596 tree lhs = gimple_call_lhs (stmt);
3597 tree base = gimple_call_arg (stmt, 0);
3598 tree offset = gimple_call_arg (stmt, 1);
3599 tree scale = gimple_call_arg (stmt, 2);
3601 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3602 rtx base_rtx = expand_normal (base);
3603 rtx offset_rtx = expand_normal (offset);
3604 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3606 int i = 0;
3607 class expand_operand ops[8];
3608 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
3609 create_address_operand (&ops[i++], base_rtx);
3610 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3611 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3612 create_integer_operand (&ops[i++], scale_int);
3613 i = add_mask_and_len_args (ops, i, stmt);
3614 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
3615 TYPE_MODE (TREE_TYPE (offset)));
3616 expand_insn (icode, i, ops);
3617 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3618 emit_move_insn (lhs_rtx, ops[0].value);
3621 /* Helper for expand_DIVMOD. Return true if the sequence starting with
3622 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
3624 static bool
3625 contains_call_div_mod (rtx_insn *insn)
3627 subrtx_iterator::array_type array;
3628 for (; insn; insn = NEXT_INSN (insn))
3629 if (CALL_P (insn))
3630 return true;
3631 else if (INSN_P (insn))
3632 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3633 switch (GET_CODE (*iter))
3635 case CALL:
3636 case DIV:
3637 case UDIV:
3638 case MOD:
3639 case UMOD:
3640 return true;
3641 default:
3642 break;
3644 return false;
3647 /* Expand DIVMOD() using:
3648 a) optab handler for udivmod/sdivmod if it is available.
3649 b) If optab_handler doesn't exist, generate call to
3650 target-specific divmod libfunc. */
3652 static void
3653 expand_DIVMOD (internal_fn, gcall *call_stmt)
3655 tree lhs = gimple_call_lhs (call_stmt);
3656 tree arg0 = gimple_call_arg (call_stmt, 0);
3657 tree arg1 = gimple_call_arg (call_stmt, 1);
3659 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3660 tree type = TREE_TYPE (TREE_TYPE (lhs));
3661 machine_mode mode = TYPE_MODE (type);
3662 bool unsignedp = TYPE_UNSIGNED (type);
3663 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3665 rtx op0 = expand_normal (arg0);
3666 rtx op1 = expand_normal (arg1);
3667 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3669 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3670 rtx_insn *insns = NULL;
3672 if (TREE_CODE (arg1) == INTEGER_CST)
3674 /* For DIVMOD by integral constants, there could be efficient code
3675 expanded inline e.g. using shifts and plus/minus. Try to expand
3676 the division and modulo and if it emits any library calls or any
3677 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3678 divmod libcall. */
3679 scalar_int_mode int_mode;
3680 if (remainder == NULL_RTX
3681 && optimize
3682 && CONST_INT_P (op1)
3683 && !pow2p_hwi (INTVAL (op1))
3684 && is_int_mode (TYPE_MODE (type), &int_mode)
3685 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
3686 && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
3687 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
3688 && optimize_insn_for_speed_p ())
3690 rtx_insn *last = get_last_insn ();
3691 remainder = NULL_RTX;
3692 quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
3693 TYPE_UNSIGNED (type));
3694 if (quotient != NULL_RTX)
3696 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
3698 rtx_insn *move = emit_move_insn (quotient, quotient);
3699 set_dst_reg_note (move, REG_EQUAL,
3700 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3701 ? UDIV : DIV, int_mode,
3702 copy_rtx (op0), op1),
3703 quotient);
3704 move = emit_move_insn (remainder, remainder);
3705 set_dst_reg_note (move, REG_EQUAL,
3706 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3707 ? UMOD : MOD, int_mode,
3708 copy_rtx (op0), op1),
3709 quotient);
3712 else
3713 delete_insns_since (last);
3716 if (remainder == NULL_RTX)
3718 struct separate_ops ops;
3719 ops.code = TRUNC_DIV_EXPR;
3720 ops.type = type;
3721 ops.op0 = make_tree (ops.type, op0);
3722 ops.op1 = arg1;
3723 ops.op2 = NULL_TREE;
3724 ops.location = gimple_location (call_stmt);
3725 start_sequence ();
3726 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3727 if (contains_call_div_mod (get_insns ()))
3728 quotient = NULL_RTX;
3729 else
3731 ops.code = TRUNC_MOD_EXPR;
3732 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
3733 EXPAND_NORMAL);
3734 if (contains_call_div_mod (get_insns ()))
3735 remainder = NULL_RTX;
3737 if (remainder)
3738 insns = get_insns ();
3739 end_sequence ();
3743 if (remainder)
3744 emit_insn (insns);
3746 /* Check if optab_handler exists for divmod_optab for given mode. */
3747 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
3749 quotient = gen_reg_rtx (mode);
3750 remainder = gen_reg_rtx (mode);
3751 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3754 /* Generate call to divmod libfunc if it exists. */
3755 else if (rtx libfunc = optab_libfunc (tab, mode))
3756 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3757 &quotient, &remainder);
3759 else
3760 gcc_unreachable ();
3762 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3763 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3764 make_tree (TREE_TYPE (arg0), quotient),
3765 make_tree (TREE_TYPE (arg1), remainder)),
3766 target, VOIDmode, EXPAND_NORMAL);
3769 /* Expand a NOP. */
3771 static void
3772 expand_NOP (internal_fn, gcall *)
3774 /* Nothing. But it shouldn't really prevail. */
3777 /* Coroutines, all should have been processed at this stage. */
3779 static void
3780 expand_CO_FRAME (internal_fn, gcall *)
3782 gcc_unreachable ();
3785 static void
3786 expand_CO_YIELD (internal_fn, gcall *)
3788 gcc_unreachable ();
3791 static void
3792 expand_CO_SUSPN (internal_fn, gcall *)
3794 gcc_unreachable ();
3797 static void
3798 expand_CO_ACTOR (internal_fn, gcall *)
3800 gcc_unreachable ();
3803 /* Expand a call to FN using the operands in STMT. FN has a single
3804 output operand and NARGS input operands. */
3806 static void
3807 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3808 unsigned int nargs)
3810 tree_pair types = direct_internal_fn_types (fn, stmt);
3811 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3812 expand_fn_using_insn (stmt, icode, 1, nargs);
3815 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3817 static void
3818 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3820 expand_operand ops[4];
3821 tree rhs_type[2];
3823 tree lhs = gimple_call_lhs (stmt);
3824 tree lhs_type = TREE_TYPE (lhs);
3825 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3826 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3828 for (unsigned int i = 0; i < 2; ++i)
3830 tree rhs = gimple_call_arg (stmt, i);
3831 rhs_type[i] = TREE_TYPE (rhs);
3832 rtx rhs_rtx = expand_normal (rhs);
3833 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3836 int opcnt;
3837 if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
3839 /* When the mask is an integer mode the exact vector length may not
3840 be clear to the backend, so we pass it in operand[3].
3841 Use the vector in arg2 for the most reliable intended size. */
3842 tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
3843 create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
3844 opcnt = 4;
3846 else
3847 /* The mask has a vector type so the length operand is unnecessary. */
3848 opcnt = 3;
3850 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3851 TYPE_MODE (lhs_type));
3853 expand_insn (icode, opcnt, ops);
3854 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3855 emit_move_insn (lhs_rtx, ops[0].value);
3858 /* Expand a call to a convert-like optab using the operands in STMT.
3859 FN has a single output operand and NARGS input operands. */
3861 static void
3862 expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
3863 unsigned int nargs)
3865 tree_pair types = direct_internal_fn_types (fn, stmt);
3866 insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
3867 TYPE_MODE (types.second));
3868 expand_fn_using_insn (stmt, icode, 1, nargs);
3871 /* Expanders for optabs that can use expand_direct_optab_fn. */
3873 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3874 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3876 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3877 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3879 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3880 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3882 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3883 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3885 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3886 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3888 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3889 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3891 #define expand_cond_len_unary_optab_fn(FN, STMT, OPTAB) \
3892 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3894 #define expand_cond_len_binary_optab_fn(FN, STMT, OPTAB) \
3895 expand_direct_optab_fn (FN, STMT, OPTAB, 6)
3897 #define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
3898 expand_direct_optab_fn (FN, STMT, OPTAB, 7)
3900 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3901 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3903 #define expand_fold_len_extract_optab_fn(FN, STMT, OPTAB) \
3904 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3906 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3907 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3909 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3910 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3912 #define expand_mask_len_fold_left_optab_fn(FN, STMT, OPTAB) \
3913 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3915 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3916 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3918 /* Expanders for optabs that can use expand_convert_optab_fn. */
3920 #define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
3921 expand_convert_optab_fn (FN, STMT, OPTAB, 1)
3923 #define expand_vec_extract_optab_fn(FN, STMT, OPTAB) \
3924 expand_convert_optab_fn (FN, STMT, OPTAB, 2)
3926 /* RETURN_TYPE and ARGS are a return type and argument list that are
3927 in principle compatible with FN (which satisfies direct_internal_fn_p).
3928 Return the types that should be used to determine whether the
3929 target supports FN. */
3931 tree_pair
3932 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3934 const direct_internal_fn_info &info = direct_internal_fn (fn);
3935 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3936 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3937 return tree_pair (type0, type1);
3940 /* CALL is a call whose return type and arguments are in principle
3941 compatible with FN (which satisfies direct_internal_fn_p). Return the
3942 types that should be used to determine whether the target supports FN. */
3944 tree_pair
3945 direct_internal_fn_types (internal_fn fn, gcall *call)
3947 const direct_internal_fn_info &info = direct_internal_fn (fn);
3948 tree op0 = (info.type0 < 0
3949 ? gimple_call_lhs (call)
3950 : gimple_call_arg (call, info.type0));
3951 tree op1 = (info.type1 < 0
3952 ? gimple_call_lhs (call)
3953 : gimple_call_arg (call, info.type1));
3954 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3957 /* Return true if OPTAB is supported for TYPES (whose modes should be
3958 the same) when the optimization type is OPT_TYPE. Used for simple
3959 direct optabs. */
3961 static bool
3962 direct_optab_supported_p (direct_optab optab, tree_pair types,
3963 optimization_type opt_type)
3965 machine_mode mode = TYPE_MODE (types.first);
3966 gcc_checking_assert (mode == TYPE_MODE (types.second));
3967 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
3970 /* Return true if OPTAB is supported for TYPES, where the first type
3971 is the destination and the second type is the source. Used for
3972 convert optabs. */
3974 static bool
3975 convert_optab_supported_p (convert_optab optab, tree_pair types,
3976 optimization_type opt_type)
3978 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3979 TYPE_MODE (types.second), opt_type)
3980 != CODE_FOR_nothing);
3983 /* Return true if load/store lanes optab OPTAB is supported for
3984 array type TYPES.first when the optimization type is OPT_TYPE. */
3986 static bool
3987 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3988 optimization_type opt_type)
3990 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3991 machine_mode imode = TYPE_MODE (types.first);
3992 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3993 return (convert_optab_handler (optab, imode, vmode, opt_type)
3994 != CODE_FOR_nothing);
3997 #define direct_unary_optab_supported_p direct_optab_supported_p
3998 #define direct_unary_convert_optab_supported_p convert_optab_supported_p
3999 #define direct_binary_optab_supported_p direct_optab_supported_p
4000 #define direct_ternary_optab_supported_p direct_optab_supported_p
4001 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
4002 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
4003 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
4004 #define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
4005 #define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
4006 #define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
4007 #define direct_mask_load_optab_supported_p convert_optab_supported_p
4008 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
4009 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
4010 #define direct_gather_load_optab_supported_p convert_optab_supported_p
4011 #define direct_len_load_optab_supported_p direct_optab_supported_p
4012 #define direct_mask_len_load_optab_supported_p convert_optab_supported_p
4013 #define direct_mask_store_optab_supported_p convert_optab_supported_p
4014 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
4015 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
4016 #define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
4017 #define direct_vec_cond_optab_supported_p convert_optab_supported_p
4018 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
4019 #define direct_len_store_optab_supported_p direct_optab_supported_p
4020 #define direct_mask_len_store_optab_supported_p convert_optab_supported_p
4021 #define direct_while_optab_supported_p convert_optab_supported_p
4022 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
4023 #define direct_fold_len_extract_optab_supported_p direct_optab_supported_p
4024 #define direct_fold_left_optab_supported_p direct_optab_supported_p
4025 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
4026 #define direct_mask_len_fold_left_optab_supported_p direct_optab_supported_p
4027 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
4028 #define direct_vec_set_optab_supported_p direct_optab_supported_p
4029 #define direct_vec_extract_optab_supported_p convert_optab_supported_p
4031 /* Return the optab used by internal function FN. */
4033 optab
4034 direct_internal_fn_optab (internal_fn fn, tree_pair types)
4036 switch (fn)
4038 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4039 case IFN_##CODE: break;
4040 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4041 case IFN_##CODE: return OPTAB##_optab;
4042 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4043 UNSIGNED_OPTAB, TYPE) \
4044 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
4045 ? UNSIGNED_OPTAB ## _optab \
4046 : SIGNED_OPTAB ## _optab);
4047 #include "internal-fn.def"
4049 case IFN_LAST:
4050 break;
4052 gcc_unreachable ();
4055 /* Return the optab used by internal function FN. */
4057 static optab
4058 direct_internal_fn_optab (internal_fn fn)
4060 switch (fn)
4062 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4063 case IFN_##CODE: break;
4064 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4065 case IFN_##CODE: return OPTAB##_optab;
4066 #include "internal-fn.def"
4068 case IFN_LAST:
4069 break;
4071 gcc_unreachable ();
4074 /* Return true if FN is supported for the types in TYPES when the
4075 optimization type is OPT_TYPE. The types are those associated with
4076 the "type0" and "type1" fields of FN's direct_internal_fn_info
4077 structure. */
4079 bool
4080 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
4081 optimization_type opt_type)
4083 switch (fn)
4085 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4086 case IFN_##CODE: break;
4087 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4088 case IFN_##CODE: \
4089 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
4090 opt_type);
4091 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4092 UNSIGNED_OPTAB, TYPE) \
4093 case IFN_##CODE: \
4095 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
4096 ? UNSIGNED_OPTAB ## _optab \
4097 : SIGNED_OPTAB ## _optab); \
4098 return direct_##TYPE##_optab_supported_p (which_optab, types, \
4099 opt_type); \
4101 #include "internal-fn.def"
4103 case IFN_LAST:
4104 break;
4106 gcc_unreachable ();
4109 /* Return true if FN is supported for type TYPE when the optimization
4110 type is OPT_TYPE. The caller knows that the "type0" and "type1"
4111 fields of FN's direct_internal_fn_info structure are the same. */
4113 bool
4114 direct_internal_fn_supported_p (internal_fn fn, tree type,
4115 optimization_type opt_type)
4117 const direct_internal_fn_info &info = direct_internal_fn (fn);
4118 gcc_checking_assert (info.type0 == info.type1);
4119 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
4122 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
4123 given that STMT is a call to a direct internal function. */
4125 bool
4126 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
4128 internal_fn fn = gimple_call_internal_fn (stmt);
4129 tree_pair types = direct_internal_fn_types (fn, stmt);
4130 return direct_internal_fn_supported_p (fn, types, opt_type);
4133 /* Return true if FN is a binary operation and if FN is commutative. */
4135 bool
4136 commutative_binary_fn_p (internal_fn fn)
4138 switch (fn)
4140 case IFN_AVG_FLOOR:
4141 case IFN_AVG_CEIL:
4142 case IFN_MULH:
4143 case IFN_MULHS:
4144 case IFN_MULHRS:
4145 case IFN_FMIN:
4146 case IFN_FMAX:
4147 case IFN_COMPLEX_MUL:
4148 case IFN_UBSAN_CHECK_ADD:
4149 case IFN_UBSAN_CHECK_MUL:
4150 case IFN_ADD_OVERFLOW:
4151 case IFN_MUL_OVERFLOW:
4152 case IFN_VEC_WIDEN_PLUS:
4153 case IFN_VEC_WIDEN_PLUS_LO:
4154 case IFN_VEC_WIDEN_PLUS_HI:
4155 case IFN_VEC_WIDEN_PLUS_EVEN:
4156 case IFN_VEC_WIDEN_PLUS_ODD:
4157 return true;
4159 default:
4160 return false;
4164 /* Return true if FN is a ternary operation and if its first two arguments
4165 are commutative. */
4167 bool
4168 commutative_ternary_fn_p (internal_fn fn)
4170 switch (fn)
4172 case IFN_FMA:
4173 case IFN_FMS:
4174 case IFN_FNMA:
4175 case IFN_FNMS:
4176 case IFN_UADDC:
4177 return true;
4179 default:
4180 return false;
4184 /* Return true if FN is an associative binary operation. */
4186 bool
4187 associative_binary_fn_p (internal_fn fn)
4189 switch (fn)
4191 case IFN_FMIN:
4192 case IFN_FMAX:
4193 return true;
4195 default:
4196 return false;
4200 /* If FN is commutative in two consecutive arguments, return the
4201 index of the first, otherwise return -1. */
4204 first_commutative_argument (internal_fn fn)
4206 switch (fn)
4208 case IFN_COND_ADD:
4209 case IFN_COND_MUL:
4210 case IFN_COND_MIN:
4211 case IFN_COND_MAX:
4212 case IFN_COND_FMIN:
4213 case IFN_COND_FMAX:
4214 case IFN_COND_AND:
4215 case IFN_COND_IOR:
4216 case IFN_COND_XOR:
4217 case IFN_COND_FMA:
4218 case IFN_COND_FMS:
4219 case IFN_COND_FNMA:
4220 case IFN_COND_FNMS:
4221 case IFN_COND_LEN_ADD:
4222 case IFN_COND_LEN_MUL:
4223 case IFN_COND_LEN_MIN:
4224 case IFN_COND_LEN_MAX:
4225 case IFN_COND_LEN_FMIN:
4226 case IFN_COND_LEN_FMAX:
4227 case IFN_COND_LEN_AND:
4228 case IFN_COND_LEN_IOR:
4229 case IFN_COND_LEN_XOR:
4230 case IFN_COND_LEN_FMA:
4231 case IFN_COND_LEN_FMS:
4232 case IFN_COND_LEN_FNMA:
4233 case IFN_COND_LEN_FNMS:
4234 return 1;
4236 default:
4237 if (commutative_binary_fn_p (fn)
4238 || commutative_ternary_fn_p (fn))
4239 return 0;
4240 return -1;
4244 /* Return true if this CODE describes an internal_fn that returns a vector with
4245 elements twice as wide as the element size of the input vectors. */
4247 bool
4248 widening_fn_p (code_helper code)
4250 if (!code.is_fn_code ())
4251 return false;
4253 if (!internal_fn_p ((combined_fn) code))
4254 return false;
4256 internal_fn fn = as_internal_fn ((combined_fn) code);
4257 switch (fn)
4259 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4260 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
4261 case IFN_##NAME: \
4262 case IFN_##NAME##_HI: \
4263 case IFN_##NAME##_LO: \
4264 case IFN_##NAME##_EVEN: \
4265 case IFN_##NAME##_ODD: \
4266 return true;
4267 #include "internal-fn.def"
4268 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4270 default:
4271 return false;
4275 /* Return true if IFN_SET_EDOM is supported. */
4277 bool
4278 set_edom_supported_p (void)
4280 #ifdef TARGET_EDOM
4281 return true;
4282 #else
4283 return false;
4284 #endif
4287 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4288 static void \
4289 expand_##CODE (internal_fn fn, gcall *stmt) \
4291 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
4293 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4294 UNSIGNED_OPTAB, TYPE) \
4295 static void \
4296 expand_##CODE (internal_fn fn, gcall *stmt) \
4298 tree_pair types = direct_internal_fn_types (fn, stmt); \
4299 optab which_optab = direct_internal_fn_optab (fn, types); \
4300 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
4302 #include "internal-fn.def"
4303 #undef DEF_INTERNAL_OPTAB_FN
4304 #undef DEF_INTERNAL_SIGNED_OPTAB_FN
4306 /* Routines to expand each internal function, indexed by function number.
4307 Each routine has the prototype:
4309 expand_<NAME> (gcall *stmt)
4311 where STMT is the statement that performs the call. */
4312 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
4314 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
4315 #include "internal-fn.def"
4319 /* Invoke T(CODE, SUFFIX) for each conditional function IFN_COND_##SUFFIX
4320 that maps to a tree code CODE. There is also an IFN_COND_LEN_##SUFFIX
4321 for each such IFN_COND_##SUFFIX. */
4322 #define FOR_EACH_CODE_MAPPING(T) \
4323 T (PLUS_EXPR, ADD) \
4324 T (MINUS_EXPR, SUB) \
4325 T (MULT_EXPR, MUL) \
4326 T (TRUNC_DIV_EXPR, DIV) \
4327 T (TRUNC_MOD_EXPR, MOD) \
4328 T (RDIV_EXPR, RDIV) \
4329 T (MIN_EXPR, MIN) \
4330 T (MAX_EXPR, MAX) \
4331 T (BIT_AND_EXPR, AND) \
4332 T (BIT_IOR_EXPR, IOR) \
4333 T (BIT_XOR_EXPR, XOR) \
4334 T (LSHIFT_EXPR, SHL) \
4335 T (RSHIFT_EXPR, SHR) \
4336 T (NEGATE_EXPR, NEG)
4338 /* Return a function that only performs CODE when a certain condition is met
4339 and that uses a given fallback value otherwise. For example, if CODE is
4340 a binary operation associated with conditional function FN:
4342 LHS = FN (COND, A, B, ELSE)
4344 is equivalent to the C expression:
4346 LHS = COND ? A CODE B : ELSE;
4348 operating elementwise if the operands are vectors.
4350 Return IFN_LAST if no such function exists. */
4352 internal_fn
4353 get_conditional_internal_fn (tree_code code)
4355 switch (code)
4357 #define CASE(CODE, IFN) case CODE: return IFN_COND_##IFN;
4358 FOR_EACH_CODE_MAPPING(CASE)
4359 #undef CASE
4360 default:
4361 return IFN_LAST;
4365 /* If IFN implements the conditional form of a tree code, return that
4366 tree code, otherwise return ERROR_MARK. */
4368 tree_code
4369 conditional_internal_fn_code (internal_fn ifn)
4371 switch (ifn)
4373 #define CASE(CODE, IFN) \
4374 case IFN_COND_##IFN: \
4375 case IFN_COND_LEN_##IFN: \
4376 return CODE;
4377 FOR_EACH_CODE_MAPPING (CASE)
4378 #undef CASE
4379 default:
4380 return ERROR_MARK;
4384 /* Like get_conditional_internal_fn, but return a function that
4385 additionally restricts the operation to the leading elements
4386 of a vector. The number of elements to process is given by a length
4387 and bias pair, as for IFN_LOAD_LEN. The values of the remaining
4388 elements are taken from the fallback ("else") argument.
4390 For example, if CODE is a binary operation associated with FN:
4392 LHS = FN (COND, A, B, ELSE, LEN, BIAS)
4394 is equivalent to the C code:
4396 for (int i = 0; i < NUNITS; i++)
4398 if (i < LEN + BIAS && COND[i])
4399 LHS[i] = A[i] CODE B[i];
4400 else
4401 LHS[i] = ELSE[i];
4405 internal_fn
4406 get_conditional_len_internal_fn (tree_code code)
4408 switch (code)
4410 #define CASE(CODE, IFN) case CODE: return IFN_COND_LEN_##IFN;
4411 FOR_EACH_CODE_MAPPING(CASE)
4412 #undef CASE
4413 default:
4414 return IFN_LAST;
4418 /* Invoke T(IFN) for each internal function IFN that also has an
4419 IFN_COND_* form. */
4420 #define FOR_EACH_COND_FN_PAIR(T) \
4421 T (FMAX) \
4422 T (FMIN) \
4423 T (FMA) \
4424 T (FMS) \
4425 T (FNMA) \
4426 T (FNMS)
4428 /* Return a function that only performs internal function FN when a
4429 certain condition is met and that uses a given fallback value otherwise.
4430 In other words, the returned function FN' is such that:
4432 LHS = FN' (COND, A1, ... An, ELSE)
4434 is equivalent to the C expression:
4436 LHS = COND ? FN (A1, ..., An) : ELSE;
4438 operating elementwise if the operands are vectors.
4440 Return IFN_LAST if no such function exists. */
4442 internal_fn
4443 get_conditional_internal_fn (internal_fn fn)
4445 switch (fn)
4447 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
4448 FOR_EACH_COND_FN_PAIR(CASE)
4449 #undef CASE
4450 default:
4451 return IFN_LAST;
4455 /* If there exists an internal function like IFN that operates on vectors,
4456 but with additional length and bias parameters, return the internal_fn
4457 for that function, otherwise return IFN_LAST. */
4458 internal_fn
4459 get_len_internal_fn (internal_fn fn)
4461 switch (fn)
4463 #undef DEF_INTERNAL_COND_FN
4464 #undef DEF_INTERNAL_SIGNED_COND_FN
4465 #define DEF_INTERNAL_COND_FN(NAME, ...) \
4466 case IFN_COND_##NAME: \
4467 return IFN_COND_LEN_##NAME;
4468 #define DEF_INTERNAL_SIGNED_COND_FN(NAME, ...) \
4469 case IFN_COND_##NAME: \
4470 return IFN_COND_LEN_##NAME;
4471 #include "internal-fn.def"
4472 #undef DEF_INTERNAL_COND_FN
4473 #undef DEF_INTERNAL_SIGNED_COND_FN
4474 default:
4475 return IFN_LAST;
4479 /* If IFN implements the conditional form of an unconditional internal
4480 function, return that unconditional function, otherwise return IFN_LAST. */
4482 internal_fn
4483 get_unconditional_internal_fn (internal_fn ifn)
4485 switch (ifn)
4487 #define CASE(NAME) \
4488 case IFN_COND_##NAME: \
4489 case IFN_COND_LEN_##NAME: \
4490 return IFN_##NAME;
4491 FOR_EACH_COND_FN_PAIR (CASE)
4492 #undef CASE
4493 default:
4494 return IFN_LAST;
4498 /* Return true if STMT can be interpreted as a conditional tree code
4499 operation of the form:
4501 LHS = COND ? OP (RHS1, ...) : ELSE;
4503 operating elementwise if the operands are vectors. This includes
4504 the case of an all-true COND, so that the operation always happens.
4506 There is an alternative approach to interpret the STMT when the operands
4507 are vectors which is the operation predicated by both conditional mask
4508 and loop control length, the equivalent C code:
4510 for (int i = 0; i < NUNTIS; i++)
4512 if (i < LEN + BIAS && COND[i])
4513 LHS[i] = A[i] CODE B[i];
4514 else
4515 LHS[i] = ELSE[i];
4518 When returning true, set:
4520 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
4521 is known to be all-true
4522 - *CODE_OUT to the tree code
4523 - OPS[I] to operand I of *CODE_OUT
4524 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
4525 condition is known to be all true.
4526 - *LEN to the len argument if it COND_LEN_* operations or to NULL_TREE.
4527 - *BIAS to the bias argument if it COND_LEN_* operations or to NULL_TREE. */
4529 bool
4530 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
4531 tree_code *code_out,
4532 tree (&ops)[3], tree *else_out,
4533 tree *len, tree *bias)
4535 *len = NULL_TREE;
4536 *bias = NULL_TREE;
4537 if (gassign *assign = dyn_cast <gassign *> (stmt))
4539 *cond_out = NULL_TREE;
4540 *code_out = gimple_assign_rhs_code (assign);
4541 ops[0] = gimple_assign_rhs1 (assign);
4542 ops[1] = gimple_assign_rhs2 (assign);
4543 ops[2] = gimple_assign_rhs3 (assign);
4544 *else_out = NULL_TREE;
4545 return true;
4547 if (gcall *call = dyn_cast <gcall *> (stmt))
4548 if (gimple_call_internal_p (call))
4550 internal_fn ifn = gimple_call_internal_fn (call);
4551 tree_code code = conditional_internal_fn_code (ifn);
4552 int len_index = internal_fn_len_index (ifn);
4553 int cond_nargs = len_index >= 0 ? 4 : 2;
4554 if (code != ERROR_MARK)
4556 *cond_out = gimple_call_arg (call, 0);
4557 *code_out = code;
4558 unsigned int nops = gimple_call_num_args (call) - cond_nargs;
4559 for (unsigned int i = 0; i < 3; ++i)
4560 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
4561 *else_out = gimple_call_arg (call, nops + 1);
4562 if (len_index < 0)
4564 if (integer_truep (*cond_out))
4566 *cond_out = NULL_TREE;
4567 *else_out = NULL_TREE;
4570 else
4572 *len = gimple_call_arg (call, len_index);
4573 *bias = gimple_call_arg (call, len_index + 1);
4575 return true;
4578 return false;
4581 /* Return true if IFN is some form of load from memory. */
4583 bool
4584 internal_load_fn_p (internal_fn fn)
4586 switch (fn)
4588 case IFN_MASK_LOAD:
4589 case IFN_LOAD_LANES:
4590 case IFN_MASK_LOAD_LANES:
4591 case IFN_MASK_LEN_LOAD_LANES:
4592 case IFN_GATHER_LOAD:
4593 case IFN_MASK_GATHER_LOAD:
4594 case IFN_MASK_LEN_GATHER_LOAD:
4595 case IFN_LEN_LOAD:
4596 case IFN_MASK_LEN_LOAD:
4597 return true;
4599 default:
4600 return false;
4604 /* Return true if IFN is some form of store to memory. */
4606 bool
4607 internal_store_fn_p (internal_fn fn)
4609 switch (fn)
4611 case IFN_MASK_STORE:
4612 case IFN_STORE_LANES:
4613 case IFN_MASK_STORE_LANES:
4614 case IFN_MASK_LEN_STORE_LANES:
4615 case IFN_SCATTER_STORE:
4616 case IFN_MASK_SCATTER_STORE:
4617 case IFN_MASK_LEN_SCATTER_STORE:
4618 case IFN_LEN_STORE:
4619 case IFN_MASK_LEN_STORE:
4620 return true;
4622 default:
4623 return false;
4627 /* Return true if IFN is some form of gather load or scatter store. */
4629 bool
4630 internal_gather_scatter_fn_p (internal_fn fn)
4632 switch (fn)
4634 case IFN_GATHER_LOAD:
4635 case IFN_MASK_GATHER_LOAD:
4636 case IFN_MASK_LEN_GATHER_LOAD:
4637 case IFN_SCATTER_STORE:
4638 case IFN_MASK_SCATTER_STORE:
4639 case IFN_MASK_LEN_SCATTER_STORE:
4640 return true;
4642 default:
4643 return false;
4647 /* If FN takes a vector len argument, return the index of that argument,
4648 otherwise return -1. */
4651 internal_fn_len_index (internal_fn fn)
4653 switch (fn)
4655 case IFN_LEN_LOAD:
4656 case IFN_LEN_STORE:
4657 return 2;
4659 case IFN_MASK_LEN_GATHER_LOAD:
4660 case IFN_MASK_LEN_SCATTER_STORE:
4661 case IFN_COND_LEN_FMA:
4662 case IFN_COND_LEN_FMS:
4663 case IFN_COND_LEN_FNMA:
4664 case IFN_COND_LEN_FNMS:
4665 return 5;
4667 case IFN_COND_LEN_ADD:
4668 case IFN_COND_LEN_SUB:
4669 case IFN_COND_LEN_MUL:
4670 case IFN_COND_LEN_DIV:
4671 case IFN_COND_LEN_MOD:
4672 case IFN_COND_LEN_RDIV:
4673 case IFN_COND_LEN_MIN:
4674 case IFN_COND_LEN_MAX:
4675 case IFN_COND_LEN_FMIN:
4676 case IFN_COND_LEN_FMAX:
4677 case IFN_COND_LEN_AND:
4678 case IFN_COND_LEN_IOR:
4679 case IFN_COND_LEN_XOR:
4680 case IFN_COND_LEN_SHL:
4681 case IFN_COND_LEN_SHR:
4682 return 4;
4684 case IFN_COND_LEN_NEG:
4685 case IFN_MASK_LEN_LOAD:
4686 case IFN_MASK_LEN_STORE:
4687 case IFN_MASK_LEN_LOAD_LANES:
4688 case IFN_MASK_LEN_STORE_LANES:
4689 return 3;
4691 default:
4692 return -1;
4696 /* If FN takes a vector mask argument, return the index of that argument,
4697 otherwise return -1. */
4700 internal_fn_mask_index (internal_fn fn)
4702 switch (fn)
4704 case IFN_MASK_LOAD:
4705 case IFN_MASK_LOAD_LANES:
4706 case IFN_MASK_LEN_LOAD_LANES:
4707 case IFN_MASK_STORE:
4708 case IFN_MASK_STORE_LANES:
4709 case IFN_MASK_LEN_STORE_LANES:
4710 case IFN_MASK_LEN_LOAD:
4711 case IFN_MASK_LEN_STORE:
4712 return 2;
4714 case IFN_MASK_GATHER_LOAD:
4715 case IFN_MASK_SCATTER_STORE:
4716 case IFN_MASK_LEN_GATHER_LOAD:
4717 case IFN_MASK_LEN_SCATTER_STORE:
4718 return 4;
4720 default:
4721 return (conditional_internal_fn_code (fn) != ERROR_MARK
4722 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
4726 /* If FN takes a value that should be stored to memory, return the index
4727 of that argument, otherwise return -1. */
4730 internal_fn_stored_value_index (internal_fn fn)
4732 switch (fn)
4734 case IFN_MASK_STORE:
4735 case IFN_MASK_STORE_LANES:
4736 case IFN_SCATTER_STORE:
4737 case IFN_MASK_SCATTER_STORE:
4738 case IFN_MASK_LEN_SCATTER_STORE:
4739 return 3;
4741 case IFN_LEN_STORE:
4742 return 4;
4744 case IFN_MASK_LEN_STORE:
4745 case IFN_MASK_LEN_STORE_LANES:
4746 return 5;
4748 default:
4749 return -1;
4753 /* Return true if the target supports gather load or scatter store function
4754 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
4755 while for stores it is the vector type of the stored data argument.
4756 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
4757 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
4758 offset from the shared base address of each loaded or stored element.
4759 SCALE is the amount by which these offsets should be multiplied
4760 *after* they have been extended to address width. */
4762 bool
4763 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
4764 tree memory_element_type,
4765 tree offset_vector_type, int scale)
4767 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
4768 TYPE_SIZE (memory_element_type)))
4769 return false;
4770 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
4771 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
4772 return false;
4773 optab optab = direct_internal_fn_optab (ifn);
4774 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
4775 TYPE_MODE (offset_vector_type));
4776 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
4777 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
4778 return (icode != CODE_FOR_nothing
4779 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
4780 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
4783 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
4784 for pointers of type TYPE when the accesses have LENGTH bytes and their
4785 common byte alignment is ALIGN. */
4787 bool
4788 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
4789 poly_uint64 length, unsigned int align)
4791 machine_mode mode = TYPE_MODE (type);
4792 optab optab = direct_internal_fn_optab (ifn);
4793 insn_code icode = direct_optab_handler (optab, mode);
4794 if (icode == CODE_FOR_nothing)
4795 return false;
4796 rtx length_rtx = immed_wide_int_const (length, mode);
4797 return (insn_operand_matches (icode, 3, length_rtx)
4798 && insn_operand_matches (icode, 4, GEN_INT (align)));
4801 /* Return the supported bias for IFN which is either IFN_{LEN_,MASK_LEN_,}LOAD
4802 or IFN_{LEN_,MASK_LEN_,}STORE. For now we only support the biases of 0 and
4803 -1 (in case 0 is not an allowable length for {len_,mask_len_}load or
4804 {len_,mask_len_}store). If none of the biases match what the backend
4805 provides, return VECT_PARTIAL_BIAS_UNSUPPORTED. */
4807 signed char
4808 internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
4810 optab optab = direct_internal_fn_optab (ifn);
4811 insn_code icode = direct_optab_handler (optab, mode);
4812 int bias_no = 3;
4814 if (icode == CODE_FOR_nothing)
4816 machine_mode mask_mode;
4817 if (!targetm.vectorize.get_mask_mode (mode).exists (&mask_mode))
4818 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4819 if (ifn == IFN_LEN_LOAD)
4821 /* Try MASK_LEN_LOAD. */
4822 optab = direct_internal_fn_optab (IFN_MASK_LEN_LOAD);
4824 else
4826 /* Try MASK_LEN_STORE. */
4827 optab = direct_internal_fn_optab (IFN_MASK_LEN_STORE);
4829 icode = convert_optab_handler (optab, mode, mask_mode);
4830 bias_no = 4;
4833 if (icode != CODE_FOR_nothing)
4835 /* For now we only support biases of 0 or -1. Try both of them. */
4836 if (insn_operand_matches (icode, bias_no, GEN_INT (0)))
4837 return 0;
4838 if (insn_operand_matches (icode, bias_no, GEN_INT (-1)))
4839 return -1;
4842 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4845 /* Expand STMT as though it were a call to internal function FN. */
4847 void
4848 expand_internal_call (internal_fn fn, gcall *stmt)
4850 internal_fn_expanders[fn] (fn, stmt);
4853 /* Expand STMT, which is a call to internal function FN. */
4855 void
4856 expand_internal_call (gcall *stmt)
4858 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
4861 /* If TYPE is a vector type, return true if IFN is a direct internal
4862 function that is supported for that type. If TYPE is a scalar type,
4863 return true if IFN is a direct internal function that is supported for
4864 the target's preferred vector version of TYPE. */
4866 bool
4867 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
4869 if (VECTOR_MODE_P (TYPE_MODE (type)))
4870 return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
4872 scalar_mode smode;
4873 if (VECTOR_TYPE_P (type)
4874 || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
4875 return false;
4877 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
4878 if (VECTOR_MODE_P (vmode))
4880 tree vectype = build_vector_type_for_mode (type, vmode);
4881 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4882 return true;
4885 auto_vector_modes vector_modes;
4886 targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
4887 for (machine_mode base_mode : vector_modes)
4888 if (related_vector_mode (base_mode, smode).exists (&vmode))
4890 tree vectype = build_vector_type_for_mode (type, vmode);
4891 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4892 return true;
4895 return false;
4898 void
4899 expand_SHUFFLEVECTOR (internal_fn, gcall *)
4901 gcc_unreachable ();
4904 void
4905 expand_PHI (internal_fn, gcall *)
4907 gcc_unreachable ();
4910 void
4911 expand_SPACESHIP (internal_fn, gcall *stmt)
4913 tree lhs = gimple_call_lhs (stmt);
4914 tree rhs1 = gimple_call_arg (stmt, 0);
4915 tree rhs2 = gimple_call_arg (stmt, 1);
4916 tree type = TREE_TYPE (rhs1);
4918 do_pending_stack_adjust ();
4920 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
4921 rtx op1 = expand_normal (rhs1);
4922 rtx op2 = expand_normal (rhs2);
4924 class expand_operand ops[3];
4925 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
4926 create_input_operand (&ops[1], op1, TYPE_MODE (type));
4927 create_input_operand (&ops[2], op2, TYPE_MODE (type));
4928 insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
4929 expand_insn (icode, 3, ops);
4930 if (!rtx_equal_p (target, ops[0].value))
4931 emit_move_insn (target, ops[0].value);
4934 void
4935 expand_ASSUME (internal_fn, gcall *)
4939 void
4940 expand_MASK_CALL (internal_fn, gcall *)
4942 /* This IFN should only exist between ifcvt and vect passes. */
4943 gcc_unreachable ();
4946 void
4947 expand_MULBITINT (internal_fn, gcall *stmt)
4949 rtx_mode_t args[6];
4950 for (int i = 0; i < 6; i++)
4951 args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
4952 (i & 1) ? SImode : ptr_mode);
4953 rtx fun = init_one_libfunc ("__mulbitint3");
4954 emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 6, args);
4957 void
4958 expand_DIVMODBITINT (internal_fn, gcall *stmt)
4960 rtx_mode_t args[8];
4961 for (int i = 0; i < 8; i++)
4962 args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
4963 (i & 1) ? SImode : ptr_mode);
4964 rtx fun = init_one_libfunc ("__divmodbitint4");
4965 emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 8, args);
4968 void
4969 expand_FLOATTOBITINT (internal_fn, gcall *stmt)
4971 machine_mode mode = TYPE_MODE (TREE_TYPE (gimple_call_arg (stmt, 2)));
4972 rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
4973 rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
4974 rtx arg2 = expand_normal (gimple_call_arg (stmt, 2));
4975 const char *mname = GET_MODE_NAME (mode);
4976 unsigned mname_len = strlen (mname);
4977 int len = 12 + mname_len;
4978 if (DECIMAL_FLOAT_MODE_P (mode))
4979 len += 4;
4980 char *libfunc_name = XALLOCAVEC (char, len);
4981 char *p = libfunc_name;
4982 const char *q;
4983 if (DECIMAL_FLOAT_MODE_P (mode))
4985 #if ENABLE_DECIMAL_BID_FORMAT
4986 memcpy (p, "__bid_fix", 9);
4987 #else
4988 memcpy (p, "__dpd_fix", 9);
4989 #endif
4990 p += 9;
4992 else
4994 memcpy (p, "__fix", 5);
4995 p += 5;
4997 for (q = mname; *q; q++)
4998 *p++ = TOLOWER (*q);
4999 memcpy (p, "bitint", 7);
5000 rtx fun = init_one_libfunc (libfunc_name);
5001 emit_library_call (fun, LCT_NORMAL, VOIDmode, arg0, ptr_mode, arg1,
5002 SImode, arg2, mode);
5005 void
5006 expand_BITINTTOFLOAT (internal_fn, gcall *stmt)
5008 tree lhs = gimple_call_lhs (stmt);
5009 if (!lhs)
5010 return;
5011 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
5012 rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
5013 rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
5014 const char *mname = GET_MODE_NAME (mode);
5015 unsigned mname_len = strlen (mname);
5016 int len = 14 + mname_len;
5017 if (DECIMAL_FLOAT_MODE_P (mode))
5018 len += 4;
5019 char *libfunc_name = XALLOCAVEC (char, len);
5020 char *p = libfunc_name;
5021 const char *q;
5022 if (DECIMAL_FLOAT_MODE_P (mode))
5024 #if ENABLE_DECIMAL_BID_FORMAT
5025 memcpy (p, "__bid_floatbitint", 17);
5026 #else
5027 memcpy (p, "__dpd_floatbitint", 17);
5028 #endif
5029 p += 17;
5031 else
5033 memcpy (p, "__floatbitint", 13);
5034 p += 13;
5036 for (q = mname; *q; q++)
5037 *p++ = TOLOWER (*q);
5038 *p = '\0';
5039 rtx fun = init_one_libfunc (libfunc_name);
5040 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
5041 rtx val = emit_library_call_value (fun, target, LCT_PURE, mode,
5042 arg0, ptr_mode, arg1, SImode);
5043 if (val != target)
5044 emit_move_insn (target, val);