tree-optimization/114485 - neg induction with partial vectors
[official-gcc.git] / gcc / internal-fn.cc
blob5269f0ac528e420d543eb4855719634aad71b5ba
1 /* Internal functions.
2 Copyright (C) 2011-2024 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"
55 #include "fold-const-call.h"
57 /* For lang_hooks.types.type_for_mode. */
58 #include "langhooks.h"
60 /* The names of each internal function, indexed by function number. */
61 const char *const internal_fn_name_array[] = {
62 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
63 #include "internal-fn.def"
64 "<invalid-fn>"
67 /* The ECF_* flags of each internal function, indexed by function number. */
68 const int internal_fn_flags_array[] = {
69 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
70 #include "internal-fn.def"
74 /* Return the internal function called NAME, or IFN_LAST if there's
75 no such function. */
77 internal_fn
78 lookup_internal_fn (const char *name)
80 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
81 static name_to_fn_map_type *name_to_fn_map;
83 if (!name_to_fn_map)
85 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
86 for (unsigned int i = 0; i < IFN_LAST; ++i)
87 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
88 internal_fn (i));
90 internal_fn *entry = name_to_fn_map->get (name);
91 return entry ? *entry : IFN_LAST;
94 /* Geven an internal_fn IFN that is a widening function, return its
95 corresponding LO and HI internal_fns. */
97 extern void
98 lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi)
100 gcc_assert (widening_fn_p (ifn));
102 switch (ifn)
104 default:
105 gcc_unreachable ();
106 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
107 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
108 case IFN_##NAME: \
109 *lo = internal_fn (IFN_##NAME##_LO); \
110 *hi = internal_fn (IFN_##NAME##_HI); \
111 break;
112 #include "internal-fn.def"
116 /* Given an internal_fn IFN that is a widening function, return its
117 corresponding _EVEN and _ODD internal_fns in *EVEN and *ODD. */
119 extern void
120 lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even,
121 internal_fn *odd)
123 gcc_assert (widening_fn_p (ifn));
125 switch (ifn)
127 default:
128 gcc_unreachable ();
129 #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
130 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
131 case IFN_##NAME: \
132 *even = internal_fn (IFN_##NAME##_EVEN); \
133 *odd = internal_fn (IFN_##NAME##_ODD); \
134 break;
135 #include "internal-fn.def"
140 /* Fnspec of each internal function, indexed by function number. */
141 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
143 void
144 init_internal_fns ()
146 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
147 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
148 build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
149 #include "internal-fn.def"
150 internal_fn_fnspec_array[IFN_LAST] = 0;
153 /* Create static initializers for the information returned by
154 direct_internal_fn. */
155 #define not_direct { -2, -2, false }
156 #define mask_load_direct { -1, 2, false }
157 #define load_lanes_direct { -1, -1, false }
158 #define mask_load_lanes_direct { -1, -1, false }
159 #define gather_load_direct { 3, 1, false }
160 #define len_load_direct { -1, -1, false }
161 #define mask_len_load_direct { -1, 4, false }
162 #define mask_store_direct { 3, 2, false }
163 #define store_lanes_direct { 0, 0, false }
164 #define mask_store_lanes_direct { 0, 0, false }
165 #define vec_cond_mask_direct { 1, 0, false }
166 #define vec_cond_mask_len_direct { 1, 1, false }
167 #define vec_cond_direct { 2, 0, false }
168 #define scatter_store_direct { 3, 1, false }
169 #define len_store_direct { 3, 3, false }
170 #define mask_len_store_direct { 4, 5, false }
171 #define vec_set_direct { 3, 3, false }
172 #define vec_extract_direct { 0, -1, false }
173 #define unary_direct { 0, 0, true }
174 #define unary_convert_direct { -1, 0, true }
175 #define binary_direct { 0, 0, true }
176 #define ternary_direct { 0, 0, true }
177 #define cond_unary_direct { 1, 1, true }
178 #define cond_binary_direct { 1, 1, true }
179 #define cond_ternary_direct { 1, 1, true }
180 #define cond_len_unary_direct { 1, 1, true }
181 #define cond_len_binary_direct { 1, 1, true }
182 #define cond_len_ternary_direct { 1, 1, true }
183 #define while_direct { 0, 2, false }
184 #define fold_extract_direct { 2, 2, false }
185 #define fold_len_extract_direct { 2, 2, false }
186 #define fold_left_direct { 1, 1, false }
187 #define mask_fold_left_direct { 1, 1, false }
188 #define mask_len_fold_left_direct { 1, 1, false }
189 #define check_ptrs_direct { 0, 0, false }
191 const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
192 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
193 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
194 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
195 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
196 #include "internal-fn.def"
197 not_direct
200 /* Expand STMT using instruction ICODE. The instruction has NOUTPUTS
201 output operands and NINPUTS input operands, where NOUTPUTS is either
202 0 or 1. The output operand (if any) comes first, followed by the
203 NINPUTS input operands. */
205 static void
206 expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
207 unsigned int ninputs)
209 gcc_assert (icode != CODE_FOR_nothing);
211 expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
212 unsigned int opno = 0;
213 rtx lhs_rtx = NULL_RTX;
214 tree lhs = gimple_call_lhs (stmt);
216 if (noutputs)
218 gcc_assert (noutputs == 1);
219 if (lhs)
220 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
222 /* Do not assign directly to a promoted subreg, since there is no
223 guarantee that the instruction will leave the upper bits of the
224 register in the state required by SUBREG_PROMOTED_SIGN. */
225 rtx dest = lhs_rtx;
226 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
227 dest = NULL_RTX;
228 create_output_operand (&ops[opno], dest,
229 insn_data[icode].operand[opno].mode);
230 opno += 1;
232 else
233 gcc_assert (!lhs);
235 for (unsigned int i = 0; i < ninputs; ++i)
237 tree rhs = gimple_call_arg (stmt, i);
238 tree rhs_type = TREE_TYPE (rhs);
239 rtx rhs_rtx = expand_normal (rhs);
240 if (INTEGRAL_TYPE_P (rhs_type))
241 create_convert_operand_from (&ops[opno], rhs_rtx,
242 TYPE_MODE (rhs_type),
243 TYPE_UNSIGNED (rhs_type));
244 else if (TREE_CODE (rhs) == SSA_NAME
245 && SSA_NAME_IS_DEFAULT_DEF (rhs)
246 && VAR_P (SSA_NAME_VAR (rhs)))
247 create_undefined_input_operand (&ops[opno], TYPE_MODE (rhs_type));
248 else if (VECTOR_BOOLEAN_TYPE_P (rhs_type)
249 && SCALAR_INT_MODE_P (TYPE_MODE (rhs_type))
250 && maybe_ne (GET_MODE_PRECISION (TYPE_MODE (rhs_type)),
251 TYPE_VECTOR_SUBPARTS (rhs_type).to_constant ()))
253 /* Ensure that the vector bitmasks do not have excess bits. */
254 int nunits = TYPE_VECTOR_SUBPARTS (rhs_type).to_constant ();
255 rtx tmp = expand_binop (TYPE_MODE (rhs_type), and_optab, rhs_rtx,
256 GEN_INT ((HOST_WIDE_INT_1U << nunits) - 1),
257 NULL_RTX, true, OPTAB_WIDEN);
258 create_input_operand (&ops[opno], tmp, TYPE_MODE (rhs_type));
260 else
261 create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
262 opno += 1;
265 gcc_assert (opno == noutputs + ninputs);
266 expand_insn (icode, opno, ops);
267 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
269 /* If the return value has an integral type, convert the instruction
270 result to that type. This is useful for things that return an
271 int regardless of the size of the input. If the instruction result
272 is smaller than required, assume that it is signed.
274 If the return value has a nonintegral type, its mode must match
275 the instruction result. */
276 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
278 /* If this is a scalar in a register that is stored in a wider
279 mode than the declared mode, compute the result into its
280 declared mode and then convert to the wider mode. */
281 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
282 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
283 convert_move (SUBREG_REG (lhs_rtx), tmp,
284 SUBREG_PROMOTED_SIGN (lhs_rtx));
286 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
287 emit_move_insn (lhs_rtx, ops[0].value);
288 else
290 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
291 convert_move (lhs_rtx, ops[0].value, 0);
296 /* ARRAY_TYPE is an array of vector modes. Return the associated insn
297 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
299 static enum insn_code
300 get_multi_vector_move (tree array_type, convert_optab optab)
302 machine_mode imode;
303 machine_mode vmode;
305 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
306 imode = TYPE_MODE (array_type);
307 vmode = TYPE_MODE (TREE_TYPE (array_type));
309 return convert_optab_handler (optab, imode, vmode);
312 /* Add mask and len arguments according to the STMT. */
314 static unsigned int
315 add_mask_and_len_args (expand_operand *ops, unsigned int opno, gcall *stmt)
317 internal_fn ifn = gimple_call_internal_fn (stmt);
318 int len_index = internal_fn_len_index (ifn);
319 /* BIAS is always consecutive next of LEN. */
320 int bias_index = len_index + 1;
321 int mask_index = internal_fn_mask_index (ifn);
322 /* The order of arguments are always {len,bias,mask}. */
323 if (mask_index >= 0)
325 tree mask = gimple_call_arg (stmt, mask_index);
326 rtx mask_rtx = expand_normal (mask);
328 tree mask_type = TREE_TYPE (mask);
329 if (VECTOR_BOOLEAN_TYPE_P (mask_type)
330 && SCALAR_INT_MODE_P (TYPE_MODE (mask_type))
331 && maybe_ne (GET_MODE_PRECISION (TYPE_MODE (mask_type)),
332 TYPE_VECTOR_SUBPARTS (mask_type).to_constant ()))
334 /* Ensure that the vector bitmasks do not have excess bits. */
335 int nunits = TYPE_VECTOR_SUBPARTS (mask_type).to_constant ();
336 mask_rtx = expand_binop (TYPE_MODE (mask_type), and_optab, mask_rtx,
337 GEN_INT ((HOST_WIDE_INT_1U << nunits) - 1),
338 NULL_RTX, true, OPTAB_WIDEN);
341 create_input_operand (&ops[opno++], mask_rtx,
342 TYPE_MODE (TREE_TYPE (mask)));
344 if (len_index >= 0)
346 tree len = gimple_call_arg (stmt, len_index);
347 rtx len_rtx = expand_normal (len);
348 create_convert_operand_from (&ops[opno++], len_rtx,
349 TYPE_MODE (TREE_TYPE (len)),
350 TYPE_UNSIGNED (TREE_TYPE (len)));
351 tree biast = gimple_call_arg (stmt, bias_index);
352 rtx bias = expand_normal (biast);
353 create_input_operand (&ops[opno++], bias, QImode);
355 return opno;
358 /* Expand LOAD_LANES call STMT using optab OPTAB. */
360 static void
361 expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
363 class expand_operand ops[2];
364 tree type, lhs, rhs;
365 rtx target, mem;
367 lhs = gimple_call_lhs (stmt);
368 rhs = gimple_call_arg (stmt, 0);
369 type = TREE_TYPE (lhs);
371 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
372 mem = expand_normal (rhs);
374 gcc_assert (MEM_P (mem));
375 PUT_MODE (mem, TYPE_MODE (type));
377 create_output_operand (&ops[0], target, TYPE_MODE (type));
378 create_fixed_operand (&ops[1], mem);
379 expand_insn (get_multi_vector_move (type, optab), 2, ops);
380 if (!rtx_equal_p (target, ops[0].value))
381 emit_move_insn (target, ops[0].value);
384 /* Expand STORE_LANES call STMT using optab OPTAB. */
386 static void
387 expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
389 class expand_operand ops[2];
390 tree type, lhs, rhs;
391 rtx target, reg;
393 lhs = gimple_call_lhs (stmt);
394 rhs = gimple_call_arg (stmt, 0);
395 type = TREE_TYPE (rhs);
397 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
398 reg = expand_normal (rhs);
400 gcc_assert (MEM_P (target));
401 PUT_MODE (target, TYPE_MODE (type));
403 create_fixed_operand (&ops[0], target);
404 create_input_operand (&ops[1], reg, TYPE_MODE (type));
405 expand_insn (get_multi_vector_move (type, optab), 2, ops);
408 static void
409 expand_ANNOTATE (internal_fn, gcall *)
411 gcc_unreachable ();
414 /* This should get expanded in omp_device_lower pass. */
416 static void
417 expand_GOMP_USE_SIMT (internal_fn, gcall *)
419 gcc_unreachable ();
422 /* This should get expanded in omp_device_lower pass. */
424 static void
425 expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
427 gcc_unreachable ();
430 /* Allocate per-lane storage and begin non-uniform execution region. */
432 static void
433 expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
435 rtx target;
436 tree lhs = gimple_call_lhs (stmt);
437 if (lhs)
438 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
439 else
440 target = gen_reg_rtx (Pmode);
441 rtx size = expand_normal (gimple_call_arg (stmt, 0));
442 rtx align = expand_normal (gimple_call_arg (stmt, 1));
443 class expand_operand ops[3];
444 create_output_operand (&ops[0], target, Pmode);
445 create_input_operand (&ops[1], size, Pmode);
446 create_input_operand (&ops[2], align, Pmode);
447 gcc_assert (targetm.have_omp_simt_enter ());
448 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
449 if (!rtx_equal_p (target, ops[0].value))
450 emit_move_insn (target, ops[0].value);
453 /* Deallocate per-lane storage and leave non-uniform execution region. */
455 static void
456 expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
458 gcc_checking_assert (!gimple_call_lhs (stmt));
459 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
460 class expand_operand ops[1];
461 create_input_operand (&ops[0], arg, Pmode);
462 gcc_assert (targetm.have_omp_simt_exit ());
463 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
466 /* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
467 without SIMT execution this should be expanded in omp_device_lower pass. */
469 static void
470 expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
472 tree lhs = gimple_call_lhs (stmt);
473 if (!lhs)
474 return;
476 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
477 gcc_assert (targetm.have_omp_simt_lane ());
478 emit_insn (targetm.gen_omp_simt_lane (target));
481 /* This should get expanded in omp_device_lower pass. */
483 static void
484 expand_GOMP_SIMT_VF (internal_fn, gcall *)
486 gcc_unreachable ();
489 /* This should get expanded in omp_device_lower pass. */
491 static void
492 expand_GOMP_TARGET_REV (internal_fn, gcall *)
494 gcc_unreachable ();
497 /* Lane index of the first SIMT lane that supplies a non-zero argument.
498 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
499 lane that executed the last iteration for handling OpenMP lastprivate. */
501 static void
502 expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
504 tree lhs = gimple_call_lhs (stmt);
505 if (!lhs)
506 return;
508 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
509 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
510 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
511 class expand_operand ops[2];
512 create_output_operand (&ops[0], target, mode);
513 create_input_operand (&ops[1], cond, mode);
514 gcc_assert (targetm.have_omp_simt_last_lane ());
515 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
516 if (!rtx_equal_p (target, ops[0].value))
517 emit_move_insn (target, ops[0].value);
520 /* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
522 static void
523 expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
525 tree lhs = gimple_call_lhs (stmt);
526 if (!lhs)
527 return;
529 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
530 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
531 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
532 class expand_operand ops[2];
533 create_output_operand (&ops[0], target, mode);
534 create_input_operand (&ops[1], ctr, mode);
535 gcc_assert (targetm.have_omp_simt_ordered ());
536 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
537 if (!rtx_equal_p (target, ops[0].value))
538 emit_move_insn (target, ops[0].value);
541 /* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
542 any lane supplies a non-zero argument. */
544 static void
545 expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
547 tree lhs = gimple_call_lhs (stmt);
548 if (!lhs)
549 return;
551 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
552 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
553 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
554 class expand_operand ops[2];
555 create_output_operand (&ops[0], target, mode);
556 create_input_operand (&ops[1], cond, mode);
557 gcc_assert (targetm.have_omp_simt_vote_any ());
558 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
559 if (!rtx_equal_p (target, ops[0].value))
560 emit_move_insn (target, ops[0].value);
563 /* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
564 is destination lane index XOR given offset. */
566 static void
567 expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
569 tree lhs = gimple_call_lhs (stmt);
570 if (!lhs)
571 return;
573 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
574 rtx src = expand_normal (gimple_call_arg (stmt, 0));
575 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
576 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
577 class expand_operand ops[3];
578 create_output_operand (&ops[0], target, mode);
579 create_input_operand (&ops[1], src, mode);
580 create_input_operand (&ops[2], idx, SImode);
581 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
582 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
583 if (!rtx_equal_p (target, ops[0].value))
584 emit_move_insn (target, ops[0].value);
587 /* Exchange between SIMT lanes according to given source lane index. */
589 static void
590 expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
592 tree lhs = gimple_call_lhs (stmt);
593 if (!lhs)
594 return;
596 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
597 rtx src = expand_normal (gimple_call_arg (stmt, 0));
598 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
599 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
600 class expand_operand ops[3];
601 create_output_operand (&ops[0], target, mode);
602 create_input_operand (&ops[1], src, mode);
603 create_input_operand (&ops[2], idx, SImode);
604 gcc_assert (targetm.have_omp_simt_xchg_idx ());
605 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
606 if (!rtx_equal_p (target, ops[0].value))
607 emit_move_insn (target, ops[0].value);
610 /* This should get expanded in adjust_simduid_builtins. */
612 static void
613 expand_GOMP_SIMD_LANE (internal_fn, gcall *)
615 gcc_unreachable ();
618 /* This should get expanded in adjust_simduid_builtins. */
620 static void
621 expand_GOMP_SIMD_VF (internal_fn, gcall *)
623 gcc_unreachable ();
626 /* This should get expanded in adjust_simduid_builtins. */
628 static void
629 expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
631 gcc_unreachable ();
634 /* This should get expanded in adjust_simduid_builtins. */
636 static void
637 expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
639 gcc_unreachable ();
642 /* This should get expanded in adjust_simduid_builtins. */
644 static void
645 expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
647 gcc_unreachable ();
650 /* This should get expanded in the sanopt pass. */
652 static void
653 expand_UBSAN_NULL (internal_fn, gcall *)
655 gcc_unreachable ();
658 /* This should get expanded in the sanopt pass. */
660 static void
661 expand_UBSAN_BOUNDS (internal_fn, gcall *)
663 gcc_unreachable ();
666 /* This should get expanded in the sanopt pass. */
668 static void
669 expand_UBSAN_VPTR (internal_fn, gcall *)
671 gcc_unreachable ();
674 /* This should get expanded in the sanopt pass. */
676 static void
677 expand_UBSAN_PTR (internal_fn, gcall *)
679 gcc_unreachable ();
682 /* This should get expanded in the sanopt pass. */
684 static void
685 expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
687 gcc_unreachable ();
690 /* This should get expanded in the sanopt pass. */
692 static void
693 expand_HWASAN_CHECK (internal_fn, gcall *)
695 gcc_unreachable ();
698 /* For hwasan stack tagging:
699 Clear tags on the dynamically allocated space.
700 For use after an object dynamically allocated on the stack goes out of
701 scope. */
702 static void
703 expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
705 gcc_assert (Pmode == ptr_mode);
706 tree restored_position = gimple_call_arg (gc, 0);
707 rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
708 EXPAND_NORMAL);
709 rtx func = init_one_libfunc ("__hwasan_tag_memory");
710 rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
711 stack_pointer_rtx, NULL_RTX, 0,
712 OPTAB_WIDEN);
713 emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
714 virtual_stack_dynamic_rtx, Pmode,
715 HWASAN_STACK_BACKGROUND, QImode,
716 off, Pmode);
719 /* For hwasan stack tagging:
720 Return a tag to be used for a dynamic allocation. */
721 static void
722 expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
724 tree tag = gimple_call_lhs (gc);
725 rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
726 machine_mode mode = GET_MODE (target);
727 gcc_assert (mode == QImode);
729 rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
730 gcc_assert (base_tag);
731 rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
732 rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
733 target, /* unsignedp = */1,
734 OPTAB_WIDEN);
735 chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
737 /* Really need to put the tag into the `target` RTX. */
738 if (chosen_tag != target)
740 rtx temp = chosen_tag;
741 gcc_assert (GET_MODE (chosen_tag) == mode);
742 emit_move_insn (target, temp);
745 hwasan_increment_frame_tag ();
748 /* For hwasan stack tagging:
749 Tag a region of space in the shadow stack according to the base pointer of
750 an object on the stack. N.b. the length provided in the internal call is
751 required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
752 static void
753 expand_HWASAN_MARK (internal_fn, gcall *gc)
755 gcc_assert (ptr_mode == Pmode);
756 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
757 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
759 tree base = gimple_call_arg (gc, 1);
760 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
761 rtx base_rtx = expand_normal (base);
763 rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
764 : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
765 rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
767 tree len = gimple_call_arg (gc, 2);
768 rtx r_len = expand_normal (len);
770 rtx func = init_one_libfunc ("__hwasan_tag_memory");
771 emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
772 tag, QImode, r_len, Pmode);
775 /* For hwasan stack tagging:
776 Store a tag into a pointer. */
777 static void
778 expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
780 gcc_assert (ptr_mode == Pmode);
781 tree g_target = gimple_call_lhs (gc);
782 tree g_ptr = gimple_call_arg (gc, 0);
783 tree g_tag = gimple_call_arg (gc, 1);
785 rtx ptr = expand_normal (g_ptr);
786 rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
787 rtx target = expand_normal (g_target);
789 rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
790 rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
791 if (tagged_value != target)
792 emit_move_insn (target, tagged_value);
795 /* This should get expanded in the sanopt pass. */
797 static void
798 expand_ASAN_CHECK (internal_fn, gcall *)
800 gcc_unreachable ();
803 /* This should get expanded in the sanopt pass. */
805 static void
806 expand_ASAN_MARK (internal_fn, gcall *)
808 gcc_unreachable ();
811 /* This should get expanded in the sanopt pass. */
813 static void
814 expand_ASAN_POISON (internal_fn, gcall *)
816 gcc_unreachable ();
819 /* This should get expanded in the sanopt pass. */
821 static void
822 expand_ASAN_POISON_USE (internal_fn, gcall *)
824 gcc_unreachable ();
827 /* This should get expanded in the tsan pass. */
829 static void
830 expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
832 gcc_unreachable ();
835 /* This should get expanded in the lower pass. */
837 static void
838 expand_FALLTHROUGH (internal_fn, gcall *call)
840 error_at (gimple_location (call),
841 "invalid use of attribute %<fallthrough%>");
844 /* Return minimum precision needed to represent all values
845 of ARG in SIGNed integral type. */
847 static int
848 get_min_precision (tree arg, signop sign)
850 int prec = TYPE_PRECISION (TREE_TYPE (arg));
851 int cnt = 0;
852 signop orig_sign = sign;
853 if (TREE_CODE (arg) == INTEGER_CST)
855 int p;
856 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
858 widest_int w = wi::to_widest (arg);
859 w = wi::ext (w, prec, sign);
860 p = wi::min_precision (w, sign);
862 else
863 p = wi::min_precision (wi::to_wide (arg), sign);
864 return MIN (p, prec);
866 while (CONVERT_EXPR_P (arg)
867 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
868 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
870 arg = TREE_OPERAND (arg, 0);
871 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
873 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
874 sign = UNSIGNED;
875 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
876 return prec + (orig_sign != sign);
877 prec = TYPE_PRECISION (TREE_TYPE (arg));
879 if (++cnt > 30)
880 return prec + (orig_sign != sign);
882 if (CONVERT_EXPR_P (arg)
883 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
884 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
886 /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
887 If y_2's min precision is smaller than prec, return that. */
888 int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
889 if (oprec < prec)
890 return oprec + (orig_sign != sign);
892 if (TREE_CODE (arg) != SSA_NAME)
893 return prec + (orig_sign != sign);
894 value_range r;
895 while (!get_global_range_query ()->range_of_expr (r, arg)
896 || r.varying_p ()
897 || r.undefined_p ())
899 gimple *g = SSA_NAME_DEF_STMT (arg);
900 if (is_gimple_assign (g)
901 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
903 tree t = gimple_assign_rhs1 (g);
904 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
905 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
907 arg = t;
908 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
910 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
911 sign = UNSIGNED;
912 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
913 return prec + (orig_sign != sign);
914 prec = TYPE_PRECISION (TREE_TYPE (arg));
916 if (++cnt > 30)
917 return prec + (orig_sign != sign);
918 continue;
921 return prec + (orig_sign != sign);
923 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
925 int p1 = wi::min_precision (r.lower_bound (), sign);
926 int p2 = wi::min_precision (r.upper_bound (), sign);
927 p1 = MAX (p1, p2);
928 prec = MIN (prec, p1);
930 else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
932 int p = wi::min_precision (r.upper_bound (), UNSIGNED);
933 prec = MIN (prec, p);
935 return prec + (orig_sign != sign);
938 /* Helper for expand_*_overflow. Set the __imag__ part to true
939 (1 except for signed:1 type, in which case store -1). */
941 static void
942 expand_arith_set_overflow (tree lhs, rtx target)
944 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
945 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
946 write_complex_part (target, constm1_rtx, true, false);
947 else
948 write_complex_part (target, const1_rtx, true, false);
951 /* Helper for expand_*_overflow. Store RES into the __real__ part
952 of TARGET. If RES has larger MODE than __real__ part of TARGET,
953 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
954 if LHS has smaller precision than its mode. */
956 static void
957 expand_arith_overflow_result_store (tree lhs, rtx target,
958 scalar_int_mode mode, rtx res)
960 scalar_int_mode tgtmode
961 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
962 rtx lres = res;
963 if (tgtmode != mode)
965 rtx_code_label *done_label = gen_label_rtx ();
966 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
967 lres = convert_modes (tgtmode, mode, res, uns);
968 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
969 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
970 EQ, true, mode, NULL_RTX, NULL, done_label,
971 profile_probability::very_likely ());
972 expand_arith_set_overflow (lhs, target);
973 emit_label (done_label);
975 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
976 int tgtprec = GET_MODE_PRECISION (tgtmode);
977 if (prec < tgtprec)
979 rtx_code_label *done_label = gen_label_rtx ();
980 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
981 res = lres;
982 if (uns)
984 rtx mask
985 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
986 tgtmode);
987 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
988 true, OPTAB_LIB_WIDEN);
990 else
992 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
993 NULL_RTX, 1);
994 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
995 NULL_RTX, 0);
997 do_compare_rtx_and_jump (res, lres,
998 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
999 profile_probability::very_likely ());
1000 expand_arith_set_overflow (lhs, target);
1001 emit_label (done_label);
1003 write_complex_part (target, lres, false, false);
1006 /* Helper for expand_*_overflow. Store RES into TARGET. */
1008 static void
1009 expand_ubsan_result_store (tree lhs, rtx target, scalar_int_mode mode,
1010 rtx res, rtx_code_label *do_error)
1012 if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE
1013 && TYPE_PRECISION (TREE_TYPE (lhs)) < GET_MODE_PRECISION (mode))
1015 int uns = TYPE_UNSIGNED (TREE_TYPE (lhs));
1016 int prec = TYPE_PRECISION (TREE_TYPE (lhs));
1017 int tgtprec = GET_MODE_PRECISION (mode);
1018 rtx resc = gen_reg_rtx (mode), lres;
1019 emit_move_insn (resc, res);
1020 if (uns)
1022 rtx mask
1023 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
1024 mode);
1025 lres = expand_simple_binop (mode, AND, res, mask, NULL_RTX,
1026 true, OPTAB_LIB_WIDEN);
1028 else
1030 lres = expand_shift (LSHIFT_EXPR, mode, res, tgtprec - prec,
1031 NULL_RTX, 1);
1032 lres = expand_shift (RSHIFT_EXPR, mode, lres, tgtprec - prec,
1033 NULL_RTX, 0);
1035 if (lres != res)
1036 emit_move_insn (res, lres);
1037 do_compare_rtx_and_jump (res, resc,
1038 NE, true, mode, NULL_RTX, NULL, do_error,
1039 profile_probability::very_unlikely ());
1041 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
1042 /* If this is a scalar in a register that is stored in a wider mode
1043 than the declared mode, compute the result into its declared mode
1044 and then convert to the wider mode. Our value is the computed
1045 expression. */
1046 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
1047 else
1048 emit_move_insn (target, res);
1051 /* Add sub/add overflow checking to the statement STMT.
1052 CODE says whether the operation is +, or -. */
1054 void
1055 expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
1056 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
1057 bool uns1_p, bool is_ubsan, tree *datap)
1059 rtx res, target = NULL_RTX;
1060 tree fn;
1061 rtx_code_label *done_label = gen_label_rtx ();
1062 rtx_code_label *do_error = gen_label_rtx ();
1063 do_pending_stack_adjust ();
1064 rtx op0 = expand_normal (arg0);
1065 rtx op1 = expand_normal (arg1);
1066 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1067 int prec = GET_MODE_PRECISION (mode);
1068 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1069 bool do_xor = false;
1071 if (is_ubsan)
1072 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1074 if (lhs)
1076 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1077 if (!is_ubsan)
1078 write_complex_part (target, const0_rtx, true, false);
1081 /* We assume both operands and result have the same precision
1082 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1083 with that precision, U for unsigned type with that precision,
1084 sgn for unsigned most significant bit in that precision.
1085 s1 is signed first operand, u1 is unsigned first operand,
1086 s2 is signed second operand, u2 is unsigned second operand,
1087 sr is signed result, ur is unsigned result and the following
1088 rules say how to compute result (which is always result of
1089 the operands as if both were unsigned, cast to the right
1090 signedness) and how to compute whether operation overflowed.
1092 s1 + s2 -> sr
1093 res = (S) ((U) s1 + (U) s2)
1094 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
1095 s1 - s2 -> sr
1096 res = (S) ((U) s1 - (U) s2)
1097 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
1098 u1 + u2 -> ur
1099 res = u1 + u2
1100 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
1101 u1 - u2 -> ur
1102 res = u1 - u2
1103 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
1104 s1 + u2 -> sr
1105 res = (S) ((U) s1 + u2)
1106 ovf = ((U) res ^ sgn) < u2
1107 s1 + u2 -> ur
1108 t1 = (S) (u2 ^ sgn)
1109 t2 = s1 + t1
1110 res = (U) t2 ^ sgn
1111 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
1112 s1 - u2 -> sr
1113 res = (S) ((U) s1 - u2)
1114 ovf = u2 > ((U) s1 ^ sgn)
1115 s1 - u2 -> ur
1116 res = (U) s1 - u2
1117 ovf = s1 < 0 || u2 > (U) s1
1118 u1 - s2 -> sr
1119 res = u1 - (U) s2
1120 ovf = u1 >= ((U) s2 ^ sgn)
1121 u1 - s2 -> ur
1122 t1 = u1 ^ sgn
1123 t2 = t1 - (U) s2
1124 res = t2 ^ sgn
1125 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
1126 s1 + s2 -> ur
1127 res = (U) s1 + (U) s2
1128 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
1129 u1 + u2 -> sr
1130 res = (S) (u1 + u2)
1131 ovf = (U) res < u2 || res < 0
1132 u1 - u2 -> sr
1133 res = (S) (u1 - u2)
1134 ovf = u1 >= u2 ? res < 0 : res >= 0
1135 s1 - s2 -> ur
1136 res = (U) s1 - (U) s2
1137 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
1139 if (code == PLUS_EXPR && uns0_p && !uns1_p)
1141 /* PLUS_EXPR is commutative, if operand signedness differs,
1142 canonicalize to the first operand being signed and second
1143 unsigned to simplify following code. */
1144 std::swap (op0, op1);
1145 std::swap (arg0, arg1);
1146 uns0_p = false;
1147 uns1_p = true;
1150 /* u1 +- u2 -> ur */
1151 if (uns0_p && uns1_p && unsr_p)
1153 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
1154 : usubv4_optab, mode);
1155 if (icode != CODE_FOR_nothing)
1157 class expand_operand ops[4];
1158 rtx_insn *last = get_last_insn ();
1160 res = gen_reg_rtx (mode);
1161 create_output_operand (&ops[0], res, mode);
1162 create_input_operand (&ops[1], op0, mode);
1163 create_input_operand (&ops[2], op1, mode);
1164 create_fixed_operand (&ops[3], do_error);
1165 if (maybe_expand_insn (icode, 4, ops))
1167 last = get_last_insn ();
1168 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1169 && JUMP_P (last)
1170 && any_condjump_p (last)
1171 && !find_reg_note (last, REG_BR_PROB, 0))
1172 add_reg_br_prob_note (last,
1173 profile_probability::very_unlikely ());
1174 emit_jump (done_label);
1175 goto do_error_label;
1178 delete_insns_since (last);
1181 /* Compute the operation. On RTL level, the addition is always
1182 unsigned. */
1183 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1184 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1185 rtx tem = op0;
1186 /* For PLUS_EXPR, the operation is commutative, so we can pick
1187 operand to compare against. For prec <= BITS_PER_WORD, I think
1188 preferring REG operand is better over CONST_INT, because
1189 the CONST_INT might enlarge the instruction or CSE would need
1190 to figure out we'd already loaded it into a register before.
1191 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
1192 as then the multi-word comparison can be perhaps simplified. */
1193 if (code == PLUS_EXPR
1194 && (prec <= BITS_PER_WORD
1195 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
1196 : CONST_SCALAR_INT_P (op1)))
1197 tem = op1;
1198 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1199 true, mode, NULL_RTX, NULL, done_label,
1200 profile_probability::very_likely ());
1201 goto do_error_label;
1204 /* s1 +- u2 -> sr */
1205 if (!uns0_p && uns1_p && !unsr_p)
1207 /* Compute the operation. On RTL level, the addition is always
1208 unsigned. */
1209 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1210 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1211 rtx tem = expand_binop (mode, add_optab,
1212 code == PLUS_EXPR ? res : op0, sgn,
1213 NULL_RTX, false, OPTAB_LIB_WIDEN);
1214 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1215 done_label, profile_probability::very_likely ());
1216 goto do_error_label;
1219 /* s1 + u2 -> ur */
1220 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
1222 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1223 OPTAB_LIB_WIDEN);
1224 /* As we've changed op1, we have to avoid using the value range
1225 for the original argument. */
1226 arg1 = error_mark_node;
1227 do_xor = true;
1228 goto do_signed;
1231 /* u1 - s2 -> ur */
1232 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
1234 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
1235 OPTAB_LIB_WIDEN);
1236 /* As we've changed op0, we have to avoid using the value range
1237 for the original argument. */
1238 arg0 = error_mark_node;
1239 do_xor = true;
1240 goto do_signed;
1243 /* s1 - u2 -> ur */
1244 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
1246 /* Compute the operation. On RTL level, the addition is always
1247 unsigned. */
1248 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1249 OPTAB_LIB_WIDEN);
1250 int pos_neg = get_range_pos_neg (arg0);
1251 if (pos_neg == 2)
1252 /* If ARG0 is known to be always negative, this is always overflow. */
1253 emit_jump (do_error);
1254 else if (pos_neg == 3)
1255 /* If ARG0 is not known to be always positive, check at runtime. */
1256 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1257 NULL, do_error, profile_probability::very_unlikely ());
1258 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1259 done_label, profile_probability::very_likely ());
1260 goto do_error_label;
1263 /* u1 - s2 -> sr */
1264 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
1266 /* Compute the operation. On RTL level, the addition is always
1267 unsigned. */
1268 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1269 OPTAB_LIB_WIDEN);
1270 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1271 OPTAB_LIB_WIDEN);
1272 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1273 done_label, profile_probability::very_likely ());
1274 goto do_error_label;
1277 /* u1 + u2 -> sr */
1278 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
1280 /* Compute the operation. On RTL level, the addition is always
1281 unsigned. */
1282 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
1283 OPTAB_LIB_WIDEN);
1284 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1285 NULL, do_error, profile_probability::very_unlikely ());
1286 rtx tem = op1;
1287 /* The operation is commutative, so we can pick operand to compare
1288 against. For prec <= BITS_PER_WORD, I think preferring REG operand
1289 is better over CONST_INT, because the CONST_INT might enlarge the
1290 instruction or CSE would need to figure out we'd already loaded it
1291 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
1292 might be more beneficial, as then the multi-word comparison can be
1293 perhaps simplified. */
1294 if (prec <= BITS_PER_WORD
1295 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
1296 : CONST_SCALAR_INT_P (op0))
1297 tem = op0;
1298 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1299 done_label, profile_probability::very_likely ());
1300 goto do_error_label;
1303 /* s1 +- s2 -> ur */
1304 if (!uns0_p && !uns1_p && unsr_p)
1306 /* Compute the operation. On RTL level, the addition is always
1307 unsigned. */
1308 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1309 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1310 int pos_neg = get_range_pos_neg (arg1);
1311 if (code == PLUS_EXPR)
1313 int pos_neg0 = get_range_pos_neg (arg0);
1314 if (pos_neg0 != 3 && pos_neg == 3)
1316 std::swap (op0, op1);
1317 pos_neg = pos_neg0;
1320 rtx tem;
1321 if (pos_neg != 3)
1323 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
1324 ? and_optab : ior_optab,
1325 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1326 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
1327 NULL, done_label, profile_probability::very_likely ());
1329 else
1331 rtx_code_label *do_ior_label = gen_label_rtx ();
1332 do_compare_rtx_and_jump (op1, const0_rtx,
1333 code == MINUS_EXPR ? GE : LT, false, mode,
1334 NULL_RTX, NULL, do_ior_label,
1335 profile_probability::even ());
1336 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
1337 OPTAB_LIB_WIDEN);
1338 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1339 NULL, done_label, profile_probability::very_likely ());
1340 emit_jump (do_error);
1341 emit_label (do_ior_label);
1342 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
1343 OPTAB_LIB_WIDEN);
1344 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1345 NULL, done_label, profile_probability::very_likely ());
1347 goto do_error_label;
1350 /* u1 - u2 -> sr */
1351 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
1353 /* Compute the operation. On RTL level, the addition is always
1354 unsigned. */
1355 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1356 OPTAB_LIB_WIDEN);
1357 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1358 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1359 op0_geu_op1, profile_probability::even ());
1360 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1361 NULL, done_label, profile_probability::very_likely ());
1362 emit_jump (do_error);
1363 emit_label (op0_geu_op1);
1364 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1365 NULL, done_label, profile_probability::very_likely ());
1366 goto do_error_label;
1369 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1371 /* s1 +- s2 -> sr */
1372 do_signed:
1374 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1375 : subv4_optab, mode);
1376 if (icode != CODE_FOR_nothing)
1378 class expand_operand ops[4];
1379 rtx_insn *last = get_last_insn ();
1381 res = gen_reg_rtx (mode);
1382 create_output_operand (&ops[0], res, mode);
1383 create_input_operand (&ops[1], op0, mode);
1384 create_input_operand (&ops[2], op1, mode);
1385 create_fixed_operand (&ops[3], do_error);
1386 if (maybe_expand_insn (icode, 4, ops))
1388 last = get_last_insn ();
1389 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1390 && JUMP_P (last)
1391 && any_condjump_p (last)
1392 && !find_reg_note (last, REG_BR_PROB, 0))
1393 add_reg_br_prob_note (last,
1394 profile_probability::very_unlikely ());
1395 emit_jump (done_label);
1396 goto do_error_label;
1399 delete_insns_since (last);
1402 /* Compute the operation. On RTL level, the addition is always
1403 unsigned. */
1404 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1405 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1407 /* If we can prove that one of the arguments (for MINUS_EXPR only
1408 the second operand, as subtraction is not commutative) is always
1409 non-negative or always negative, we can do just one comparison
1410 and conditional jump. */
1411 int pos_neg = get_range_pos_neg (arg1);
1412 if (code == PLUS_EXPR)
1414 int pos_neg0 = get_range_pos_neg (arg0);
1415 if (pos_neg0 != 3 && pos_neg == 3)
1417 std::swap (op0, op1);
1418 pos_neg = pos_neg0;
1422 /* Addition overflows if and only if the two operands have the same sign,
1423 and the result has the opposite sign. Subtraction overflows if and
1424 only if the two operands have opposite sign, and the subtrahend has
1425 the same sign as the result. Here 0 is counted as positive. */
1426 if (pos_neg == 3)
1428 /* Compute op0 ^ op1 (operands have opposite sign). */
1429 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1430 OPTAB_LIB_WIDEN);
1432 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1433 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1434 OPTAB_LIB_WIDEN);
1436 rtx tem;
1437 if (code == PLUS_EXPR)
1439 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1440 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1441 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1442 OPTAB_LIB_WIDEN);
1444 else
1446 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1447 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1448 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1449 OPTAB_LIB_WIDEN);
1452 /* No overflow if the result has bit sign cleared. */
1453 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1454 NULL, done_label, profile_probability::very_likely ());
1457 /* Compare the result of the operation with the first operand.
1458 No overflow for addition if second operand is positive and result
1459 is larger or second operand is negative and result is smaller.
1460 Likewise for subtraction with sign of second operand flipped. */
1461 else
1462 do_compare_rtx_and_jump (res, op0,
1463 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
1464 false, mode, NULL_RTX, NULL, done_label,
1465 profile_probability::very_likely ());
1468 do_error_label:
1469 emit_label (do_error);
1470 if (is_ubsan)
1472 /* Expand the ubsan builtin call. */
1473 push_temp_slots ();
1474 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1475 arg0, arg1, datap);
1476 expand_normal (fn);
1477 pop_temp_slots ();
1478 do_pending_stack_adjust ();
1480 else if (lhs)
1481 expand_arith_set_overflow (lhs, target);
1483 /* We're done. */
1484 emit_label (done_label);
1486 if (lhs)
1488 if (is_ubsan)
1489 expand_ubsan_result_store (lhs, target, mode, res, do_error);
1490 else
1492 if (do_xor)
1493 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1494 OPTAB_LIB_WIDEN);
1496 expand_arith_overflow_result_store (lhs, target, mode, res);
1501 /* Add negate overflow checking to the statement STMT. */
1503 static void
1504 expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1505 tree *datap)
1507 rtx res, op1;
1508 tree fn;
1509 rtx_code_label *done_label, *do_error;
1510 rtx target = NULL_RTX;
1512 done_label = gen_label_rtx ();
1513 do_error = gen_label_rtx ();
1515 do_pending_stack_adjust ();
1516 op1 = expand_normal (arg1);
1518 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
1519 if (lhs)
1521 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1522 if (!is_ubsan)
1523 write_complex_part (target, const0_rtx, true, false);
1526 enum insn_code icode = optab_handler (negv3_optab, mode);
1527 if (icode != CODE_FOR_nothing)
1529 class expand_operand ops[3];
1530 rtx_insn *last = get_last_insn ();
1532 res = gen_reg_rtx (mode);
1533 create_output_operand (&ops[0], res, mode);
1534 create_input_operand (&ops[1], op1, mode);
1535 create_fixed_operand (&ops[2], do_error);
1536 if (maybe_expand_insn (icode, 3, ops))
1538 last = get_last_insn ();
1539 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1540 && JUMP_P (last)
1541 && any_condjump_p (last)
1542 && !find_reg_note (last, REG_BR_PROB, 0))
1543 add_reg_br_prob_note (last,
1544 profile_probability::very_unlikely ());
1545 emit_jump (done_label);
1547 else
1549 delete_insns_since (last);
1550 icode = CODE_FOR_nothing;
1554 if (icode == CODE_FOR_nothing)
1556 /* Compute the operation. On RTL level, the addition is always
1557 unsigned. */
1558 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1560 /* Compare the operand with the most negative value. */
1561 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1562 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
1563 done_label, profile_probability::very_likely ());
1566 emit_label (do_error);
1567 if (is_ubsan)
1569 /* Expand the ubsan builtin call. */
1570 push_temp_slots ();
1571 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1572 arg1, NULL_TREE, datap);
1573 expand_normal (fn);
1574 pop_temp_slots ();
1575 do_pending_stack_adjust ();
1577 else if (lhs)
1578 expand_arith_set_overflow (lhs, target);
1580 /* We're done. */
1581 emit_label (done_label);
1583 if (lhs)
1585 if (is_ubsan)
1586 expand_ubsan_result_store (lhs, target, mode, res, do_error);
1587 else
1588 expand_arith_overflow_result_store (lhs, target, mode, res);
1592 /* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1593 mode MODE can be expanded without using a libcall. */
1595 static bool
1596 can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1597 rtx op0, rtx op1, bool uns)
1599 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1600 != CODE_FOR_nothing)
1601 return true;
1603 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1604 != CODE_FOR_nothing)
1605 return true;
1607 rtx_insn *last = get_last_insn ();
1608 if (CONSTANT_P (op0))
1609 op0 = convert_modes (wmode, mode, op0, uns);
1610 else
1611 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1612 if (CONSTANT_P (op1))
1613 op1 = convert_modes (wmode, mode, op1, uns);
1614 else
1615 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1616 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1617 delete_insns_since (last);
1618 return ret != NULL_RTX;
1621 /* Add mul overflow checking to the statement STMT. */
1623 static void
1624 expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1625 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1626 tree *datap)
1628 rtx res, op0, op1;
1629 tree fn, type;
1630 rtx_code_label *done_label, *do_error;
1631 rtx target = NULL_RTX;
1632 signop sign;
1633 enum insn_code icode;
1635 done_label = gen_label_rtx ();
1636 do_error = gen_label_rtx ();
1638 do_pending_stack_adjust ();
1639 op0 = expand_normal (arg0);
1640 op1 = expand_normal (arg1);
1642 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1643 bool uns = unsr_p;
1644 if (lhs)
1646 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1647 if (!is_ubsan)
1648 write_complex_part (target, const0_rtx, true, false);
1651 if (is_ubsan)
1652 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1654 /* We assume both operands and result have the same precision
1655 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1656 with that precision, U for unsigned type with that precision,
1657 sgn for unsigned most significant bit in that precision.
1658 s1 is signed first operand, u1 is unsigned first operand,
1659 s2 is signed second operand, u2 is unsigned second operand,
1660 sr is signed result, ur is unsigned result and the following
1661 rules say how to compute result (which is always result of
1662 the operands as if both were unsigned, cast to the right
1663 signedness) and how to compute whether operation overflowed.
1664 main_ovf (false) stands for jump on signed multiplication
1665 overflow or the main algorithm with uns == false.
1666 main_ovf (true) stands for jump on unsigned multiplication
1667 overflow or the main algorithm with uns == true.
1669 s1 * s2 -> sr
1670 res = (S) ((U) s1 * (U) s2)
1671 ovf = main_ovf (false)
1672 u1 * u2 -> ur
1673 res = u1 * u2
1674 ovf = main_ovf (true)
1675 s1 * u2 -> ur
1676 res = (U) s1 * u2
1677 ovf = (s1 < 0 && u2) || main_ovf (true)
1678 u1 * u2 -> sr
1679 res = (S) (u1 * u2)
1680 ovf = res < 0 || main_ovf (true)
1681 s1 * u2 -> sr
1682 res = (S) ((U) s1 * u2)
1683 ovf = (S) u2 >= 0 ? main_ovf (false)
1684 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1685 s1 * s2 -> ur
1686 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1687 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1688 res = t1 * t2
1689 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1691 if (uns0_p && !uns1_p)
1693 /* Multiplication is commutative, if operand signedness differs,
1694 canonicalize to the first operand being signed and second
1695 unsigned to simplify following code. */
1696 std::swap (op0, op1);
1697 std::swap (arg0, arg1);
1698 uns0_p = false;
1699 uns1_p = true;
1702 int pos_neg0 = get_range_pos_neg (arg0);
1703 int pos_neg1 = get_range_pos_neg (arg1);
1704 /* Unsigned types with smaller than mode precision, even if they have most
1705 significant bit set, are still zero-extended. */
1706 if (uns0_p && TYPE_PRECISION (TREE_TYPE (arg0)) < GET_MODE_PRECISION (mode))
1707 pos_neg0 = 1;
1708 if (uns1_p && TYPE_PRECISION (TREE_TYPE (arg1)) < GET_MODE_PRECISION (mode))
1709 pos_neg1 = 1;
1711 /* s1 * u2 -> ur */
1712 if (!uns0_p && uns1_p && unsr_p)
1714 switch (pos_neg0)
1716 case 1:
1717 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1718 goto do_main;
1719 case 2:
1720 /* If s1 is negative, avoid the main code, just multiply and
1721 signal overflow if op1 is not 0. */
1722 struct separate_ops ops;
1723 ops.code = MULT_EXPR;
1724 ops.type = TREE_TYPE (arg1);
1725 ops.op0 = make_tree (ops.type, op0);
1726 ops.op1 = make_tree (ops.type, op1);
1727 ops.op2 = NULL_TREE;
1728 ops.location = loc;
1729 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1730 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1731 NULL, done_label, profile_probability::very_likely ());
1732 goto do_error_label;
1733 case 3:
1734 if (get_min_precision (arg1, UNSIGNED)
1735 + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
1737 /* If the first operand is sign extended from narrower type, the
1738 second operand is zero extended from narrower type and
1739 the sum of the two precisions is smaller or equal to the
1740 result precision: if the first argument is at runtime
1741 non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
1742 and there will be no overflow, if the first argument is
1743 negative and the second argument zero, the result will be
1744 0 and there will be no overflow, if the first argument is
1745 negative and the second argument positive, the result when
1746 treated as signed will be negative (minimum -0x7f80 or
1747 -0x7f..f80..0) there will be always overflow. So, do
1748 res = (U) (s1 * u2)
1749 ovf = (S) res < 0 */
1750 struct separate_ops ops;
1751 ops.code = MULT_EXPR;
1752 ops.type
1753 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1755 ops.op0 = make_tree (ops.type, op0);
1756 ops.op1 = make_tree (ops.type, op1);
1757 ops.op2 = NULL_TREE;
1758 ops.location = loc;
1759 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1760 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1761 mode, NULL_RTX, NULL, done_label,
1762 profile_probability::very_likely ());
1763 goto do_error_label;
1765 rtx_code_label *do_main_label;
1766 do_main_label = gen_label_rtx ();
1767 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1768 NULL, do_main_label, profile_probability::very_likely ());
1769 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1770 NULL, do_main_label, profile_probability::very_likely ());
1771 expand_arith_set_overflow (lhs, target);
1772 emit_label (do_main_label);
1773 goto do_main;
1774 default:
1775 gcc_unreachable ();
1779 /* u1 * u2 -> sr */
1780 if (uns0_p && uns1_p && !unsr_p)
1782 if ((pos_neg0 | pos_neg1) == 1)
1784 /* If both arguments are zero extended from narrower types,
1785 the MSB will be clear on both and so we can pretend it is
1786 a normal s1 * s2 -> sr multiplication. */
1787 uns0_p = false;
1788 uns1_p = false;
1790 else
1791 uns = true;
1792 /* Rest of handling of this case after res is computed. */
1793 goto do_main;
1796 /* s1 * u2 -> sr */
1797 if (!uns0_p && uns1_p && !unsr_p)
1799 switch (pos_neg1)
1801 case 1:
1802 goto do_main;
1803 case 2:
1804 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1805 avoid the main code, just multiply and signal overflow
1806 unless 0 * u2 or -1 * ((U) Smin). */
1807 struct separate_ops ops;
1808 ops.code = MULT_EXPR;
1809 ops.type = TREE_TYPE (arg1);
1810 ops.op0 = make_tree (ops.type, op0);
1811 ops.op1 = make_tree (ops.type, op1);
1812 ops.op2 = NULL_TREE;
1813 ops.location = loc;
1814 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1815 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1816 NULL, done_label, profile_probability::very_likely ());
1817 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1818 NULL, do_error, profile_probability::very_unlikely ());
1819 int prec;
1820 prec = GET_MODE_PRECISION (mode);
1821 rtx sgn;
1822 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1823 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1824 NULL, done_label, profile_probability::very_likely ());
1825 goto do_error_label;
1826 case 3:
1827 /* Rest of handling of this case after res is computed. */
1828 goto do_main;
1829 default:
1830 gcc_unreachable ();
1834 /* s1 * s2 -> ur */
1835 if (!uns0_p && !uns1_p && unsr_p)
1837 rtx tem;
1838 switch (pos_neg0 | pos_neg1)
1840 case 1: /* Both operands known to be non-negative. */
1841 goto do_main;
1842 case 2: /* Both operands known to be negative. */
1843 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1844 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1845 /* Avoid looking at arg0/arg1 ranges, as we've changed
1846 the arguments. */
1847 arg0 = error_mark_node;
1848 arg1 = error_mark_node;
1849 goto do_main;
1850 case 3:
1851 if ((pos_neg0 ^ pos_neg1) == 3)
1853 /* If one operand is known to be negative and the other
1854 non-negative, this overflows always, unless the non-negative
1855 one is 0. Just do normal multiply and set overflow
1856 unless one of the operands is 0. */
1857 struct separate_ops ops;
1858 ops.code = MULT_EXPR;
1859 ops.type
1860 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1862 ops.op0 = make_tree (ops.type, op0);
1863 ops.op1 = make_tree (ops.type, op1);
1864 ops.op2 = NULL_TREE;
1865 ops.location = loc;
1866 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1867 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1868 true, mode, NULL_RTX, NULL, done_label,
1869 profile_probability::very_likely ());
1870 goto do_error_label;
1872 if (get_min_precision (arg0, SIGNED)
1873 + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
1875 /* If both operands are sign extended from narrower types and
1876 the sum of the two precisions is smaller or equal to the
1877 result precision: if both arguments are at runtime
1878 non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
1879 and there will be no overflow, if both arguments are negative,
1880 maximum result will be 0x40..00 and there will be no overflow
1881 either, if one argument is positive and the other argument
1882 negative, the result when treated as signed will be negative
1883 and there will be always overflow, and if one argument is
1884 zero and the other negative the result will be zero and no
1885 overflow. So, do
1886 res = (U) (s1 * s2)
1887 ovf = (S) res < 0 */
1888 struct separate_ops ops;
1889 ops.code = MULT_EXPR;
1890 ops.type
1891 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1893 ops.op0 = make_tree (ops.type, op0);
1894 ops.op1 = make_tree (ops.type, op1);
1895 ops.op2 = NULL_TREE;
1896 ops.location = loc;
1897 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1898 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1899 mode, NULL_RTX, NULL, done_label,
1900 profile_probability::very_likely ());
1901 goto do_error_label;
1903 /* The general case, do all the needed comparisons at runtime. */
1904 rtx_code_label *do_main_label, *after_negate_label;
1905 rtx rop0, rop1;
1906 rop0 = gen_reg_rtx (mode);
1907 rop1 = gen_reg_rtx (mode);
1908 emit_move_insn (rop0, op0);
1909 emit_move_insn (rop1, op1);
1910 op0 = rop0;
1911 op1 = rop1;
1912 do_main_label = gen_label_rtx ();
1913 after_negate_label = gen_label_rtx ();
1914 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1915 OPTAB_LIB_WIDEN);
1916 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1917 NULL, after_negate_label, profile_probability::very_likely ());
1918 /* Both arguments negative here, negate them and continue with
1919 normal unsigned overflow checking multiplication. */
1920 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1921 NULL_RTX, false));
1922 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1923 NULL_RTX, false));
1924 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1925 the arguments. */
1926 arg0 = error_mark_node;
1927 arg1 = error_mark_node;
1928 emit_jump (do_main_label);
1929 emit_label (after_negate_label);
1930 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1931 OPTAB_LIB_WIDEN);
1932 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1933 NULL, do_main_label,
1934 profile_probability::very_likely ());
1935 /* One argument is negative here, the other positive. This
1936 overflows always, unless one of the arguments is 0. But
1937 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1938 is, thus we can keep do_main code oring in overflow as is. */
1939 if (pos_neg0 != 2)
1940 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1941 NULL, do_main_label,
1942 profile_probability::very_unlikely ());
1943 if (pos_neg1 != 2)
1944 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1945 NULL, do_main_label,
1946 profile_probability::very_unlikely ());
1947 expand_arith_set_overflow (lhs, target);
1948 emit_label (do_main_label);
1949 goto do_main;
1950 default:
1951 gcc_unreachable ();
1955 do_main:
1956 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1957 sign = uns ? UNSIGNED : SIGNED;
1958 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
1959 if (uns
1960 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1961 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1963 /* Optimize unsigned multiplication by power of 2 constant
1964 using 2 shifts, one for result, one to extract the shifted
1965 out bits to see if they are all zero.
1966 Don't do this if optimizing for size and we have umulv4_optab,
1967 in that case assume multiplication will be shorter.
1968 This is heuristics based on the single target that provides
1969 umulv4 right now (i?86/x86_64), if further targets add it, this
1970 might need to be revisited.
1971 Cases where both operands are constant should be folded already
1972 during GIMPLE, and cases where one operand is constant but not
1973 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1974 below can be done without multiplication, just by shifts and adds,
1975 or we'd need to divide the result (and hope it actually doesn't
1976 really divide nor multiply) and compare the result of the division
1977 with the original operand. */
1978 rtx opn0 = op0;
1979 rtx opn1 = op1;
1980 tree argn0 = arg0;
1981 tree argn1 = arg1;
1982 if (integer_pow2p (arg0))
1984 std::swap (opn0, opn1);
1985 std::swap (argn0, argn1);
1987 int cnt = tree_log2 (argn1);
1988 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1990 rtx upper = const0_rtx;
1991 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1992 if (cnt != 0)
1993 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1994 GET_MODE_PRECISION (mode) - cnt,
1995 NULL_RTX, uns);
1996 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1997 NULL_RTX, NULL, done_label,
1998 profile_probability::very_likely ());
1999 goto do_error_label;
2002 if (icode != CODE_FOR_nothing)
2004 class expand_operand ops[4];
2005 rtx_insn *last = get_last_insn ();
2007 res = gen_reg_rtx (mode);
2008 create_output_operand (&ops[0], res, mode);
2009 create_input_operand (&ops[1], op0, mode);
2010 create_input_operand (&ops[2], op1, mode);
2011 create_fixed_operand (&ops[3], do_error);
2012 if (maybe_expand_insn (icode, 4, ops))
2014 last = get_last_insn ();
2015 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
2016 && JUMP_P (last)
2017 && any_condjump_p (last)
2018 && !find_reg_note (last, REG_BR_PROB, 0))
2019 add_reg_br_prob_note (last,
2020 profile_probability::very_unlikely ());
2021 emit_jump (done_label);
2023 else
2025 delete_insns_since (last);
2026 icode = CODE_FOR_nothing;
2030 if (icode == CODE_FOR_nothing)
2032 struct separate_ops ops;
2033 int prec = GET_MODE_PRECISION (mode);
2034 scalar_int_mode hmode, wmode;
2035 ops.op0 = make_tree (type, op0);
2036 ops.op1 = make_tree (type, op1);
2037 ops.op2 = NULL_TREE;
2038 ops.location = loc;
2040 /* Optimize unsigned overflow check where we don't use the
2041 multiplication result, just whether overflow happened.
2042 If we can do MULT_HIGHPART_EXPR, that followed by
2043 comparison of the result against zero is cheapest.
2044 We'll still compute res, but it should be DCEd later. */
2045 use_operand_p use;
2046 gimple *use_stmt;
2047 if (!is_ubsan
2048 && lhs
2049 && uns
2050 && !(uns0_p && uns1_p && !unsr_p)
2051 && can_mult_highpart_p (mode, uns) == 1
2052 && single_imm_use (lhs, &use, &use_stmt)
2053 && is_gimple_assign (use_stmt)
2054 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
2055 goto highpart;
2057 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2058 && targetm.scalar_mode_supported_p (wmode)
2059 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
2061 twoxwider:
2062 ops.code = WIDEN_MULT_EXPR;
2063 ops.type
2064 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
2066 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
2067 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
2068 NULL_RTX, uns);
2069 hipart = convert_modes (mode, wmode, hipart, uns);
2070 res = convert_modes (mode, wmode, res, uns);
2071 if (uns)
2072 /* For the unsigned multiplication, there was overflow if
2073 HIPART is non-zero. */
2074 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2075 NULL_RTX, NULL, done_label,
2076 profile_probability::very_likely ());
2077 else
2079 /* RES is used more than once, place it in a pseudo. */
2080 res = force_reg (mode, res);
2082 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2083 NULL_RTX, 0);
2084 /* RES is low half of the double width result, HIPART
2085 the high half. There was overflow if
2086 HIPART is different from RES < 0 ? -1 : 0. */
2087 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2088 NULL_RTX, NULL, done_label,
2089 profile_probability::very_likely ());
2092 else if (can_mult_highpart_p (mode, uns) == 1)
2094 highpart:
2095 ops.code = MULT_HIGHPART_EXPR;
2096 ops.type = type;
2098 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
2099 EXPAND_NORMAL);
2100 ops.code = MULT_EXPR;
2101 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2102 if (uns)
2103 /* For the unsigned multiplication, there was overflow if
2104 HIPART is non-zero. */
2105 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2106 NULL_RTX, NULL, done_label,
2107 profile_probability::very_likely ());
2108 else
2110 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2111 NULL_RTX, 0);
2112 /* RES is low half of the double width result, HIPART
2113 the high half. There was overflow if
2114 HIPART is different from RES < 0 ? -1 : 0. */
2115 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2116 NULL_RTX, NULL, done_label,
2117 profile_probability::very_likely ());
2121 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
2122 && 2 * GET_MODE_PRECISION (hmode) == prec)
2124 rtx_code_label *large_op0 = gen_label_rtx ();
2125 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
2126 rtx_code_label *one_small_one_large = gen_label_rtx ();
2127 rtx_code_label *both_ops_large = gen_label_rtx ();
2128 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
2129 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
2130 rtx_code_label *do_overflow = gen_label_rtx ();
2131 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
2133 unsigned int hprec = GET_MODE_PRECISION (hmode);
2134 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
2135 NULL_RTX, uns);
2136 hipart0 = convert_modes (hmode, mode, hipart0, uns);
2137 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
2138 rtx signbit0 = const0_rtx;
2139 if (!uns)
2140 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
2141 NULL_RTX, 0);
2142 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
2143 NULL_RTX, uns);
2144 hipart1 = convert_modes (hmode, mode, hipart1, uns);
2145 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
2146 rtx signbit1 = const0_rtx;
2147 if (!uns)
2148 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
2149 NULL_RTX, 0);
2151 res = gen_reg_rtx (mode);
2153 /* True if op0 resp. op1 are known to be in the range of
2154 halfstype. */
2155 bool op0_small_p = false;
2156 bool op1_small_p = false;
2157 /* True if op0 resp. op1 are known to have all zeros or all ones
2158 in the upper half of bits, but are not known to be
2159 op{0,1}_small_p. */
2160 bool op0_medium_p = false;
2161 bool op1_medium_p = false;
2162 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
2163 nonnegative, 1 if unknown. */
2164 int op0_sign = 1;
2165 int op1_sign = 1;
2167 if (pos_neg0 == 1)
2168 op0_sign = 0;
2169 else if (pos_neg0 == 2)
2170 op0_sign = -1;
2171 if (pos_neg1 == 1)
2172 op1_sign = 0;
2173 else if (pos_neg1 == 2)
2174 op1_sign = -1;
2176 unsigned int mprec0 = prec;
2177 if (arg0 != error_mark_node)
2178 mprec0 = get_min_precision (arg0, sign);
2179 if (mprec0 <= hprec)
2180 op0_small_p = true;
2181 else if (!uns && mprec0 <= hprec + 1)
2182 op0_medium_p = true;
2183 unsigned int mprec1 = prec;
2184 if (arg1 != error_mark_node)
2185 mprec1 = get_min_precision (arg1, sign);
2186 if (mprec1 <= hprec)
2187 op1_small_p = true;
2188 else if (!uns && mprec1 <= hprec + 1)
2189 op1_medium_p = true;
2191 int smaller_sign = 1;
2192 int larger_sign = 1;
2193 if (op0_small_p)
2195 smaller_sign = op0_sign;
2196 larger_sign = op1_sign;
2198 else if (op1_small_p)
2200 smaller_sign = op1_sign;
2201 larger_sign = op0_sign;
2203 else if (op0_sign == op1_sign)
2205 smaller_sign = op0_sign;
2206 larger_sign = op0_sign;
2209 if (!op0_small_p)
2210 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
2211 NULL_RTX, NULL, large_op0,
2212 profile_probability::unlikely ());
2214 if (!op1_small_p)
2215 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2216 NULL_RTX, NULL, small_op0_large_op1,
2217 profile_probability::unlikely ());
2219 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
2220 hmode to mode, the multiplication will never overflow. We can
2221 do just one hmode x hmode => mode widening multiplication. */
2222 tree halfstype = build_nonstandard_integer_type (hprec, uns);
2223 ops.op0 = make_tree (halfstype, lopart0);
2224 ops.op1 = make_tree (halfstype, lopart1);
2225 ops.code = WIDEN_MULT_EXPR;
2226 ops.type = type;
2227 rtx thisres
2228 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2229 emit_move_insn (res, thisres);
2230 emit_jump (done_label);
2232 emit_label (small_op0_large_op1);
2234 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
2235 but op1 is not, just swap the arguments and handle it as op1
2236 sign/zero extended, op0 not. */
2237 rtx larger = gen_reg_rtx (mode);
2238 rtx hipart = gen_reg_rtx (hmode);
2239 rtx lopart = gen_reg_rtx (hmode);
2240 emit_move_insn (larger, op1);
2241 emit_move_insn (hipart, hipart1);
2242 emit_move_insn (lopart, lopart0);
2243 emit_jump (one_small_one_large);
2245 emit_label (large_op0);
2247 if (!op1_small_p)
2248 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
2249 NULL_RTX, NULL, both_ops_large,
2250 profile_probability::unlikely ());
2252 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
2253 but op0 is not, prepare larger, hipart and lopart pseudos and
2254 handle it together with small_op0_large_op1. */
2255 emit_move_insn (larger, op0);
2256 emit_move_insn (hipart, hipart0);
2257 emit_move_insn (lopart, lopart1);
2259 emit_label (one_small_one_large);
2261 /* lopart is the low part of the operand that is sign extended
2262 to mode, larger is the other operand, hipart is the
2263 high part of larger and lopart0 and lopart1 are the low parts
2264 of both operands.
2265 We perform lopart0 * lopart1 and lopart * hipart widening
2266 multiplications. */
2267 tree halfutype = build_nonstandard_integer_type (hprec, 1);
2268 ops.op0 = make_tree (halfutype, lopart0);
2269 ops.op1 = make_tree (halfutype, lopart1);
2270 rtx lo0xlo1
2271 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2273 ops.op0 = make_tree (halfutype, lopart);
2274 ops.op1 = make_tree (halfutype, hipart);
2275 rtx loxhi = gen_reg_rtx (mode);
2276 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2277 emit_move_insn (loxhi, tem);
2279 if (!uns)
2281 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
2282 if (larger_sign == 0)
2283 emit_jump (after_hipart_neg);
2284 else if (larger_sign != -1)
2285 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
2286 NULL_RTX, NULL, after_hipart_neg,
2287 profile_probability::even ());
2289 tem = convert_modes (mode, hmode, lopart, 1);
2290 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
2291 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
2292 1, OPTAB_WIDEN);
2293 emit_move_insn (loxhi, tem);
2295 emit_label (after_hipart_neg);
2297 /* if (lopart < 0) loxhi -= larger; */
2298 if (smaller_sign == 0)
2299 emit_jump (after_lopart_neg);
2300 else if (smaller_sign != -1)
2301 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
2302 NULL_RTX, NULL, after_lopart_neg,
2303 profile_probability::even ());
2305 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
2306 1, OPTAB_WIDEN);
2307 emit_move_insn (loxhi, tem);
2309 emit_label (after_lopart_neg);
2312 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
2313 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
2314 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
2315 1, OPTAB_WIDEN);
2316 emit_move_insn (loxhi, tem);
2318 /* if (loxhi >> (bitsize / 2)
2319 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
2320 if (loxhi >> (bitsize / 2) == 0 (if uns). */
2321 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
2322 NULL_RTX, 0);
2323 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
2324 rtx signbitloxhi = const0_rtx;
2325 if (!uns)
2326 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
2327 convert_modes (hmode, mode,
2328 loxhi, 0),
2329 hprec - 1, NULL_RTX, 0);
2331 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
2332 NULL_RTX, NULL, do_overflow,
2333 profile_probability::very_unlikely ());
2335 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
2336 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
2337 NULL_RTX, 1);
2338 tem = convert_modes (mode, hmode,
2339 convert_modes (hmode, mode, lo0xlo1, 1), 1);
2341 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
2342 1, OPTAB_WIDEN);
2343 if (tem != res)
2344 emit_move_insn (res, tem);
2345 emit_jump (done_label);
2347 emit_label (both_ops_large);
2349 /* If both operands are large (not sign (!uns) or zero (uns)
2350 extended from hmode), then perform the full multiplication
2351 which will be the result of the operation.
2352 The only cases which don't overflow are for signed multiplication
2353 some cases where both hipart0 and highpart1 are 0 or -1.
2354 For unsigned multiplication when high parts are both non-zero
2355 this overflows always. */
2356 ops.code = MULT_EXPR;
2357 ops.op0 = make_tree (type, op0);
2358 ops.op1 = make_tree (type, op1);
2359 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2360 emit_move_insn (res, tem);
2362 if (!uns)
2364 if (!op0_medium_p)
2366 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
2367 NULL_RTX, 1, OPTAB_WIDEN);
2368 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2369 NULL_RTX, NULL, do_error,
2370 profile_probability::very_unlikely ());
2373 if (!op1_medium_p)
2375 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
2376 NULL_RTX, 1, OPTAB_WIDEN);
2377 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
2378 NULL_RTX, NULL, do_error,
2379 profile_probability::very_unlikely ());
2382 /* At this point hipart{0,1} are both in [-1, 0]. If they are
2383 the same, overflow happened if res is non-positive, if they
2384 are different, overflow happened if res is positive. */
2385 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
2386 emit_jump (hipart_different);
2387 else if (op0_sign == 1 || op1_sign == 1)
2388 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
2389 NULL_RTX, NULL, hipart_different,
2390 profile_probability::even ());
2392 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
2393 NULL_RTX, NULL, do_error,
2394 profile_probability::very_unlikely ());
2395 emit_jump (done_label);
2397 emit_label (hipart_different);
2399 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
2400 NULL_RTX, NULL, do_error,
2401 profile_probability::very_unlikely ());
2402 emit_jump (done_label);
2405 emit_label (do_overflow);
2407 /* Overflow, do full multiplication and fallthru into do_error. */
2408 ops.op0 = make_tree (type, op0);
2409 ops.op1 = make_tree (type, op1);
2410 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2411 emit_move_insn (res, tem);
2413 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2414 && targetm.scalar_mode_supported_p (wmode))
2415 /* Even emitting a libcall is better than not detecting overflow
2416 at all. */
2417 goto twoxwider;
2418 else
2420 gcc_assert (!is_ubsan);
2421 ops.code = MULT_EXPR;
2422 ops.type = type;
2423 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2424 emit_jump (done_label);
2428 do_error_label:
2429 emit_label (do_error);
2430 if (is_ubsan)
2432 /* Expand the ubsan builtin call. */
2433 push_temp_slots ();
2434 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
2435 arg0, arg1, datap);
2436 expand_normal (fn);
2437 pop_temp_slots ();
2438 do_pending_stack_adjust ();
2440 else if (lhs)
2441 expand_arith_set_overflow (lhs, target);
2443 /* We're done. */
2444 emit_label (done_label);
2446 /* u1 * u2 -> sr */
2447 if (uns0_p && uns1_p && !unsr_p)
2449 rtx_code_label *all_done_label = gen_label_rtx ();
2450 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
2451 NULL, all_done_label, profile_probability::very_likely ());
2452 expand_arith_set_overflow (lhs, target);
2453 emit_label (all_done_label);
2456 /* s1 * u2 -> sr */
2457 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2459 rtx_code_label *all_done_label = gen_label_rtx ();
2460 rtx_code_label *set_noovf = gen_label_rtx ();
2461 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
2462 NULL, all_done_label, profile_probability::very_likely ());
2463 expand_arith_set_overflow (lhs, target);
2464 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
2465 NULL, set_noovf, profile_probability::very_likely ());
2466 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
2467 NULL, all_done_label, profile_probability::very_unlikely ());
2468 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
2469 all_done_label, profile_probability::very_unlikely ());
2470 emit_label (set_noovf);
2471 write_complex_part (target, const0_rtx, true, false);
2472 emit_label (all_done_label);
2475 if (lhs)
2477 if (is_ubsan)
2478 expand_ubsan_result_store (lhs, target, mode, res, do_error);
2479 else
2480 expand_arith_overflow_result_store (lhs, target, mode, res);
2484 /* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2486 static void
2487 expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2488 tree arg0, tree arg1)
2490 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
2491 rtx_code_label *loop_lab = NULL;
2492 rtx cntvar = NULL_RTX;
2493 tree cntv = NULL_TREE;
2494 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2495 tree sz = TYPE_SIZE (eltype);
2496 tree data = NULL_TREE;
2497 tree resv = NULL_TREE;
2498 rtx lhsr = NULL_RTX;
2499 rtx resvr = NULL_RTX;
2500 unsigned HOST_WIDE_INT const_cnt = 0;
2501 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
2503 if (lhs)
2505 optab op;
2506 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2507 if (!VECTOR_MODE_P (GET_MODE (lhsr))
2508 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2509 optab_default)) == unknown_optab
2510 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2511 == CODE_FOR_nothing))
2513 if (MEM_P (lhsr))
2514 resv = make_tree (TREE_TYPE (lhs), lhsr);
2515 else
2517 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2518 resv = make_tree (TREE_TYPE (lhs), resvr);
2522 if (use_loop_p)
2524 do_pending_stack_adjust ();
2525 loop_lab = gen_label_rtx ();
2526 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2527 cntv = make_tree (sizetype, cntvar);
2528 emit_move_insn (cntvar, const0_rtx);
2529 emit_label (loop_lab);
2531 if (TREE_CODE (arg0) != VECTOR_CST)
2533 rtx arg0r = expand_normal (arg0);
2534 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2536 if (TREE_CODE (arg1) != VECTOR_CST)
2538 rtx arg1r = expand_normal (arg1);
2539 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2541 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
2543 tree op0, op1, res = NULL_TREE;
2544 if (use_loop_p)
2546 tree atype = build_array_type_nelts (eltype, cnt);
2547 op0 = uniform_vector_p (arg0);
2548 if (op0 == NULL_TREE)
2550 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2551 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2552 NULL_TREE, NULL_TREE);
2554 op1 = uniform_vector_p (arg1);
2555 if (op1 == NULL_TREE)
2557 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2558 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2559 NULL_TREE, NULL_TREE);
2561 if (resv)
2563 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2564 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2565 NULL_TREE, NULL_TREE);
2568 else
2570 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2571 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2572 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2573 if (resv)
2574 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2575 bitpos);
2577 switch (code)
2579 case PLUS_EXPR:
2580 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2581 false, false, false, true, &data);
2582 break;
2583 case MINUS_EXPR:
2584 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
2585 expand_neg_overflow (loc, res, op1, true, &data);
2586 else
2587 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2588 false, false, false, true, &data);
2589 break;
2590 case MULT_EXPR:
2591 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2592 true, &data);
2593 break;
2594 default:
2595 gcc_unreachable ();
2598 if (use_loop_p)
2600 struct separate_ops ops;
2601 ops.code = PLUS_EXPR;
2602 ops.type = TREE_TYPE (cntv);
2603 ops.op0 = cntv;
2604 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2605 ops.op2 = NULL_TREE;
2606 ops.location = loc;
2607 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2608 EXPAND_NORMAL);
2609 if (ret != cntvar)
2610 emit_move_insn (cntvar, ret);
2611 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2612 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
2613 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
2614 profile_probability::very_likely ());
2616 if (lhs && resv == NULL_TREE)
2618 struct separate_ops ops;
2619 ops.code = code;
2620 ops.type = TREE_TYPE (arg0);
2621 ops.op0 = arg0;
2622 ops.op1 = arg1;
2623 ops.op2 = NULL_TREE;
2624 ops.location = loc;
2625 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2626 EXPAND_NORMAL);
2627 if (ret != lhsr)
2628 emit_move_insn (lhsr, ret);
2630 else if (resvr)
2631 emit_move_insn (lhsr, resvr);
2634 /* Expand UBSAN_CHECK_ADD call STMT. */
2636 static void
2637 expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
2639 location_t loc = gimple_location (stmt);
2640 tree lhs = gimple_call_lhs (stmt);
2641 tree arg0 = gimple_call_arg (stmt, 0);
2642 tree arg1 = gimple_call_arg (stmt, 1);
2643 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2644 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2645 else
2646 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2647 false, false, false, true, NULL);
2650 /* Expand UBSAN_CHECK_SUB call STMT. */
2652 static void
2653 expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
2655 location_t loc = gimple_location (stmt);
2656 tree lhs = gimple_call_lhs (stmt);
2657 tree arg0 = gimple_call_arg (stmt, 0);
2658 tree arg1 = gimple_call_arg (stmt, 1);
2659 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2660 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2661 else if (integer_zerop (arg0))
2662 expand_neg_overflow (loc, lhs, arg1, true, NULL);
2663 else
2664 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
2665 false, false, false, true, NULL);
2668 /* Expand UBSAN_CHECK_MUL call STMT. */
2670 static void
2671 expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
2673 location_t loc = gimple_location (stmt);
2674 tree lhs = gimple_call_lhs (stmt);
2675 tree arg0 = gimple_call_arg (stmt, 0);
2676 tree arg1 = gimple_call_arg (stmt, 1);
2677 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2678 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2679 else
2680 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2681 NULL);
2684 /* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2686 static void
2687 expand_arith_overflow (enum tree_code code, gimple *stmt)
2689 tree lhs = gimple_call_lhs (stmt);
2690 if (lhs == NULL_TREE)
2691 return;
2692 tree arg0 = gimple_call_arg (stmt, 0);
2693 tree arg1 = gimple_call_arg (stmt, 1);
2694 tree type = TREE_TYPE (TREE_TYPE (lhs));
2695 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2696 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2697 int unsr_p = TYPE_UNSIGNED (type);
2698 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2699 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2700 int precres = TYPE_PRECISION (type);
2701 location_t loc = gimple_location (stmt);
2702 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2703 uns0_p = true;
2704 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2705 uns1_p = true;
2706 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2707 prec0 = MIN (prec0, pr);
2708 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2709 prec1 = MIN (prec1, pr);
2711 /* If uns0_p && uns1_p, precop is minimum needed precision
2712 of unsigned type to hold the exact result, otherwise
2713 precop is minimum needed precision of signed type to
2714 hold the exact result. */
2715 int precop;
2716 if (code == MULT_EXPR)
2717 precop = prec0 + prec1 + (uns0_p != uns1_p);
2718 else
2720 if (uns0_p == uns1_p)
2721 precop = MAX (prec0, prec1) + 1;
2722 else if (uns0_p)
2723 precop = MAX (prec0 + 1, prec1) + 1;
2724 else
2725 precop = MAX (prec0, prec1 + 1) + 1;
2727 int orig_precres = precres;
2731 if ((uns0_p && uns1_p)
2732 ? ((precop + !unsr_p) <= precres
2733 /* u1 - u2 -> ur can overflow, no matter what precision
2734 the result has. */
2735 && (code != MINUS_EXPR || !unsr_p))
2736 : (!unsr_p && precop <= precres))
2738 /* The infinity precision result will always fit into result. */
2739 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2740 write_complex_part (target, const0_rtx, true, false);
2741 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
2742 struct separate_ops ops;
2743 ops.code = code;
2744 ops.type = type;
2745 ops.op0 = fold_convert_loc (loc, type, arg0);
2746 ops.op1 = fold_convert_loc (loc, type, arg1);
2747 ops.op2 = NULL_TREE;
2748 ops.location = loc;
2749 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2750 expand_arith_overflow_result_store (lhs, target, mode, tem);
2751 return;
2754 /* For operations with low precision, if target doesn't have them, start
2755 with precres widening right away, otherwise do it only if the most
2756 simple cases can't be used. */
2757 const int min_precision = targetm.min_arithmetic_precision ();
2758 if (orig_precres == precres && precres < min_precision)
2760 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2761 && prec1 <= precres)
2762 || ((!uns0_p || !uns1_p) && !unsr_p
2763 && prec0 + uns0_p <= precres
2764 && prec1 + uns1_p <= precres))
2766 arg0 = fold_convert_loc (loc, type, arg0);
2767 arg1 = fold_convert_loc (loc, type, arg1);
2768 switch (code)
2770 case MINUS_EXPR:
2771 if (integer_zerop (arg0) && !unsr_p)
2773 expand_neg_overflow (loc, lhs, arg1, false, NULL);
2774 return;
2776 /* FALLTHRU */
2777 case PLUS_EXPR:
2778 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2779 unsr_p, unsr_p, false, NULL);
2780 return;
2781 case MULT_EXPR:
2782 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2783 unsr_p, unsr_p, false, NULL);
2784 return;
2785 default:
2786 gcc_unreachable ();
2790 /* For sub-word operations, retry with a wider type first. */
2791 if (orig_precres == precres && precop <= BITS_PER_WORD)
2793 int p = MAX (min_precision, precop);
2794 scalar_int_mode m = smallest_int_mode_for_size (p);
2795 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2796 uns0_p && uns1_p
2797 && unsr_p);
2798 p = TYPE_PRECISION (optype);
2799 if (p > precres)
2801 precres = p;
2802 unsr_p = TYPE_UNSIGNED (optype);
2803 type = optype;
2804 continue;
2808 if (prec0 <= precres && prec1 <= precres)
2810 tree types[2];
2811 if (unsr_p)
2813 types[0] = build_nonstandard_integer_type (precres, 0);
2814 types[1] = type;
2816 else
2818 types[0] = type;
2819 types[1] = build_nonstandard_integer_type (precres, 1);
2821 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2822 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2823 if (code != MULT_EXPR)
2824 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2825 uns0_p, uns1_p, false, NULL);
2826 else
2827 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2828 uns0_p, uns1_p, false, NULL);
2829 return;
2832 /* Retry with a wider type. */
2833 if (orig_precres == precres)
2835 int p = MAX (prec0, prec1);
2836 scalar_int_mode m = smallest_int_mode_for_size (p);
2837 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2838 uns0_p && uns1_p
2839 && unsr_p);
2840 p = TYPE_PRECISION (optype);
2841 if (p > precres)
2843 precres = p;
2844 unsr_p = TYPE_UNSIGNED (optype);
2845 type = optype;
2846 continue;
2850 gcc_unreachable ();
2852 while (1);
2855 /* Expand ADD_OVERFLOW STMT. */
2857 static void
2858 expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
2860 expand_arith_overflow (PLUS_EXPR, stmt);
2863 /* Expand SUB_OVERFLOW STMT. */
2865 static void
2866 expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
2868 expand_arith_overflow (MINUS_EXPR, stmt);
2871 /* Expand MUL_OVERFLOW STMT. */
2873 static void
2874 expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
2876 expand_arith_overflow (MULT_EXPR, stmt);
2879 /* Expand UADDC STMT. */
2881 static void
2882 expand_UADDC (internal_fn ifn, gcall *stmt)
2884 tree lhs = gimple_call_lhs (stmt);
2885 tree arg1 = gimple_call_arg (stmt, 0);
2886 tree arg2 = gimple_call_arg (stmt, 1);
2887 tree arg3 = gimple_call_arg (stmt, 2);
2888 tree type = TREE_TYPE (arg1);
2889 machine_mode mode = TYPE_MODE (type);
2890 insn_code icode = optab_handler (ifn == IFN_UADDC
2891 ? uaddc5_optab : usubc5_optab, mode);
2892 rtx op1 = expand_normal (arg1);
2893 rtx op2 = expand_normal (arg2);
2894 rtx op3 = expand_normal (arg3);
2895 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2896 rtx re = gen_reg_rtx (mode);
2897 rtx im = gen_reg_rtx (mode);
2898 class expand_operand ops[5];
2899 create_output_operand (&ops[0], re, mode);
2900 create_output_operand (&ops[1], im, mode);
2901 create_input_operand (&ops[2], op1, mode);
2902 create_input_operand (&ops[3], op2, mode);
2903 create_input_operand (&ops[4], op3, mode);
2904 expand_insn (icode, 5, ops);
2905 write_complex_part (target, re, false, false);
2906 write_complex_part (target, im, true, false);
2909 /* Expand USUBC STMT. */
2911 static void
2912 expand_USUBC (internal_fn ifn, gcall *stmt)
2914 expand_UADDC (ifn, stmt);
2917 /* This should get folded in tree-vectorizer.cc. */
2919 static void
2920 expand_LOOP_VECTORIZED (internal_fn, gcall *)
2922 gcc_unreachable ();
2925 /* This should get folded in tree-vectorizer.cc. */
2927 static void
2928 expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2930 gcc_unreachable ();
2933 /* Return a memory reference of type TYPE for argument INDEX of STMT.
2934 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2936 static tree
2937 expand_call_mem_ref (tree type, gcall *stmt, int index)
2939 tree addr = gimple_call_arg (stmt, index);
2940 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2941 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2942 if (TYPE_ALIGN (type) != align)
2943 type = build_aligned_type (type, align);
2945 tree tmp = addr;
2946 if (TREE_CODE (tmp) == SSA_NAME)
2948 gimple *def = SSA_NAME_DEF_STMT (tmp);
2949 if (gimple_assign_single_p (def))
2950 tmp = gimple_assign_rhs1 (def);
2953 if (TREE_CODE (tmp) == ADDR_EXPR)
2955 tree mem = TREE_OPERAND (tmp, 0);
2956 if (TREE_CODE (mem) == TARGET_MEM_REF
2957 && types_compatible_p (TREE_TYPE (mem), type))
2959 tree offset = TMR_OFFSET (mem);
2960 if (type != TREE_TYPE (mem)
2961 || alias_ptr_type != TREE_TYPE (offset)
2962 || !integer_zerop (offset))
2964 mem = copy_node (mem);
2965 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2966 wi::to_poly_wide (offset));
2967 TREE_TYPE (mem) = type;
2969 return mem;
2973 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2976 /* Expand MASK_LOAD{,_LANES}, MASK_LEN_LOAD or LEN_LOAD call STMT using optab
2977 * OPTAB. */
2979 static void
2980 expand_partial_load_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
2982 int i = 0;
2983 class expand_operand ops[5];
2984 tree type, lhs, rhs, maskt;
2985 rtx mem, target;
2986 insn_code icode;
2988 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
2989 lhs = gimple_call_lhs (stmt);
2990 if (lhs == NULL_TREE)
2991 return;
2992 type = TREE_TYPE (lhs);
2993 rhs = expand_call_mem_ref (type, stmt, 0);
2995 if (optab == vec_mask_load_lanes_optab
2996 || optab == vec_mask_len_load_lanes_optab)
2997 icode = get_multi_vector_move (type, optab);
2998 else if (optab == len_load_optab)
2999 icode = direct_optab_handler (optab, TYPE_MODE (type));
3000 else
3001 icode = convert_optab_handler (optab, TYPE_MODE (type),
3002 TYPE_MODE (TREE_TYPE (maskt)));
3004 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3005 gcc_assert (MEM_P (mem));
3006 /* The built MEM_REF does not accurately reflect that the load
3007 is only partial. Clear it. */
3008 set_mem_expr (mem, NULL_TREE);
3009 clear_mem_offset (mem);
3010 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3011 create_output_operand (&ops[i++], target, TYPE_MODE (type));
3012 create_fixed_operand (&ops[i++], mem);
3013 i = add_mask_and_len_args (ops, i, stmt);
3014 expand_insn (icode, i, ops);
3016 if (!rtx_equal_p (target, ops[0].value))
3017 emit_move_insn (target, ops[0].value);
3020 #define expand_mask_load_optab_fn expand_partial_load_optab_fn
3021 #define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
3022 #define expand_len_load_optab_fn expand_partial_load_optab_fn
3023 #define expand_mask_len_load_optab_fn expand_partial_load_optab_fn
3025 /* Expand MASK_STORE{,_LANES}, MASK_LEN_STORE or LEN_STORE call STMT using optab
3026 * OPTAB. */
3028 static void
3029 expand_partial_store_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
3031 int i = 0;
3032 class expand_operand ops[5];
3033 tree type, lhs, rhs, maskt;
3034 rtx mem, reg;
3035 insn_code icode;
3037 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
3038 rhs = gimple_call_arg (stmt, internal_fn_stored_value_index (ifn));
3039 type = TREE_TYPE (rhs);
3040 lhs = expand_call_mem_ref (type, stmt, 0);
3042 if (optab == vec_mask_store_lanes_optab
3043 || optab == vec_mask_len_store_lanes_optab)
3044 icode = get_multi_vector_move (type, optab);
3045 else if (optab == len_store_optab)
3046 icode = direct_optab_handler (optab, TYPE_MODE (type));
3047 else
3048 icode = convert_optab_handler (optab, TYPE_MODE (type),
3049 TYPE_MODE (TREE_TYPE (maskt)));
3051 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3052 gcc_assert (MEM_P (mem));
3053 /* The built MEM_REF does not accurately reflect that the store
3054 is only partial. Clear it. */
3055 set_mem_expr (mem, NULL_TREE);
3056 clear_mem_offset (mem);
3057 reg = expand_normal (rhs);
3058 create_fixed_operand (&ops[i++], mem);
3059 create_input_operand (&ops[i++], reg, TYPE_MODE (type));
3060 i = add_mask_and_len_args (ops, i, stmt);
3061 expand_insn (icode, i, ops);
3064 #define expand_mask_store_optab_fn expand_partial_store_optab_fn
3065 #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
3066 #define expand_len_store_optab_fn expand_partial_store_optab_fn
3067 #define expand_mask_len_store_optab_fn expand_partial_store_optab_fn
3069 /* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
3070 The expansion of STMT happens based on OPTAB table associated. */
3072 static void
3073 expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3075 class expand_operand ops[6];
3076 insn_code icode;
3077 tree lhs = gimple_call_lhs (stmt);
3078 tree op0a = gimple_call_arg (stmt, 0);
3079 tree op0b = gimple_call_arg (stmt, 1);
3080 tree op1 = gimple_call_arg (stmt, 2);
3081 tree op2 = gimple_call_arg (stmt, 3);
3082 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
3084 tree vec_cond_type = TREE_TYPE (lhs);
3085 tree op_mode = TREE_TYPE (op0a);
3086 bool unsignedp = TYPE_UNSIGNED (op_mode);
3088 machine_mode mode = TYPE_MODE (vec_cond_type);
3089 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
3091 icode = convert_optab_handler (optab, mode, cmp_op_mode);
3092 rtx comparison
3093 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
3094 /* vector_compare_rtx legitimizes operands, preserve equality when
3095 expanding op1/op2. */
3096 rtx rtx_op1, rtx_op2;
3097 if (operand_equal_p (op1, op0a))
3098 rtx_op1 = XEXP (comparison, 0);
3099 else if (operand_equal_p (op1, op0b))
3100 rtx_op1 = XEXP (comparison, 1);
3101 else
3102 rtx_op1 = expand_normal (op1);
3103 if (operand_equal_p (op2, op0a))
3104 rtx_op2 = XEXP (comparison, 0);
3105 else if (operand_equal_p (op2, op0b))
3106 rtx_op2 = XEXP (comparison, 1);
3107 else
3108 rtx_op2 = expand_normal (op2);
3110 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3111 create_output_operand (&ops[0], target, mode);
3112 create_input_operand (&ops[1], rtx_op1, mode);
3113 create_input_operand (&ops[2], rtx_op2, mode);
3114 create_fixed_operand (&ops[3], comparison);
3115 create_fixed_operand (&ops[4], XEXP (comparison, 0));
3116 create_fixed_operand (&ops[5], XEXP (comparison, 1));
3117 expand_insn (icode, 6, ops);
3118 if (!rtx_equal_p (ops[0].value, target))
3119 emit_move_insn (target, ops[0].value);
3122 /* Expand VCOND_MASK optab internal function.
3123 The expansion of STMT happens based on OPTAB table associated. */
3125 static void
3126 expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3128 class expand_operand ops[4];
3130 tree lhs = gimple_call_lhs (stmt);
3131 tree op0 = gimple_call_arg (stmt, 0);
3132 tree op1 = gimple_call_arg (stmt, 1);
3133 tree op2 = gimple_call_arg (stmt, 2);
3134 tree vec_cond_type = TREE_TYPE (lhs);
3136 machine_mode mode = TYPE_MODE (vec_cond_type);
3137 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
3138 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
3139 rtx mask, rtx_op1, rtx_op2;
3141 gcc_assert (icode != CODE_FOR_nothing);
3143 mask = expand_normal (op0);
3144 rtx_op1 = expand_normal (op1);
3145 rtx_op2 = expand_normal (op2);
3147 mask = force_reg (mask_mode, mask);
3148 rtx_op1 = force_reg (mode, rtx_op1);
3150 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3151 create_output_operand (&ops[0], target, mode);
3152 create_input_operand (&ops[1], rtx_op1, mode);
3153 create_input_operand (&ops[2], rtx_op2, mode);
3154 create_input_operand (&ops[3], mask, mask_mode);
3155 expand_insn (icode, 4, ops);
3156 if (!rtx_equal_p (ops[0].value, target))
3157 emit_move_insn (target, ops[0].value);
3160 /* Expand VEC_SET internal functions. */
3162 static void
3163 expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3165 tree lhs = gimple_call_lhs (stmt);
3166 tree op0 = gimple_call_arg (stmt, 0);
3167 tree op1 = gimple_call_arg (stmt, 1);
3168 tree op2 = gimple_call_arg (stmt, 2);
3169 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3170 rtx src = expand_normal (op0);
3172 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3173 scalar_mode innermode = GET_MODE_INNER (outermode);
3175 rtx value = expand_normal (op1);
3176 rtx pos = expand_normal (op2);
3178 class expand_operand ops[3];
3179 enum insn_code icode = optab_handler (optab, outermode);
3181 if (icode != CODE_FOR_nothing)
3183 rtx temp = gen_reg_rtx (outermode);
3184 emit_move_insn (temp, src);
3186 create_fixed_operand (&ops[0], temp);
3187 create_input_operand (&ops[1], value, innermode);
3188 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
3189 true);
3190 if (maybe_expand_insn (icode, 3, ops))
3192 emit_move_insn (target, temp);
3193 return;
3196 gcc_unreachable ();
3199 static void
3200 expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
3204 static void
3205 expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
3207 /* When guessing was done, the hints should be already stripped away. */
3208 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
3210 rtx target;
3211 tree lhs = gimple_call_lhs (stmt);
3212 if (lhs)
3213 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3214 else
3215 target = const0_rtx;
3216 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
3217 if (lhs && val != target)
3218 emit_move_insn (target, val);
3221 /* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
3222 should never be called. */
3224 static void
3225 expand_VA_ARG (internal_fn, gcall *)
3227 gcc_unreachable ();
3230 /* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
3231 dummy function should never be called. */
3233 static void
3234 expand_VEC_CONVERT (internal_fn, gcall *)
3236 gcc_unreachable ();
3239 /* Expand IFN_RAWMEMCHR internal function. */
3241 void
3242 expand_RAWMEMCHR (internal_fn, gcall *stmt)
3244 expand_operand ops[3];
3246 tree lhs = gimple_call_lhs (stmt);
3247 if (!lhs)
3248 return;
3249 machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
3250 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3251 create_output_operand (&ops[0], lhs_rtx, lhs_mode);
3253 tree mem = gimple_call_arg (stmt, 0);
3254 rtx mem_rtx = get_memory_rtx (mem, NULL);
3255 create_fixed_operand (&ops[1], mem_rtx);
3257 tree pattern = gimple_call_arg (stmt, 1);
3258 machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
3259 rtx pattern_rtx = expand_normal (pattern);
3260 create_input_operand (&ops[2], pattern_rtx, mode);
3262 insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
3264 expand_insn (icode, 3, ops);
3265 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3266 emit_move_insn (lhs_rtx, ops[0].value);
3269 /* Expand the IFN_UNIQUE function according to its first argument. */
3271 static void
3272 expand_UNIQUE (internal_fn, gcall *stmt)
3274 rtx pattern = NULL_RTX;
3275 enum ifn_unique_kind kind
3276 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
3278 switch (kind)
3280 default:
3281 gcc_unreachable ();
3283 case IFN_UNIQUE_UNSPEC:
3284 if (targetm.have_unique ())
3285 pattern = targetm.gen_unique ();
3286 break;
3288 case IFN_UNIQUE_OACC_FORK:
3289 case IFN_UNIQUE_OACC_JOIN:
3290 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
3292 tree lhs = gimple_call_lhs (stmt);
3293 rtx target = const0_rtx;
3295 if (lhs)
3296 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3298 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
3299 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
3301 if (kind == IFN_UNIQUE_OACC_FORK)
3302 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
3303 else
3304 pattern = targetm.gen_oacc_join (target, data_dep, axis);
3306 else
3307 gcc_unreachable ();
3308 break;
3311 if (pattern)
3312 emit_insn (pattern);
3315 /* Expand the IFN_DEFERRED_INIT function:
3316 LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
3318 Initialize the LHS with zero/pattern according to its second argument
3319 INIT_TYPE:
3320 if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
3321 if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
3322 to initialize;
3323 The LHS variable is initialized including paddings.
3324 The reasons to choose 0xFE for pattern initialization are:
3325 1. It is a non-canonical virtual address on x86_64, and at the
3326 high end of the i386 kernel address space.
3327 2. It is a very large float value (-1.694739530317379e+38).
3328 3. It is also an unusual number for integers. */
3329 #define INIT_PATTERN_VALUE 0xFE
3330 static void
3331 expand_DEFERRED_INIT (internal_fn, gcall *stmt)
3333 tree lhs = gimple_call_lhs (stmt);
3334 tree var_size = gimple_call_arg (stmt, 0);
3335 enum auto_init_type init_type
3336 = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
3337 bool reg_lhs = true;
3339 tree var_type = TREE_TYPE (lhs);
3340 gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
3342 if (TREE_CODE (lhs) == SSA_NAME)
3343 reg_lhs = true;
3344 else
3346 tree lhs_base = lhs;
3347 while (handled_component_p (lhs_base))
3348 lhs_base = TREE_OPERAND (lhs_base, 0);
3349 reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
3350 || non_mem_decl_p (lhs_base));
3351 /* If this expands to a register and the underlying decl is wrapped in
3352 a MEM_REF that just serves as an access type change expose the decl
3353 if it is of correct size. This avoids a situation as in PR103271
3354 if the target does not support a direct move to the registers mode. */
3355 if (reg_lhs
3356 && TREE_CODE (lhs_base) == MEM_REF
3357 && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
3358 && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
3359 && integer_zerop (TREE_OPERAND (lhs_base, 1))
3360 && tree_fits_uhwi_p (var_size)
3361 && tree_int_cst_equal
3362 (var_size,
3363 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
3365 lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
3366 var_type = TREE_TYPE (lhs);
3370 if (!reg_lhs)
3372 /* If the variable is not in register, expand to a memset
3373 to initialize it. */
3374 mark_addressable (lhs);
3375 tree var_addr = build_fold_addr_expr (lhs);
3377 tree value = (init_type == AUTO_INIT_PATTERN)
3378 ? build_int_cst (integer_type_node,
3379 INIT_PATTERN_VALUE)
3380 : integer_zero_node;
3381 tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
3382 3, var_addr, value, var_size);
3383 /* Expand this memset call. */
3384 expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
3386 else
3388 /* If this variable is in a register use expand_assignment.
3389 For boolean scalars force zero-init. */
3390 tree init;
3391 scalar_int_mode var_mode;
3392 if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
3393 && tree_fits_uhwi_p (var_size)
3394 && (init_type == AUTO_INIT_PATTERN
3395 || !is_gimple_reg_type (var_type))
3396 && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
3397 0).exists (&var_mode)
3398 && have_insn_for (SET, var_mode))
3400 unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
3401 unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
3402 memset (buf, (init_type == AUTO_INIT_PATTERN
3403 ? INIT_PATTERN_VALUE : 0), total_bytes);
3404 tree itype = build_nonstandard_integer_type
3405 (total_bytes * BITS_PER_UNIT, 1);
3406 wide_int w = wi::from_buffer (buf, total_bytes);
3407 init = wide_int_to_tree (itype, w);
3408 /* Pun the LHS to make sure its type has constant size
3409 unless it is an SSA name where that's already known. */
3410 if (TREE_CODE (lhs) != SSA_NAME)
3411 lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
3412 else
3413 init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
3415 else
3416 /* Use zero-init also for variable-length sizes. */
3417 init = build_zero_cst (var_type);
3419 expand_assignment (lhs, init, false);
3423 /* The size of an OpenACC compute dimension. */
3425 static void
3426 expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
3428 tree lhs = gimple_call_lhs (stmt);
3430 if (!lhs)
3431 return;
3433 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3434 if (targetm.have_oacc_dim_size ())
3436 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3437 VOIDmode, EXPAND_NORMAL);
3438 emit_insn (targetm.gen_oacc_dim_size (target, dim));
3440 else
3441 emit_move_insn (target, GEN_INT (1));
3444 /* The position of an OpenACC execution engine along one compute axis. */
3446 static void
3447 expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
3449 tree lhs = gimple_call_lhs (stmt);
3451 if (!lhs)
3452 return;
3454 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3455 if (targetm.have_oacc_dim_pos ())
3457 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3458 VOIDmode, EXPAND_NORMAL);
3459 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
3461 else
3462 emit_move_insn (target, const0_rtx);
3465 /* This is expanded by oacc_device_lower pass. */
3467 static void
3468 expand_GOACC_LOOP (internal_fn, gcall *)
3470 gcc_unreachable ();
3473 /* This is expanded by oacc_device_lower pass. */
3475 static void
3476 expand_GOACC_REDUCTION (internal_fn, gcall *)
3478 gcc_unreachable ();
3481 /* This is expanded by oacc_device_lower pass. */
3483 static void
3484 expand_GOACC_TILE (internal_fn, gcall *)
3486 gcc_unreachable ();
3489 /* Set errno to EDOM. */
3491 static void
3492 expand_SET_EDOM (internal_fn, gcall *)
3494 #ifdef TARGET_EDOM
3495 #ifdef GEN_ERRNO_RTX
3496 rtx errno_rtx = GEN_ERRNO_RTX;
3497 #else
3498 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
3499 #endif
3500 emit_move_insn (errno_rtx,
3501 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
3502 #else
3503 gcc_unreachable ();
3504 #endif
3507 /* Expand atomic bit test and set. */
3509 static void
3510 expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
3512 expand_ifn_atomic_bit_test_and (call);
3515 /* Expand atomic bit test and complement. */
3517 static void
3518 expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
3520 expand_ifn_atomic_bit_test_and (call);
3523 /* Expand atomic bit test and reset. */
3525 static void
3526 expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
3528 expand_ifn_atomic_bit_test_and (call);
3531 /* Expand atomic bit test and set. */
3533 static void
3534 expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
3536 expand_ifn_atomic_compare_exchange (call);
3539 /* Expand atomic add fetch and cmp with 0. */
3541 static void
3542 expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
3544 expand_ifn_atomic_op_fetch_cmp_0 (call);
3547 /* Expand atomic sub fetch and cmp with 0. */
3549 static void
3550 expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
3552 expand_ifn_atomic_op_fetch_cmp_0 (call);
3555 /* Expand atomic and fetch and cmp with 0. */
3557 static void
3558 expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
3560 expand_ifn_atomic_op_fetch_cmp_0 (call);
3563 /* Expand atomic or fetch and cmp with 0. */
3565 static void
3566 expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
3568 expand_ifn_atomic_op_fetch_cmp_0 (call);
3571 /* Expand atomic xor fetch and cmp with 0. */
3573 static void
3574 expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
3576 expand_ifn_atomic_op_fetch_cmp_0 (call);
3579 /* Expand LAUNDER to assignment, lhs = arg0. */
3581 static void
3582 expand_LAUNDER (internal_fn, gcall *call)
3584 tree lhs = gimple_call_lhs (call);
3586 if (!lhs)
3587 return;
3589 expand_assignment (lhs, gimple_call_arg (call, 0), false);
3592 /* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
3594 static void
3595 expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3597 internal_fn ifn = gimple_call_internal_fn (stmt);
3598 int rhs_index = internal_fn_stored_value_index (ifn);
3599 tree base = gimple_call_arg (stmt, 0);
3600 tree offset = gimple_call_arg (stmt, 1);
3601 tree scale = gimple_call_arg (stmt, 2);
3602 tree rhs = gimple_call_arg (stmt, rhs_index);
3604 rtx base_rtx = expand_normal (base);
3605 rtx offset_rtx = expand_normal (offset);
3606 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3607 rtx rhs_rtx = expand_normal (rhs);
3609 class expand_operand ops[8];
3610 int i = 0;
3611 create_address_operand (&ops[i++], base_rtx);
3612 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3613 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3614 create_integer_operand (&ops[i++], scale_int);
3615 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
3616 i = add_mask_and_len_args (ops, i, stmt);
3618 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
3619 TYPE_MODE (TREE_TYPE (offset)));
3620 expand_insn (icode, i, ops);
3623 /* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
3625 static void
3626 expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3628 tree lhs = gimple_call_lhs (stmt);
3629 tree base = gimple_call_arg (stmt, 0);
3630 tree offset = gimple_call_arg (stmt, 1);
3631 tree scale = gimple_call_arg (stmt, 2);
3633 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3634 rtx base_rtx = expand_normal (base);
3635 rtx offset_rtx = expand_normal (offset);
3636 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3638 int i = 0;
3639 class expand_operand ops[8];
3640 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
3641 create_address_operand (&ops[i++], base_rtx);
3642 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3643 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3644 create_integer_operand (&ops[i++], scale_int);
3645 i = add_mask_and_len_args (ops, i, stmt);
3646 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
3647 TYPE_MODE (TREE_TYPE (offset)));
3648 expand_insn (icode, i, ops);
3649 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3650 emit_move_insn (lhs_rtx, ops[0].value);
3653 /* Helper for expand_DIVMOD. Return true if the sequence starting with
3654 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
3656 static bool
3657 contains_call_div_mod (rtx_insn *insn)
3659 subrtx_iterator::array_type array;
3660 for (; insn; insn = NEXT_INSN (insn))
3661 if (CALL_P (insn))
3662 return true;
3663 else if (INSN_P (insn))
3664 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3665 switch (GET_CODE (*iter))
3667 case CALL:
3668 case DIV:
3669 case UDIV:
3670 case MOD:
3671 case UMOD:
3672 return true;
3673 default:
3674 break;
3676 return false;
3679 /* Expand DIVMOD() using:
3680 a) optab handler for udivmod/sdivmod if it is available.
3681 b) If optab_handler doesn't exist, generate call to
3682 target-specific divmod libfunc. */
3684 static void
3685 expand_DIVMOD (internal_fn, gcall *call_stmt)
3687 tree lhs = gimple_call_lhs (call_stmt);
3688 tree arg0 = gimple_call_arg (call_stmt, 0);
3689 tree arg1 = gimple_call_arg (call_stmt, 1);
3691 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3692 tree type = TREE_TYPE (TREE_TYPE (lhs));
3693 machine_mode mode = TYPE_MODE (type);
3694 bool unsignedp = TYPE_UNSIGNED (type);
3695 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3697 rtx op0 = expand_normal (arg0);
3698 rtx op1 = expand_normal (arg1);
3699 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3701 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3702 rtx_insn *insns = NULL;
3704 if (TREE_CODE (arg1) == INTEGER_CST)
3706 /* For DIVMOD by integral constants, there could be efficient code
3707 expanded inline e.g. using shifts and plus/minus. Try to expand
3708 the division and modulo and if it emits any library calls or any
3709 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3710 divmod libcall. */
3711 scalar_int_mode int_mode;
3712 if (remainder == NULL_RTX
3713 && optimize
3714 && CONST_INT_P (op1)
3715 && !pow2p_hwi (INTVAL (op1))
3716 && is_int_mode (TYPE_MODE (type), &int_mode)
3717 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
3718 && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
3719 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
3720 && optimize_insn_for_speed_p ())
3722 rtx_insn *last = get_last_insn ();
3723 remainder = NULL_RTX;
3724 quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
3725 TYPE_UNSIGNED (type));
3726 if (quotient != NULL_RTX)
3728 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
3730 rtx_insn *move = emit_move_insn (quotient, quotient);
3731 set_dst_reg_note (move, REG_EQUAL,
3732 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3733 ? UDIV : DIV, int_mode,
3734 copy_rtx (op0), op1),
3735 quotient);
3736 move = emit_move_insn (remainder, remainder);
3737 set_dst_reg_note (move, REG_EQUAL,
3738 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3739 ? UMOD : MOD, int_mode,
3740 copy_rtx (op0), op1),
3741 quotient);
3744 else
3745 delete_insns_since (last);
3748 if (remainder == NULL_RTX)
3750 struct separate_ops ops;
3751 ops.code = TRUNC_DIV_EXPR;
3752 ops.type = type;
3753 ops.op0 = make_tree (ops.type, op0);
3754 ops.op1 = arg1;
3755 ops.op2 = NULL_TREE;
3756 ops.location = gimple_location (call_stmt);
3757 start_sequence ();
3758 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
3759 if (contains_call_div_mod (get_insns ()))
3760 quotient = NULL_RTX;
3761 else
3763 ops.code = TRUNC_MOD_EXPR;
3764 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
3765 EXPAND_NORMAL);
3766 if (contains_call_div_mod (get_insns ()))
3767 remainder = NULL_RTX;
3769 if (remainder)
3770 insns = get_insns ();
3771 end_sequence ();
3775 if (remainder)
3776 emit_insn (insns);
3778 /* Check if optab_handler exists for divmod_optab for given mode. */
3779 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
3781 quotient = gen_reg_rtx (mode);
3782 remainder = gen_reg_rtx (mode);
3783 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3786 /* Generate call to divmod libfunc if it exists. */
3787 else if (rtx libfunc = optab_libfunc (tab, mode))
3788 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3789 &quotient, &remainder);
3791 else
3792 gcc_unreachable ();
3794 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3795 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3796 make_tree (TREE_TYPE (arg0), quotient),
3797 make_tree (TREE_TYPE (arg1), remainder)),
3798 target, VOIDmode, EXPAND_NORMAL);
3801 /* Expand a NOP. */
3803 static void
3804 expand_NOP (internal_fn, gcall *)
3806 /* Nothing. But it shouldn't really prevail. */
3809 /* Coroutines, all should have been processed at this stage. */
3811 static void
3812 expand_CO_FRAME (internal_fn, gcall *)
3814 gcc_unreachable ();
3817 static void
3818 expand_CO_YIELD (internal_fn, gcall *)
3820 gcc_unreachable ();
3823 static void
3824 expand_CO_SUSPN (internal_fn, gcall *)
3826 gcc_unreachable ();
3829 static void
3830 expand_CO_ACTOR (internal_fn, gcall *)
3832 gcc_unreachable ();
3835 /* Expand a call to FN using the operands in STMT. FN has a single
3836 output operand and NARGS input operands. */
3838 static void
3839 expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3840 unsigned int nargs)
3842 tree_pair types = direct_internal_fn_types (fn, stmt);
3843 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
3844 expand_fn_using_insn (stmt, icode, 1, nargs);
3847 /* Expand WHILE_ULT call STMT using optab OPTAB. */
3849 static void
3850 expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3852 expand_operand ops[4];
3853 tree rhs_type[2];
3855 tree lhs = gimple_call_lhs (stmt);
3856 tree lhs_type = TREE_TYPE (lhs);
3857 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3858 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3860 for (unsigned int i = 0; i < 2; ++i)
3862 tree rhs = gimple_call_arg (stmt, i);
3863 rhs_type[i] = TREE_TYPE (rhs);
3864 rtx rhs_rtx = expand_normal (rhs);
3865 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3868 int opcnt;
3869 if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
3871 /* When the mask is an integer mode the exact vector length may not
3872 be clear to the backend, so we pass it in operand[3].
3873 Use the vector in arg2 for the most reliable intended size. */
3874 tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
3875 create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
3876 opcnt = 4;
3878 else
3879 /* The mask has a vector type so the length operand is unnecessary. */
3880 opcnt = 3;
3882 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3883 TYPE_MODE (lhs_type));
3885 expand_insn (icode, opcnt, ops);
3886 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3887 emit_move_insn (lhs_rtx, ops[0].value);
3890 /* Expand a call to a convert-like optab using the operands in STMT.
3891 FN has a single output operand and NARGS input operands. */
3893 static void
3894 expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
3895 unsigned int nargs)
3897 tree_pair types = direct_internal_fn_types (fn, stmt);
3898 insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
3899 TYPE_MODE (types.second));
3900 expand_fn_using_insn (stmt, icode, 1, nargs);
3903 /* Expanders for optabs that can use expand_direct_optab_fn. */
3905 #define expand_unary_optab_fn(FN, STMT, OPTAB) \
3906 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
3908 #define expand_binary_optab_fn(FN, STMT, OPTAB) \
3909 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3911 #define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3912 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3914 #define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
3915 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3917 #define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
3918 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3920 #define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3921 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3923 #define expand_cond_len_unary_optab_fn(FN, STMT, OPTAB) \
3924 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3926 #define expand_cond_len_binary_optab_fn(FN, STMT, OPTAB) \
3927 expand_direct_optab_fn (FN, STMT, OPTAB, 6)
3929 #define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
3930 expand_direct_optab_fn (FN, STMT, OPTAB, 7)
3932 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3933 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3935 #define expand_fold_len_extract_optab_fn(FN, STMT, OPTAB) \
3936 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3938 #define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3939 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3941 #define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3942 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3944 #define expand_mask_len_fold_left_optab_fn(FN, STMT, OPTAB) \
3945 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3947 #define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3948 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3950 /* Expanders for optabs that can use expand_convert_optab_fn. */
3952 #define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
3953 expand_convert_optab_fn (FN, STMT, OPTAB, 1)
3955 #define expand_vec_extract_optab_fn(FN, STMT, OPTAB) \
3956 expand_convert_optab_fn (FN, STMT, OPTAB, 2)
3958 /* RETURN_TYPE and ARGS are a return type and argument list that are
3959 in principle compatible with FN (which satisfies direct_internal_fn_p).
3960 Return the types that should be used to determine whether the
3961 target supports FN. */
3963 tree_pair
3964 direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3966 const direct_internal_fn_info &info = direct_internal_fn (fn);
3967 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3968 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3969 return tree_pair (type0, type1);
3972 /* CALL is a call whose return type and arguments are in principle
3973 compatible with FN (which satisfies direct_internal_fn_p). Return the
3974 types that should be used to determine whether the target supports FN. */
3976 tree_pair
3977 direct_internal_fn_types (internal_fn fn, gcall *call)
3979 const direct_internal_fn_info &info = direct_internal_fn (fn);
3980 tree op0 = (info.type0 < 0
3981 ? gimple_call_lhs (call)
3982 : gimple_call_arg (call, info.type0));
3983 tree op1 = (info.type1 < 0
3984 ? gimple_call_lhs (call)
3985 : gimple_call_arg (call, info.type1));
3986 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3989 /* Return true if OPTAB is supported for TYPES (whose modes should be
3990 the same) when the optimization type is OPT_TYPE. Used for simple
3991 direct optabs. */
3993 static bool
3994 direct_optab_supported_p (direct_optab optab, tree_pair types,
3995 optimization_type opt_type)
3997 machine_mode mode = TYPE_MODE (types.first);
3998 gcc_checking_assert (mode == TYPE_MODE (types.second));
3999 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
4002 /* Return true if OPTAB is supported for TYPES, where the first type
4003 is the destination and the second type is the source. Used for
4004 convert optabs. */
4006 static bool
4007 convert_optab_supported_p (convert_optab optab, tree_pair types,
4008 optimization_type opt_type)
4010 return (convert_optab_handler (optab, TYPE_MODE (types.first),
4011 TYPE_MODE (types.second), opt_type)
4012 != CODE_FOR_nothing);
4015 /* Return true if load/store lanes optab OPTAB is supported for
4016 array type TYPES.first when the optimization type is OPT_TYPE. */
4018 static bool
4019 multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
4020 optimization_type opt_type)
4022 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
4023 machine_mode imode = TYPE_MODE (types.first);
4024 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
4025 return (convert_optab_handler (optab, imode, vmode, opt_type)
4026 != CODE_FOR_nothing);
4029 #define direct_unary_optab_supported_p direct_optab_supported_p
4030 #define direct_unary_convert_optab_supported_p convert_optab_supported_p
4031 #define direct_binary_optab_supported_p direct_optab_supported_p
4032 #define direct_ternary_optab_supported_p direct_optab_supported_p
4033 #define direct_cond_unary_optab_supported_p direct_optab_supported_p
4034 #define direct_cond_binary_optab_supported_p direct_optab_supported_p
4035 #define direct_cond_ternary_optab_supported_p direct_optab_supported_p
4036 #define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
4037 #define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
4038 #define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
4039 #define direct_mask_load_optab_supported_p convert_optab_supported_p
4040 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
4041 #define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
4042 #define direct_gather_load_optab_supported_p convert_optab_supported_p
4043 #define direct_len_load_optab_supported_p direct_optab_supported_p
4044 #define direct_mask_len_load_optab_supported_p convert_optab_supported_p
4045 #define direct_mask_store_optab_supported_p convert_optab_supported_p
4046 #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
4047 #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
4048 #define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
4049 #define direct_vec_cond_optab_supported_p convert_optab_supported_p
4050 #define direct_scatter_store_optab_supported_p convert_optab_supported_p
4051 #define direct_len_store_optab_supported_p direct_optab_supported_p
4052 #define direct_mask_len_store_optab_supported_p convert_optab_supported_p
4053 #define direct_while_optab_supported_p convert_optab_supported_p
4054 #define direct_fold_extract_optab_supported_p direct_optab_supported_p
4055 #define direct_fold_len_extract_optab_supported_p direct_optab_supported_p
4056 #define direct_fold_left_optab_supported_p direct_optab_supported_p
4057 #define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
4058 #define direct_mask_len_fold_left_optab_supported_p direct_optab_supported_p
4059 #define direct_check_ptrs_optab_supported_p direct_optab_supported_p
4060 #define direct_vec_set_optab_supported_p direct_optab_supported_p
4061 #define direct_vec_extract_optab_supported_p convert_optab_supported_p
4063 /* Return the optab used by internal function FN. */
4065 optab
4066 direct_internal_fn_optab (internal_fn fn, tree_pair types)
4068 switch (fn)
4070 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4071 case IFN_##CODE: break;
4072 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4073 case IFN_##CODE: return OPTAB##_optab;
4074 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4075 UNSIGNED_OPTAB, TYPE) \
4076 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
4077 ? UNSIGNED_OPTAB ## _optab \
4078 : SIGNED_OPTAB ## _optab);
4079 #include "internal-fn.def"
4081 case IFN_LAST:
4082 break;
4084 gcc_unreachable ();
4087 /* Return the optab used by internal function FN. */
4089 static optab
4090 direct_internal_fn_optab (internal_fn fn)
4092 switch (fn)
4094 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4095 case IFN_##CODE: break;
4096 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4097 case IFN_##CODE: return OPTAB##_optab;
4098 #include "internal-fn.def"
4100 case IFN_LAST:
4101 break;
4103 gcc_unreachable ();
4106 /* Return true if FN is supported for the types in TYPES when the
4107 optimization type is OPT_TYPE. The types are those associated with
4108 the "type0" and "type1" fields of FN's direct_internal_fn_info
4109 structure. */
4111 bool
4112 direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
4113 optimization_type opt_type)
4115 switch (fn)
4117 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4118 case IFN_##CODE: break;
4119 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4120 case IFN_##CODE: \
4121 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
4122 opt_type);
4123 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4124 UNSIGNED_OPTAB, TYPE) \
4125 case IFN_##CODE: \
4127 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
4128 ? UNSIGNED_OPTAB ## _optab \
4129 : SIGNED_OPTAB ## _optab); \
4130 return direct_##TYPE##_optab_supported_p (which_optab, types, \
4131 opt_type); \
4133 #include "internal-fn.def"
4135 case IFN_LAST:
4136 break;
4138 gcc_unreachable ();
4141 /* Return true if FN is supported for type TYPE when the optimization
4142 type is OPT_TYPE. The caller knows that the "type0" and "type1"
4143 fields of FN's direct_internal_fn_info structure are the same. */
4145 bool
4146 direct_internal_fn_supported_p (internal_fn fn, tree type,
4147 optimization_type opt_type)
4149 const direct_internal_fn_info &info = direct_internal_fn (fn);
4150 gcc_checking_assert (info.type0 == info.type1);
4151 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
4154 /* Return true if the STMT is supported when the optimization type is OPT_TYPE,
4155 given that STMT is a call to a direct internal function. */
4157 bool
4158 direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
4160 internal_fn fn = gimple_call_internal_fn (stmt);
4161 tree_pair types = direct_internal_fn_types (fn, stmt);
4162 return direct_internal_fn_supported_p (fn, types, opt_type);
4165 /* Return true if FN is a binary operation and if FN is commutative. */
4167 bool
4168 commutative_binary_fn_p (internal_fn fn)
4170 switch (fn)
4172 case IFN_AVG_FLOOR:
4173 case IFN_AVG_CEIL:
4174 case IFN_MULH:
4175 case IFN_MULHS:
4176 case IFN_MULHRS:
4177 case IFN_FMIN:
4178 case IFN_FMAX:
4179 case IFN_COMPLEX_MUL:
4180 case IFN_UBSAN_CHECK_ADD:
4181 case IFN_UBSAN_CHECK_MUL:
4182 case IFN_ADD_OVERFLOW:
4183 case IFN_MUL_OVERFLOW:
4184 case IFN_VEC_WIDEN_PLUS:
4185 case IFN_VEC_WIDEN_PLUS_LO:
4186 case IFN_VEC_WIDEN_PLUS_HI:
4187 case IFN_VEC_WIDEN_PLUS_EVEN:
4188 case IFN_VEC_WIDEN_PLUS_ODD:
4189 return true;
4191 default:
4192 return false;
4196 /* Return true if FN is a ternary operation and if its first two arguments
4197 are commutative. */
4199 bool
4200 commutative_ternary_fn_p (internal_fn fn)
4202 switch (fn)
4204 case IFN_FMA:
4205 case IFN_FMS:
4206 case IFN_FNMA:
4207 case IFN_FNMS:
4208 case IFN_UADDC:
4209 return true;
4211 default:
4212 return false;
4216 /* Return true if FN is an associative binary operation. */
4218 bool
4219 associative_binary_fn_p (internal_fn fn)
4221 switch (fn)
4223 case IFN_FMIN:
4224 case IFN_FMAX:
4225 return true;
4227 default:
4228 return false;
4232 /* If FN is commutative in two consecutive arguments, return the
4233 index of the first, otherwise return -1. */
4236 first_commutative_argument (internal_fn fn)
4238 switch (fn)
4240 case IFN_COND_ADD:
4241 case IFN_COND_MUL:
4242 case IFN_COND_MIN:
4243 case IFN_COND_MAX:
4244 case IFN_COND_FMIN:
4245 case IFN_COND_FMAX:
4246 case IFN_COND_AND:
4247 case IFN_COND_IOR:
4248 case IFN_COND_XOR:
4249 case IFN_COND_FMA:
4250 case IFN_COND_FMS:
4251 case IFN_COND_FNMA:
4252 case IFN_COND_FNMS:
4253 case IFN_COND_LEN_ADD:
4254 case IFN_COND_LEN_MUL:
4255 case IFN_COND_LEN_MIN:
4256 case IFN_COND_LEN_MAX:
4257 case IFN_COND_LEN_FMIN:
4258 case IFN_COND_LEN_FMAX:
4259 case IFN_COND_LEN_AND:
4260 case IFN_COND_LEN_IOR:
4261 case IFN_COND_LEN_XOR:
4262 case IFN_COND_LEN_FMA:
4263 case IFN_COND_LEN_FMS:
4264 case IFN_COND_LEN_FNMA:
4265 case IFN_COND_LEN_FNMS:
4266 return 1;
4268 default:
4269 if (commutative_binary_fn_p (fn)
4270 || commutative_ternary_fn_p (fn))
4271 return 0;
4272 return -1;
4276 /* Return true if this CODE describes an internal_fn that returns a vector with
4277 elements twice as wide as the element size of the input vectors. */
4279 bool
4280 widening_fn_p (code_helper code)
4282 if (!code.is_fn_code ())
4283 return false;
4285 if (!internal_fn_p ((combined_fn) code))
4286 return false;
4288 internal_fn fn = as_internal_fn ((combined_fn) code);
4289 switch (fn)
4291 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
4292 case IFN_##NAME: \
4293 case IFN_##NAME##_HI: \
4294 case IFN_##NAME##_LO: \
4295 case IFN_##NAME##_EVEN: \
4296 case IFN_##NAME##_ODD: \
4297 return true;
4298 #include "internal-fn.def"
4300 default:
4301 return false;
4305 /* Return true if IFN_SET_EDOM is supported. */
4307 bool
4308 set_edom_supported_p (void)
4310 #ifdef TARGET_EDOM
4311 return true;
4312 #else
4313 return false;
4314 #endif
4317 #define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4318 static void \
4319 expand_##CODE (internal_fn fn, gcall *stmt) \
4321 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
4323 #define DEF_INTERNAL_INT_EXT_FN(CODE, FLAGS, OPTAB, TYPE)
4324 #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4325 UNSIGNED_OPTAB, TYPE) \
4326 static void \
4327 expand_##CODE (internal_fn fn, gcall *stmt) \
4329 tree_pair types = direct_internal_fn_types (fn, stmt); \
4330 optab which_optab = direct_internal_fn_optab (fn, types); \
4331 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
4333 #include "internal-fn.def"
4335 /* Routines to expand each internal function, indexed by function number.
4336 Each routine has the prototype:
4338 expand_<NAME> (gcall *stmt)
4340 where STMT is the statement that performs the call. */
4341 static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
4343 #define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
4344 #include "internal-fn.def"
4348 /* Invoke T(CODE, SUFFIX) for each conditional function IFN_COND_##SUFFIX
4349 that maps to a tree code CODE. There is also an IFN_COND_LEN_##SUFFIX
4350 for each such IFN_COND_##SUFFIX. */
4351 #define FOR_EACH_CODE_MAPPING(T) \
4352 T (PLUS_EXPR, ADD) \
4353 T (MINUS_EXPR, SUB) \
4354 T (MULT_EXPR, MUL) \
4355 T (TRUNC_DIV_EXPR, DIV) \
4356 T (TRUNC_MOD_EXPR, MOD) \
4357 T (RDIV_EXPR, RDIV) \
4358 T (MIN_EXPR, MIN) \
4359 T (MAX_EXPR, MAX) \
4360 T (BIT_AND_EXPR, AND) \
4361 T (BIT_IOR_EXPR, IOR) \
4362 T (BIT_XOR_EXPR, XOR) \
4363 T (LSHIFT_EXPR, SHL) \
4364 T (RSHIFT_EXPR, SHR) \
4365 T (NEGATE_EXPR, NEG)
4367 /* Return a function that only performs CODE when a certain condition is met
4368 and that uses a given fallback value otherwise. For example, if CODE is
4369 a binary operation associated with conditional function FN:
4371 LHS = FN (COND, A, B, ELSE)
4373 is equivalent to the C expression:
4375 LHS = COND ? A CODE B : ELSE;
4377 operating elementwise if the operands are vectors.
4379 Return IFN_LAST if no such function exists. */
4381 internal_fn
4382 get_conditional_internal_fn (tree_code code)
4384 switch (code)
4386 #define CASE(CODE, IFN) case CODE: return IFN_COND_##IFN;
4387 FOR_EACH_CODE_MAPPING(CASE)
4388 #undef CASE
4389 default:
4390 return IFN_LAST;
4394 /* If IFN implements the conditional form of a tree code, return that
4395 tree code, otherwise return ERROR_MARK. */
4397 tree_code
4398 conditional_internal_fn_code (internal_fn ifn)
4400 switch (ifn)
4402 #define CASE(CODE, IFN) \
4403 case IFN_COND_##IFN: \
4404 case IFN_COND_LEN_##IFN: \
4405 return CODE;
4406 FOR_EACH_CODE_MAPPING (CASE)
4407 #undef CASE
4408 default:
4409 return ERROR_MARK;
4413 /* Like get_conditional_internal_fn, but return a function that
4414 additionally restricts the operation to the leading elements
4415 of a vector. The number of elements to process is given by a length
4416 and bias pair, as for IFN_LOAD_LEN. The values of the remaining
4417 elements are taken from the fallback ("else") argument.
4419 For example, if CODE is a binary operation associated with FN:
4421 LHS = FN (COND, A, B, ELSE, LEN, BIAS)
4423 is equivalent to the C code:
4425 for (int i = 0; i < NUNITS; i++)
4427 if (i < LEN + BIAS && COND[i])
4428 LHS[i] = A[i] CODE B[i];
4429 else
4430 LHS[i] = ELSE[i];
4434 internal_fn
4435 get_conditional_len_internal_fn (tree_code code)
4437 switch (code)
4439 #define CASE(CODE, IFN) case CODE: return IFN_COND_LEN_##IFN;
4440 FOR_EACH_CODE_MAPPING(CASE)
4441 #undef CASE
4442 default:
4443 return IFN_LAST;
4447 /* Invoke T(IFN) for each internal function IFN that also has an
4448 IFN_COND_* form. */
4449 #define FOR_EACH_COND_FN_PAIR(T) \
4450 T (FMAX) \
4451 T (FMIN) \
4452 T (FMA) \
4453 T (FMS) \
4454 T (FNMA) \
4455 T (FNMS)
4457 /* Return a function that only performs internal function FN when a
4458 certain condition is met and that uses a given fallback value otherwise.
4459 In other words, the returned function FN' is such that:
4461 LHS = FN' (COND, A1, ... An, ELSE)
4463 is equivalent to the C expression:
4465 LHS = COND ? FN (A1, ..., An) : ELSE;
4467 operating elementwise if the operands are vectors.
4469 Return IFN_LAST if no such function exists. */
4471 internal_fn
4472 get_conditional_internal_fn (internal_fn fn)
4474 switch (fn)
4476 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
4477 FOR_EACH_COND_FN_PAIR(CASE)
4478 #undef CASE
4479 default:
4480 return IFN_LAST;
4484 /* If there exists an internal function like IFN that operates on vectors,
4485 but with additional length and bias parameters, return the internal_fn
4486 for that function, otherwise return IFN_LAST. */
4487 internal_fn
4488 get_len_internal_fn (internal_fn fn)
4490 switch (fn)
4492 #define DEF_INTERNAL_COND_FN(NAME, ...) \
4493 case IFN_COND_##NAME: \
4494 return IFN_COND_LEN_##NAME;
4495 #define DEF_INTERNAL_SIGNED_COND_FN(NAME, ...) \
4496 case IFN_COND_##NAME: \
4497 return IFN_COND_LEN_##NAME;
4498 #include "internal-fn.def"
4499 default:
4500 return IFN_LAST;
4504 /* If IFN implements the conditional form of an unconditional internal
4505 function, return that unconditional function, otherwise return IFN_LAST. */
4507 internal_fn
4508 get_unconditional_internal_fn (internal_fn ifn)
4510 switch (ifn)
4512 #define CASE(NAME) \
4513 case IFN_COND_##NAME: \
4514 case IFN_COND_LEN_##NAME: \
4515 return IFN_##NAME;
4516 FOR_EACH_COND_FN_PAIR (CASE)
4517 #undef CASE
4518 default:
4519 return IFN_LAST;
4523 /* Return true if STMT can be interpreted as a conditional tree code
4524 operation of the form:
4526 LHS = COND ? OP (RHS1, ...) : ELSE;
4528 operating elementwise if the operands are vectors. This includes
4529 the case of an all-true COND, so that the operation always happens.
4531 There is an alternative approach to interpret the STMT when the operands
4532 are vectors which is the operation predicated by both conditional mask
4533 and loop control length, the equivalent C code:
4535 for (int i = 0; i < NUNTIS; i++)
4537 if (i < LEN + BIAS && COND[i])
4538 LHS[i] = A[i] CODE B[i];
4539 else
4540 LHS[i] = ELSE[i];
4543 When returning true, set:
4545 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
4546 is known to be all-true
4547 - *CODE_OUT to the tree code
4548 - OPS[I] to operand I of *CODE_OUT
4549 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
4550 condition is known to be all true.
4551 - *LEN to the len argument if it COND_LEN_* operations or to NULL_TREE.
4552 - *BIAS to the bias argument if it COND_LEN_* operations or to NULL_TREE. */
4554 bool
4555 can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
4556 tree_code *code_out,
4557 tree (&ops)[3], tree *else_out,
4558 tree *len, tree *bias)
4560 *len = NULL_TREE;
4561 *bias = NULL_TREE;
4562 if (gassign *assign = dyn_cast <gassign *> (stmt))
4564 *cond_out = NULL_TREE;
4565 *code_out = gimple_assign_rhs_code (assign);
4566 ops[0] = gimple_assign_rhs1 (assign);
4567 ops[1] = gimple_assign_rhs2 (assign);
4568 ops[2] = gimple_assign_rhs3 (assign);
4569 *else_out = NULL_TREE;
4570 return true;
4572 if (gcall *call = dyn_cast <gcall *> (stmt))
4573 if (gimple_call_internal_p (call))
4575 internal_fn ifn = gimple_call_internal_fn (call);
4576 tree_code code = conditional_internal_fn_code (ifn);
4577 int len_index = internal_fn_len_index (ifn);
4578 int cond_nargs = len_index >= 0 ? 4 : 2;
4579 if (code != ERROR_MARK)
4581 *cond_out = gimple_call_arg (call, 0);
4582 *code_out = code;
4583 unsigned int nops = gimple_call_num_args (call) - cond_nargs;
4584 for (unsigned int i = 0; i < 3; ++i)
4585 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
4586 *else_out = gimple_call_arg (call, nops + 1);
4587 if (len_index < 0)
4589 if (integer_truep (*cond_out))
4591 *cond_out = NULL_TREE;
4592 *else_out = NULL_TREE;
4595 else
4597 *len = gimple_call_arg (call, len_index);
4598 *bias = gimple_call_arg (call, len_index + 1);
4600 return true;
4603 return false;
4606 /* Return true if IFN is some form of load from memory. */
4608 bool
4609 internal_load_fn_p (internal_fn fn)
4611 switch (fn)
4613 case IFN_MASK_LOAD:
4614 case IFN_LOAD_LANES:
4615 case IFN_MASK_LOAD_LANES:
4616 case IFN_MASK_LEN_LOAD_LANES:
4617 case IFN_GATHER_LOAD:
4618 case IFN_MASK_GATHER_LOAD:
4619 case IFN_MASK_LEN_GATHER_LOAD:
4620 case IFN_LEN_LOAD:
4621 case IFN_MASK_LEN_LOAD:
4622 return true;
4624 default:
4625 return false;
4629 /* Return true if IFN is some form of store to memory. */
4631 bool
4632 internal_store_fn_p (internal_fn fn)
4634 switch (fn)
4636 case IFN_MASK_STORE:
4637 case IFN_STORE_LANES:
4638 case IFN_MASK_STORE_LANES:
4639 case IFN_MASK_LEN_STORE_LANES:
4640 case IFN_SCATTER_STORE:
4641 case IFN_MASK_SCATTER_STORE:
4642 case IFN_MASK_LEN_SCATTER_STORE:
4643 case IFN_LEN_STORE:
4644 case IFN_MASK_LEN_STORE:
4645 return true;
4647 default:
4648 return false;
4652 /* Return true if IFN is some form of gather load or scatter store. */
4654 bool
4655 internal_gather_scatter_fn_p (internal_fn fn)
4657 switch (fn)
4659 case IFN_GATHER_LOAD:
4660 case IFN_MASK_GATHER_LOAD:
4661 case IFN_MASK_LEN_GATHER_LOAD:
4662 case IFN_SCATTER_STORE:
4663 case IFN_MASK_SCATTER_STORE:
4664 case IFN_MASK_LEN_SCATTER_STORE:
4665 return true;
4667 default:
4668 return false;
4672 /* If FN takes a vector len argument, return the index of that argument,
4673 otherwise return -1. */
4676 internal_fn_len_index (internal_fn fn)
4678 switch (fn)
4680 case IFN_LEN_LOAD:
4681 case IFN_LEN_STORE:
4682 return 2;
4684 case IFN_MASK_LEN_GATHER_LOAD:
4685 case IFN_MASK_LEN_SCATTER_STORE:
4686 case IFN_COND_LEN_FMA:
4687 case IFN_COND_LEN_FMS:
4688 case IFN_COND_LEN_FNMA:
4689 case IFN_COND_LEN_FNMS:
4690 return 5;
4692 case IFN_COND_LEN_ADD:
4693 case IFN_COND_LEN_SUB:
4694 case IFN_COND_LEN_MUL:
4695 case IFN_COND_LEN_DIV:
4696 case IFN_COND_LEN_MOD:
4697 case IFN_COND_LEN_RDIV:
4698 case IFN_COND_LEN_MIN:
4699 case IFN_COND_LEN_MAX:
4700 case IFN_COND_LEN_FMIN:
4701 case IFN_COND_LEN_FMAX:
4702 case IFN_COND_LEN_AND:
4703 case IFN_COND_LEN_IOR:
4704 case IFN_COND_LEN_XOR:
4705 case IFN_COND_LEN_SHL:
4706 case IFN_COND_LEN_SHR:
4707 return 4;
4709 case IFN_COND_LEN_NEG:
4710 case IFN_MASK_LEN_LOAD:
4711 case IFN_MASK_LEN_STORE:
4712 case IFN_MASK_LEN_LOAD_LANES:
4713 case IFN_MASK_LEN_STORE_LANES:
4714 case IFN_VCOND_MASK_LEN:
4715 return 3;
4717 default:
4718 return -1;
4722 /* If FN is an IFN_COND_* or IFN_COND_LEN_* function, return the index of the
4723 argument that is used when the condition is false. Return -1 otherwise. */
4726 internal_fn_else_index (internal_fn fn)
4728 switch (fn)
4730 case IFN_COND_NEG:
4731 case IFN_COND_NOT:
4732 case IFN_COND_LEN_NEG:
4733 case IFN_COND_LEN_NOT:
4734 return 2;
4736 case IFN_COND_ADD:
4737 case IFN_COND_SUB:
4738 case IFN_COND_MUL:
4739 case IFN_COND_DIV:
4740 case IFN_COND_MOD:
4741 case IFN_COND_MIN:
4742 case IFN_COND_MAX:
4743 case IFN_COND_FMIN:
4744 case IFN_COND_FMAX:
4745 case IFN_COND_AND:
4746 case IFN_COND_IOR:
4747 case IFN_COND_XOR:
4748 case IFN_COND_SHL:
4749 case IFN_COND_SHR:
4750 case IFN_COND_LEN_ADD:
4751 case IFN_COND_LEN_SUB:
4752 case IFN_COND_LEN_MUL:
4753 case IFN_COND_LEN_DIV:
4754 case IFN_COND_LEN_MOD:
4755 case IFN_COND_LEN_MIN:
4756 case IFN_COND_LEN_MAX:
4757 case IFN_COND_LEN_FMIN:
4758 case IFN_COND_LEN_FMAX:
4759 case IFN_COND_LEN_AND:
4760 case IFN_COND_LEN_IOR:
4761 case IFN_COND_LEN_XOR:
4762 case IFN_COND_LEN_SHL:
4763 case IFN_COND_LEN_SHR:
4764 return 3;
4766 case IFN_COND_FMA:
4767 case IFN_COND_FMS:
4768 case IFN_COND_FNMA:
4769 case IFN_COND_FNMS:
4770 case IFN_COND_LEN_FMA:
4771 case IFN_COND_LEN_FMS:
4772 case IFN_COND_LEN_FNMA:
4773 case IFN_COND_LEN_FNMS:
4774 return 4;
4776 default:
4777 return -1;
4780 return -1;
4783 /* If FN takes a vector mask argument, return the index of that argument,
4784 otherwise return -1. */
4787 internal_fn_mask_index (internal_fn fn)
4789 switch (fn)
4791 case IFN_MASK_LOAD:
4792 case IFN_MASK_LOAD_LANES:
4793 case IFN_MASK_LEN_LOAD_LANES:
4794 case IFN_MASK_STORE:
4795 case IFN_MASK_STORE_LANES:
4796 case IFN_MASK_LEN_STORE_LANES:
4797 case IFN_MASK_LEN_LOAD:
4798 case IFN_MASK_LEN_STORE:
4799 return 2;
4801 case IFN_MASK_GATHER_LOAD:
4802 case IFN_MASK_SCATTER_STORE:
4803 case IFN_MASK_LEN_GATHER_LOAD:
4804 case IFN_MASK_LEN_SCATTER_STORE:
4805 return 4;
4807 case IFN_VCOND_MASK_LEN:
4808 return 0;
4810 default:
4811 return (conditional_internal_fn_code (fn) != ERROR_MARK
4812 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
4816 /* If FN takes a value that should be stored to memory, return the index
4817 of that argument, otherwise return -1. */
4820 internal_fn_stored_value_index (internal_fn fn)
4822 switch (fn)
4824 case IFN_MASK_STORE:
4825 case IFN_MASK_STORE_LANES:
4826 case IFN_SCATTER_STORE:
4827 case IFN_MASK_SCATTER_STORE:
4828 case IFN_MASK_LEN_SCATTER_STORE:
4829 return 3;
4831 case IFN_LEN_STORE:
4832 return 4;
4834 case IFN_MASK_LEN_STORE:
4835 case IFN_MASK_LEN_STORE_LANES:
4836 return 5;
4838 default:
4839 return -1;
4843 /* Return true if the target supports gather load or scatter store function
4844 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
4845 while for stores it is the vector type of the stored data argument.
4846 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
4847 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
4848 offset from the shared base address of each loaded or stored element.
4849 SCALE is the amount by which these offsets should be multiplied
4850 *after* they have been extended to address width. */
4852 bool
4853 internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
4854 tree memory_element_type,
4855 tree offset_vector_type, int scale)
4857 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
4858 TYPE_SIZE (memory_element_type)))
4859 return false;
4860 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
4861 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
4862 return false;
4863 optab optab = direct_internal_fn_optab (ifn);
4864 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
4865 TYPE_MODE (offset_vector_type));
4866 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
4867 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
4868 return (icode != CODE_FOR_nothing
4869 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
4870 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
4873 /* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
4874 for pointers of type TYPE when the accesses have LENGTH bytes and their
4875 common byte alignment is ALIGN. */
4877 bool
4878 internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
4879 poly_uint64 length, unsigned int align)
4881 machine_mode mode = TYPE_MODE (type);
4882 optab optab = direct_internal_fn_optab (ifn);
4883 insn_code icode = direct_optab_handler (optab, mode);
4884 if (icode == CODE_FOR_nothing)
4885 return false;
4886 rtx length_rtx = immed_wide_int_const (length, mode);
4887 return (insn_operand_matches (icode, 3, length_rtx)
4888 && insn_operand_matches (icode, 4, GEN_INT (align)));
4891 /* Return the supported bias for IFN which is either IFN_{LEN_,MASK_LEN_,}LOAD
4892 or IFN_{LEN_,MASK_LEN_,}STORE. For now we only support the biases of 0 and
4893 -1 (in case 0 is not an allowable length for {len_,mask_len_}load or
4894 {len_,mask_len_}store). If none of the biases match what the backend
4895 provides, return VECT_PARTIAL_BIAS_UNSUPPORTED. */
4897 signed char
4898 internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
4900 optab optab = direct_internal_fn_optab (ifn);
4901 insn_code icode = direct_optab_handler (optab, mode);
4902 int bias_no = 3;
4904 if (icode == CODE_FOR_nothing)
4906 machine_mode mask_mode;
4907 if (!targetm.vectorize.get_mask_mode (mode).exists (&mask_mode))
4908 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4909 if (ifn == IFN_LEN_LOAD)
4911 /* Try MASK_LEN_LOAD. */
4912 optab = direct_internal_fn_optab (IFN_MASK_LEN_LOAD);
4914 else
4916 /* Try MASK_LEN_STORE. */
4917 optab = direct_internal_fn_optab (IFN_MASK_LEN_STORE);
4919 icode = convert_optab_handler (optab, mode, mask_mode);
4920 bias_no = 4;
4923 if (icode != CODE_FOR_nothing)
4925 /* For now we only support biases of 0 or -1. Try both of them. */
4926 if (insn_operand_matches (icode, bias_no, GEN_INT (0)))
4927 return 0;
4928 if (insn_operand_matches (icode, bias_no, GEN_INT (-1)))
4929 return -1;
4932 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4935 /* Expand STMT as though it were a call to internal function FN. */
4937 void
4938 expand_internal_call (internal_fn fn, gcall *stmt)
4940 internal_fn_expanders[fn] (fn, stmt);
4943 /* Expand STMT, which is a call to internal function FN. */
4945 void
4946 expand_internal_call (gcall *stmt)
4948 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
4951 /* If TYPE is a vector type, return true if IFN is a direct internal
4952 function that is supported for that type. If TYPE is a scalar type,
4953 return true if IFN is a direct internal function that is supported for
4954 the target's preferred vector version of TYPE. */
4956 bool
4957 vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
4959 if (VECTOR_MODE_P (TYPE_MODE (type)))
4960 return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
4962 scalar_mode smode;
4963 if (VECTOR_TYPE_P (type)
4964 || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
4965 return false;
4967 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
4968 if (VECTOR_MODE_P (vmode))
4970 tree vectype = build_vector_type_for_mode (type, vmode);
4971 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4972 return true;
4975 auto_vector_modes vector_modes;
4976 targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
4977 for (machine_mode base_mode : vector_modes)
4978 if (related_vector_mode (base_mode, smode).exists (&vmode))
4980 tree vectype = build_vector_type_for_mode (type, vmode);
4981 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4982 return true;
4985 return false;
4988 void
4989 expand_SHUFFLEVECTOR (internal_fn, gcall *)
4991 gcc_unreachable ();
4994 void
4995 expand_PHI (internal_fn, gcall *)
4997 gcc_unreachable ();
5000 void
5001 expand_SPACESHIP (internal_fn, gcall *stmt)
5003 tree lhs = gimple_call_lhs (stmt);
5004 tree rhs1 = gimple_call_arg (stmt, 0);
5005 tree rhs2 = gimple_call_arg (stmt, 1);
5006 tree type = TREE_TYPE (rhs1);
5008 do_pending_stack_adjust ();
5010 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
5011 rtx op1 = expand_normal (rhs1);
5012 rtx op2 = expand_normal (rhs2);
5014 class expand_operand ops[3];
5015 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
5016 create_input_operand (&ops[1], op1, TYPE_MODE (type));
5017 create_input_operand (&ops[2], op2, TYPE_MODE (type));
5018 insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
5019 expand_insn (icode, 3, ops);
5020 if (!rtx_equal_p (target, ops[0].value))
5021 emit_move_insn (target, ops[0].value);
5024 void
5025 expand_ASSUME (internal_fn, gcall *)
5029 void
5030 expand_MASK_CALL (internal_fn, gcall *)
5032 /* This IFN should only exist between ifcvt and vect passes. */
5033 gcc_unreachable ();
5036 void
5037 expand_MULBITINT (internal_fn, gcall *stmt)
5039 rtx_mode_t args[6];
5040 for (int i = 0; i < 6; i++)
5041 args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
5042 (i & 1) ? SImode : ptr_mode);
5043 rtx fun = init_one_libfunc ("__mulbitint3");
5044 emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 6, args);
5047 void
5048 expand_DIVMODBITINT (internal_fn, gcall *stmt)
5050 rtx_mode_t args[8];
5051 for (int i = 0; i < 8; i++)
5052 args[i] = rtx_mode_t (expand_normal (gimple_call_arg (stmt, i)),
5053 (i & 1) ? SImode : ptr_mode);
5054 rtx fun = init_one_libfunc ("__divmodbitint4");
5055 emit_library_call_value_1 (0, fun, NULL_RTX, LCT_NORMAL, VOIDmode, 8, args);
5058 void
5059 expand_FLOATTOBITINT (internal_fn, gcall *stmt)
5061 machine_mode mode = TYPE_MODE (TREE_TYPE (gimple_call_arg (stmt, 2)));
5062 rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
5063 rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
5064 rtx arg2 = expand_normal (gimple_call_arg (stmt, 2));
5065 const char *mname = GET_MODE_NAME (mode);
5066 unsigned mname_len = strlen (mname);
5067 int len = 12 + mname_len;
5068 if (DECIMAL_FLOAT_MODE_P (mode))
5069 len += 4;
5070 char *libfunc_name = XALLOCAVEC (char, len);
5071 char *p = libfunc_name;
5072 const char *q;
5073 if (DECIMAL_FLOAT_MODE_P (mode))
5075 #if ENABLE_DECIMAL_BID_FORMAT
5076 memcpy (p, "__bid_fix", 9);
5077 #else
5078 memcpy (p, "__dpd_fix", 9);
5079 #endif
5080 p += 9;
5082 else
5084 memcpy (p, "__fix", 5);
5085 p += 5;
5087 for (q = mname; *q; q++)
5088 *p++ = TOLOWER (*q);
5089 memcpy (p, "bitint", 7);
5090 rtx fun = init_one_libfunc (libfunc_name);
5091 emit_library_call (fun, LCT_NORMAL, VOIDmode, arg0, ptr_mode, arg1,
5092 SImode, arg2, mode);
5095 void
5096 expand_BITINTTOFLOAT (internal_fn, gcall *stmt)
5098 tree lhs = gimple_call_lhs (stmt);
5099 if (!lhs)
5100 return;
5101 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
5102 rtx arg0 = expand_normal (gimple_call_arg (stmt, 0));
5103 rtx arg1 = expand_normal (gimple_call_arg (stmt, 1));
5104 const char *mname = GET_MODE_NAME (mode);
5105 unsigned mname_len = strlen (mname);
5106 int len = 14 + mname_len;
5107 if (DECIMAL_FLOAT_MODE_P (mode))
5108 len += 4;
5109 char *libfunc_name = XALLOCAVEC (char, len);
5110 char *p = libfunc_name;
5111 const char *q;
5112 if (DECIMAL_FLOAT_MODE_P (mode))
5114 #if ENABLE_DECIMAL_BID_FORMAT
5115 memcpy (p, "__bid_floatbitint", 17);
5116 #else
5117 memcpy (p, "__dpd_floatbitint", 17);
5118 #endif
5119 p += 17;
5121 else
5123 memcpy (p, "__floatbitint", 13);
5124 p += 13;
5126 for (q = mname; *q; q++)
5127 *p++ = TOLOWER (*q);
5128 *p = '\0';
5129 rtx fun = init_one_libfunc (libfunc_name);
5130 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
5131 rtx val = emit_library_call_value (fun, target, LCT_PURE, mode,
5132 arg0, ptr_mode, arg1, SImode);
5133 if (val != target)
5134 emit_move_insn (target, val);
5137 static bool
5138 expand_bitquery (internal_fn fn, gcall *stmt)
5140 tree lhs = gimple_call_lhs (stmt);
5141 if (lhs == NULL_TREE)
5142 return false;
5143 tree arg = gimple_call_arg (stmt, 0);
5144 if (TREE_CODE (arg) == INTEGER_CST)
5146 tree ret = fold_const_call (as_combined_fn (fn), TREE_TYPE (arg), arg);
5147 gcc_checking_assert (ret && TREE_CODE (ret) == INTEGER_CST);
5148 expand_assignment (lhs, ret, false);
5149 return false;
5151 return true;
5154 void
5155 expand_CLRSB (internal_fn fn, gcall *stmt)
5157 if (expand_bitquery (fn, stmt))
5158 expand_unary_optab_fn (fn, stmt, clrsb_optab);
5161 void
5162 expand_CLZ (internal_fn fn, gcall *stmt)
5164 if (expand_bitquery (fn, stmt))
5165 expand_unary_optab_fn (fn, stmt, clz_optab);
5168 void
5169 expand_CTZ (internal_fn fn, gcall *stmt)
5171 if (expand_bitquery (fn, stmt))
5172 expand_unary_optab_fn (fn, stmt, ctz_optab);
5175 void
5176 expand_FFS (internal_fn fn, gcall *stmt)
5178 if (expand_bitquery (fn, stmt))
5179 expand_unary_optab_fn (fn, stmt, ffs_optab);
5182 void
5183 expand_PARITY (internal_fn fn, gcall *stmt)
5185 if (expand_bitquery (fn, stmt))
5186 expand_unary_optab_fn (fn, stmt, parity_optab);
5189 void
5190 expand_POPCOUNT (internal_fn fn, gcall *stmt)
5192 if (!expand_bitquery (fn, stmt))
5193 return;
5194 if (gimple_call_num_args (stmt) == 1)
5196 expand_unary_optab_fn (fn, stmt, popcount_optab);
5197 return;
5199 /* If .POPCOUNT call has 2 arguments, match_single_bit_test marked it
5200 because the result is only used in an equality comparison against 1.
5201 Use rtx costs in that case to determine if .POPCOUNT (arg) == 1
5202 or (arg ^ (arg - 1)) > arg - 1 is cheaper.
5203 If .POPCOUNT second argument is 0, we additionally know that arg
5204 is non-zero, so use arg & (arg - 1) == 0 instead. */
5205 bool speed_p = optimize_insn_for_speed_p ();
5206 tree lhs = gimple_call_lhs (stmt);
5207 tree arg = gimple_call_arg (stmt, 0);
5208 bool nonzero_arg = integer_zerop (gimple_call_arg (stmt, 1));
5209 tree type = TREE_TYPE (arg);
5210 machine_mode mode = TYPE_MODE (type);
5211 do_pending_stack_adjust ();
5212 start_sequence ();
5213 expand_unary_optab_fn (fn, stmt, popcount_optab);
5214 rtx_insn *popcount_insns = get_insns ();
5215 end_sequence ();
5216 start_sequence ();
5217 rtx plhs = expand_normal (lhs);
5218 rtx pcmp = emit_store_flag (NULL_RTX, EQ, plhs, const1_rtx, mode, 0, 0);
5219 if (pcmp == NULL_RTX)
5221 fail:
5222 end_sequence ();
5223 emit_insn (popcount_insns);
5224 return;
5226 rtx_insn *popcount_cmp_insns = get_insns ();
5227 end_sequence ();
5228 start_sequence ();
5229 rtx op0 = expand_normal (arg);
5230 rtx argm1 = expand_simple_binop (mode, PLUS, op0, constm1_rtx, NULL_RTX,
5231 1, OPTAB_DIRECT);
5232 if (argm1 == NULL_RTX)
5233 goto fail;
5234 rtx argxorargm1 = expand_simple_binop (mode, nonzero_arg ? AND : XOR, op0,
5235 argm1, NULL_RTX, 1, OPTAB_DIRECT);
5236 if (argxorargm1 == NULL_RTX)
5237 goto fail;
5238 rtx cmp;
5239 if (nonzero_arg)
5240 cmp = emit_store_flag (NULL_RTX, EQ, argxorargm1, const0_rtx, mode, 1, 1);
5241 else
5242 cmp = emit_store_flag (NULL_RTX, GTU, argxorargm1, argm1, mode, 1, 1);
5243 if (cmp == NULL_RTX)
5244 goto fail;
5245 rtx_insn *cmp_insns = get_insns ();
5246 end_sequence ();
5247 unsigned popcount_cost = (seq_cost (popcount_insns, speed_p)
5248 + seq_cost (popcount_cmp_insns, speed_p));
5249 unsigned cmp_cost = seq_cost (cmp_insns, speed_p);
5250 if (popcount_cost <= cmp_cost)
5251 emit_insn (popcount_insns);
5252 else
5254 emit_insn (cmp_insns);
5255 plhs = expand_normal (lhs);
5256 if (GET_MODE (cmp) != GET_MODE (plhs))
5257 cmp = convert_to_mode (GET_MODE (plhs), cmp, 1);
5258 emit_move_insn (plhs, cmp);