]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/internal-fn.cc
libgomp.texi: add cross ref, remove duplicated entry
[thirdparty/gcc.git] / gcc / internal-fn.cc
CommitLineData
25583c4f 1/* Internal functions.
aeee4812 2 Copyright (C) 2011-2023 Free Software Foundation, Inc.
25583c4f
RS
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
c7131fb2 23#include "backend.h"
957060b5
AM
24#include "target.h"
25#include "rtl.h"
25583c4f 26#include "tree.h"
c7131fb2 27#include "gimple.h"
957060b5
AM
28#include "predict.h"
29#include "stringpool.h"
f90aa46c 30#include "tree-vrp.h"
957060b5
AM
31#include "tree-ssanames.h"
32#include "expmed.h"
4d0cdd0c 33#include "memmodel.h"
957060b5
AM
34#include "optabs.h"
35#include "emit-rtl.h"
36#include "diagnostic-core.h"
40e23961 37#include "fold-const.h"
0e37a2f3 38#include "internal-fn.h"
d8a2d370 39#include "stor-layout.h"
36566b39 40#include "dojump.h"
25583c4f 41#include "expr.h"
314e6352
ML
42#include "stringpool.h"
43#include "attribs.h"
e3174bdf 44#include "asan.h"
31e071ae 45#include "ubsan.h"
686ee971 46#include "recog.h"
adedd5c1 47#include "builtins.h"
1705cebd 48#include "optabs-tree.h"
0b99f253
JJ
49#include "gimple-ssa.h"
50#include "tree-phinodes.h"
51#include "ssa-iterators.h"
502d63b6 52#include "explow.h"
bf510679 53#include "rtl-iter.h"
45f4e2b0 54#include "gimple-range.h"
25583c4f 55
a25e0b5e 56/* For lang_hooks.types.type_for_mode. */
57#include "langhooks.h"
58
25583c4f
RS
59/* The names of each internal function, indexed by function number. */
60const char *const internal_fn_name_array[] = {
b78475cf 61#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
25583c4f 62#include "internal-fn.def"
25583c4f
RS
63 "<invalid-fn>"
64};
65
66/* The ECF_* flags of each internal function, indexed by function number. */
67const int internal_fn_flags_array[] = {
b78475cf 68#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
25583c4f 69#include "internal-fn.def"
25583c4f
RS
70 0
71};
72
e4f81565
RS
73/* Return the internal function called NAME, or IFN_LAST if there's
74 no such function. */
75
76internal_fn
77lookup_internal_fn (const char *name)
78{
79 typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
80 static name_to_fn_map_type *name_to_fn_map;
81
82 if (!name_to_fn_map)
83 {
84 name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
85 for (unsigned int i = 0; i < IFN_LAST; ++i)
86 name_to_fn_map->put (internal_fn_name (internal_fn (i)),
87 internal_fn (i));
88 }
89 internal_fn *entry = name_to_fn_map->get (name);
90 return entry ? *entry : IFN_LAST;
91}
92
2f482a07
AV
93/* Geven an internal_fn IFN that is a widening function, return its
94 corresponding LO and HI internal_fns. */
95
96extern void
97lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi)
98{
99 gcc_assert (widening_fn_p (ifn));
100
101 switch (ifn)
102 {
103 default:
104 gcc_unreachable ();
105#undef DEF_INTERNAL_FN
106#undef DEF_INTERNAL_WIDENING_OPTAB_FN
107#define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
108#define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
109 case IFN_##NAME: \
110 *lo = internal_fn (IFN_##NAME##_LO); \
111 *hi = internal_fn (IFN_##NAME##_HI); \
112 break;
113#include "internal-fn.def"
114#undef DEF_INTERNAL_FN
115#undef DEF_INTERNAL_WIDENING_OPTAB_FN
116 }
117}
118
119/* Given an internal_fn IFN that is a widening function, return its
120 corresponding _EVEN and _ODD internal_fns in *EVEN and *ODD. */
121
122extern void
123lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even,
124 internal_fn *odd)
125{
126 gcc_assert (widening_fn_p (ifn));
127
128 switch (ifn)
129 {
130 default:
131 gcc_unreachable ();
132#undef DEF_INTERNAL_FN
133#undef DEF_INTERNAL_WIDENING_OPTAB_FN
134#define DEF_INTERNAL_FN(NAME, FLAGS, TYPE)
135#define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
136 case IFN_##NAME: \
137 *even = internal_fn (IFN_##NAME##_EVEN); \
138 *odd = internal_fn (IFN_##NAME##_ODD); \
139 break;
140#include "internal-fn.def"
141#undef DEF_INTERNAL_FN
142#undef DEF_INTERNAL_WIDENING_OPTAB_FN
143 }
144}
145
146
b78475cf
YG
147/* Fnspec of each internal function, indexed by function number. */
148const_tree internal_fn_fnspec_array[IFN_LAST + 1];
149
150void
151init_internal_fns ()
152{
153#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
154 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
ba663ac1 155 build_string ((int) sizeof (FNSPEC) - 1, FNSPEC ? FNSPEC : "");
b78475cf 156#include "internal-fn.def"
b78475cf
YG
157 internal_fn_fnspec_array[IFN_LAST] = 0;
158}
159
ab23f5d9
RS
160/* Create static initializers for the information returned by
161 direct_internal_fn. */
9d2fe6d4
RS
162#define not_direct { -2, -2, false }
163#define mask_load_direct { -1, 2, false }
164#define load_lanes_direct { -1, -1, false }
165#define mask_load_lanes_direct { -1, -1, false }
166#define gather_load_direct { 3, 1, false }
167#define len_load_direct { -1, -1, false }
b8806f6f 168#define len_maskload_direct { -1, 4, false }
9d2fe6d4
RS
169#define mask_store_direct { 3, 2, false }
170#define store_lanes_direct { 0, 0, false }
171#define mask_store_lanes_direct { 0, 0, false }
172#define vec_cond_mask_direct { 1, 0, false }
173#define vec_cond_direct { 2, 0, false }
174#define scatter_store_direct { 3, 1, false }
175#define len_store_direct { 3, 3, false }
b8806f6f 176#define len_maskstore_direct { 4, 5, false }
9d2fe6d4 177#define vec_set_direct { 3, 3, false }
c30efd8c 178#define vec_extract_direct { 3, 3, false }
9d2fe6d4 179#define unary_direct { 0, 0, true }
00eab0c6 180#define unary_convert_direct { -1, 0, true }
9d2fe6d4
RS
181#define binary_direct { 0, 0, true }
182#define ternary_direct { 0, 0, true }
183#define cond_unary_direct { 1, 1, true }
184#define cond_binary_direct { 1, 1, true }
185#define cond_ternary_direct { 1, 1, true }
6c96d1e4
JZZ
186#define cond_len_unary_direct { 1, 1, true }
187#define cond_len_binary_direct { 1, 1, true }
188#define cond_len_ternary_direct { 1, 1, true }
9d2fe6d4
RS
189#define while_direct { 0, 2, false }
190#define fold_extract_direct { 2, 2, false }
191#define fold_left_direct { 1, 1, false }
192#define mask_fold_left_direct { 1, 1, false }
193#define check_ptrs_direct { 0, 0, false }
ab23f5d9
RS
194
195const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
196#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
197#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
16d24520
RS
198#define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
199 UNSIGNED_OPTAB, TYPE) TYPE##_direct,
ab23f5d9
RS
200#include "internal-fn.def"
201 not_direct
202};
203
1d205dba
RS
204/* Expand STMT using instruction ICODE. The instruction has NOUTPUTS
205 output operands and NINPUTS input operands, where NOUTPUTS is either
206 0 or 1. The output operand (if any) comes first, followed by the
207 NINPUTS input operands. */
208
209static void
210expand_fn_using_insn (gcall *stmt, insn_code icode, unsigned int noutputs,
211 unsigned int ninputs)
212{
213 gcc_assert (icode != CODE_FOR_nothing);
214
215 expand_operand *ops = XALLOCAVEC (expand_operand, noutputs + ninputs);
216 unsigned int opno = 0;
217 rtx lhs_rtx = NULL_RTX;
218 tree lhs = gimple_call_lhs (stmt);
219
220 if (noutputs)
221 {
222 gcc_assert (noutputs == 1);
223 if (lhs)
224 lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
225
226 /* Do not assign directly to a promoted subreg, since there is no
227 guarantee that the instruction will leave the upper bits of the
228 register in the state required by SUBREG_PROMOTED_SIGN. */
229 rtx dest = lhs_rtx;
230 if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest))
231 dest = NULL_RTX;
232 create_output_operand (&ops[opno], dest,
233 insn_data[icode].operand[opno].mode);
234 opno += 1;
235 }
236 else
237 gcc_assert (!lhs);
238
239 for (unsigned int i = 0; i < ninputs; ++i)
240 {
241 tree rhs = gimple_call_arg (stmt, i);
242 tree rhs_type = TREE_TYPE (rhs);
243 rtx rhs_rtx = expand_normal (rhs);
244 if (INTEGRAL_TYPE_P (rhs_type))
245 create_convert_operand_from (&ops[opno], rhs_rtx,
246 TYPE_MODE (rhs_type),
247 TYPE_UNSIGNED (rhs_type));
248 else
249 create_input_operand (&ops[opno], rhs_rtx, TYPE_MODE (rhs_type));
250 opno += 1;
251 }
252
253 gcc_assert (opno == noutputs + ninputs);
254 expand_insn (icode, opno, ops);
255 if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value))
256 {
257 /* If the return value has an integral type, convert the instruction
258 result to that type. This is useful for things that return an
259 int regardless of the size of the input. If the instruction result
260 is smaller than required, assume that it is signed.
261
262 If the return value has a nonintegral type, its mode must match
263 the instruction result. */
264 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
265 {
266 /* If this is a scalar in a register that is stored in a wider
267 mode than the declared mode, compute the result into its
268 declared mode and then convert to the wider mode. */
269 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
270 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
271 convert_move (SUBREG_REG (lhs_rtx), tmp,
272 SUBREG_PROMOTED_SIGN (lhs_rtx));
273 }
274 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
275 emit_move_insn (lhs_rtx, ops[0].value);
276 else
277 {
278 gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs)));
279 convert_move (lhs_rtx, ops[0].value, 0);
280 }
281 }
282}
283
272c6793 284/* ARRAY_TYPE is an array of vector modes. Return the associated insn
ab23f5d9 285 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
272c6793
RS
286
287static enum insn_code
288get_multi_vector_move (tree array_type, convert_optab optab)
289{
ef4bddc2
RS
290 machine_mode imode;
291 machine_mode vmode;
272c6793
RS
292
293 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
294 imode = TYPE_MODE (array_type);
295 vmode = TYPE_MODE (TREE_TYPE (array_type));
296
ab23f5d9 297 return convert_optab_handler (optab, imode, vmode);
272c6793
RS
298}
299
b8806f6f
JZZ
300/* Add len and mask arguments according to the STMT. */
301
302static unsigned int
303add_len_and_mask_args (expand_operand *ops, unsigned int opno, gcall *stmt)
304{
305 internal_fn ifn = gimple_call_internal_fn (stmt);
306 int len_index = internal_fn_len_index (ifn);
307 /* BIAS is always consecutive next of LEN. */
308 int bias_index = len_index + 1;
309 int mask_index = internal_fn_mask_index (ifn);
310 /* The order of arguments are always {len,bias,mask}. */
311 if (len_index >= 0)
312 {
313 tree len = gimple_call_arg (stmt, len_index);
314 rtx len_rtx = expand_normal (len);
315 create_convert_operand_from (&ops[opno++], len_rtx,
316 TYPE_MODE (TREE_TYPE (len)),
317 TYPE_UNSIGNED (TREE_TYPE (len)));
318 tree biast = gimple_call_arg (stmt, bias_index);
319 rtx bias = expand_normal (biast);
320 create_input_operand (&ops[opno++], bias, QImode);
321 }
322 if (mask_index >= 0)
323 {
324 tree mask = gimple_call_arg (stmt, mask_index);
325 rtx mask_rtx = expand_normal (mask);
326 create_input_operand (&ops[opno++], mask_rtx,
327 TYPE_MODE (TREE_TYPE (mask)));
328 }
329 return opno;
330}
331
ab23f5d9 332/* Expand LOAD_LANES call STMT using optab OPTAB. */
272c6793
RS
333
334static void
4cfe7a6c 335expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
272c6793 336{
99b1c316 337 class expand_operand ops[2];
272c6793
RS
338 tree type, lhs, rhs;
339 rtx target, mem;
340
341 lhs = gimple_call_lhs (stmt);
342 rhs = gimple_call_arg (stmt, 0);
343 type = TREE_TYPE (lhs);
344
345 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
346 mem = expand_normal (rhs);
347
348 gcc_assert (MEM_P (mem));
349 PUT_MODE (mem, TYPE_MODE (type));
350
351 create_output_operand (&ops[0], target, TYPE_MODE (type));
352 create_fixed_operand (&ops[1], mem);
ab23f5d9 353 expand_insn (get_multi_vector_move (type, optab), 2, ops);
3af3bec2
RS
354 if (!rtx_equal_p (target, ops[0].value))
355 emit_move_insn (target, ops[0].value);
272c6793
RS
356}
357
ab23f5d9 358/* Expand STORE_LANES call STMT using optab OPTAB. */
272c6793
RS
359
360static void
4cfe7a6c 361expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
272c6793 362{
99b1c316 363 class expand_operand ops[2];
272c6793
RS
364 tree type, lhs, rhs;
365 rtx target, reg;
366
367 lhs = gimple_call_lhs (stmt);
368 rhs = gimple_call_arg (stmt, 0);
369 type = TREE_TYPE (rhs);
370
371 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
372 reg = expand_normal (rhs);
373
374 gcc_assert (MEM_P (target));
375 PUT_MODE (target, TYPE_MODE (type));
376
377 create_fixed_operand (&ops[0], target);
378 create_input_operand (&ops[1], reg, TYPE_MODE (type));
ab23f5d9 379 expand_insn (get_multi_vector_move (type, optab), 2, ops);
272c6793
RS
380}
381
8170608b 382static void
4cfe7a6c 383expand_ANNOTATE (internal_fn, gcall *)
8170608b
TB
384{
385 gcc_unreachable ();
386}
387
6c7509bc
JJ
388/* This should get expanded in omp_device_lower pass. */
389
390static void
391expand_GOMP_USE_SIMT (internal_fn, gcall *)
392{
393 gcc_unreachable ();
394}
395
0c6b03b5
AM
396/* This should get expanded in omp_device_lower pass. */
397
398static void
399expand_GOMP_SIMT_ENTER (internal_fn, gcall *)
400{
401 gcc_unreachable ();
402}
403
9d2fe6d4
RS
404/* Allocate per-lane storage and begin non-uniform execution region. */
405
406static void
407expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt)
408{
409 rtx target;
410 tree lhs = gimple_call_lhs (stmt);
411 if (lhs)
412 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
413 else
414 target = gen_reg_rtx (Pmode);
415 rtx size = expand_normal (gimple_call_arg (stmt, 0));
416 rtx align = expand_normal (gimple_call_arg (stmt, 1));
417 class expand_operand ops[3];
418 create_output_operand (&ops[0], target, Pmode);
419 create_input_operand (&ops[1], size, Pmode);
420 create_input_operand (&ops[2], align, Pmode);
421 gcc_assert (targetm.have_omp_simt_enter ());
422 expand_insn (targetm.code_for_omp_simt_enter, 3, ops);
423 if (!rtx_equal_p (target, ops[0].value))
424 emit_move_insn (target, ops[0].value);
425}
426
427/* Deallocate per-lane storage and leave non-uniform execution region. */
428
429static void
430expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt)
431{
432 gcc_checking_assert (!gimple_call_lhs (stmt));
433 rtx arg = expand_normal (gimple_call_arg (stmt, 0));
434 class expand_operand ops[1];
435 create_input_operand (&ops[0], arg, Pmode);
436 gcc_assert (targetm.have_omp_simt_exit ());
437 expand_insn (targetm.code_for_omp_simt_exit, 1, ops);
438}
439
440/* Lane index on SIMT targets: thread index in the warp on NVPTX. On targets
441 without SIMT execution this should be expanded in omp_device_lower pass. */
442
443static void
444expand_GOMP_SIMT_LANE (internal_fn, gcall *stmt)
445{
446 tree lhs = gimple_call_lhs (stmt);
447 if (!lhs)
448 return;
449
450 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
451 gcc_assert (targetm.have_omp_simt_lane ());
452 emit_insn (targetm.gen_omp_simt_lane (target));
453}
454
9669b00b
AM
455/* This should get expanded in omp_device_lower pass. */
456
457static void
458expand_GOMP_SIMT_VF (internal_fn, gcall *)
459{
460 gcc_unreachable ();
461}
462
d6621a2f
TB
463/* This should get expanded in omp_device_lower pass. */
464
465static void
466expand_GOMP_TARGET_REV (internal_fn, gcall *)
467{
468 gcc_unreachable ();
469}
470
9d2fe6d4
RS
471/* Lane index of the first SIMT lane that supplies a non-zero argument.
472 This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the
473 lane that executed the last iteration for handling OpenMP lastprivate. */
474
475static void
476expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt)
477{
478 tree lhs = gimple_call_lhs (stmt);
479 if (!lhs)
480 return;
481
482 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
483 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
484 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
485 class expand_operand ops[2];
486 create_output_operand (&ops[0], target, mode);
487 create_input_operand (&ops[1], cond, mode);
488 gcc_assert (targetm.have_omp_simt_last_lane ());
489 expand_insn (targetm.code_for_omp_simt_last_lane, 2, ops);
490 if (!rtx_equal_p (target, ops[0].value))
491 emit_move_insn (target, ops[0].value);
492}
493
494/* Non-transparent predicate used in SIMT lowering of OpenMP "ordered". */
495
496static void
497expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt)
498{
499 tree lhs = gimple_call_lhs (stmt);
500 if (!lhs)
501 return;
502
503 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
504 rtx ctr = expand_normal (gimple_call_arg (stmt, 0));
505 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
506 class expand_operand ops[2];
507 create_output_operand (&ops[0], target, mode);
508 create_input_operand (&ops[1], ctr, mode);
509 gcc_assert (targetm.have_omp_simt_ordered ());
510 expand_insn (targetm.code_for_omp_simt_ordered, 2, ops);
511 if (!rtx_equal_p (target, ops[0].value))
512 emit_move_insn (target, ops[0].value);
513}
514
515/* "Or" boolean reduction across SIMT lanes: return non-zero in all lanes if
516 any lane supplies a non-zero argument. */
517
518static void
519expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt)
520{
521 tree lhs = gimple_call_lhs (stmt);
522 if (!lhs)
523 return;
524
525 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
526 rtx cond = expand_normal (gimple_call_arg (stmt, 0));
527 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
528 class expand_operand ops[2];
529 create_output_operand (&ops[0], target, mode);
530 create_input_operand (&ops[1], cond, mode);
531 gcc_assert (targetm.have_omp_simt_vote_any ());
532 expand_insn (targetm.code_for_omp_simt_vote_any, 2, ops);
533 if (!rtx_equal_p (target, ops[0].value))
534 emit_move_insn (target, ops[0].value);
535}
536
537/* Exchange between SIMT lanes with a "butterfly" pattern: source lane index
538 is destination lane index XOR given offset. */
539
540static void
541expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt)
542{
543 tree lhs = gimple_call_lhs (stmt);
544 if (!lhs)
545 return;
546
547 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
548 rtx src = expand_normal (gimple_call_arg (stmt, 0));
549 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
550 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
551 class expand_operand ops[3];
552 create_output_operand (&ops[0], target, mode);
553 create_input_operand (&ops[1], src, mode);
554 create_input_operand (&ops[2], idx, SImode);
555 gcc_assert (targetm.have_omp_simt_xchg_bfly ());
556 expand_insn (targetm.code_for_omp_simt_xchg_bfly, 3, ops);
557 if (!rtx_equal_p (target, ops[0].value))
558 emit_move_insn (target, ops[0].value);
559}
560
561/* Exchange between SIMT lanes according to given source lane index. */
562
563static void
564expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt)
565{
566 tree lhs = gimple_call_lhs (stmt);
567 if (!lhs)
568 return;
569
570 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
571 rtx src = expand_normal (gimple_call_arg (stmt, 0));
572 rtx idx = expand_normal (gimple_call_arg (stmt, 1));
573 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
574 class expand_operand ops[3];
575 create_output_operand (&ops[0], target, mode);
576 create_input_operand (&ops[1], src, mode);
577 create_input_operand (&ops[2], idx, SImode);
578 gcc_assert (targetm.have_omp_simt_xchg_idx ());
579 expand_insn (targetm.code_for_omp_simt_xchg_idx, 3, ops);
580 if (!rtx_equal_p (target, ops[0].value))
581 emit_move_insn (target, ops[0].value);
582}
583
74bf76ed
JJ
584/* This should get expanded in adjust_simduid_builtins. */
585
586static void
4cfe7a6c 587expand_GOMP_SIMD_LANE (internal_fn, gcall *)
74bf76ed
JJ
588{
589 gcc_unreachable ();
590}
591
592/* This should get expanded in adjust_simduid_builtins. */
593
594static void
4cfe7a6c 595expand_GOMP_SIMD_VF (internal_fn, gcall *)
74bf76ed
JJ
596{
597 gcc_unreachable ();
598}
599
600/* This should get expanded in adjust_simduid_builtins. */
601
602static void
4cfe7a6c 603expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
74bf76ed
JJ
604{
605 gcc_unreachable ();
606}
607
d9a6bd32
JJ
608/* This should get expanded in adjust_simduid_builtins. */
609
610static void
4cfe7a6c 611expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
d9a6bd32
JJ
612{
613 gcc_unreachable ();
614}
615
616/* This should get expanded in adjust_simduid_builtins. */
617
618static void
4cfe7a6c 619expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
d9a6bd32
JJ
620{
621 gcc_unreachable ();
622}
623
b9a55b13
MP
624/* This should get expanded in the sanopt pass. */
625
626static void
4cfe7a6c 627expand_UBSAN_NULL (internal_fn, gcall *)
b9a55b13
MP
628{
629 gcc_unreachable ();
630}
631
0e37a2f3
MP
632/* This should get expanded in the sanopt pass. */
633
634static void
4cfe7a6c 635expand_UBSAN_BOUNDS (internal_fn, gcall *)
0e82f089
MP
636{
637 gcc_unreachable ();
638}
639
640/* This should get expanded in the sanopt pass. */
641
642static void
4cfe7a6c 643expand_UBSAN_VPTR (internal_fn, gcall *)
0e37a2f3
MP
644{
645 gcc_unreachable ();
646}
647
c62ccb9a
YG
648/* This should get expanded in the sanopt pass. */
649
c9b39a49
JJ
650static void
651expand_UBSAN_PTR (internal_fn, gcall *)
652{
653 gcc_unreachable ();
654}
655
656/* This should get expanded in the sanopt pass. */
657
c62ccb9a 658static void
4cfe7a6c 659expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
35228ac7
JJ
660{
661 gcc_unreachable ();
662}
663
664/* This should get expanded in the sanopt pass. */
665
93a73251
MM
666static void
667expand_HWASAN_CHECK (internal_fn, gcall *)
668{
669 gcc_unreachable ();
670}
671
672/* For hwasan stack tagging:
673 Clear tags on the dynamically allocated space.
674 For use after an object dynamically allocated on the stack goes out of
675 scope. */
676static void
677expand_HWASAN_ALLOCA_UNPOISON (internal_fn, gcall *gc)
678{
679 gcc_assert (Pmode == ptr_mode);
680 tree restored_position = gimple_call_arg (gc, 0);
681 rtx restored_rtx = expand_expr (restored_position, NULL_RTX, VOIDmode,
682 EXPAND_NORMAL);
683 rtx func = init_one_libfunc ("__hwasan_tag_memory");
684 rtx off = expand_simple_binop (Pmode, MINUS, restored_rtx,
685 stack_pointer_rtx, NULL_RTX, 0,
686 OPTAB_WIDEN);
687 emit_library_call_value (func, NULL_RTX, LCT_NORMAL, VOIDmode,
688 virtual_stack_dynamic_rtx, Pmode,
689 HWASAN_STACK_BACKGROUND, QImode,
690 off, Pmode);
691}
692
693/* For hwasan stack tagging:
694 Return a tag to be used for a dynamic allocation. */
695static void
696expand_HWASAN_CHOOSE_TAG (internal_fn, gcall *gc)
697{
698 tree tag = gimple_call_lhs (gc);
699 rtx target = expand_expr (tag, NULL_RTX, VOIDmode, EXPAND_NORMAL);
700 machine_mode mode = GET_MODE (target);
701 gcc_assert (mode == QImode);
702
703 rtx base_tag = targetm.memtag.extract_tag (hwasan_frame_base (), NULL_RTX);
704 gcc_assert (base_tag);
705 rtx tag_offset = gen_int_mode (hwasan_current_frame_tag (), QImode);
706 rtx chosen_tag = expand_simple_binop (QImode, PLUS, base_tag, tag_offset,
707 target, /* unsignedp = */1,
708 OPTAB_WIDEN);
709 chosen_tag = hwasan_truncate_to_tag_size (chosen_tag, target);
710
711 /* Really need to put the tag into the `target` RTX. */
712 if (chosen_tag != target)
713 {
714 rtx temp = chosen_tag;
715 gcc_assert (GET_MODE (chosen_tag) == mode);
716 emit_move_insn (target, temp);
717 }
718
719 hwasan_increment_frame_tag ();
720}
721
722/* For hwasan stack tagging:
723 Tag a region of space in the shadow stack according to the base pointer of
724 an object on the stack. N.b. the length provided in the internal call is
725 required to be aligned to HWASAN_TAG_GRANULE_SIZE. */
726static void
727expand_HWASAN_MARK (internal_fn, gcall *gc)
728{
729 gcc_assert (ptr_mode == Pmode);
730 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (gc, 0));
731 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
732
733 tree base = gimple_call_arg (gc, 1);
734 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
735 rtx base_rtx = expand_normal (base);
736
737 rtx tag = is_poison ? HWASAN_STACK_BACKGROUND
738 : targetm.memtag.extract_tag (base_rtx, NULL_RTX);
739 rtx address = targetm.memtag.untagged_pointer (base_rtx, NULL_RTX);
740
741 tree len = gimple_call_arg (gc, 2);
742 rtx r_len = expand_normal (len);
743
744 rtx func = init_one_libfunc ("__hwasan_tag_memory");
745 emit_library_call (func, LCT_NORMAL, VOIDmode, address, Pmode,
746 tag, QImode, r_len, Pmode);
747}
748
749/* For hwasan stack tagging:
750 Store a tag into a pointer. */
751static void
752expand_HWASAN_SET_TAG (internal_fn, gcall *gc)
753{
754 gcc_assert (ptr_mode == Pmode);
755 tree g_target = gimple_call_lhs (gc);
756 tree g_ptr = gimple_call_arg (gc, 0);
757 tree g_tag = gimple_call_arg (gc, 1);
758
759 rtx ptr = expand_normal (g_ptr);
760 rtx tag = expand_expr (g_tag, NULL_RTX, QImode, EXPAND_NORMAL);
761 rtx target = expand_normal (g_target);
762
763 rtx untagged = targetm.memtag.untagged_pointer (ptr, target);
764 rtx tagged_value = targetm.memtag.set_tag (untagged, tag, target);
765 if (tagged_value != target)
766 emit_move_insn (target, tagged_value);
767}
768
769/* This should get expanded in the sanopt pass. */
770
35228ac7 771static void
4cfe7a6c 772expand_ASAN_CHECK (internal_fn, gcall *)
c62ccb9a
YG
773{
774 gcc_unreachable ();
775}
776
6dc4a604
ML
777/* This should get expanded in the sanopt pass. */
778
779static void
780expand_ASAN_MARK (internal_fn, gcall *)
781{
782 gcc_unreachable ();
783}
784
c7775327
ML
785/* This should get expanded in the sanopt pass. */
786
787static void
788expand_ASAN_POISON (internal_fn, gcall *)
789{
790 gcc_unreachable ();
791}
6dc4a604 792
f6b9f2ff
ML
793/* This should get expanded in the sanopt pass. */
794
795static void
796expand_ASAN_POISON_USE (internal_fn, gcall *)
797{
798 gcc_unreachable ();
799}
800
fca4adf2
JJ
801/* This should get expanded in the tsan pass. */
802
803static void
4cfe7a6c 804expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
fca4adf2
JJ
805{
806 gcc_unreachable ();
807}
808
81fea426
MP
809/* This should get expanded in the lower pass. */
810
811static void
812expand_FALLTHROUGH (internal_fn, gcall *call)
813{
814 error_at (gimple_location (call),
815 "invalid use of attribute %<fallthrough%>");
816}
817
1304953e
JJ
818/* Return minimum precision needed to represent all values
819 of ARG in SIGNed integral type. */
820
821static int
822get_min_precision (tree arg, signop sign)
823{
824 int prec = TYPE_PRECISION (TREE_TYPE (arg));
825 int cnt = 0;
826 signop orig_sign = sign;
827 if (TREE_CODE (arg) == INTEGER_CST)
828 {
829 int p;
830 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
831 {
832 widest_int w = wi::to_widest (arg);
833 w = wi::ext (w, prec, sign);
834 p = wi::min_precision (w, sign);
835 }
836 else
8e6cdc90 837 p = wi::min_precision (wi::to_wide (arg), sign);
1304953e
JJ
838 return MIN (p, prec);
839 }
840 while (CONVERT_EXPR_P (arg)
841 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
842 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
843 {
844 arg = TREE_OPERAND (arg, 0);
845 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
846 {
847 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
848 sign = UNSIGNED;
849 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
850 return prec + (orig_sign != sign);
851 prec = TYPE_PRECISION (TREE_TYPE (arg));
852 }
853 if (++cnt > 30)
854 return prec + (orig_sign != sign);
855 }
049ce9d2
JJ
856 if (CONVERT_EXPR_P (arg)
857 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
858 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) > prec)
859 {
860 /* We have e.g. (unsigned short) y_2 where int y_2 = (int) x_1(D);
861 If y_2's min precision is smaller than prec, return that. */
862 int oprec = get_min_precision (TREE_OPERAND (arg, 0), sign);
863 if (oprec < prec)
864 return oprec + (orig_sign != sign);
865 }
1304953e
JJ
866 if (TREE_CODE (arg) != SSA_NAME)
867 return prec + (orig_sign != sign);
45f4e2b0
AH
868 value_range r;
869 while (!get_global_range_query ()->range_of_expr (r, arg)
637037f4
AH
870 || r.varying_p ()
871 || r.undefined_p ())
1304953e 872 {
355fe088 873 gimple *g = SSA_NAME_DEF_STMT (arg);
1304953e
JJ
874 if (is_gimple_assign (g)
875 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
876 {
877 tree t = gimple_assign_rhs1 (g);
878 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
879 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
880 {
881 arg = t;
882 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
883 {
884 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
885 sign = UNSIGNED;
886 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
887 return prec + (orig_sign != sign);
888 prec = TYPE_PRECISION (TREE_TYPE (arg));
889 }
890 if (++cnt > 30)
891 return prec + (orig_sign != sign);
892 continue;
893 }
894 }
895 return prec + (orig_sign != sign);
896 }
897 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
898 {
45f4e2b0
AH
899 int p1 = wi::min_precision (r.lower_bound (), sign);
900 int p2 = wi::min_precision (r.upper_bound (), sign);
1304953e
JJ
901 p1 = MAX (p1, p2);
902 prec = MIN (prec, p1);
903 }
45f4e2b0 904 else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
1304953e 905 {
45f4e2b0 906 int p = wi::min_precision (r.upper_bound (), UNSIGNED);
1304953e
JJ
907 prec = MIN (prec, p);
908 }
909 return prec + (orig_sign != sign);
910}
911
a86451b9
JJ
912/* Helper for expand_*_overflow. Set the __imag__ part to true
913 (1 except for signed:1 type, in which case store -1). */
914
915static void
916expand_arith_set_overflow (tree lhs, rtx target)
917{
918 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
919 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
13f44099 920 write_complex_part (target, constm1_rtx, true, false);
a86451b9 921 else
13f44099 922 write_complex_part (target, const1_rtx, true, false);
a86451b9
JJ
923}
924
1304953e
JJ
925/* Helper for expand_*_overflow. Store RES into the __real__ part
926 of TARGET. If RES has larger MODE than __real__ part of TARGET,
a86451b9
JJ
927 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
928 if LHS has smaller precision than its mode. */
1304953e
JJ
929
930static void
931expand_arith_overflow_result_store (tree lhs, rtx target,
095a2d76 932 scalar_int_mode mode, rtx res)
1304953e 933{
c7ad039d
RS
934 scalar_int_mode tgtmode
935 = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
1304953e
JJ
936 rtx lres = res;
937 if (tgtmode != mode)
938 {
939 rtx_code_label *done_label = gen_label_rtx ();
940 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
941 lres = convert_modes (tgtmode, mode, res, uns);
942 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
92344ed0 943 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
1476d1bd 944 EQ, true, mode, NULL_RTX, NULL, done_label,
357067f2 945 profile_probability::very_likely ());
a86451b9
JJ
946 expand_arith_set_overflow (lhs, target);
947 emit_label (done_label);
948 }
949 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
950 int tgtprec = GET_MODE_PRECISION (tgtmode);
951 if (prec < tgtprec)
952 {
953 rtx_code_label *done_label = gen_label_rtx ();
954 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
955 res = lres;
956 if (uns)
957 {
958 rtx mask
959 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
960 tgtmode);
961 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
95ef39f4 962 true, OPTAB_LIB_WIDEN);
a86451b9
JJ
963 }
964 else
965 {
966 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
967 NULL_RTX, 1);
968 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
969 NULL_RTX, 0);
970 }
971 do_compare_rtx_and_jump (res, lres,
972 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
357067f2 973 profile_probability::very_likely ());
a86451b9 974 expand_arith_set_overflow (lhs, target);
1304953e
JJ
975 emit_label (done_label);
976 }
13f44099 977 write_complex_part (target, lres, false, false);
1304953e
JJ
978}
979
5620052d
JJ
980/* Helper for expand_*_overflow. Store RES into TARGET. */
981
982static void
983expand_ubsan_result_store (rtx target, rtx res)
984{
985 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
986 /* If this is a scalar in a register that is stored in a wider mode
987 than the declared mode, compute the result into its declared mode
988 and then convert to the wider mode. Our value is the computed
989 expression. */
990 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
991 else
992 emit_move_insn (target, res);
993}
994
31e071ae
MP
995/* Add sub/add overflow checking to the statement STMT.
996 CODE says whether the operation is +, or -. */
997
4d87bd39 998void
1304953e
JJ
999expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
1000 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
1705cebd 1001 bool uns1_p, bool is_ubsan, tree *datap)
31e071ae 1002{
1304953e
JJ
1003 rtx res, target = NULL_RTX;
1004 tree fn;
1005 rtx_code_label *done_label = gen_label_rtx ();
1006 rtx_code_label *do_error = gen_label_rtx ();
31e071ae 1007 do_pending_stack_adjust ();
1304953e
JJ
1008 rtx op0 = expand_normal (arg0);
1009 rtx op1 = expand_normal (arg1);
7a504f33 1010 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1304953e
JJ
1011 int prec = GET_MODE_PRECISION (mode);
1012 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
1013 bool do_xor = false;
1014
1015 if (is_ubsan)
1016 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1017
31e071ae 1018 if (lhs)
1304953e
JJ
1019 {
1020 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1021 if (!is_ubsan)
13f44099 1022 write_complex_part (target, const0_rtx, true, false);
1304953e
JJ
1023 }
1024
1025 /* We assume both operands and result have the same precision
1026 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1027 with that precision, U for unsigned type with that precision,
1028 sgn for unsigned most significant bit in that precision.
1029 s1 is signed first operand, u1 is unsigned first operand,
1030 s2 is signed second operand, u2 is unsigned second operand,
1031 sr is signed result, ur is unsigned result and the following
1032 rules say how to compute result (which is always result of
1033 the operands as if both were unsigned, cast to the right
1034 signedness) and how to compute whether operation overflowed.
1035
1036 s1 + s2 -> sr
1037 res = (S) ((U) s1 + (U) s2)
1038 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
1039 s1 - s2 -> sr
1040 res = (S) ((U) s1 - (U) s2)
1041 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
1042 u1 + u2 -> ur
1043 res = u1 + u2
1044 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
1045 u1 - u2 -> ur
1046 res = u1 - u2
1047 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
1048 s1 + u2 -> sr
1049 res = (S) ((U) s1 + u2)
1050 ovf = ((U) res ^ sgn) < u2
1051 s1 + u2 -> ur
1052 t1 = (S) (u2 ^ sgn)
1053 t2 = s1 + t1
1054 res = (U) t2 ^ sgn
1055 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
1056 s1 - u2 -> sr
1057 res = (S) ((U) s1 - u2)
1058 ovf = u2 > ((U) s1 ^ sgn)
1059 s1 - u2 -> ur
1060 res = (U) s1 - u2
1061 ovf = s1 < 0 || u2 > (U) s1
1062 u1 - s2 -> sr
1063 res = u1 - (U) s2
1064 ovf = u1 >= ((U) s2 ^ sgn)
1065 u1 - s2 -> ur
1066 t1 = u1 ^ sgn
1067 t2 = t1 - (U) s2
1068 res = t2 ^ sgn
1069 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
1070 s1 + s2 -> ur
1071 res = (U) s1 + (U) s2
1072 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
1073 u1 + u2 -> sr
1074 res = (S) (u1 + u2)
1075 ovf = (U) res < u2 || res < 0
1076 u1 - u2 -> sr
1077 res = (S) (u1 - u2)
1078 ovf = u1 >= u2 ? res < 0 : res >= 0
1079 s1 - s2 -> ur
1080 res = (U) s1 - (U) s2
1081 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
1082
1083 if (code == PLUS_EXPR && uns0_p && !uns1_p)
1084 {
1085 /* PLUS_EXPR is commutative, if operand signedness differs,
1086 canonicalize to the first operand being signed and second
1087 unsigned to simplify following code. */
6b4db501
MM
1088 std::swap (op0, op1);
1089 std::swap (arg0, arg1);
1090 uns0_p = false;
1091 uns1_p = true;
1304953e
JJ
1092 }
1093
1094 /* u1 +- u2 -> ur */
1095 if (uns0_p && uns1_p && unsr_p)
1096 {
cde9d596
RH
1097 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
1098 : usubv4_optab, mode);
1099 if (icode != CODE_FOR_nothing)
1100 {
99b1c316 1101 class expand_operand ops[4];
cde9d596
RH
1102 rtx_insn *last = get_last_insn ();
1103
1104 res = gen_reg_rtx (mode);
1105 create_output_operand (&ops[0], res, mode);
1106 create_input_operand (&ops[1], op0, mode);
1107 create_input_operand (&ops[2], op1, mode);
1108 create_fixed_operand (&ops[3], do_error);
1109 if (maybe_expand_insn (icode, 4, ops))
1110 {
1111 last = get_last_insn ();
1112 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1113 && JUMP_P (last)
1114 && any_condjump_p (last)
1115 && !find_reg_note (last, REG_BR_PROB, 0))
5fa396ad
JH
1116 add_reg_br_prob_note (last,
1117 profile_probability::very_unlikely ());
cde9d596
RH
1118 emit_jump (done_label);
1119 goto do_error_label;
1120 }
1121
1122 delete_insns_since (last);
1123 }
1124
1304953e
JJ
1125 /* Compute the operation. On RTL level, the addition is always
1126 unsigned. */
1127 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1128 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1129 rtx tem = op0;
1130 /* For PLUS_EXPR, the operation is commutative, so we can pick
1131 operand to compare against. For prec <= BITS_PER_WORD, I think
1132 preferring REG operand is better over CONST_INT, because
1133 the CONST_INT might enlarge the instruction or CSE would need
1134 to figure out we'd already loaded it into a register before.
1135 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
1136 as then the multi-word comparison can be perhaps simplified. */
1137 if (code == PLUS_EXPR
1138 && (prec <= BITS_PER_WORD
1139 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
1140 : CONST_SCALAR_INT_P (op1)))
1141 tem = op1;
92344ed0 1142 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1476d1bd 1143 true, mode, NULL_RTX, NULL, done_label,
357067f2 1144 profile_probability::very_likely ());
1304953e
JJ
1145 goto do_error_label;
1146 }
1147
1148 /* s1 +- u2 -> sr */
1149 if (!uns0_p && uns1_p && !unsr_p)
1150 {
1151 /* Compute the operation. On RTL level, the addition is always
1152 unsigned. */
1153 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1154 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1155 rtx tem = expand_binop (mode, add_optab,
1156 code == PLUS_EXPR ? res : op0, sgn,
1157 NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd 1158 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
357067f2 1159 done_label, profile_probability::very_likely ());
1304953e
JJ
1160 goto do_error_label;
1161 }
1162
1163 /* s1 + u2 -> ur */
1164 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
1165 {
1166 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1167 OPTAB_LIB_WIDEN);
1168 /* As we've changed op1, we have to avoid using the value range
1169 for the original argument. */
1170 arg1 = error_mark_node;
1171 do_xor = true;
1172 goto do_signed;
1173 }
1174
1175 /* u1 - s2 -> ur */
1176 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
1177 {
1178 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
1179 OPTAB_LIB_WIDEN);
1180 /* As we've changed op0, we have to avoid using the value range
1181 for the original argument. */
1182 arg0 = error_mark_node;
1183 do_xor = true;
1184 goto do_signed;
1185 }
1186
1187 /* s1 - u2 -> ur */
1188 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
1189 {
1190 /* Compute the operation. On RTL level, the addition is always
1191 unsigned. */
1192 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1193 OPTAB_LIB_WIDEN);
1194 int pos_neg = get_range_pos_neg (arg0);
1195 if (pos_neg == 2)
1196 /* If ARG0 is known to be always negative, this is always overflow. */
1197 emit_jump (do_error);
1198 else if (pos_neg == 3)
1199 /* If ARG0 is not known to be always positive, check at runtime. */
92344ed0 1200 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
357067f2 1201 NULL, do_error, profile_probability::very_unlikely ());
1476d1bd 1202 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
357067f2 1203 done_label, profile_probability::very_likely ());
1304953e
JJ
1204 goto do_error_label;
1205 }
1206
1207 /* u1 - s2 -> sr */
1208 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
1209 {
1210 /* Compute the operation. On RTL level, the addition is always
1211 unsigned. */
1212 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1213 OPTAB_LIB_WIDEN);
1214 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
1215 OPTAB_LIB_WIDEN);
1476d1bd 1216 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
357067f2 1217 done_label, profile_probability::very_likely ());
1304953e
JJ
1218 goto do_error_label;
1219 }
1220
1221 /* u1 + u2 -> sr */
1222 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
1223 {
1224 /* Compute the operation. On RTL level, the addition is always
1225 unsigned. */
1226 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
1227 OPTAB_LIB_WIDEN);
92344ed0 1228 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
357067f2 1229 NULL, do_error, profile_probability::very_unlikely ());
1304953e
JJ
1230 rtx tem = op1;
1231 /* The operation is commutative, so we can pick operand to compare
1232 against. For prec <= BITS_PER_WORD, I think preferring REG operand
1233 is better over CONST_INT, because the CONST_INT might enlarge the
1234 instruction or CSE would need to figure out we'd already loaded it
1235 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
1236 might be more beneficial, as then the multi-word comparison can be
1237 perhaps simplified. */
1238 if (prec <= BITS_PER_WORD
1239 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
1240 : CONST_SCALAR_INT_P (op0))
1241 tem = op0;
1476d1bd 1242 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
357067f2 1243 done_label, profile_probability::very_likely ());
1304953e
JJ
1244 goto do_error_label;
1245 }
1246
1247 /* s1 +- s2 -> ur */
1248 if (!uns0_p && !uns1_p && unsr_p)
1249 {
1250 /* Compute the operation. On RTL level, the addition is always
1251 unsigned. */
1252 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1253 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1254 int pos_neg = get_range_pos_neg (arg1);
1255 if (code == PLUS_EXPR)
1256 {
1257 int pos_neg0 = get_range_pos_neg (arg0);
1258 if (pos_neg0 != 3 && pos_neg == 3)
1259 {
6b4db501 1260 std::swap (op0, op1);
1304953e
JJ
1261 pos_neg = pos_neg0;
1262 }
1263 }
1264 rtx tem;
1265 if (pos_neg != 3)
1266 {
1267 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
1268 ? and_optab : ior_optab,
1269 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd 1270 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
357067f2 1271 NULL, done_label, profile_probability::very_likely ());
1304953e
JJ
1272 }
1273 else
1274 {
1275 rtx_code_label *do_ior_label = gen_label_rtx ();
92344ed0
JJ
1276 do_compare_rtx_and_jump (op1, const0_rtx,
1277 code == MINUS_EXPR ? GE : LT, false, mode,
1476d1bd 1278 NULL_RTX, NULL, do_ior_label,
357067f2 1279 profile_probability::even ());
1304953e
JJ
1280 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
1281 OPTAB_LIB_WIDEN);
92344ed0 1282 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 1283 NULL, done_label, profile_probability::very_likely ());
1304953e
JJ
1284 emit_jump (do_error);
1285 emit_label (do_ior_label);
1286 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
1287 OPTAB_LIB_WIDEN);
92344ed0 1288 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 1289 NULL, done_label, profile_probability::very_likely ());
1304953e
JJ
1290 }
1291 goto do_error_label;
1292 }
1293
1294 /* u1 - u2 -> sr */
1295 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
1296 {
1297 /* Compute the operation. On RTL level, the addition is always
1298 unsigned. */
1299 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
1300 OPTAB_LIB_WIDEN);
1301 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1476d1bd 1302 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
357067f2 1303 op0_geu_op1, profile_probability::even ());
92344ed0 1304 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
357067f2 1305 NULL, done_label, profile_probability::very_likely ());
1304953e
JJ
1306 emit_jump (do_error);
1307 emit_label (op0_geu_op1);
92344ed0 1308 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 1309 NULL, done_label, profile_probability::very_likely ());
1304953e
JJ
1310 goto do_error_label;
1311 }
31e071ae 1312
1304953e
JJ
1313 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
1314
1315 /* s1 +- s2 -> sr */
cde9d596
RH
1316 do_signed:
1317 {
1318 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
1319 : subv4_optab, mode);
1320 if (icode != CODE_FOR_nothing)
1321 {
99b1c316 1322 class expand_operand ops[4];
cde9d596
RH
1323 rtx_insn *last = get_last_insn ();
1324
1325 res = gen_reg_rtx (mode);
1326 create_output_operand (&ops[0], res, mode);
1327 create_input_operand (&ops[1], op0, mode);
1328 create_input_operand (&ops[2], op1, mode);
1329 create_fixed_operand (&ops[3], do_error);
1330 if (maybe_expand_insn (icode, 4, ops))
1331 {
1332 last = get_last_insn ();
1333 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
1334 && JUMP_P (last)
1335 && any_condjump_p (last)
1336 && !find_reg_note (last, REG_BR_PROB, 0))
5fa396ad
JH
1337 add_reg_br_prob_note (last,
1338 profile_probability::very_unlikely ());
cde9d596
RH
1339 emit_jump (done_label);
1340 goto do_error_label;
1341 }
1342
1343 delete_insns_since (last);
1344 }
1345
cde9d596
RH
1346 /* Compute the operation. On RTL level, the addition is always
1347 unsigned. */
1348 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
1349 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
1350
47135167 1351 /* If we can prove that one of the arguments (for MINUS_EXPR only
cde9d596
RH
1352 the second operand, as subtraction is not commutative) is always
1353 non-negative or always negative, we can do just one comparison
47135167
EB
1354 and conditional jump. */
1355 int pos_neg = get_range_pos_neg (arg1);
1356 if (code == PLUS_EXPR)
cde9d596 1357 {
47135167
EB
1358 int pos_neg0 = get_range_pos_neg (arg0);
1359 if (pos_neg0 != 3 && pos_neg == 3)
1360 {
1361 std::swap (op0, op1);
1362 pos_neg = pos_neg0;
1363 }
cde9d596 1364 }
cde9d596 1365
47135167
EB
1366 /* Addition overflows if and only if the two operands have the same sign,
1367 and the result has the opposite sign. Subtraction overflows if and
1368 only if the two operands have opposite sign, and the subtrahend has
1369 the same sign as the result. Here 0 is counted as positive. */
cde9d596 1370 if (pos_neg == 3)
47135167
EB
1371 {
1372 /* Compute op0 ^ op1 (operands have opposite sign). */
1373 rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1374 OPTAB_LIB_WIDEN);
cde9d596 1375
47135167
EB
1376 /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
1377 rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
1378 OPTAB_LIB_WIDEN);
97286431 1379
47135167
EB
1380 rtx tem;
1381 if (code == PLUS_EXPR)
1382 {
1383 /* Compute (res ^ op1) & ~(op0 ^ op1). */
1384 tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
1385 tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
1386 OPTAB_LIB_WIDEN);
1387 }
1388 else
1389 {
1390 /* Compute (op0 ^ op1) & ~(res ^ op1). */
1391 tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
1392 tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
1393 OPTAB_LIB_WIDEN);
1394 }
1395
1396 /* No overflow if the result has bit sign cleared. */
1397 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 1398 NULL, done_label, profile_probability::very_likely ());
cde9d596 1399 }
31e071ae 1400
47135167
EB
1401 /* Compare the result of the operation with the first operand.
1402 No overflow for addition if second operand is positive and result
1403 is larger or second operand is negative and result is smaller.
1404 Likewise for subtraction with sign of second operand flipped. */
1405 else
1406 do_compare_rtx_and_jump (res, op0,
1407 (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
cde9d596 1408 false, mode, NULL_RTX, NULL, done_label,
357067f2 1409 profile_probability::very_likely ());
cde9d596 1410 }
31e071ae 1411
1304953e 1412 do_error_label:
1769415d 1413 emit_label (do_error);
1304953e
JJ
1414 if (is_ubsan)
1415 {
1416 /* Expand the ubsan builtin call. */
1417 push_temp_slots ();
1418 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
1705cebd 1419 arg0, arg1, datap);
1304953e
JJ
1420 expand_normal (fn);
1421 pop_temp_slots ();
1422 do_pending_stack_adjust ();
1423 }
1424 else if (lhs)
a86451b9 1425 expand_arith_set_overflow (lhs, target);
31e071ae 1426
1769415d
MP
1427 /* We're done. */
1428 emit_label (done_label);
31e071ae
MP
1429
1430 if (lhs)
1304953e
JJ
1431 {
1432 if (is_ubsan)
5620052d 1433 expand_ubsan_result_store (target, res);
1304953e
JJ
1434 else
1435 {
1436 if (do_xor)
1437 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
1438 OPTAB_LIB_WIDEN);
1439
1440 expand_arith_overflow_result_store (lhs, target, mode, res);
1441 }
1442 }
31e071ae
MP
1443}
1444
1445/* Add negate overflow checking to the statement STMT. */
1446
1304953e 1447static void
1705cebd
JJ
1448expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
1449 tree *datap)
31e071ae
MP
1450{
1451 rtx res, op1;
1304953e 1452 tree fn;
da664544
DM
1453 rtx_code_label *done_label, *do_error;
1454 rtx target = NULL_RTX;
31e071ae 1455
31e071ae
MP
1456 done_label = gen_label_rtx ();
1457 do_error = gen_label_rtx ();
31e071ae
MP
1458
1459 do_pending_stack_adjust ();
1460 op1 = expand_normal (arg1);
1461
7a504f33 1462 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
31e071ae 1463 if (lhs)
1304953e
JJ
1464 {
1465 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1466 if (!is_ubsan)
13f44099 1467 write_complex_part (target, const0_rtx, true, false);
1304953e 1468 }
31e071ae
MP
1469
1470 enum insn_code icode = optab_handler (negv3_optab, mode);
1471 if (icode != CODE_FOR_nothing)
1472 {
99b1c316 1473 class expand_operand ops[3];
da664544 1474 rtx_insn *last = get_last_insn ();
31e071ae
MP
1475
1476 res = gen_reg_rtx (mode);
1477 create_output_operand (&ops[0], res, mode);
1478 create_input_operand (&ops[1], op1, mode);
1479 create_fixed_operand (&ops[2], do_error);
1480 if (maybe_expand_insn (icode, 3, ops))
1481 {
1482 last = get_last_insn ();
0a6a6ac9 1483 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
1484 && JUMP_P (last)
1485 && any_condjump_p (last)
1486 && !find_reg_note (last, REG_BR_PROB, 0))
5fa396ad
JH
1487 add_reg_br_prob_note (last,
1488 profile_probability::very_unlikely ());
31e071ae
MP
1489 emit_jump (done_label);
1490 }
1491 else
1492 {
1493 delete_insns_since (last);
1494 icode = CODE_FOR_nothing;
1495 }
1496 }
1497
1498 if (icode == CODE_FOR_nothing)
1499 {
1500 /* Compute the operation. On RTL level, the addition is always
1501 unsigned. */
1502 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1503
1504 /* Compare the operand with the most negative value. */
1505 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1476d1bd 1506 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
357067f2 1507 done_label, profile_probability::very_likely ());
31e071ae
MP
1508 }
1509
1510 emit_label (do_error);
1304953e
JJ
1511 if (is_ubsan)
1512 {
1513 /* Expand the ubsan builtin call. */
1514 push_temp_slots ();
1515 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1705cebd 1516 arg1, NULL_TREE, datap);
1304953e
JJ
1517 expand_normal (fn);
1518 pop_temp_slots ();
1519 do_pending_stack_adjust ();
1520 }
1521 else if (lhs)
a86451b9 1522 expand_arith_set_overflow (lhs, target);
31e071ae
MP
1523
1524 /* We're done. */
1525 emit_label (done_label);
1526
1527 if (lhs)
1304953e
JJ
1528 {
1529 if (is_ubsan)
5620052d 1530 expand_ubsan_result_store (target, res);
1304953e
JJ
1531 else
1532 expand_arith_overflow_result_store (lhs, target, mode, res);
1533 }
31e071ae
MP
1534}
1535
0b99f253
JJ
1536/* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand
1537 mode MODE can be expanded without using a libcall. */
1538
1539static bool
1540can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode,
1541 rtx op0, rtx op1, bool uns)
1542{
1543 if (find_widening_optab_handler (umul_widen_optab, wmode, mode)
1544 != CODE_FOR_nothing)
1545 return true;
1546
1547 if (find_widening_optab_handler (smul_widen_optab, wmode, mode)
1548 != CODE_FOR_nothing)
1549 return true;
1550
1551 rtx_insn *last = get_last_insn ();
1552 if (CONSTANT_P (op0))
1553 op0 = convert_modes (wmode, mode, op0, uns);
1554 else
1555 op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1);
1556 if (CONSTANT_P (op1))
1557 op1 = convert_modes (wmode, mode, op1, uns);
1558 else
1559 op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2);
1560 rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true);
1561 delete_insns_since (last);
1562 return ret != NULL_RTX;
1563}
1564
31e071ae
MP
1565/* Add mul overflow checking to the statement STMT. */
1566
1304953e
JJ
1567static void
1568expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1705cebd
JJ
1569 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan,
1570 tree *datap)
31e071ae
MP
1571{
1572 rtx res, op0, op1;
1304953e 1573 tree fn, type;
da664544
DM
1574 rtx_code_label *done_label, *do_error;
1575 rtx target = NULL_RTX;
1304953e
JJ
1576 signop sign;
1577 enum insn_code icode;
31e071ae 1578
31e071ae
MP
1579 done_label = gen_label_rtx ();
1580 do_error = gen_label_rtx ();
31e071ae
MP
1581
1582 do_pending_stack_adjust ();
1583 op0 = expand_normal (arg0);
1584 op1 = expand_normal (arg1);
1585
7a504f33 1586 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
1304953e 1587 bool uns = unsr_p;
31e071ae 1588 if (lhs)
1304953e
JJ
1589 {
1590 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1591 if (!is_ubsan)
13f44099 1592 write_complex_part (target, const0_rtx, true, false);
1304953e
JJ
1593 }
1594
1595 if (is_ubsan)
1596 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1597
1598 /* We assume both operands and result have the same precision
1599 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1600 with that precision, U for unsigned type with that precision,
1601 sgn for unsigned most significant bit in that precision.
1602 s1 is signed first operand, u1 is unsigned first operand,
1603 s2 is signed second operand, u2 is unsigned second operand,
1604 sr is signed result, ur is unsigned result and the following
1605 rules say how to compute result (which is always result of
1606 the operands as if both were unsigned, cast to the right
1607 signedness) and how to compute whether operation overflowed.
1608 main_ovf (false) stands for jump on signed multiplication
1609 overflow or the main algorithm with uns == false.
1610 main_ovf (true) stands for jump on unsigned multiplication
1611 overflow or the main algorithm with uns == true.
1612
1613 s1 * s2 -> sr
1614 res = (S) ((U) s1 * (U) s2)
1615 ovf = main_ovf (false)
1616 u1 * u2 -> ur
1617 res = u1 * u2
1618 ovf = main_ovf (true)
1619 s1 * u2 -> ur
1620 res = (U) s1 * u2
1621 ovf = (s1 < 0 && u2) || main_ovf (true)
1622 u1 * u2 -> sr
1623 res = (S) (u1 * u2)
1624 ovf = res < 0 || main_ovf (true)
1625 s1 * u2 -> sr
1626 res = (S) ((U) s1 * u2)
1627 ovf = (S) u2 >= 0 ? main_ovf (false)
1628 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1629 s1 * s2 -> ur
1630 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1631 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1632 res = t1 * t2
1633 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1634
1635 if (uns0_p && !uns1_p)
1636 {
1637 /* Multiplication is commutative, if operand signedness differs,
1638 canonicalize to the first operand being signed and second
1639 unsigned to simplify following code. */
6b4db501
MM
1640 std::swap (op0, op1);
1641 std::swap (arg0, arg1);
1642 uns0_p = false;
1643 uns1_p = true;
1304953e
JJ
1644 }
1645
1646 int pos_neg0 = get_range_pos_neg (arg0);
1647 int pos_neg1 = get_range_pos_neg (arg1);
1648
1649 /* s1 * u2 -> ur */
1650 if (!uns0_p && uns1_p && unsr_p)
1651 {
1652 switch (pos_neg0)
1653 {
1654 case 1:
1655 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1656 goto do_main;
1657 case 2:
1658 /* If s1 is negative, avoid the main code, just multiply and
1659 signal overflow if op1 is not 0. */
1660 struct separate_ops ops;
1661 ops.code = MULT_EXPR;
1662 ops.type = TREE_TYPE (arg1);
1663 ops.op0 = make_tree (ops.type, op0);
1664 ops.op1 = make_tree (ops.type, op1);
1665 ops.op2 = NULL_TREE;
1666 ops.location = loc;
1667 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1668 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
357067f2 1669 NULL, done_label, profile_probability::very_likely ());
1304953e
JJ
1670 goto do_error_label;
1671 case 3:
049ce9d2
JJ
1672 if (get_min_precision (arg1, UNSIGNED)
1673 + get_min_precision (arg0, SIGNED) <= GET_MODE_PRECISION (mode))
1674 {
1675 /* If the first operand is sign extended from narrower type, the
1676 second operand is zero extended from narrower type and
1677 the sum of the two precisions is smaller or equal to the
1678 result precision: if the first argument is at runtime
1679 non-negative, maximum result will be 0x7e81 or 0x7f..fe80..01
1680 and there will be no overflow, if the first argument is
1681 negative and the second argument zero, the result will be
1682 0 and there will be no overflow, if the first argument is
1683 negative and the second argument positive, the result when
1684 treated as signed will be negative (minimum -0x7f80 or
027e3041 1685 -0x7f..f80..0) there will be always overflow. So, do
049ce9d2
JJ
1686 res = (U) (s1 * u2)
1687 ovf = (S) res < 0 */
1688 struct separate_ops ops;
1689 ops.code = MULT_EXPR;
1690 ops.type
1691 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1692 1);
1693 ops.op0 = make_tree (ops.type, op0);
1694 ops.op1 = make_tree (ops.type, op1);
1695 ops.op2 = NULL_TREE;
1696 ops.location = loc;
1697 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1698 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1699 mode, NULL_RTX, NULL, done_label,
1700 profile_probability::very_likely ());
1701 goto do_error_label;
1702 }
1304953e
JJ
1703 rtx_code_label *do_main_label;
1704 do_main_label = gen_label_rtx ();
92344ed0 1705 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 1706 NULL, do_main_label, profile_probability::very_likely ());
92344ed0 1707 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
357067f2 1708 NULL, do_main_label, profile_probability::very_likely ());
a86451b9 1709 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1710 emit_label (do_main_label);
1711 goto do_main;
1712 default:
1713 gcc_unreachable ();
1714 }
1715 }
1716
1717 /* u1 * u2 -> sr */
1718 if (uns0_p && uns1_p && !unsr_p)
1719 {
049ce9d2
JJ
1720 if ((pos_neg0 | pos_neg1) == 1)
1721 {
1722 /* If both arguments are zero extended from narrower types,
1723 the MSB will be clear on both and so we can pretend it is
1724 a normal s1 * s2 -> sr multiplication. */
1725 uns0_p = false;
1726 uns1_p = false;
1727 }
1728 else
1729 uns = true;
1304953e
JJ
1730 /* Rest of handling of this case after res is computed. */
1731 goto do_main;
1732 }
1733
1734 /* s1 * u2 -> sr */
1735 if (!uns0_p && uns1_p && !unsr_p)
1736 {
1737 switch (pos_neg1)
1738 {
1739 case 1:
1740 goto do_main;
1741 case 2:
1742 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1743 avoid the main code, just multiply and signal overflow
1744 unless 0 * u2 or -1 * ((U) Smin). */
1745 struct separate_ops ops;
1746 ops.code = MULT_EXPR;
1747 ops.type = TREE_TYPE (arg1);
1748 ops.op0 = make_tree (ops.type, op0);
1749 ops.op1 = make_tree (ops.type, op1);
1750 ops.op2 = NULL_TREE;
1751 ops.location = loc;
1752 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1753 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
357067f2 1754 NULL, done_label, profile_probability::very_likely ());
92344ed0 1755 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
357067f2 1756 NULL, do_error, profile_probability::very_unlikely ());
1304953e
JJ
1757 int prec;
1758 prec = GET_MODE_PRECISION (mode);
1759 rtx sgn;
1760 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
92344ed0 1761 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
357067f2 1762 NULL, done_label, profile_probability::very_likely ());
1304953e
JJ
1763 goto do_error_label;
1764 case 3:
1765 /* Rest of handling of this case after res is computed. */
1766 goto do_main;
1767 default:
1768 gcc_unreachable ();
1769 }
1770 }
31e071ae 1771
1304953e
JJ
1772 /* s1 * s2 -> ur */
1773 if (!uns0_p && !uns1_p && unsr_p)
1774 {
beeac4c2 1775 rtx tem;
1304953e
JJ
1776 switch (pos_neg0 | pos_neg1)
1777 {
1778 case 1: /* Both operands known to be non-negative. */
1779 goto do_main;
1780 case 2: /* Both operands known to be negative. */
1781 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1782 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1783 /* Avoid looking at arg0/arg1 ranges, as we've changed
1784 the arguments. */
1785 arg0 = error_mark_node;
1786 arg1 = error_mark_node;
1787 goto do_main;
1788 case 3:
1789 if ((pos_neg0 ^ pos_neg1) == 3)
1790 {
1791 /* If one operand is known to be negative and the other
1792 non-negative, this overflows always, unless the non-negative
1793 one is 0. Just do normal multiply and set overflow
1794 unless one of the operands is 0. */
1795 struct separate_ops ops;
1796 ops.code = MULT_EXPR;
1797 ops.type
1798 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1799 1);
1800 ops.op0 = make_tree (ops.type, op0);
1801 ops.op1 = make_tree (ops.type, op1);
1802 ops.op2 = NULL_TREE;
1803 ops.location = loc;
1804 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
beeac4c2
JJ
1805 do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
1806 true, mode, NULL_RTX, NULL, done_label,
357067f2 1807 profile_probability::very_likely ());
1304953e
JJ
1808 goto do_error_label;
1809 }
049ce9d2
JJ
1810 if (get_min_precision (arg0, SIGNED)
1811 + get_min_precision (arg1, SIGNED) <= GET_MODE_PRECISION (mode))
1812 {
1813 /* If both operands are sign extended from narrower types and
1814 the sum of the two precisions is smaller or equal to the
1815 result precision: if both arguments are at runtime
1816 non-negative, maximum result will be 0x3f01 or 0x3f..f0..01
1817 and there will be no overflow, if both arguments are negative,
1818 maximum result will be 0x40..00 and there will be no overflow
1819 either, if one argument is positive and the other argument
1820 negative, the result when treated as signed will be negative
1821 and there will be always overflow, and if one argument is
1822 zero and the other negative the result will be zero and no
1823 overflow. So, do
1824 res = (U) (s1 * s2)
1825 ovf = (S) res < 0 */
1826 struct separate_ops ops;
1827 ops.code = MULT_EXPR;
1828 ops.type
1829 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1830 1);
1831 ops.op0 = make_tree (ops.type, op0);
1832 ops.op1 = make_tree (ops.type, op1);
1833 ops.op2 = NULL_TREE;
1834 ops.location = loc;
1835 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1836 do_compare_rtx_and_jump (res, const0_rtx, GE, false,
1837 mode, NULL_RTX, NULL, done_label,
1838 profile_probability::very_likely ());
1839 goto do_error_label;
1840 }
1304953e
JJ
1841 /* The general case, do all the needed comparisons at runtime. */
1842 rtx_code_label *do_main_label, *after_negate_label;
1843 rtx rop0, rop1;
1844 rop0 = gen_reg_rtx (mode);
1845 rop1 = gen_reg_rtx (mode);
1846 emit_move_insn (rop0, op0);
1847 emit_move_insn (rop1, op1);
1848 op0 = rop0;
1849 op1 = rop1;
1850 do_main_label = gen_label_rtx ();
1851 after_negate_label = gen_label_rtx ();
1852 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1853 OPTAB_LIB_WIDEN);
92344ed0 1854 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 1855 NULL, after_negate_label, profile_probability::very_likely ());
1304953e
JJ
1856 /* Both arguments negative here, negate them and continue with
1857 normal unsigned overflow checking multiplication. */
1858 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1859 NULL_RTX, false));
1860 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1861 NULL_RTX, false));
1862 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1863 the arguments. */
1864 arg0 = error_mark_node;
1865 arg1 = error_mark_node;
1866 emit_jump (do_main_label);
1867 emit_label (after_negate_label);
beeac4c2
JJ
1868 tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1869 OPTAB_LIB_WIDEN);
1870 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1871 NULL, do_main_label,
1872 profile_probability::very_likely ());
1304953e
JJ
1873 /* One argument is negative here, the other positive. This
1874 overflows always, unless one of the arguments is 0. But
1875 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1876 is, thus we can keep do_main code oring in overflow as is. */
beeac4c2
JJ
1877 if (pos_neg0 != 2)
1878 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1879 NULL, do_main_label,
1880 profile_probability::very_unlikely ());
1881 if (pos_neg1 != 2)
1882 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1883 NULL, do_main_label,
1884 profile_probability::very_unlikely ());
a86451b9 1885 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1886 emit_label (do_main_label);
1887 goto do_main;
1888 default:
1889 gcc_unreachable ();
1890 }
1891 }
1892
1893 do_main:
1894 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1895 sign = uns ? UNSIGNED : SIGNED;
1896 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
89b1427f
JJ
1897 if (uns
1898 && (integer_pow2p (arg0) || integer_pow2p (arg1))
1899 && (optimize_insn_for_speed_p () || icode == CODE_FOR_nothing))
1900 {
1901 /* Optimize unsigned multiplication by power of 2 constant
1902 using 2 shifts, one for result, one to extract the shifted
1903 out bits to see if they are all zero.
1904 Don't do this if optimizing for size and we have umulv4_optab,
1905 in that case assume multiplication will be shorter.
1906 This is heuristics based on the single target that provides
1907 umulv4 right now (i?86/x86_64), if further targets add it, this
1908 might need to be revisited.
1909 Cases where both operands are constant should be folded already
1910 during GIMPLE, and cases where one operand is constant but not
1911 power of 2 are questionable, either the WIDEN_MULT_EXPR case
1912 below can be done without multiplication, just by shifts and adds,
1913 or we'd need to divide the result (and hope it actually doesn't
1914 really divide nor multiply) and compare the result of the division
1915 with the original operand. */
1916 rtx opn0 = op0;
1917 rtx opn1 = op1;
1918 tree argn0 = arg0;
1919 tree argn1 = arg1;
1920 if (integer_pow2p (arg0))
1921 {
1922 std::swap (opn0, opn1);
1923 std::swap (argn0, argn1);
1924 }
1925 int cnt = tree_log2 (argn1);
1926 if (cnt >= 0 && cnt < GET_MODE_PRECISION (mode))
1927 {
1928 rtx upper = const0_rtx;
1929 res = expand_shift (LSHIFT_EXPR, mode, opn0, cnt, NULL_RTX, uns);
1930 if (cnt != 0)
1931 upper = expand_shift (RSHIFT_EXPR, mode, opn0,
1932 GET_MODE_PRECISION (mode) - cnt,
1933 NULL_RTX, uns);
1934 do_compare_rtx_and_jump (upper, const0_rtx, EQ, true, mode,
1935 NULL_RTX, NULL, done_label,
1936 profile_probability::very_likely ());
1937 goto do_error_label;
1938 }
1939 }
31e071ae
MP
1940 if (icode != CODE_FOR_nothing)
1941 {
99b1c316 1942 class expand_operand ops[4];
da664544 1943 rtx_insn *last = get_last_insn ();
31e071ae
MP
1944
1945 res = gen_reg_rtx (mode);
1946 create_output_operand (&ops[0], res, mode);
1947 create_input_operand (&ops[1], op0, mode);
1948 create_input_operand (&ops[2], op1, mode);
1949 create_fixed_operand (&ops[3], do_error);
1950 if (maybe_expand_insn (icode, 4, ops))
1951 {
1952 last = get_last_insn ();
0a6a6ac9 1953 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
1954 && JUMP_P (last)
1955 && any_condjump_p (last)
1956 && !find_reg_note (last, REG_BR_PROB, 0))
5fa396ad
JH
1957 add_reg_br_prob_note (last,
1958 profile_probability::very_unlikely ());
31e071ae
MP
1959 emit_jump (done_label);
1960 }
1961 else
1962 {
1963 delete_insns_since (last);
1964 icode = CODE_FOR_nothing;
1965 }
1966 }
1967
1968 if (icode == CODE_FOR_nothing)
1969 {
1970 struct separate_ops ops;
1304953e 1971 int prec = GET_MODE_PRECISION (mode);
095a2d76 1972 scalar_int_mode hmode, wmode;
1304953e
JJ
1973 ops.op0 = make_tree (type, op0);
1974 ops.op1 = make_tree (type, op1);
31e071ae 1975 ops.op2 = NULL_TREE;
1304953e 1976 ops.location = loc;
0b99f253
JJ
1977
1978 /* Optimize unsigned overflow check where we don't use the
1979 multiplication result, just whether overflow happened.
1980 If we can do MULT_HIGHPART_EXPR, that followed by
1981 comparison of the result against zero is cheapest.
1982 We'll still compute res, but it should be DCEd later. */
1983 use_operand_p use;
1984 gimple *use_stmt;
1985 if (!is_ubsan
1986 && lhs
1987 && uns
1988 && !(uns0_p && uns1_p && !unsr_p)
1989 && can_mult_highpart_p (mode, uns) == 1
1990 && single_imm_use (lhs, &use, &use_stmt)
1991 && is_gimple_assign (use_stmt)
1992 && gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR)
1993 goto highpart;
1994
490d0f6c 1995 if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
0b99f253
JJ
1996 && targetm.scalar_mode_supported_p (wmode)
1997 && can_widen_mult_without_libcall (wmode, mode, op0, op1, uns))
31e071ae 1998 {
0b99f253 1999 twoxwider:
31e071ae
MP
2000 ops.code = WIDEN_MULT_EXPR;
2001 ops.type
1304953e 2002 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
31e071ae
MP
2003
2004 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1304953e
JJ
2005 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
2006 NULL_RTX, uns);
4ed543bc
KC
2007 hipart = convert_modes (mode, wmode, hipart, uns);
2008 res = convert_modes (mode, wmode, res, uns);
1304953e
JJ
2009 if (uns)
2010 /* For the unsigned multiplication, there was overflow if
2011 HIPART is non-zero. */
92344ed0 2012 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1476d1bd 2013 NULL_RTX, NULL, done_label,
357067f2 2014 profile_probability::very_likely ());
1304953e
JJ
2015 else
2016 {
2b4bbc17
RS
2017 /* RES is used more than once, place it in a pseudo. */
2018 res = force_reg (mode, res);
2019
1304953e
JJ
2020 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2021 NULL_RTX, 0);
2022 /* RES is low half of the double width result, HIPART
2023 the high half. There was overflow if
2024 HIPART is different from RES < 0 ? -1 : 0. */
92344ed0 2025 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1476d1bd 2026 NULL_RTX, NULL, done_label,
357067f2 2027 profile_probability::very_likely ());
1304953e 2028 }
31e071ae 2029 }
0b99f253
JJ
2030 else if (can_mult_highpart_p (mode, uns) == 1)
2031 {
2032 highpart:
2033 ops.code = MULT_HIGHPART_EXPR;
2034 ops.type = type;
2035
2036 rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode,
2037 EXPAND_NORMAL);
2038 ops.code = MULT_EXPR;
2039 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2040 if (uns)
2041 /* For the unsigned multiplication, there was overflow if
2042 HIPART is non-zero. */
2043 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
2044 NULL_RTX, NULL, done_label,
2045 profile_probability::very_likely ());
2046 else
2047 {
2048 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
2049 NULL_RTX, 0);
2050 /* RES is low half of the double width result, HIPART
2051 the high half. There was overflow if
2052 HIPART is different from RES < 0 ? -1 : 0. */
2053 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
2054 NULL_RTX, NULL, done_label,
2055 profile_probability::very_likely ());
2056 }
2057
2058 }
fffbab82
RS
2059 else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
2060 && 2 * GET_MODE_PRECISION (hmode) == prec)
d5fa9cc9 2061 {
da664544
DM
2062 rtx_code_label *large_op0 = gen_label_rtx ();
2063 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
2064 rtx_code_label *one_small_one_large = gen_label_rtx ();
2065 rtx_code_label *both_ops_large = gen_label_rtx ();
1304953e
JJ
2066 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
2067 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
da664544 2068 rtx_code_label *do_overflow = gen_label_rtx ();
1304953e 2069 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
d5fa9cc9 2070
807e902e 2071 unsigned int hprec = GET_MODE_PRECISION (hmode);
d5fa9cc9 2072 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1304953e 2073 NULL_RTX, uns);
4ed543bc
KC
2074 hipart0 = convert_modes (hmode, mode, hipart0, uns);
2075 rtx lopart0 = convert_modes (hmode, mode, op0, uns);
1304953e
JJ
2076 rtx signbit0 = const0_rtx;
2077 if (!uns)
2078 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
2079 NULL_RTX, 0);
d5fa9cc9 2080 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1304953e 2081 NULL_RTX, uns);
4ed543bc
KC
2082 hipart1 = convert_modes (hmode, mode, hipart1, uns);
2083 rtx lopart1 = convert_modes (hmode, mode, op1, uns);
1304953e
JJ
2084 rtx signbit1 = const0_rtx;
2085 if (!uns)
2086 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
2087 NULL_RTX, 0);
d5fa9cc9
JJ
2088
2089 res = gen_reg_rtx (mode);
2090
2091 /* True if op0 resp. op1 are known to be in the range of
2092 halfstype. */
2093 bool op0_small_p = false;
2094 bool op1_small_p = false;
2095 /* True if op0 resp. op1 are known to have all zeros or all ones
2096 in the upper half of bits, but are not known to be
2097 op{0,1}_small_p. */
2098 bool op0_medium_p = false;
2099 bool op1_medium_p = false;
2100 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
2101 nonnegative, 1 if unknown. */
2102 int op0_sign = 1;
2103 int op1_sign = 1;
2104
1304953e
JJ
2105 if (pos_neg0 == 1)
2106 op0_sign = 0;
2107 else if (pos_neg0 == 2)
2108 op0_sign = -1;
2109 if (pos_neg1 == 1)
2110 op1_sign = 0;
2111 else if (pos_neg1 == 2)
2112 op1_sign = -1;
2113
2114 unsigned int mprec0 = prec;
2115 if (arg0 != error_mark_node)
2116 mprec0 = get_min_precision (arg0, sign);
2117 if (mprec0 <= hprec)
2118 op0_small_p = true;
2119 else if (!uns && mprec0 <= hprec + 1)
2120 op0_medium_p = true;
2121 unsigned int mprec1 = prec;
2122 if (arg1 != error_mark_node)
2123 mprec1 = get_min_precision (arg1, sign);
2124 if (mprec1 <= hprec)
2125 op1_small_p = true;
2126 else if (!uns && mprec1 <= hprec + 1)
2127 op1_medium_p = true;
d5fa9cc9
JJ
2128
2129 int smaller_sign = 1;
2130 int larger_sign = 1;
2131 if (op0_small_p)
2132 {
2133 smaller_sign = op0_sign;
2134 larger_sign = op1_sign;
2135 }
2136 else if (op1_small_p)
2137 {
2138 smaller_sign = op1_sign;
2139 larger_sign = op0_sign;
2140 }
2141 else if (op0_sign == op1_sign)
2142 {
2143 smaller_sign = op0_sign;
2144 larger_sign = op0_sign;
2145 }
2146
2147 if (!op0_small_p)
92344ed0 2148 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1476d1bd 2149 NULL_RTX, NULL, large_op0,
357067f2 2150 profile_probability::unlikely ());
d5fa9cc9
JJ
2151
2152 if (!op1_small_p)
92344ed0 2153 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 2154 NULL_RTX, NULL, small_op0_large_op1,
357067f2 2155 profile_probability::unlikely ());
d5fa9cc9 2156
1304953e
JJ
2157 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
2158 hmode to mode, the multiplication will never overflow. We can
2159 do just one hmode x hmode => mode widening multiplication. */
1304953e 2160 tree halfstype = build_nonstandard_integer_type (hprec, uns);
0764a0d2
JJ
2161 ops.op0 = make_tree (halfstype, lopart0);
2162 ops.op1 = make_tree (halfstype, lopart1);
d5fa9cc9 2163 ops.code = WIDEN_MULT_EXPR;
1304953e 2164 ops.type = type;
d5fa9cc9
JJ
2165 rtx thisres
2166 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2167 emit_move_insn (res, thisres);
2168 emit_jump (done_label);
2169
2170 emit_label (small_op0_large_op1);
2171
1304953e
JJ
2172 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
2173 but op1 is not, just swap the arguments and handle it as op1
2174 sign/zero extended, op0 not. */
d5fa9cc9
JJ
2175 rtx larger = gen_reg_rtx (mode);
2176 rtx hipart = gen_reg_rtx (hmode);
2177 rtx lopart = gen_reg_rtx (hmode);
2178 emit_move_insn (larger, op1);
2179 emit_move_insn (hipart, hipart1);
2180 emit_move_insn (lopart, lopart0);
2181 emit_jump (one_small_one_large);
2182
2183 emit_label (large_op0);
2184
2185 if (!op1_small_p)
92344ed0 2186 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 2187 NULL_RTX, NULL, both_ops_large,
357067f2 2188 profile_probability::unlikely ());
d5fa9cc9 2189
1304953e
JJ
2190 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
2191 but op0 is not, prepare larger, hipart and lopart pseudos and
2192 handle it together with small_op0_large_op1. */
d5fa9cc9
JJ
2193 emit_move_insn (larger, op0);
2194 emit_move_insn (hipart, hipart0);
2195 emit_move_insn (lopart, lopart1);
2196
2197 emit_label (one_small_one_large);
2198
2199 /* lopart is the low part of the operand that is sign extended
026c3cfd 2200 to mode, larger is the other operand, hipart is the
d5fa9cc9
JJ
2201 high part of larger and lopart0 and lopart1 are the low parts
2202 of both operands.
2203 We perform lopart0 * lopart1 and lopart * hipart widening
2204 multiplications. */
2205 tree halfutype = build_nonstandard_integer_type (hprec, 1);
2206 ops.op0 = make_tree (halfutype, lopart0);
2207 ops.op1 = make_tree (halfutype, lopart1);
2208 rtx lo0xlo1
2209 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2210
2211 ops.op0 = make_tree (halfutype, lopart);
2212 ops.op1 = make_tree (halfutype, hipart);
2213 rtx loxhi = gen_reg_rtx (mode);
2214 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2215 emit_move_insn (loxhi, tem);
2216
1304953e
JJ
2217 if (!uns)
2218 {
2219 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
2220 if (larger_sign == 0)
2221 emit_jump (after_hipart_neg);
2222 else if (larger_sign != -1)
92344ed0 2223 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1476d1bd 2224 NULL_RTX, NULL, after_hipart_neg,
357067f2 2225 profile_probability::even ());
1304953e
JJ
2226
2227 tem = convert_modes (mode, hmode, lopart, 1);
2228 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
2229 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
644f0132 2230 1, OPTAB_WIDEN);
1304953e
JJ
2231 emit_move_insn (loxhi, tem);
2232
2233 emit_label (after_hipart_neg);
2234
2235 /* if (lopart < 0) loxhi -= larger; */
2236 if (smaller_sign == 0)
2237 emit_jump (after_lopart_neg);
2238 else if (smaller_sign != -1)
92344ed0 2239 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1476d1bd 2240 NULL_RTX, NULL, after_lopart_neg,
357067f2 2241 profile_probability::even ());
1304953e
JJ
2242
2243 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
644f0132 2244 1, OPTAB_WIDEN);
1304953e
JJ
2245 emit_move_insn (loxhi, tem);
2246
2247 emit_label (after_lopart_neg);
2248 }
d5fa9cc9
JJ
2249
2250 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
2251 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
2252 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
644f0132 2253 1, OPTAB_WIDEN);
d5fa9cc9
JJ
2254 emit_move_insn (loxhi, tem);
2255
2256 /* if (loxhi >> (bitsize / 2)
1304953e
JJ
2257 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
2258 if (loxhi >> (bitsize / 2) == 0 (if uns). */
d5fa9cc9
JJ
2259 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
2260 NULL_RTX, 0);
4ed543bc 2261 hipartloxhi = convert_modes (hmode, mode, hipartloxhi, 0);
1304953e
JJ
2262 rtx signbitloxhi = const0_rtx;
2263 if (!uns)
2264 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
4ed543bc
KC
2265 convert_modes (hmode, mode,
2266 loxhi, 0),
1304953e 2267 hprec - 1, NULL_RTX, 0);
d5fa9cc9 2268
92344ed0 2269 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1476d1bd 2270 NULL_RTX, NULL, do_overflow,
357067f2 2271 profile_probability::very_unlikely ());
d5fa9cc9
JJ
2272
2273 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
2274 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
2275 NULL_RTX, 1);
4ed543bc
KC
2276 tem = convert_modes (mode, hmode,
2277 convert_modes (hmode, mode, lo0xlo1, 1), 1);
d5fa9cc9
JJ
2278
2279 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
644f0132 2280 1, OPTAB_WIDEN);
d5fa9cc9
JJ
2281 if (tem != res)
2282 emit_move_insn (res, tem);
2283 emit_jump (done_label);
2284
2285 emit_label (both_ops_large);
2286
1304953e
JJ
2287 /* If both operands are large (not sign (!uns) or zero (uns)
2288 extended from hmode), then perform the full multiplication
2289 which will be the result of the operation.
2290 The only cases which don't overflow are for signed multiplication
2291 some cases where both hipart0 and highpart1 are 0 or -1.
2292 For unsigned multiplication when high parts are both non-zero
2293 this overflows always. */
d5fa9cc9 2294 ops.code = MULT_EXPR;
1304953e
JJ
2295 ops.op0 = make_tree (type, op0);
2296 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
2297 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2298 emit_move_insn (res, tem);
2299
1304953e 2300 if (!uns)
d5fa9cc9 2301 {
1304953e
JJ
2302 if (!op0_medium_p)
2303 {
2304 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
644f0132 2305 NULL_RTX, 1, OPTAB_WIDEN);
92344ed0 2306 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 2307 NULL_RTX, NULL, do_error,
357067f2 2308 profile_probability::very_unlikely ());
1304953e 2309 }
d5fa9cc9 2310
1304953e
JJ
2311 if (!op1_medium_p)
2312 {
2313 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
644f0132 2314 NULL_RTX, 1, OPTAB_WIDEN);
92344ed0 2315 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 2316 NULL_RTX, NULL, do_error,
357067f2 2317 profile_probability::very_unlikely ());
1304953e 2318 }
d5fa9cc9 2319
1304953e 2320 /* At this point hipart{0,1} are both in [-1, 0]. If they are
e7176f75
JJ
2321 the same, overflow happened if res is non-positive, if they
2322 are different, overflow happened if res is positive. */
1304953e
JJ
2323 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
2324 emit_jump (hipart_different);
2325 else if (op0_sign == 1 || op1_sign == 1)
92344ed0 2326 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1476d1bd 2327 NULL_RTX, NULL, hipart_different,
357067f2 2328 profile_probability::even ());
d5fa9cc9 2329
e7176f75 2330 do_compare_rtx_and_jump (res, const0_rtx, LE, false, mode,
1476d1bd 2331 NULL_RTX, NULL, do_error,
357067f2 2332 profile_probability::very_unlikely ());
1304953e 2333 emit_jump (done_label);
d5fa9cc9 2334
1304953e
JJ
2335 emit_label (hipart_different);
2336
92344ed0 2337 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1476d1bd 2338 NULL_RTX, NULL, do_error,
357067f2 2339 profile_probability::very_unlikely ());
1304953e
JJ
2340 emit_jump (done_label);
2341 }
d5fa9cc9
JJ
2342
2343 emit_label (do_overflow);
2344
2345 /* Overflow, do full multiplication and fallthru into do_error. */
1304953e
JJ
2346 ops.op0 = make_tree (type, op0);
2347 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
2348 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2349 emit_move_insn (res, tem);
2350 }
0b99f253
JJ
2351 else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
2352 && targetm.scalar_mode_supported_p (wmode))
2353 /* Even emitting a libcall is better than not detecting overflow
2354 at all. */
2355 goto twoxwider;
31e071ae
MP
2356 else
2357 {
1304953e 2358 gcc_assert (!is_ubsan);
31e071ae 2359 ops.code = MULT_EXPR;
1304953e 2360 ops.type = type;
31e071ae
MP
2361 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2362 emit_jump (done_label);
2363 }
2364 }
2365
1304953e 2366 do_error_label:
31e071ae 2367 emit_label (do_error);
1304953e
JJ
2368 if (is_ubsan)
2369 {
2370 /* Expand the ubsan builtin call. */
2371 push_temp_slots ();
2372 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1705cebd 2373 arg0, arg1, datap);
1304953e
JJ
2374 expand_normal (fn);
2375 pop_temp_slots ();
2376 do_pending_stack_adjust ();
2377 }
2378 else if (lhs)
a86451b9 2379 expand_arith_set_overflow (lhs, target);
31e071ae
MP
2380
2381 /* We're done. */
2382 emit_label (done_label);
2383
1304953e
JJ
2384 /* u1 * u2 -> sr */
2385 if (uns0_p && uns1_p && !unsr_p)
2386 {
2387 rtx_code_label *all_done_label = gen_label_rtx ();
92344ed0 2388 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 2389 NULL, all_done_label, profile_probability::very_likely ());
a86451b9 2390 expand_arith_set_overflow (lhs, target);
1304953e
JJ
2391 emit_label (all_done_label);
2392 }
2393
2394 /* s1 * u2 -> sr */
2395 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
2396 {
2397 rtx_code_label *all_done_label = gen_label_rtx ();
2398 rtx_code_label *set_noovf = gen_label_rtx ();
92344ed0 2399 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
357067f2 2400 NULL, all_done_label, profile_probability::very_likely ());
a86451b9 2401 expand_arith_set_overflow (lhs, target);
92344ed0 2402 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
357067f2 2403 NULL, set_noovf, profile_probability::very_likely ());
92344ed0 2404 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
357067f2 2405 NULL, all_done_label, profile_probability::very_unlikely ());
1476d1bd 2406 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
357067f2 2407 all_done_label, profile_probability::very_unlikely ());
1304953e 2408 emit_label (set_noovf);
13f44099 2409 write_complex_part (target, const0_rtx, true, false);
1304953e
JJ
2410 emit_label (all_done_label);
2411 }
2412
31e071ae 2413 if (lhs)
1304953e
JJ
2414 {
2415 if (is_ubsan)
5620052d 2416 expand_ubsan_result_store (target, res);
1304953e
JJ
2417 else
2418 expand_arith_overflow_result_store (lhs, target, mode, res);
2419 }
31e071ae
MP
2420}
2421
1705cebd
JJ
2422/* Expand UBSAN_CHECK_* internal function if it has vector operands. */
2423
2424static void
2425expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs,
2426 tree arg0, tree arg1)
2427{
07626e49 2428 poly_uint64 cnt = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
1705cebd
JJ
2429 rtx_code_label *loop_lab = NULL;
2430 rtx cntvar = NULL_RTX;
2431 tree cntv = NULL_TREE;
2432 tree eltype = TREE_TYPE (TREE_TYPE (arg0));
2433 tree sz = TYPE_SIZE (eltype);
2434 tree data = NULL_TREE;
2435 tree resv = NULL_TREE;
2436 rtx lhsr = NULL_RTX;
2437 rtx resvr = NULL_RTX;
07626e49
RS
2438 unsigned HOST_WIDE_INT const_cnt = 0;
2439 bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4);
1705cebd
JJ
2440
2441 if (lhs)
2442 {
2443 optab op;
2444 lhsr = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
6a5cdb0e 2445 if (!VECTOR_MODE_P (GET_MODE (lhsr))
1705cebd
JJ
2446 || (op = optab_for_tree_code (code, TREE_TYPE (arg0),
2447 optab_default)) == unknown_optab
2448 || (optab_handler (op, TYPE_MODE (TREE_TYPE (arg0)))
2449 == CODE_FOR_nothing))
2450 {
2451 if (MEM_P (lhsr))
2452 resv = make_tree (TREE_TYPE (lhs), lhsr);
2453 else
2454 {
2455 resvr = assign_temp (TREE_TYPE (lhs), 1, 1);
2456 resv = make_tree (TREE_TYPE (lhs), resvr);
2457 }
2458 }
2459 }
07626e49 2460 if (use_loop_p)
1705cebd
JJ
2461 {
2462 do_pending_stack_adjust ();
2463 loop_lab = gen_label_rtx ();
2464 cntvar = gen_reg_rtx (TYPE_MODE (sizetype));
2465 cntv = make_tree (sizetype, cntvar);
2466 emit_move_insn (cntvar, const0_rtx);
2467 emit_label (loop_lab);
2468 }
2469 if (TREE_CODE (arg0) != VECTOR_CST)
2470 {
2471 rtx arg0r = expand_normal (arg0);
2472 arg0 = make_tree (TREE_TYPE (arg0), arg0r);
2473 }
2474 if (TREE_CODE (arg1) != VECTOR_CST)
2475 {
2476 rtx arg1r = expand_normal (arg1);
2477 arg1 = make_tree (TREE_TYPE (arg1), arg1r);
2478 }
07626e49 2479 for (unsigned int i = 0; i < (use_loop_p ? 1 : const_cnt); i++)
1705cebd
JJ
2480 {
2481 tree op0, op1, res = NULL_TREE;
07626e49 2482 if (use_loop_p)
1705cebd
JJ
2483 {
2484 tree atype = build_array_type_nelts (eltype, cnt);
4b48e883
JJ
2485 op0 = uniform_vector_p (arg0);
2486 if (op0 == NULL_TREE)
2487 {
2488 op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg0);
2489 op0 = build4_loc (loc, ARRAY_REF, eltype, op0, cntv,
2490 NULL_TREE, NULL_TREE);
2491 }
2492 op1 = uniform_vector_p (arg1);
2493 if (op1 == NULL_TREE)
2494 {
2495 op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, arg1);
2496 op1 = build4_loc (loc, ARRAY_REF, eltype, op1, cntv,
2497 NULL_TREE, NULL_TREE);
2498 }
1705cebd
JJ
2499 if (resv)
2500 {
2501 res = fold_build1_loc (loc, VIEW_CONVERT_EXPR, atype, resv);
2502 res = build4_loc (loc, ARRAY_REF, eltype, res, cntv,
2503 NULL_TREE, NULL_TREE);
2504 }
2505 }
2506 else
2507 {
2508 tree bitpos = bitsize_int (tree_to_uhwi (sz) * i);
2509 op0 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg0, sz, bitpos);
2510 op1 = fold_build3_loc (loc, BIT_FIELD_REF, eltype, arg1, sz, bitpos);
2511 if (resv)
2512 res = fold_build3_loc (loc, BIT_FIELD_REF, eltype, resv, sz,
2513 bitpos);
2514 }
2515 switch (code)
2516 {
2517 case PLUS_EXPR:
2518 expand_addsub_overflow (loc, PLUS_EXPR, res, op0, op1,
2519 false, false, false, true, &data);
2520 break;
2521 case MINUS_EXPR:
07626e49 2522 if (use_loop_p ? integer_zerop (arg0) : integer_zerop (op0))
1705cebd
JJ
2523 expand_neg_overflow (loc, res, op1, true, &data);
2524 else
2525 expand_addsub_overflow (loc, MINUS_EXPR, res, op0, op1,
2526 false, false, false, true, &data);
2527 break;
2528 case MULT_EXPR:
2529 expand_mul_overflow (loc, res, op0, op1, false, false, false,
2530 true, &data);
2531 break;
2532 default:
2533 gcc_unreachable ();
2534 }
2535 }
07626e49 2536 if (use_loop_p)
1705cebd
JJ
2537 {
2538 struct separate_ops ops;
2539 ops.code = PLUS_EXPR;
2540 ops.type = TREE_TYPE (cntv);
2541 ops.op0 = cntv;
2542 ops.op1 = build_int_cst (TREE_TYPE (cntv), 1);
2543 ops.op2 = NULL_TREE;
2544 ops.location = loc;
2545 rtx ret = expand_expr_real_2 (&ops, cntvar, TYPE_MODE (sizetype),
2546 EXPAND_NORMAL);
2547 if (ret != cntvar)
2548 emit_move_insn (cntvar, ret);
07626e49
RS
2549 rtx cntrtx = gen_int_mode (cnt, TYPE_MODE (sizetype));
2550 do_compare_rtx_and_jump (cntvar, cntrtx, NE, false,
1705cebd 2551 TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
357067f2 2552 profile_probability::very_likely ());
1705cebd
JJ
2553 }
2554 if (lhs && resv == NULL_TREE)
2555 {
2556 struct separate_ops ops;
2557 ops.code = code;
2558 ops.type = TREE_TYPE (arg0);
2559 ops.op0 = arg0;
2560 ops.op1 = arg1;
2561 ops.op2 = NULL_TREE;
2562 ops.location = loc;
2563 rtx ret = expand_expr_real_2 (&ops, lhsr, TYPE_MODE (TREE_TYPE (arg0)),
2564 EXPAND_NORMAL);
2565 if (ret != lhsr)
2566 emit_move_insn (lhsr, ret);
2567 }
2568 else if (resvr)
2569 emit_move_insn (lhsr, resvr);
2570}
2571
31e071ae
MP
2572/* Expand UBSAN_CHECK_ADD call STMT. */
2573
2574static void
4cfe7a6c 2575expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
31e071ae 2576{
1304953e
JJ
2577 location_t loc = gimple_location (stmt);
2578 tree lhs = gimple_call_lhs (stmt);
2579 tree arg0 = gimple_call_arg (stmt, 0);
2580 tree arg1 = gimple_call_arg (stmt, 1);
1705cebd
JJ
2581 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2582 expand_vector_ubsan_overflow (loc, PLUS_EXPR, lhs, arg0, arg1);
2583 else
2584 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
2585 false, false, false, true, NULL);
31e071ae
MP
2586}
2587
2588/* Expand UBSAN_CHECK_SUB call STMT. */
2589
2590static void
4cfe7a6c 2591expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
31e071ae 2592{
1304953e
JJ
2593 location_t loc = gimple_location (stmt);
2594 tree lhs = gimple_call_lhs (stmt);
2595 tree arg0 = gimple_call_arg (stmt, 0);
2596 tree arg1 = gimple_call_arg (stmt, 1);
1705cebd
JJ
2597 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2598 expand_vector_ubsan_overflow (loc, MINUS_EXPR, lhs, arg0, arg1);
2599 else if (integer_zerop (arg0))
2600 expand_neg_overflow (loc, lhs, arg1, true, NULL);
31e071ae 2601 else
1304953e 2602 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
1705cebd 2603 false, false, false, true, NULL);
31e071ae
MP
2604}
2605
2606/* Expand UBSAN_CHECK_MUL call STMT. */
2607
2608static void
4cfe7a6c 2609expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
31e071ae 2610{
1304953e
JJ
2611 location_t loc = gimple_location (stmt);
2612 tree lhs = gimple_call_lhs (stmt);
2613 tree arg0 = gimple_call_arg (stmt, 0);
2614 tree arg1 = gimple_call_arg (stmt, 1);
1705cebd
JJ
2615 if (VECTOR_TYPE_P (TREE_TYPE (arg0)))
2616 expand_vector_ubsan_overflow (loc, MULT_EXPR, lhs, arg0, arg1);
2617 else
2618 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true,
2619 NULL);
1304953e
JJ
2620}
2621
2622/* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
2623
2624static void
355fe088 2625expand_arith_overflow (enum tree_code code, gimple *stmt)
1304953e
JJ
2626{
2627 tree lhs = gimple_call_lhs (stmt);
2628 if (lhs == NULL_TREE)
2629 return;
2630 tree arg0 = gimple_call_arg (stmt, 0);
2631 tree arg1 = gimple_call_arg (stmt, 1);
2632 tree type = TREE_TYPE (TREE_TYPE (lhs));
2633 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
2634 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
2635 int unsr_p = TYPE_UNSIGNED (type);
2636 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
2637 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
2638 int precres = TYPE_PRECISION (type);
2639 location_t loc = gimple_location (stmt);
2640 if (!uns0_p && get_range_pos_neg (arg0) == 1)
2641 uns0_p = true;
2642 if (!uns1_p && get_range_pos_neg (arg1) == 1)
2643 uns1_p = true;
2644 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
2645 prec0 = MIN (prec0, pr);
2646 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
2647 prec1 = MIN (prec1, pr);
2648
2649 /* If uns0_p && uns1_p, precop is minimum needed precision
2650 of unsigned type to hold the exact result, otherwise
2651 precop is minimum needed precision of signed type to
2652 hold the exact result. */
2653 int precop;
2654 if (code == MULT_EXPR)
2655 precop = prec0 + prec1 + (uns0_p != uns1_p);
2656 else
2657 {
2658 if (uns0_p == uns1_p)
2659 precop = MAX (prec0, prec1) + 1;
2660 else if (uns0_p)
2661 precop = MAX (prec0 + 1, prec1) + 1;
2662 else
2663 precop = MAX (prec0, prec1 + 1) + 1;
2664 }
2665 int orig_precres = precres;
2666
2667 do
2668 {
2669 if ((uns0_p && uns1_p)
2670 ? ((precop + !unsr_p) <= precres
2671 /* u1 - u2 -> ur can overflow, no matter what precision
2672 the result has. */
2673 && (code != MINUS_EXPR || !unsr_p))
2674 : (!unsr_p && precop <= precres))
2675 {
2676 /* The infinity precision result will always fit into result. */
2677 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
13f44099 2678 write_complex_part (target, const0_rtx, true, false);
7a504f33 2679 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
1304953e
JJ
2680 struct separate_ops ops;
2681 ops.code = code;
2682 ops.type = type;
2683 ops.op0 = fold_convert_loc (loc, type, arg0);
2684 ops.op1 = fold_convert_loc (loc, type, arg1);
2685 ops.op2 = NULL_TREE;
2686 ops.location = loc;
2687 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
2688 expand_arith_overflow_result_store (lhs, target, mode, tem);
2689 return;
2690 }
2691
894d8b41
EB
2692 /* For operations with low precision, if target doesn't have them, start
2693 with precres widening right away, otherwise do it only if the most
2694 simple cases can't be used. */
2695 const int min_precision = targetm.min_arithmetic_precision ();
2696 if (orig_precres == precres && precres < min_precision)
1304953e 2697 ;
9e11bfef
TS
2698 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
2699 && prec1 <= precres)
1304953e
JJ
2700 || ((!uns0_p || !uns1_p) && !unsr_p
2701 && prec0 + uns0_p <= precres
2702 && prec1 + uns1_p <= precres))
2703 {
2704 arg0 = fold_convert_loc (loc, type, arg0);
2705 arg1 = fold_convert_loc (loc, type, arg1);
2706 switch (code)
2707 {
2708 case MINUS_EXPR:
2709 if (integer_zerop (arg0) && !unsr_p)
7d704548 2710 {
1705cebd 2711 expand_neg_overflow (loc, lhs, arg1, false, NULL);
7d704548
JJ
2712 return;
2713 }
1304953e
JJ
2714 /* FALLTHRU */
2715 case PLUS_EXPR:
1705cebd
JJ
2716 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
2717 unsr_p, unsr_p, false, NULL);
1304953e
JJ
2718 return;
2719 case MULT_EXPR:
1705cebd
JJ
2720 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
2721 unsr_p, unsr_p, false, NULL);
1304953e
JJ
2722 return;
2723 default:
2724 gcc_unreachable ();
2725 }
2726 }
2727
2728 /* For sub-word operations, retry with a wider type first. */
2729 if (orig_precres == precres && precop <= BITS_PER_WORD)
2730 {
894d8b41 2731 int p = MAX (min_precision, precop);
f67f4dff 2732 scalar_int_mode m = smallest_int_mode_for_size (p);
1304953e
JJ
2733 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2734 uns0_p && uns1_p
2735 && unsr_p);
2736 p = TYPE_PRECISION (optype);
2737 if (p > precres)
2738 {
2739 precres = p;
2740 unsr_p = TYPE_UNSIGNED (optype);
2741 type = optype;
2742 continue;
2743 }
2744 }
2745
2746 if (prec0 <= precres && prec1 <= precres)
2747 {
2748 tree types[2];
2749 if (unsr_p)
2750 {
2751 types[0] = build_nonstandard_integer_type (precres, 0);
2752 types[1] = type;
2753 }
2754 else
2755 {
2756 types[0] = type;
2757 types[1] = build_nonstandard_integer_type (precres, 1);
2758 }
2759 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
2760 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
2761 if (code != MULT_EXPR)
2762 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
1705cebd 2763 uns0_p, uns1_p, false, NULL);
1304953e
JJ
2764 else
2765 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
1705cebd 2766 uns0_p, uns1_p, false, NULL);
1304953e
JJ
2767 return;
2768 }
2769
2770 /* Retry with a wider type. */
2771 if (orig_precres == precres)
2772 {
2773 int p = MAX (prec0, prec1);
f67f4dff 2774 scalar_int_mode m = smallest_int_mode_for_size (p);
1304953e
JJ
2775 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
2776 uns0_p && uns1_p
2777 && unsr_p);
2778 p = TYPE_PRECISION (optype);
2779 if (p > precres)
2780 {
2781 precres = p;
2782 unsr_p = TYPE_UNSIGNED (optype);
2783 type = optype;
2784 continue;
2785 }
2786 }
2787
2788 gcc_unreachable ();
2789 }
2790 while (1);
2791}
2792
2793/* Expand ADD_OVERFLOW STMT. */
2794
2795static void
4cfe7a6c 2796expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
2797{
2798 expand_arith_overflow (PLUS_EXPR, stmt);
2799}
2800
2801/* Expand SUB_OVERFLOW STMT. */
2802
2803static void
4cfe7a6c 2804expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
2805{
2806 expand_arith_overflow (MINUS_EXPR, stmt);
2807}
2808
2809/* Expand MUL_OVERFLOW STMT. */
2810
2811static void
4cfe7a6c 2812expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
2813{
2814 expand_arith_overflow (MULT_EXPR, stmt);
31e071ae
MP
2815}
2816
43a3252c
JJ
2817/* Expand UADDC STMT. */
2818
2819static void
2820expand_UADDC (internal_fn ifn, gcall *stmt)
2821{
2822 tree lhs = gimple_call_lhs (stmt);
2823 tree arg1 = gimple_call_arg (stmt, 0);
2824 tree arg2 = gimple_call_arg (stmt, 1);
2825 tree arg3 = gimple_call_arg (stmt, 2);
2826 tree type = TREE_TYPE (arg1);
2827 machine_mode mode = TYPE_MODE (type);
2828 insn_code icode = optab_handler (ifn == IFN_UADDC
2829 ? uaddc5_optab : usubc5_optab, mode);
2830 rtx op1 = expand_normal (arg1);
2831 rtx op2 = expand_normal (arg2);
2832 rtx op3 = expand_normal (arg3);
2833 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2834 rtx re = gen_reg_rtx (mode);
2835 rtx im = gen_reg_rtx (mode);
2836 class expand_operand ops[5];
2837 create_output_operand (&ops[0], re, mode);
2838 create_output_operand (&ops[1], im, mode);
2839 create_input_operand (&ops[2], op1, mode);
2840 create_input_operand (&ops[3], op2, mode);
2841 create_input_operand (&ops[4], op3, mode);
2842 expand_insn (icode, 5, ops);
2843 write_complex_part (target, re, false, false);
2844 write_complex_part (target, im, true, false);
2845}
2846
2847/* Expand USUBC STMT. */
2848
2849static void
2850expand_USUBC (internal_fn ifn, gcall *stmt)
2851{
2852 expand_UADDC (ifn, stmt);
2853}
2854
e53b6e56 2855/* This should get folded in tree-vectorizer.cc. */
5ce9450f
JJ
2856
2857static void
4cfe7a6c 2858expand_LOOP_VECTORIZED (internal_fn, gcall *)
5ce9450f
JJ
2859{
2860 gcc_unreachable ();
2861}
2862
e53b6e56 2863/* This should get folded in tree-vectorizer.cc. */
542e7230
BC
2864
2865static void
2866expand_LOOP_DIST_ALIAS (internal_fn, gcall *)
2867{
2868 gcc_unreachable ();
2869}
2870
65dd1346
RS
2871/* Return a memory reference of type TYPE for argument INDEX of STMT.
2872 Use argument INDEX + 1 to derive the second (TBAA) operand. */
2873
2874static tree
2875expand_call_mem_ref (tree type, gcall *stmt, int index)
2876{
2877 tree addr = gimple_call_arg (stmt, index);
2878 tree alias_ptr_type = TREE_TYPE (gimple_call_arg (stmt, index + 1));
2879 unsigned int align = tree_to_shwi (gimple_call_arg (stmt, index + 1));
2880 if (TYPE_ALIGN (type) != align)
2881 type = build_aligned_type (type, align);
2882
2883 tree tmp = addr;
2884 if (TREE_CODE (tmp) == SSA_NAME)
2885 {
2886 gimple *def = SSA_NAME_DEF_STMT (tmp);
2887 if (gimple_assign_single_p (def))
2888 tmp = gimple_assign_rhs1 (def);
2889 }
2890
2891 if (TREE_CODE (tmp) == ADDR_EXPR)
2892 {
2893 tree mem = TREE_OPERAND (tmp, 0);
2894 if (TREE_CODE (mem) == TARGET_MEM_REF
2895 && types_compatible_p (TREE_TYPE (mem), type))
2896 {
2897 tree offset = TMR_OFFSET (mem);
9bd958c5
RS
2898 if (type != TREE_TYPE (mem)
2899 || alias_ptr_type != TREE_TYPE (offset)
2900 || !integer_zerop (offset))
65dd1346
RS
2901 {
2902 mem = copy_node (mem);
2903 TMR_OFFSET (mem) = wide_int_to_tree (alias_ptr_type,
2904 wi::to_poly_wide (offset));
9bd958c5 2905 TREE_TYPE (mem) = type;
65dd1346
RS
2906 }
2907 return mem;
2908 }
2909 }
2910
2911 return fold_build2 (MEM_REF, type, addr, build_int_cst (alias_ptr_type, 0));
2912}
2913
ccfdda34
JZZ
2914/* Expand MASK_LOAD{,_LANES}, LEN_MASK_LOAD or LEN_LOAD call STMT using optab
2915 * OPTAB. */
ab23f5d9 2916
5ce9450f 2917static void
b8806f6f 2918expand_partial_load_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
5ce9450f 2919{
b8806f6f 2920 int i = 0;
ccfdda34 2921 class expand_operand ops[5];
b8806f6f
JZZ
2922 tree type, lhs, rhs, maskt;
2923 rtx mem, target;
7e11fc7f 2924 insn_code icode;
5ce9450f 2925
b8806f6f 2926 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
5ce9450f 2927 lhs = gimple_call_lhs (stmt);
8e91d222
JJ
2928 if (lhs == NULL_TREE)
2929 return;
5ce9450f 2930 type = TREE_TYPE (lhs);
65dd1346 2931 rhs = expand_call_mem_ref (type, stmt, 0);
5ce9450f 2932
7e11fc7f
RS
2933 if (optab == vec_mask_load_lanes_optab)
2934 icode = get_multi_vector_move (type, optab);
d496134a
KL
2935 else if (optab == len_load_optab)
2936 icode = direct_optab_handler (optab, TYPE_MODE (type));
7e11fc7f
RS
2937 else
2938 icode = convert_optab_handler (optab, TYPE_MODE (type),
2939 TYPE_MODE (TREE_TYPE (maskt)));
2940
5ce9450f
JJ
2941 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2942 gcc_assert (MEM_P (mem));
5ce9450f 2943 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
b8806f6f
JZZ
2944 create_output_operand (&ops[i++], target, TYPE_MODE (type));
2945 create_fixed_operand (&ops[i++], mem);
2946 i = add_len_and_mask_args (ops, i, stmt);
2947 expand_insn (icode, i, ops);
b0e51639 2948
3af3bec2
RS
2949 if (!rtx_equal_p (target, ops[0].value))
2950 emit_move_insn (target, ops[0].value);
5ce9450f
JJ
2951}
2952
d496134a 2953#define expand_mask_load_optab_fn expand_partial_load_optab_fn
7e11fc7f 2954#define expand_mask_load_lanes_optab_fn expand_mask_load_optab_fn
d496134a 2955#define expand_len_load_optab_fn expand_partial_load_optab_fn
ccfdda34 2956#define expand_len_maskload_optab_fn expand_partial_load_optab_fn
7e11fc7f 2957
ccfdda34
JZZ
2958/* Expand MASK_STORE{,_LANES}, LEN_MASK_STORE or LEN_STORE call STMT using optab
2959 * OPTAB. */
ab23f5d9 2960
5ce9450f 2961static void
d39f4889 2962expand_partial_store_optab_fn (internal_fn ifn, gcall *stmt, convert_optab optab)
5ce9450f 2963{
b8806f6f 2964 int i = 0;
ccfdda34 2965 class expand_operand ops[5];
b8806f6f
JZZ
2966 tree type, lhs, rhs, maskt;
2967 rtx mem, reg;
7e11fc7f 2968 insn_code icode;
5ce9450f 2969
b8806f6f 2970 maskt = gimple_call_arg (stmt, internal_fn_mask_index (ifn));
d39f4889 2971 rhs = gimple_call_arg (stmt, internal_fn_stored_value_index (ifn));
5ce9450f 2972 type = TREE_TYPE (rhs);
65dd1346 2973 lhs = expand_call_mem_ref (type, stmt, 0);
5ce9450f 2974
7e11fc7f
RS
2975 if (optab == vec_mask_store_lanes_optab)
2976 icode = get_multi_vector_move (type, optab);
d496134a
KL
2977 else if (optab == len_store_optab)
2978 icode = direct_optab_handler (optab, TYPE_MODE (type));
7e11fc7f
RS
2979 else
2980 icode = convert_optab_handler (optab, TYPE_MODE (type),
2981 TYPE_MODE (TREE_TYPE (maskt)));
2982
5ce9450f
JJ
2983 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2984 gcc_assert (MEM_P (mem));
5ce9450f 2985 reg = expand_normal (rhs);
b8806f6f
JZZ
2986 create_fixed_operand (&ops[i++], mem);
2987 create_input_operand (&ops[i++], reg, TYPE_MODE (type));
2988 i = add_len_and_mask_args (ops, i, stmt);
2989 expand_insn (icode, i, ops);
5ce9450f
JJ
2990}
2991
d496134a 2992#define expand_mask_store_optab_fn expand_partial_store_optab_fn
7e11fc7f 2993#define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
d496134a 2994#define expand_len_store_optab_fn expand_partial_store_optab_fn
ccfdda34 2995#define expand_len_maskstore_optab_fn expand_partial_store_optab_fn
7e11fc7f 2996
502d63b6
ML
2997/* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
2998 The expansion of STMT happens based on OPTAB table associated. */
2999
3000static void
298e76e6 3001expand_vec_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
502d63b6
ML
3002{
3003 class expand_operand ops[6];
3004 insn_code icode;
3005 tree lhs = gimple_call_lhs (stmt);
3006 tree op0a = gimple_call_arg (stmt, 0);
3007 tree op0b = gimple_call_arg (stmt, 1);
3008 tree op1 = gimple_call_arg (stmt, 2);
3009 tree op2 = gimple_call_arg (stmt, 3);
3010 enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
3011
3012 tree vec_cond_type = TREE_TYPE (lhs);
3013 tree op_mode = TREE_TYPE (op0a);
3014 bool unsignedp = TYPE_UNSIGNED (op_mode);
3015
3016 machine_mode mode = TYPE_MODE (vec_cond_type);
3017 machine_mode cmp_op_mode = TYPE_MODE (op_mode);
3018
3019 icode = convert_optab_handler (optab, mode, cmp_op_mode);
3020 rtx comparison
3021 = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
3022 rtx rtx_op1 = expand_normal (op1);
3023 rtx rtx_op2 = expand_normal (op2);
3024
3025 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3026 create_output_operand (&ops[0], target, mode);
3027 create_input_operand (&ops[1], rtx_op1, mode);
3028 create_input_operand (&ops[2], rtx_op2, mode);
3029 create_fixed_operand (&ops[3], comparison);
3030 create_fixed_operand (&ops[4], XEXP (comparison, 0));
3031 create_fixed_operand (&ops[5], XEXP (comparison, 1));
3032 expand_insn (icode, 6, ops);
eccc3d43
RB
3033 if (!rtx_equal_p (ops[0].value, target))
3034 emit_move_insn (target, ops[0].value);
502d63b6
ML
3035}
3036
502d63b6
ML
3037/* Expand VCOND_MASK optab internal function.
3038 The expansion of STMT happens based on OPTAB table associated. */
3039
3040static void
298e76e6 3041expand_vec_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
502d63b6
ML
3042{
3043 class expand_operand ops[4];
3044
3045 tree lhs = gimple_call_lhs (stmt);
3046 tree op0 = gimple_call_arg (stmt, 0);
3047 tree op1 = gimple_call_arg (stmt, 1);
3048 tree op2 = gimple_call_arg (stmt, 2);
3049 tree vec_cond_type = TREE_TYPE (lhs);
3050
3051 machine_mode mode = TYPE_MODE (vec_cond_type);
3052 machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
3053 enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
3054 rtx mask, rtx_op1, rtx_op2;
3055
3056 gcc_assert (icode != CODE_FOR_nothing);
3057
3058 mask = expand_normal (op0);
3059 rtx_op1 = expand_normal (op1);
3060 rtx_op2 = expand_normal (op2);
3061
3062 mask = force_reg (mask_mode, mask);
bc909324 3063 rtx_op1 = force_reg (mode, rtx_op1);
502d63b6
ML
3064
3065 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3066 create_output_operand (&ops[0], target, mode);
3067 create_input_operand (&ops[1], rtx_op1, mode);
3068 create_input_operand (&ops[2], rtx_op2, mode);
3069 create_input_operand (&ops[3], mask, mask_mode);
3070 expand_insn (icode, 4, ops);
eccc3d43
RB
3071 if (!rtx_equal_p (ops[0].value, target))
3072 emit_move_insn (target, ops[0].value);
502d63b6
ML
3073}
3074
683e55fa
XL
3075/* Expand VEC_SET internal functions. */
3076
3077static void
3078expand_vec_set_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3079{
3080 tree lhs = gimple_call_lhs (stmt);
3081 tree op0 = gimple_call_arg (stmt, 0);
3082 tree op1 = gimple_call_arg (stmt, 1);
3083 tree op2 = gimple_call_arg (stmt, 2);
3084 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3085 rtx src = expand_normal (op0);
3086
3087 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3088 scalar_mode innermode = GET_MODE_INNER (outermode);
3089
3090 rtx value = expand_normal (op1);
3091 rtx pos = expand_normal (op2);
3092
3093 class expand_operand ops[3];
3094 enum insn_code icode = optab_handler (optab, outermode);
3095
3096 if (icode != CODE_FOR_nothing)
3097 {
3098 rtx temp = gen_reg_rtx (outermode);
3099 emit_move_insn (temp, src);
3100
3101 create_fixed_operand (&ops[0], temp);
3102 create_input_operand (&ops[1], value, innermode);
3103 create_convert_operand_from (&ops[2], pos, TYPE_MODE (TREE_TYPE (op2)),
3104 true);
3105 if (maybe_expand_insn (icode, 3, ops))
3106 {
3107 emit_move_insn (target, temp);
3108 return;
3109 }
3110 }
3111 gcc_unreachable ();
3112}
3113
c30efd8c
RD
3114/* Expand VEC_EXTRACT optab internal function. */
3115
3116static void
3117expand_vec_extract_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3118{
3119 tree lhs = gimple_call_lhs (stmt);
3120 tree op0 = gimple_call_arg (stmt, 0);
3121 tree op1 = gimple_call_arg (stmt, 1);
3122
3123 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3124
3125 machine_mode outermode = TYPE_MODE (TREE_TYPE (op0));
3126 machine_mode extract_mode = TYPE_MODE (TREE_TYPE (lhs));
3127
3128 rtx src = expand_normal (op0);
3129 rtx pos = expand_normal (op1);
3130
3131 class expand_operand ops[3];
3132 enum insn_code icode = convert_optab_handler (optab, outermode,
3133 extract_mode);
3134
3135 if (icode != CODE_FOR_nothing)
3136 {
3137 create_output_operand (&ops[0], target, extract_mode);
3138 create_input_operand (&ops[1], src, outermode);
3139 create_convert_operand_from (&ops[2], pos,
3140 TYPE_MODE (TREE_TYPE (op1)), true);
3141 if (maybe_expand_insn (icode, 3, ops))
3142 {
3143 if (!rtx_equal_p (target, ops[0].value))
3144 emit_move_insn (target, ops[0].value);
3145 return;
3146 }
3147 }
3148 gcc_unreachable ();
3149}
3150
09b22f48 3151static void
4cfe7a6c 3152expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
09b22f48
JJ
3153{
3154}
3155
ed9c79e1 3156static void
4cfe7a6c 3157expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
ed9c79e1
JJ
3158{
3159 /* When guessing was done, the hints should be already stripped away. */
3160 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
3161
3162 rtx target;
3163 tree lhs = gimple_call_lhs (stmt);
3164 if (lhs)
3165 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3166 else
3167 target = const0_rtx;
3168 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
3169 if (lhs && val != target)
3170 emit_move_insn (target, val);
3171}
3172
f8e89441
TV
3173/* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
3174 should never be called. */
3175
3176static void
4cfe7a6c 3177expand_VA_ARG (internal_fn, gcall *)
d8fcab68
JJ
3178{
3179 gcc_unreachable ();
3180}
3181
3182/* IFN_VEC_CONVERT is supposed to be expanded at pass_lower_vector. So this
3183 dummy function should never be called. */
3184
3185static void
3186expand_VEC_CONVERT (internal_fn, gcall *)
f8e89441
TV
3187{
3188 gcc_unreachable ();
3189}
3190
6f966f06
SSF
3191/* Expand IFN_RAWMEMCHAR internal function. */
3192
3193void
3194expand_RAWMEMCHR (internal_fn, gcall *stmt)
3195{
3196 expand_operand ops[3];
3197
3198 tree lhs = gimple_call_lhs (stmt);
3199 if (!lhs)
3200 return;
3201 machine_mode lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
3202 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3203 create_output_operand (&ops[0], lhs_rtx, lhs_mode);
3204
3205 tree mem = gimple_call_arg (stmt, 0);
3206 rtx mem_rtx = get_memory_rtx (mem, NULL);
3207 create_fixed_operand (&ops[1], mem_rtx);
3208
3209 tree pattern = gimple_call_arg (stmt, 1);
3210 machine_mode mode = TYPE_MODE (TREE_TYPE (pattern));
3211 rtx pattern_rtx = expand_normal (pattern);
3212 create_input_operand (&ops[2], pattern_rtx, mode);
3213
3214 insn_code icode = direct_optab_handler (rawmemchr_optab, mode);
3215
3216 expand_insn (icode, 3, ops);
3217 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3218 emit_move_insn (lhs_rtx, ops[0].value);
3219}
3220
8ab78162
NS
3221/* Expand the IFN_UNIQUE function according to its first argument. */
3222
3223static void
4cfe7a6c 3224expand_UNIQUE (internal_fn, gcall *stmt)
8ab78162
NS
3225{
3226 rtx pattern = NULL_RTX;
3227 enum ifn_unique_kind kind
3228 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
3229
3230 switch (kind)
3231 {
3232 default:
3233 gcc_unreachable ();
3234
3235 case IFN_UNIQUE_UNSPEC:
3236 if (targetm.have_unique ())
3237 pattern = targetm.gen_unique ();
3238 break;
9bd46bc9
NS
3239
3240 case IFN_UNIQUE_OACC_FORK:
3241 case IFN_UNIQUE_OACC_JOIN:
3242 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
3243 {
3244 tree lhs = gimple_call_lhs (stmt);
3245 rtx target = const0_rtx;
3246
3247 if (lhs)
3248 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3249
3250 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
3251 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
3252
3253 if (kind == IFN_UNIQUE_OACC_FORK)
3254 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
3255 else
3256 pattern = targetm.gen_oacc_join (target, data_dep, axis);
3257 }
3258 else
3259 gcc_unreachable ();
3260 break;
8ab78162
NS
3261 }
3262
3263 if (pattern)
3264 emit_insn (pattern);
3265}
3266
a25e0b5e 3267/* Expand the IFN_DEFERRED_INIT function:
6c98c8b4 3268 LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL);
a25e0b5e 3269
3270 Initialize the LHS with zero/pattern according to its second argument
3271 INIT_TYPE:
3272 if INIT_TYPE is AUTO_INIT_ZERO, use zeroes to initialize;
3273 if INIT_TYPE is AUTO_INIT_PATTERN, use 0xFE byte-repeatable pattern
3274 to initialize;
3275 The LHS variable is initialized including paddings.
3276 The reasons to choose 0xFE for pattern initialization are:
3277 1. It is a non-canonical virtual address on x86_64, and at the
3278 high end of the i386 kernel address space.
3279 2. It is a very large float value (-1.694739530317379e+38).
3280 3. It is also an unusual number for integers. */
3281#define INIT_PATTERN_VALUE 0xFE
3282static void
3283expand_DEFERRED_INIT (internal_fn, gcall *stmt)
3284{
3285 tree lhs = gimple_call_lhs (stmt);
3286 tree var_size = gimple_call_arg (stmt, 0);
3287 enum auto_init_type init_type
3288 = (enum auto_init_type) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
a25e0b5e 3289 bool reg_lhs = true;
3290
3291 tree var_type = TREE_TYPE (lhs);
3292 gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
3293
79f488de 3294 if (TREE_CODE (lhs) == SSA_NAME)
a25e0b5e 3295 reg_lhs = true;
3296 else
3297 {
7e0c0500
RB
3298 tree lhs_base = lhs;
3299 while (handled_component_p (lhs_base))
3300 lhs_base = TREE_OPERAND (lhs_base, 0);
3301 reg_lhs = (mem_ref_refers_to_non_mem_p (lhs_base)
3302 || non_mem_decl_p (lhs_base));
06b8cdc8
RB
3303 /* If this expands to a register and the underlying decl is wrapped in
3304 a MEM_REF that just serves as an access type change expose the decl
3305 if it is of correct size. This avoids a situation as in PR103271
3306 if the target does not support a direct move to the registers mode. */
3307 if (reg_lhs
3308 && TREE_CODE (lhs_base) == MEM_REF
3309 && TREE_CODE (TREE_OPERAND (lhs_base, 0)) == ADDR_EXPR
3310 && DECL_P (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))
3311 && integer_zerop (TREE_OPERAND (lhs_base, 1))
3312 && tree_fits_uhwi_p (var_size)
3313 && tree_int_cst_equal
3314 (var_size,
3315 DECL_SIZE_UNIT (TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0))))
3316 {
3317 lhs = TREE_OPERAND (TREE_OPERAND (lhs_base, 0), 0);
3318 var_type = TREE_TYPE (lhs);
3319 }
a25e0b5e 3320 }
3321
a25e0b5e 3322 if (!reg_lhs)
3323 {
6c98c8b4
QZ
3324 /* If the variable is not in register, expand to a memset
3325 to initialize it. */
a25e0b5e 3326 mark_addressable (lhs);
3327 tree var_addr = build_fold_addr_expr (lhs);
3328
1c04af34
QZ
3329 tree value = (init_type == AUTO_INIT_PATTERN)
3330 ? build_int_cst (integer_type_node,
3331 INIT_PATTERN_VALUE)
3332 : integer_zero_node;
a25e0b5e 3333 tree m_call = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMSET),
3334 3, var_addr, value, var_size);
3335 /* Expand this memset call. */
3336 expand_builtin_memset (m_call, NULL_RTX, TYPE_MODE (var_type));
3337 }
604459a0 3338 else
a25e0b5e 3339 {
c081d0a3
RB
3340 /* If this variable is in a register use expand_assignment.
3341 For boolean scalars force zero-init. */
604459a0 3342 tree init;
1c04af34 3343 scalar_int_mode var_mode;
c081d0a3
RB
3344 if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
3345 && tree_fits_uhwi_p (var_size)
604459a0 3346 && (init_type == AUTO_INIT_PATTERN
33872565
RB
3347 || !is_gimple_reg_type (var_type))
3348 && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
1c04af34
QZ
3349 0).exists (&var_mode)
3350 && have_insn_for (SET, var_mode))
a25e0b5e 3351 {
604459a0 3352 unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
1c04af34 3353 unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
604459a0
RB
3354 memset (buf, (init_type == AUTO_INIT_PATTERN
3355 ? INIT_PATTERN_VALUE : 0), total_bytes);
c081d0a3
RB
3356 tree itype = build_nonstandard_integer_type
3357 (total_bytes * BITS_PER_UNIT, 1);
3358 wide_int w = wi::from_buffer (buf, total_bytes);
3359 init = wide_int_to_tree (itype, w);
3360 /* Pun the LHS to make sure its type has constant size
3361 unless it is an SSA name where that's already known. */
3362 if (TREE_CODE (lhs) != SSA_NAME)
3363 lhs = build1 (VIEW_CONVERT_EXPR, itype, lhs);
8d6b12b2 3364 else
c081d0a3 3365 init = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), init);
a25e0b5e 3366 }
604459a0
RB
3367 else
3368 /* Use zero-init also for variable-length sizes. */
3369 init = build_zero_cst (var_type);
a25e0b5e 3370
3371 expand_assignment (lhs, init, false);
3372 }
3373}
3374
9bd46bc9
NS
3375/* The size of an OpenACC compute dimension. */
3376
3377static void
4cfe7a6c 3378expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
9bd46bc9
NS
3379{
3380 tree lhs = gimple_call_lhs (stmt);
3381
3382 if (!lhs)
3383 return;
3384
3385 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3386 if (targetm.have_oacc_dim_size ())
3387 {
3388 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3389 VOIDmode, EXPAND_NORMAL);
3390 emit_insn (targetm.gen_oacc_dim_size (target, dim));
3391 }
3392 else
3393 emit_move_insn (target, GEN_INT (1));
3394}
3395
3396/* The position of an OpenACC execution engine along one compute axis. */
3397
3398static void
4cfe7a6c 3399expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
9bd46bc9
NS
3400{
3401 tree lhs = gimple_call_lhs (stmt);
3402
3403 if (!lhs)
3404 return;
3405
3406 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3407 if (targetm.have_oacc_dim_pos ())
3408 {
3409 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
3410 VOIDmode, EXPAND_NORMAL);
3411 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
3412 }
3413 else
3414 emit_move_insn (target, const0_rtx);
3415}
3416
3417/* This is expanded by oacc_device_lower pass. */
3418
3419static void
4cfe7a6c 3420expand_GOACC_LOOP (internal_fn, gcall *)
9bd46bc9
NS
3421{
3422 gcc_unreachable ();
3423}
3424
e5014671
NS
3425/* This is expanded by oacc_device_lower pass. */
3426
3427static void
4cfe7a6c 3428expand_GOACC_REDUCTION (internal_fn, gcall *)
e5014671
NS
3429{
3430 gcc_unreachable ();
02889d23
CLT
3431}
3432
3433/* This is expanded by oacc_device_lower pass. */
3434
3435static void
3436expand_GOACC_TILE (internal_fn, gcall *)
3437{
3438 gcc_unreachable ();
e5014671
NS
3439}
3440
883cabde
RS
3441/* Set errno to EDOM. */
3442
3443static void
3444expand_SET_EDOM (internal_fn, gcall *)
3445{
3446#ifdef TARGET_EDOM
3447#ifdef GEN_ERRNO_RTX
3448 rtx errno_rtx = GEN_ERRNO_RTX;
3449#else
3450 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
3451#endif
3452 emit_move_insn (errno_rtx,
3453 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
3454#else
3455 gcc_unreachable ();
3456#endif
3457}
3458
adedd5c1
JJ
3459/* Expand atomic bit test and set. */
3460
3461static void
3462expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
3463{
3464 expand_ifn_atomic_bit_test_and (call);
3465}
3466
3467/* Expand atomic bit test and complement. */
3468
3469static void
3470expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
3471{
3472 expand_ifn_atomic_bit_test_and (call);
3473}
3474
3475/* Expand atomic bit test and reset. */
3476
3477static void
3478expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
3479{
3480 expand_ifn_atomic_bit_test_and (call);
3481}
3482
849a76a5
JJ
3483/* Expand atomic bit test and set. */
3484
3485static void
3486expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
3487{
3488 expand_ifn_atomic_compare_exchange (call);
3489}
3490
6362627b
JJ
3491/* Expand atomic add fetch and cmp with 0. */
3492
3493static void
3494expand_ATOMIC_ADD_FETCH_CMP_0 (internal_fn, gcall *call)
3495{
3496 expand_ifn_atomic_op_fetch_cmp_0 (call);
3497}
3498
3499/* Expand atomic sub fetch and cmp with 0. */
3500
3501static void
3502expand_ATOMIC_SUB_FETCH_CMP_0 (internal_fn, gcall *call)
3503{
3504 expand_ifn_atomic_op_fetch_cmp_0 (call);
3505}
3506
3507/* Expand atomic and fetch and cmp with 0. */
3508
3509static void
3510expand_ATOMIC_AND_FETCH_CMP_0 (internal_fn, gcall *call)
3511{
3512 expand_ifn_atomic_op_fetch_cmp_0 (call);
3513}
3514
3515/* Expand atomic or fetch and cmp with 0. */
3516
3517static void
3518expand_ATOMIC_OR_FETCH_CMP_0 (internal_fn, gcall *call)
3519{
3520 expand_ifn_atomic_op_fetch_cmp_0 (call);
3521}
3522
3523/* Expand atomic xor fetch and cmp with 0. */
3524
3525static void
3526expand_ATOMIC_XOR_FETCH_CMP_0 (internal_fn, gcall *call)
3527{
3528 expand_ifn_atomic_op_fetch_cmp_0 (call);
3529}
3530
e16f1cc7
JJ
3531/* Expand LAUNDER to assignment, lhs = arg0. */
3532
3533static void
3534expand_LAUNDER (internal_fn, gcall *call)
3535{
3536 tree lhs = gimple_call_lhs (call);
3537
3538 if (!lhs)
3539 return;
3540
3541 expand_assignment (lhs, gimple_call_arg (call, 0), false);
3542}
3543
f307441a
RS
3544/* Expand {MASK_,}SCATTER_STORE{S,U} call CALL using optab OPTAB. */
3545
3546static void
3547expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3548{
3549 internal_fn ifn = gimple_call_internal_fn (stmt);
3550 int rhs_index = internal_fn_stored_value_index (ifn);
f307441a
RS
3551 tree base = gimple_call_arg (stmt, 0);
3552 tree offset = gimple_call_arg (stmt, 1);
3553 tree scale = gimple_call_arg (stmt, 2);
3554 tree rhs = gimple_call_arg (stmt, rhs_index);
3555
3556 rtx base_rtx = expand_normal (base);
3557 rtx offset_rtx = expand_normal (offset);
3558 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3559 rtx rhs_rtx = expand_normal (rhs);
3560
db3efdaf 3561 class expand_operand ops[8];
f307441a
RS
3562 int i = 0;
3563 create_address_operand (&ops[i++], base_rtx);
3564 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3565 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3566 create_integer_operand (&ops[i++], scale_int);
3567 create_input_operand (&ops[i++], rhs_rtx, TYPE_MODE (TREE_TYPE (rhs)));
db3efdaf 3568 i = add_len_and_mask_args (ops, i, stmt);
f307441a 3569
09eb042a
RS
3570 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
3571 TYPE_MODE (TREE_TYPE (offset)));
f307441a
RS
3572 expand_insn (icode, i, ops);
3573}
3574
bfaa08b7
RS
3575/* Expand {MASK_,}GATHER_LOAD call CALL using optab OPTAB. */
3576
3577static void
3578expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
3579{
3580 tree lhs = gimple_call_lhs (stmt);
3581 tree base = gimple_call_arg (stmt, 0);
3582 tree offset = gimple_call_arg (stmt, 1);
3583 tree scale = gimple_call_arg (stmt, 2);
3584
3585 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3586 rtx base_rtx = expand_normal (base);
3587 rtx offset_rtx = expand_normal (offset);
3588 HOST_WIDE_INT scale_int = tree_to_shwi (scale);
3589
3590 int i = 0;
db3efdaf 3591 class expand_operand ops[8];
bfaa08b7
RS
3592 create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs)));
3593 create_address_operand (&ops[i++], base_rtx);
3594 create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset)));
3595 create_integer_operand (&ops[i++], TYPE_UNSIGNED (TREE_TYPE (offset)));
3596 create_integer_operand (&ops[i++], scale_int);
db3efdaf 3597 i = add_len_and_mask_args (ops, i, stmt);
09eb042a
RS
3598 insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
3599 TYPE_MODE (TREE_TYPE (offset)));
bfaa08b7 3600 expand_insn (icode, i, ops);
3af3bec2
RS
3601 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3602 emit_move_insn (lhs_rtx, ops[0].value);
bfaa08b7
RS
3603}
3604
bf510679
JJ
3605/* Helper for expand_DIVMOD. Return true if the sequence starting with
3606 INSN contains any call insns or insns with {,U}{DIV,MOD} rtxes. */
3607
3608static bool
3609contains_call_div_mod (rtx_insn *insn)
3610{
3611 subrtx_iterator::array_type array;
3612 for (; insn; insn = NEXT_INSN (insn))
3613 if (CALL_P (insn))
3614 return true;
3615 else if (INSN_P (insn))
3616 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
3617 switch (GET_CODE (*iter))
3618 {
3619 case CALL:
3620 case DIV:
3621 case UDIV:
3622 case MOD:
3623 case UMOD:
3624 return true;
3625 default:
3626 break;
3627 }
3628 return false;
3629 }
3630
e72531b9
PK
3631/* Expand DIVMOD() using:
3632 a) optab handler for udivmod/sdivmod if it is available.
3633 b) If optab_handler doesn't exist, generate call to
3634 target-specific divmod libfunc. */
3635
3636static void
3637expand_DIVMOD (internal_fn, gcall *call_stmt)
3638{
3639 tree lhs = gimple_call_lhs (call_stmt);
3640 tree arg0 = gimple_call_arg (call_stmt, 0);
3641 tree arg1 = gimple_call_arg (call_stmt, 1);
3642
3643 gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
3644 tree type = TREE_TYPE (TREE_TYPE (lhs));
3645 machine_mode mode = TYPE_MODE (type);
3646 bool unsignedp = TYPE_UNSIGNED (type);
3647 optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
3648
3649 rtx op0 = expand_normal (arg0);
3650 rtx op1 = expand_normal (arg1);
3651 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3652
bf510679
JJ
3653 rtx quotient = NULL_RTX, remainder = NULL_RTX;
3654 rtx_insn *insns = NULL;
3655
3656 if (TREE_CODE (arg1) == INTEGER_CST)
3657 {
3658 /* For DIVMOD by integral constants, there could be efficient code
3659 expanded inline e.g. using shifts and plus/minus. Try to expand
3660 the division and modulo and if it emits any library calls or any
3661 {,U}{DIV,MOD} rtxes throw it away and use a divmod optab or
3662 divmod libcall. */
037fe26e
JJ
3663 scalar_int_mode int_mode;
3664 if (remainder == NULL_RTX
3665 && optimize
3666 && CONST_INT_P (op1)
3667 && !pow2p_hwi (INTVAL (op1))
3668 && is_int_mode (TYPE_MODE (type), &int_mode)
3669 && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
3670 && optab_handler (and_optab, word_mode) != CODE_FOR_nothing
3671 && optab_handler (add_optab, word_mode) != CODE_FOR_nothing
3672 && optimize_insn_for_speed_p ())
3673 {
3674 rtx_insn *last = get_last_insn ();
3675 remainder = NULL_RTX;
3676 quotient = expand_doubleword_divmod (int_mode, op0, op1, &remainder,
3677 TYPE_UNSIGNED (type));
3678 if (quotient != NULL_RTX)
3679 {
3680 if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
3681 {
3682 rtx_insn *move = emit_move_insn (quotient, quotient);
3683 set_dst_reg_note (move, REG_EQUAL,
3684 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3685 ? UDIV : DIV, int_mode,
3686 copy_rtx (op0), op1),
3687 quotient);
3688 move = emit_move_insn (remainder, remainder);
3689 set_dst_reg_note (move, REG_EQUAL,
3690 gen_rtx_fmt_ee (TYPE_UNSIGNED (type)
3691 ? UMOD : MOD, int_mode,
3692 copy_rtx (op0), op1),
3693 quotient);
3694 }
3695 }
3696 else
3697 delete_insns_since (last);
3698 }
3699
3700 if (remainder == NULL_RTX)
bf510679 3701 {
037fe26e
JJ
3702 struct separate_ops ops;
3703 ops.code = TRUNC_DIV_EXPR;
3704 ops.type = type;
3705 ops.op0 = make_tree (ops.type, op0);
3706 ops.op1 = arg1;
3707 ops.op2 = NULL_TREE;
3708 ops.location = gimple_location (call_stmt);
3709 start_sequence ();
3710 quotient = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
bf510679 3711 if (contains_call_div_mod (get_insns ()))
037fe26e
JJ
3712 quotient = NULL_RTX;
3713 else
3714 {
3715 ops.code = TRUNC_MOD_EXPR;
3716 remainder = expand_expr_real_2 (&ops, NULL_RTX, mode,
3717 EXPAND_NORMAL);
3718 if (contains_call_div_mod (get_insns ()))
3719 remainder = NULL_RTX;
3720 }
3721 if (remainder)
3722 insns = get_insns ();
3723 end_sequence ();
bf510679 3724 }
bf510679
JJ
3725 }
3726
3727 if (remainder)
3728 emit_insn (insns);
e72531b9
PK
3729
3730 /* Check if optab_handler exists for divmod_optab for given mode. */
bf510679 3731 else if (optab_handler (tab, mode) != CODE_FOR_nothing)
e72531b9
PK
3732 {
3733 quotient = gen_reg_rtx (mode);
3734 remainder = gen_reg_rtx (mode);
3735 expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
3736 }
3737
3738 /* Generate call to divmod libfunc if it exists. */
bf510679 3739 else if (rtx libfunc = optab_libfunc (tab, mode))
e72531b9
PK
3740 targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
3741 &quotient, &remainder);
3742
3743 else
3744 gcc_unreachable ();
3745
3746 /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
3747 expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
3748 make_tree (TREE_TYPE (arg0), quotient),
3749 make_tree (TREE_TYPE (arg1), remainder)),
0b99f253 3750 target, VOIDmode, EXPAND_NORMAL);
e72531b9
PK
3751}
3752
87a5e0e8
RB
3753/* Expand a NOP. */
3754
3755static void
3756expand_NOP (internal_fn, gcall *)
3757{
3758 /* Nothing. But it shouldn't really prevail. */
3759}
3760
49789fd0
IS
3761/* Coroutines, all should have been processed at this stage. */
3762
3763static void
3764expand_CO_FRAME (internal_fn, gcall *)
3765{
3766 gcc_unreachable ();
3767}
3768
3769static void
3770expand_CO_YIELD (internal_fn, gcall *)
3771{
3772 gcc_unreachable ();
3773}
3774
3775static void
3776expand_CO_SUSPN (internal_fn, gcall *)
3777{
3778 gcc_unreachable ();
3779}
3780
3781static void
3782expand_CO_ACTOR (internal_fn, gcall *)
3783{
3784 gcc_unreachable ();
3785}
3786
4cfe7a6c
RS
3787/* Expand a call to FN using the operands in STMT. FN has a single
3788 output operand and NARGS input operands. */
686ee971
RS
3789
3790static void
4cfe7a6c
RS
3791expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
3792 unsigned int nargs)
686ee971 3793{
686ee971
RS
3794 tree_pair types = direct_internal_fn_types (fn, stmt);
3795 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
1d205dba 3796 expand_fn_using_insn (stmt, icode, 1, nargs);
686ee971
RS
3797}
3798
7cfb4d93
RS
3799/* Expand WHILE_ULT call STMT using optab OPTAB. */
3800
3801static void
3802expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
3803{
48960b68 3804 expand_operand ops[4];
7cfb4d93
RS
3805 tree rhs_type[2];
3806
3807 tree lhs = gimple_call_lhs (stmt);
3808 tree lhs_type = TREE_TYPE (lhs);
3809 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
3810 create_output_operand (&ops[0], lhs_rtx, TYPE_MODE (lhs_type));
3811
3812 for (unsigned int i = 0; i < 2; ++i)
3813 {
3814 tree rhs = gimple_call_arg (stmt, i);
3815 rhs_type[i] = TREE_TYPE (rhs);
3816 rtx rhs_rtx = expand_normal (rhs);
3817 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type[i]));
3818 }
3819
48960b68
AS
3820 int opcnt;
3821 if (!VECTOR_MODE_P (TYPE_MODE (lhs_type)))
3822 {
3823 /* When the mask is an integer mode the exact vector length may not
3824 be clear to the backend, so we pass it in operand[3].
3825 Use the vector in arg2 for the most reliable intended size. */
3826 tree type = TREE_TYPE (gimple_call_arg (stmt, 2));
3827 create_integer_operand (&ops[3], TYPE_VECTOR_SUBPARTS (type));
3828 opcnt = 4;
3829 }
3830 else
3831 /* The mask has a vector type so the length operand is unnecessary. */
3832 opcnt = 3;
3833
7cfb4d93
RS
3834 insn_code icode = convert_optab_handler (optab, TYPE_MODE (rhs_type[0]),
3835 TYPE_MODE (lhs_type));
3836
48960b68 3837 expand_insn (icode, opcnt, ops);
7cfb4d93
RS
3838 if (!rtx_equal_p (lhs_rtx, ops[0].value))
3839 emit_move_insn (lhs_rtx, ops[0].value);
3840}
3841
00eab0c6
RS
3842/* Expand a call to a convert-like optab using the operands in STMT.
3843 FN has a single output operand and NARGS input operands. */
3844
3845static void
3846expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
3847 unsigned int nargs)
3848{
3849 tree_pair types = direct_internal_fn_types (fn, stmt);
3850 insn_code icode = convert_optab_handler (optab, TYPE_MODE (types.first),
3851 TYPE_MODE (types.second));
3852 expand_fn_using_insn (stmt, icode, 1, nargs);
3853}
3854
686ee971
RS
3855/* Expanders for optabs that can use expand_direct_optab_fn. */
3856
4cfe7a6c
RS
3857#define expand_unary_optab_fn(FN, STMT, OPTAB) \
3858 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
686ee971 3859
4cfe7a6c
RS
3860#define expand_binary_optab_fn(FN, STMT, OPTAB) \
3861 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
686ee971 3862
c566cc9f
RS
3863#define expand_ternary_optab_fn(FN, STMT, OPTAB) \
3864 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3865
bfe1bb57 3866#define expand_cond_unary_optab_fn(FN, STMT, OPTAB) \
9d4ac06e 3867 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
bfe1bb57 3868
0972596e 3869#define expand_cond_binary_optab_fn(FN, STMT, OPTAB) \
9d4ac06e 3870 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
0972596e 3871
b41d1f6e
RS
3872#define expand_cond_ternary_optab_fn(FN, STMT, OPTAB) \
3873 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3874
6c96d1e4
JZZ
3875#define expand_cond_len_unary_optab_fn(FN, STMT, OPTAB) \
3876 expand_direct_optab_fn (FN, STMT, OPTAB, 5)
3877
3878#define expand_cond_len_binary_optab_fn(FN, STMT, OPTAB) \
3879 expand_direct_optab_fn (FN, STMT, OPTAB, 6)
3880
3881#define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
3882 expand_direct_optab_fn (FN, STMT, OPTAB, 7)
3883
bb6c2b68
RS
3884#define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
3885 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3886
b781a135
RS
3887#define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
3888 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
3889
bce29d65
AM
3890#define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
3891 expand_direct_optab_fn (FN, STMT, OPTAB, 3)
3892
58c036c8
RS
3893#define expand_check_ptrs_optab_fn(FN, STMT, OPTAB) \
3894 expand_direct_optab_fn (FN, STMT, OPTAB, 4)
3895
00eab0c6
RS
3896/* Expanders for optabs that can use expand_convert_optab_fn. */
3897
3898#define expand_unary_convert_optab_fn(FN, STMT, OPTAB) \
3899 expand_convert_optab_fn (FN, STMT, OPTAB, 1)
3900
ab23f5d9
RS
3901/* RETURN_TYPE and ARGS are a return type and argument list that are
3902 in principle compatible with FN (which satisfies direct_internal_fn_p).
3903 Return the types that should be used to determine whether the
3904 target supports FN. */
3905
3906tree_pair
3907direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
3908{
3909 const direct_internal_fn_info &info = direct_internal_fn (fn);
3910 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
3911 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
3912 return tree_pair (type0, type1);
3913}
3914
3915/* CALL is a call whose return type and arguments are in principle
3916 compatible with FN (which satisfies direct_internal_fn_p). Return the
3917 types that should be used to determine whether the target supports FN. */
3918
3919tree_pair
3920direct_internal_fn_types (internal_fn fn, gcall *call)
3921{
3922 const direct_internal_fn_info &info = direct_internal_fn (fn);
3923 tree op0 = (info.type0 < 0
3924 ? gimple_call_lhs (call)
3925 : gimple_call_arg (call, info.type0));
3926 tree op1 = (info.type1 < 0
3927 ? gimple_call_lhs (call)
3928 : gimple_call_arg (call, info.type1));
3929 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
3930}
3931
3932/* Return true if OPTAB is supported for TYPES (whose modes should be
d95ab70a
RS
3933 the same) when the optimization type is OPT_TYPE. Used for simple
3934 direct optabs. */
ab23f5d9
RS
3935
3936static bool
d95ab70a
RS
3937direct_optab_supported_p (direct_optab optab, tree_pair types,
3938 optimization_type opt_type)
ab23f5d9
RS
3939{
3940 machine_mode mode = TYPE_MODE (types.first);
3941 gcc_checking_assert (mode == TYPE_MODE (types.second));
d95ab70a 3942 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
ab23f5d9
RS
3943}
3944
7cfb4d93
RS
3945/* Return true if OPTAB is supported for TYPES, where the first type
3946 is the destination and the second type is the source. Used for
3947 convert optabs. */
3948
3949static bool
3950convert_optab_supported_p (convert_optab optab, tree_pair types,
3951 optimization_type opt_type)
3952{
3953 return (convert_optab_handler (optab, TYPE_MODE (types.first),
3954 TYPE_MODE (types.second), opt_type)
3955 != CODE_FOR_nothing);
3956}
3957
ab23f5d9 3958/* Return true if load/store lanes optab OPTAB is supported for
d95ab70a 3959 array type TYPES.first when the optimization type is OPT_TYPE. */
ab23f5d9
RS
3960
3961static bool
d95ab70a
RS
3962multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
3963 optimization_type opt_type)
ab23f5d9 3964{
d95ab70a
RS
3965 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
3966 machine_mode imode = TYPE_MODE (types.first);
3967 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
3968 return (convert_optab_handler (optab, imode, vmode, opt_type)
3969 != CODE_FOR_nothing);
ab23f5d9
RS
3970}
3971
686ee971 3972#define direct_unary_optab_supported_p direct_optab_supported_p
00eab0c6 3973#define direct_unary_convert_optab_supported_p convert_optab_supported_p
686ee971 3974#define direct_binary_optab_supported_p direct_optab_supported_p
c566cc9f 3975#define direct_ternary_optab_supported_p direct_optab_supported_p
bfe1bb57 3976#define direct_cond_unary_optab_supported_p direct_optab_supported_p
0972596e 3977#define direct_cond_binary_optab_supported_p direct_optab_supported_p
b41d1f6e 3978#define direct_cond_ternary_optab_supported_p direct_optab_supported_p
6c96d1e4
JZZ
3979#define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
3980#define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
3981#define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
ef8d1da1 3982#define direct_mask_load_optab_supported_p convert_optab_supported_p
ab23f5d9 3983#define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
7e11fc7f 3984#define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
09eb042a 3985#define direct_gather_load_optab_supported_p convert_optab_supported_p
d496134a 3986#define direct_len_load_optab_supported_p direct_optab_supported_p
ccfdda34 3987#define direct_len_maskload_optab_supported_p convert_optab_supported_p
ef8d1da1 3988#define direct_mask_store_optab_supported_p convert_optab_supported_p
ab23f5d9 3989#define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
7e11fc7f 3990#define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
298e76e6
RS
3991#define direct_vec_cond_mask_optab_supported_p convert_optab_supported_p
3992#define direct_vec_cond_optab_supported_p convert_optab_supported_p
09eb042a 3993#define direct_scatter_store_optab_supported_p convert_optab_supported_p
d496134a 3994#define direct_len_store_optab_supported_p direct_optab_supported_p
ccfdda34 3995#define direct_len_maskstore_optab_supported_p convert_optab_supported_p
7cfb4d93 3996#define direct_while_optab_supported_p convert_optab_supported_p
bb6c2b68 3997#define direct_fold_extract_optab_supported_p direct_optab_supported_p
b781a135 3998#define direct_fold_left_optab_supported_p direct_optab_supported_p
bce29d65 3999#define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
58c036c8 4000#define direct_check_ptrs_optab_supported_p direct_optab_supported_p
683e55fa 4001#define direct_vec_set_optab_supported_p direct_optab_supported_p
c30efd8c 4002#define direct_vec_extract_optab_supported_p direct_optab_supported_p
ab23f5d9 4003
16d24520
RS
4004/* Return the optab used by internal function FN. */
4005
2f482a07 4006optab
16d24520
RS
4007direct_internal_fn_optab (internal_fn fn, tree_pair types)
4008{
4009 switch (fn)
4010 {
4011#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4012 case IFN_##CODE: break;
4013#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4014 case IFN_##CODE: return OPTAB##_optab;
4015#define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4016 UNSIGNED_OPTAB, TYPE) \
4017 case IFN_##CODE: return (TYPE_UNSIGNED (types.SELECTOR) \
4018 ? UNSIGNED_OPTAB ## _optab \
4019 : SIGNED_OPTAB ## _optab);
4020#include "internal-fn.def"
4021
4022 case IFN_LAST:
4023 break;
4024 }
4025 gcc_unreachable ();
4026}
4027
bfaa08b7
RS
4028/* Return the optab used by internal function FN. */
4029
4030static optab
4031direct_internal_fn_optab (internal_fn fn)
4032{
4033 switch (fn)
4034 {
4035#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4036 case IFN_##CODE: break;
4037#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4038 case IFN_##CODE: return OPTAB##_optab;
4039#include "internal-fn.def"
4040
4041 case IFN_LAST:
4042 break;
4043 }
4044 gcc_unreachable ();
4045}
4046
d95ab70a
RS
4047/* Return true if FN is supported for the types in TYPES when the
4048 optimization type is OPT_TYPE. The types are those associated with
4049 the "type0" and "type1" fields of FN's direct_internal_fn_info
4050 structure. */
ab23f5d9
RS
4051
4052bool
d95ab70a
RS
4053direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
4054 optimization_type opt_type)
ab23f5d9
RS
4055{
4056 switch (fn)
4057 {
4058#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
4059 case IFN_##CODE: break;
4060#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4061 case IFN_##CODE: \
d95ab70a
RS
4062 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
4063 opt_type);
16d24520
RS
4064#define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4065 UNSIGNED_OPTAB, TYPE) \
4066 case IFN_##CODE: \
4067 { \
4068 optab which_optab = (TYPE_UNSIGNED (types.SELECTOR) \
4069 ? UNSIGNED_OPTAB ## _optab \
4070 : SIGNED_OPTAB ## _optab); \
4071 return direct_##TYPE##_optab_supported_p (which_optab, types, \
4072 opt_type); \
4073 }
ab23f5d9
RS
4074#include "internal-fn.def"
4075
4076 case IFN_LAST:
4077 break;
4078 }
4079 gcc_unreachable ();
4080}
4081
d95ab70a
RS
4082/* Return true if FN is supported for type TYPE when the optimization
4083 type is OPT_TYPE. The caller knows that the "type0" and "type1"
4084 fields of FN's direct_internal_fn_info structure are the same. */
ab23f5d9
RS
4085
4086bool
d95ab70a
RS
4087direct_internal_fn_supported_p (internal_fn fn, tree type,
4088 optimization_type opt_type)
ab23f5d9
RS
4089{
4090 const direct_internal_fn_info &info = direct_internal_fn (fn);
4091 gcc_checking_assert (info.type0 == info.type1);
d95ab70a 4092 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
ab23f5d9
RS
4093}
4094
41241199
RL
4095/* Return true if the STMT is supported when the optimization type is OPT_TYPE,
4096 given that STMT is a call to a direct internal function. */
4097
4098bool
4099direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
4100{
4101 internal_fn fn = gimple_call_internal_fn (stmt);
4102 tree_pair types = direct_internal_fn_types (fn, stmt);
4103 return direct_internal_fn_supported_p (fn, types, opt_type);
4104}
4105
30213ae9 4106/* Return true if FN is a binary operation and if FN is commutative. */
0246112a 4107
30213ae9
RS
4108bool
4109commutative_binary_fn_p (internal_fn fn)
0246112a
RS
4110{
4111 switch (fn)
4112 {
0246112a
RS
4113 case IFN_AVG_FLOOR:
4114 case IFN_AVG_CEIL:
a1d27560 4115 case IFN_MULH:
58cc9876
YW
4116 case IFN_MULHS:
4117 case IFN_MULHRS:
0246112a
RS
4118 case IFN_FMIN:
4119 case IFN_FMAX:
71207246 4120 case IFN_COMPLEX_MUL:
12e38012
RS
4121 case IFN_UBSAN_CHECK_ADD:
4122 case IFN_UBSAN_CHECK_MUL:
b1d15146
RS
4123 case IFN_ADD_OVERFLOW:
4124 case IFN_MUL_OVERFLOW:
2f482a07
AV
4125 case IFN_VEC_WIDEN_PLUS:
4126 case IFN_VEC_WIDEN_PLUS_LO:
4127 case IFN_VEC_WIDEN_PLUS_HI:
4128 case IFN_VEC_WIDEN_PLUS_EVEN:
4129 case IFN_VEC_WIDEN_PLUS_ODD:
30213ae9
RS
4130 return true;
4131
4132 default:
4133 return false;
4134 }
4135}
4136
4137/* Return true if FN is a ternary operation and if its first two arguments
4138 are commutative. */
4139
4140bool
4141commutative_ternary_fn_p (internal_fn fn)
4142{
4143 switch (fn)
4144 {
4145 case IFN_FMA:
4146 case IFN_FMS:
4147 case IFN_FNMA:
4148 case IFN_FNMS:
43a3252c 4149 case IFN_UADDC:
30213ae9
RS
4150 return true;
4151
4152 default:
4153 return false;
4154 }
4155}
4156
4157/* Return true if FN is an associative binary operation. */
4158
4159bool
4160associative_binary_fn_p (internal_fn fn)
4161{
4162 switch (fn)
4163 {
4164 case IFN_FMIN:
4165 case IFN_FMAX:
4166 return true;
0246112a 4167
30213ae9
RS
4168 default:
4169 return false;
4170 }
4171}
4172
4173/* If FN is commutative in two consecutive arguments, return the
4174 index of the first, otherwise return -1. */
4175
4176int
4177first_commutative_argument (internal_fn fn)
4178{
4179 switch (fn)
4180 {
0246112a
RS
4181 case IFN_COND_ADD:
4182 case IFN_COND_MUL:
4183 case IFN_COND_MIN:
4184 case IFN_COND_MAX:
70613000
RS
4185 case IFN_COND_FMIN:
4186 case IFN_COND_FMAX:
0246112a
RS
4187 case IFN_COND_AND:
4188 case IFN_COND_IOR:
4189 case IFN_COND_XOR:
4190 case IFN_COND_FMA:
4191 case IFN_COND_FMS:
4192 case IFN_COND_FNMA:
4193 case IFN_COND_FNMS:
4194 return 1;
4195
4196 default:
30213ae9
RS
4197 if (commutative_binary_fn_p (fn)
4198 || commutative_ternary_fn_p (fn))
4199 return 0;
0246112a
RS
4200 return -1;
4201 }
4202}
4203
2f482a07
AV
4204/* Return true if this CODE describes an internal_fn that returns a vector with
4205 elements twice as wide as the element size of the input vectors. */
4206
4207bool
4208widening_fn_p (code_helper code)
4209{
4210 if (!code.is_fn_code ())
4211 return false;
4212
4213 if (!internal_fn_p ((combined_fn) code))
4214 return false;
4215
4216 internal_fn fn = as_internal_fn ((combined_fn) code);
4217 switch (fn)
4218 {
4219 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4220 #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \
4221 case IFN_##NAME: \
4222 case IFN_##NAME##_HI: \
4223 case IFN_##NAME##_LO: \
4224 case IFN_##NAME##_EVEN: \
4225 case IFN_##NAME##_ODD: \
4226 return true;
4227 #include "internal-fn.def"
4228 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
4229
4230 default:
4231 return false;
4232 }
4233}
4234
883cabde
RS
4235/* Return true if IFN_SET_EDOM is supported. */
4236
4237bool
4238set_edom_supported_p (void)
4239{
4240#ifdef TARGET_EDOM
4241 return true;
4242#else
4243 return false;
4244#endif
4245}
4246
ab23f5d9
RS
4247#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
4248 static void \
4cfe7a6c 4249 expand_##CODE (internal_fn fn, gcall *stmt) \
ab23f5d9 4250 { \
4cfe7a6c 4251 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
ab23f5d9 4252 }
16d24520
RS
4253#define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \
4254 UNSIGNED_OPTAB, TYPE) \
4255 static void \
4256 expand_##CODE (internal_fn fn, gcall *stmt) \
4257 { \
4258 tree_pair types = direct_internal_fn_types (fn, stmt); \
4259 optab which_optab = direct_internal_fn_optab (fn, types); \
4260 expand_##TYPE##_optab_fn (fn, stmt, which_optab); \
4261 }
ab23f5d9 4262#include "internal-fn.def"
2f482a07
AV
4263#undef DEF_INTERNAL_OPTAB_FN
4264#undef DEF_INTERNAL_SIGNED_OPTAB_FN
ab23f5d9 4265
25583c4f
RS
4266/* Routines to expand each internal function, indexed by function number.
4267 Each routine has the prototype:
4268
538dd0b7 4269 expand_<NAME> (gcall *stmt)
25583c4f
RS
4270
4271 where STMT is the statement that performs the call. */
4cfe7a6c 4272static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
2f482a07 4273
b78475cf 4274#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
25583c4f 4275#include "internal-fn.def"
25583c4f
RS
4276 0
4277};
4278
6a86928d
RS
4279/* Invoke T(CODE, IFN) for each conditional function IFN that maps to a
4280 tree code CODE. */
4281#define FOR_EACH_CODE_MAPPING(T) \
4282 T (PLUS_EXPR, IFN_COND_ADD) \
4283 T (MINUS_EXPR, IFN_COND_SUB) \
4284 T (MULT_EXPR, IFN_COND_MUL) \
4285 T (TRUNC_DIV_EXPR, IFN_COND_DIV) \
4286 T (TRUNC_MOD_EXPR, IFN_COND_MOD) \
4287 T (RDIV_EXPR, IFN_COND_RDIV) \
4288 T (MIN_EXPR, IFN_COND_MIN) \
4289 T (MAX_EXPR, IFN_COND_MAX) \
4290 T (BIT_AND_EXPR, IFN_COND_AND) \
4291 T (BIT_IOR_EXPR, IFN_COND_IOR) \
20103c0e
RS
4292 T (BIT_XOR_EXPR, IFN_COND_XOR) \
4293 T (LSHIFT_EXPR, IFN_COND_SHL) \
20dcda98 4294 T (RSHIFT_EXPR, IFN_COND_SHR) \
4295 T (NEGATE_EXPR, IFN_COND_NEG)
6a86928d 4296
9d4ac06e
RS
4297/* Return a function that only performs CODE when a certain condition is met
4298 and that uses a given fallback value otherwise. For example, if CODE is
4299 a binary operation associated with conditional function FN:
4300
4301 LHS = FN (COND, A, B, ELSE)
4302
4303 is equivalent to the C expression:
4304
4305 LHS = COND ? A CODE B : ELSE;
0972596e 4306
9d4ac06e 4307 operating elementwise if the operands are vectors.
0972596e 4308
9d4ac06e 4309 Return IFN_LAST if no such function exists. */
0972596e
RS
4310
4311internal_fn
4312get_conditional_internal_fn (tree_code code)
4313{
4314 switch (code)
4315 {
6a86928d
RS
4316#define CASE(CODE, IFN) case CODE: return IFN;
4317 FOR_EACH_CODE_MAPPING(CASE)
4318#undef CASE
0972596e
RS
4319 default:
4320 return IFN_LAST;
4321 }
4322}
4323
6a86928d
RS
4324/* If IFN implements the conditional form of a tree code, return that
4325 tree code, otherwise return ERROR_MARK. */
4326
4327tree_code
4328conditional_internal_fn_code (internal_fn ifn)
4329{
4330 switch (ifn)
4331 {
4332#define CASE(CODE, IFN) case IFN: return CODE;
4333 FOR_EACH_CODE_MAPPING(CASE)
4334#undef CASE
4335 default:
4336 return ERROR_MARK;
4337 }
4338}
4339
b41d1f6e
RS
4340/* Invoke T(IFN) for each internal function IFN that also has an
4341 IFN_COND_* form. */
4342#define FOR_EACH_COND_FN_PAIR(T) \
70613000
RS
4343 T (FMAX) \
4344 T (FMIN) \
b41d1f6e
RS
4345 T (FMA) \
4346 T (FMS) \
4347 T (FNMA) \
4348 T (FNMS)
4349
4350/* Return a function that only performs internal function FN when a
4351 certain condition is met and that uses a given fallback value otherwise.
4352 In other words, the returned function FN' is such that:
4353
4354 LHS = FN' (COND, A1, ... An, ELSE)
4355
4356 is equivalent to the C expression:
4357
4358 LHS = COND ? FN (A1, ..., An) : ELSE;
4359
4360 operating elementwise if the operands are vectors.
4361
4362 Return IFN_LAST if no such function exists. */
4363
4364internal_fn
4365get_conditional_internal_fn (internal_fn fn)
4366{
4367 switch (fn)
4368 {
4369#define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
4370 FOR_EACH_COND_FN_PAIR(CASE)
4371#undef CASE
4372 default:
4373 return IFN_LAST;
4374 }
4375}
4376
4377/* If IFN implements the conditional form of an unconditional internal
4378 function, return that unconditional function, otherwise return IFN_LAST. */
4379
4380internal_fn
4381get_unconditional_internal_fn (internal_fn ifn)
4382{
4383 switch (ifn)
4384 {
4385#define CASE(NAME) case IFN_COND_##NAME: return IFN_##NAME;
4386 FOR_EACH_COND_FN_PAIR(CASE)
4387#undef CASE
4388 default:
4389 return IFN_LAST;
4390 }
4391}
4392
0936858f
RS
4393/* Return true if STMT can be interpreted as a conditional tree code
4394 operation of the form:
4395
4396 LHS = COND ? OP (RHS1, ...) : ELSE;
4397
4398 operating elementwise if the operands are vectors. This includes
4399 the case of an all-true COND, so that the operation always happens.
4400
4401 When returning true, set:
4402
4403 - *COND_OUT to the condition COND, or to NULL_TREE if the condition
4404 is known to be all-true
4405 - *CODE_OUT to the tree code
4406 - OPS[I] to operand I of *CODE_OUT
4407 - *ELSE_OUT to the fallback value ELSE, or to NULL_TREE if the
4408 condition is known to be all true. */
4409
4410bool
4411can_interpret_as_conditional_op_p (gimple *stmt, tree *cond_out,
4412 tree_code *code_out,
4413 tree (&ops)[3], tree *else_out)
4414{
4415 if (gassign *assign = dyn_cast <gassign *> (stmt))
4416 {
4417 *cond_out = NULL_TREE;
4418 *code_out = gimple_assign_rhs_code (assign);
4419 ops[0] = gimple_assign_rhs1 (assign);
4420 ops[1] = gimple_assign_rhs2 (assign);
4421 ops[2] = gimple_assign_rhs3 (assign);
4422 *else_out = NULL_TREE;
4423 return true;
4424 }
4425 if (gcall *call = dyn_cast <gcall *> (stmt))
4426 if (gimple_call_internal_p (call))
4427 {
4428 internal_fn ifn = gimple_call_internal_fn (call);
4429 tree_code code = conditional_internal_fn_code (ifn);
4430 if (code != ERROR_MARK)
4431 {
4432 *cond_out = gimple_call_arg (call, 0);
4433 *code_out = code;
4434 unsigned int nops = gimple_call_num_args (call) - 2;
4435 for (unsigned int i = 0; i < 3; ++i)
4436 ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
4437 *else_out = gimple_call_arg (call, nops + 1);
4438 if (integer_truep (*cond_out))
4439 {
4440 *cond_out = NULL_TREE;
4441 *else_out = NULL_TREE;
4442 }
4443 return true;
4444 }
4445 }
4446 return false;
4447}
4448
bfaa08b7
RS
4449/* Return true if IFN is some form of load from memory. */
4450
4451bool
4452internal_load_fn_p (internal_fn fn)
4453{
4454 switch (fn)
4455 {
4456 case IFN_MASK_LOAD:
4457 case IFN_LOAD_LANES:
4458 case IFN_MASK_LOAD_LANES:
4459 case IFN_GATHER_LOAD:
4460 case IFN_MASK_GATHER_LOAD:
db3efdaf 4461 case IFN_LEN_MASK_GATHER_LOAD:
d496134a 4462 case IFN_LEN_LOAD:
d39f4889 4463 case IFN_LEN_MASK_LOAD:
bfaa08b7
RS
4464 return true;
4465
4466 default:
4467 return false;
4468 }
4469}
4470
f307441a
RS
4471/* Return true if IFN is some form of store to memory. */
4472
4473bool
4474internal_store_fn_p (internal_fn fn)
4475{
4476 switch (fn)
4477 {
4478 case IFN_MASK_STORE:
4479 case IFN_STORE_LANES:
4480 case IFN_MASK_STORE_LANES:
4481 case IFN_SCATTER_STORE:
4482 case IFN_MASK_SCATTER_STORE:
db3efdaf 4483 case IFN_LEN_MASK_SCATTER_STORE:
d496134a 4484 case IFN_LEN_STORE:
d39f4889 4485 case IFN_LEN_MASK_STORE:
f307441a
RS
4486 return true;
4487
4488 default:
4489 return false;
4490 }
4491}
4492
bfaa08b7
RS
4493/* Return true if IFN is some form of gather load or scatter store. */
4494
4495bool
4496internal_gather_scatter_fn_p (internal_fn fn)
4497{
4498 switch (fn)
4499 {
4500 case IFN_GATHER_LOAD:
4501 case IFN_MASK_GATHER_LOAD:
db3efdaf 4502 case IFN_LEN_MASK_GATHER_LOAD:
f307441a
RS
4503 case IFN_SCATTER_STORE:
4504 case IFN_MASK_SCATTER_STORE:
db3efdaf 4505 case IFN_LEN_MASK_SCATTER_STORE:
bfaa08b7
RS
4506 return true;
4507
4508 default:
4509 return false;
4510 }
4511}
4512
b8806f6f
JZZ
4513/* If FN takes a vector len argument, return the index of that argument,
4514 otherwise return -1. */
4515
4516int
4517internal_fn_len_index (internal_fn fn)
4518{
4519 switch (fn)
4520 {
4521 case IFN_LEN_LOAD:
4522 case IFN_LEN_STORE:
4523 case IFN_LEN_MASK_LOAD:
4524 case IFN_LEN_MASK_STORE:
4525 return 2;
4526
db3efdaf
JZZ
4527 case IFN_LEN_MASK_GATHER_LOAD:
4528 case IFN_LEN_MASK_SCATTER_STORE:
34c614b7 4529 return 5;
db3efdaf 4530
b8806f6f
JZZ
4531 default:
4532 return -1;
4533 }
4534}
4535
bfaa08b7
RS
4536/* If FN takes a vector mask argument, return the index of that argument,
4537 otherwise return -1. */
4538
4539int
4540internal_fn_mask_index (internal_fn fn)
4541{
4542 switch (fn)
4543 {
4544 case IFN_MASK_LOAD:
4545 case IFN_MASK_LOAD_LANES:
4546 case IFN_MASK_STORE:
4547 case IFN_MASK_STORE_LANES:
4548 return 2;
4549
4550 case IFN_MASK_GATHER_LOAD:
f307441a 4551 case IFN_MASK_SCATTER_STORE:
d39f4889
JZZ
4552 case IFN_LEN_MASK_LOAD:
4553 case IFN_LEN_MASK_STORE:
db3efdaf
JZZ
4554 case IFN_LEN_MASK_GATHER_LOAD:
4555 case IFN_LEN_MASK_SCATTER_STORE:
34c614b7 4556 return 4;
db3efdaf 4557
f307441a 4558 default:
2c58d42c
RS
4559 return (conditional_internal_fn_code (fn) != ERROR_MARK
4560 || get_unconditional_internal_fn (fn) != IFN_LAST ? 0 : -1);
f307441a
RS
4561 }
4562}
4563
4564/* If FN takes a value that should be stored to memory, return the index
4565 of that argument, otherwise return -1. */
4566
4567int
4568internal_fn_stored_value_index (internal_fn fn)
4569{
4570 switch (fn)
4571 {
4572 case IFN_MASK_STORE:
bd28b730 4573 case IFN_MASK_STORE_LANES:
f307441a
RS
4574 case IFN_SCATTER_STORE:
4575 case IFN_MASK_SCATTER_STORE:
db3efdaf 4576 case IFN_LEN_MASK_SCATTER_STORE:
f307441a
RS
4577 return 3;
4578
b8806f6f 4579 case IFN_LEN_STORE:
d39f4889
JZZ
4580 return 4;
4581
b8806f6f
JZZ
4582 case IFN_LEN_MASK_STORE:
4583 return 5;
4584
bfaa08b7
RS
4585 default:
4586 return -1;
4587 }
4588}
4589
4590/* Return true if the target supports gather load or scatter store function
4591 IFN. For loads, VECTOR_TYPE is the vector type of the load result,
4592 while for stores it is the vector type of the stored data argument.
4593 MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
09eb042a
RS
4594 or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
4595 offset from the shared base address of each loaded or stored element.
4596 SCALE is the amount by which these offsets should be multiplied
4597 *after* they have been extended to address width. */
bfaa08b7
RS
4598
4599bool
4600internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
4601 tree memory_element_type,
09eb042a 4602 tree offset_vector_type, int scale)
bfaa08b7
RS
4603{
4604 if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
4605 TYPE_SIZE (memory_element_type)))
4606 return false;
09eb042a
RS
4607 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
4608 TYPE_VECTOR_SUBPARTS (offset_vector_type)))
4609 return false;
bfaa08b7 4610 optab optab = direct_internal_fn_optab (ifn);
09eb042a
RS
4611 insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
4612 TYPE_MODE (offset_vector_type));
f307441a 4613 int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
09eb042a 4614 bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
bfaa08b7 4615 return (icode != CODE_FOR_nothing
09eb042a
RS
4616 && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
4617 && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
bfaa08b7
RS
4618}
4619
58c036c8
RS
4620/* Return true if the target supports IFN_CHECK_{RAW,WAR}_PTRS function IFN
4621 for pointers of type TYPE when the accesses have LENGTH bytes and their
4622 common byte alignment is ALIGN. */
4623
4624bool
4625internal_check_ptrs_fn_supported_p (internal_fn ifn, tree type,
4626 poly_uint64 length, unsigned int align)
4627{
4628 machine_mode mode = TYPE_MODE (type);
4629 optab optab = direct_internal_fn_optab (ifn);
4630 insn_code icode = direct_optab_handler (optab, mode);
4631 if (icode == CODE_FOR_nothing)
4632 return false;
4633 rtx length_rtx = immed_wide_int_const (length, mode);
4634 return (insn_operand_matches (icode, 3, length_rtx)
4635 && insn_operand_matches (icode, 4, GEN_INT (align)));
4636}
4637
b0e51639
RD
4638/* Return the supported bias for IFN which is either IFN_LEN_LOAD
4639 or IFN_LEN_STORE. For now we only support the biases of 0 and -1
4640 (in case 0 is not an allowable length for len_load or len_store).
4641 If none of the biases match what the backend provides, return
4642 VECT_PARTIAL_BIAS_UNSUPPORTED. */
4643
4644signed char
4645internal_len_load_store_bias (internal_fn ifn, machine_mode mode)
4646{
4647 optab optab = direct_internal_fn_optab (ifn);
4648 insn_code icode = direct_optab_handler (optab, mode);
d39f4889
JZZ
4649
4650 if (icode == CODE_FOR_nothing)
4651 {
4652 machine_mode mask_mode;
4653 if (!targetm.vectorize.get_mask_mode (mode).exists (&mask_mode))
4654 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4655 if (ifn == IFN_LEN_LOAD)
4656 {
4657 /* Try LEN_MASK_LOAD. */
4658 optab = direct_internal_fn_optab (IFN_LEN_MASK_LOAD);
4659 }
4660 else
4661 {
4662 /* Try LEN_MASK_STORE. */
4663 optab = direct_internal_fn_optab (IFN_LEN_MASK_STORE);
4664 }
4665 icode = convert_optab_handler (optab, mode, mask_mode);
d39f4889 4666 }
b0e51639
RD
4667
4668 if (icode != CODE_FOR_nothing)
4669 {
4670 /* For now we only support biases of 0 or -1. Try both of them. */
b8806f6f 4671 if (insn_operand_matches (icode, 3, GEN_INT (0)))
b0e51639 4672 return 0;
b8806f6f 4673 if (insn_operand_matches (icode, 3, GEN_INT (-1)))
b0e51639
RD
4674 return -1;
4675 }
4676
4677 return VECT_PARTIAL_BIAS_UNSUPPORTED;
4678}
4679
4cfe7a6c
RS
4680/* Expand STMT as though it were a call to internal function FN. */
4681
4682void
4683expand_internal_call (internal_fn fn, gcall *stmt)
4684{
4685 internal_fn_expanders[fn] (fn, stmt);
4686}
4687
25583c4f
RS
4688/* Expand STMT, which is a call to internal function FN. */
4689
4690void
538dd0b7 4691expand_internal_call (gcall *stmt)
25583c4f 4692{
4cfe7a6c 4693 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
25583c4f 4694}
1ee62b92 4695
2c58d42c
RS
4696/* If TYPE is a vector type, return true if IFN is a direct internal
4697 function that is supported for that type. If TYPE is a scalar type,
4698 return true if IFN is a direct internal function that is supported for
4699 the target's preferred vector version of TYPE. */
4700
4701bool
4702vectorized_internal_fn_supported_p (internal_fn ifn, tree type)
4703{
0ae469e8
RS
4704 if (VECTOR_MODE_P (TYPE_MODE (type)))
4705 return direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED);
4706
2c58d42c 4707 scalar_mode smode;
72f8d228
RB
4708 if (VECTOR_TYPE_P (type)
4709 || !is_a <scalar_mode> (TYPE_MODE (type), &smode))
0ae469e8
RS
4710 return false;
4711
4712 machine_mode vmode = targetm.vectorize.preferred_simd_mode (smode);
4713 if (VECTOR_MODE_P (vmode))
2c58d42c 4714 {
0ae469e8
RS
4715 tree vectype = build_vector_type_for_mode (type, vmode);
4716 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4717 return true;
2c58d42c
RS
4718 }
4719
0ae469e8
RS
4720 auto_vector_modes vector_modes;
4721 targetm.vectorize.autovectorize_vector_modes (&vector_modes, true);
4722 for (machine_mode base_mode : vector_modes)
4723 if (related_vector_mode (base_mode, smode).exists (&vmode))
4724 {
4725 tree vectype = build_vector_type_for_mode (type, vmode);
4726 if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
4727 return true;
4728 }
4729
4730 return false;
2c58d42c
RS
4731}
4732
ef8176e0
RB
4733void
4734expand_SHUFFLEVECTOR (internal_fn, gcall *)
4735{
4736 gcc_unreachable ();
4737}
4738
1ee62b92
PG
4739void
4740expand_PHI (internal_fn, gcall *)
4741{
463d9108
JJ
4742 gcc_unreachable ();
4743}
4744
4745void
4746expand_SPACESHIP (internal_fn, gcall *stmt)
4747{
4748 tree lhs = gimple_call_lhs (stmt);
4749 tree rhs1 = gimple_call_arg (stmt, 0);
4750 tree rhs2 = gimple_call_arg (stmt, 1);
4751 tree type = TREE_TYPE (rhs1);
4752
526fbcfa
JJ
4753 do_pending_stack_adjust ();
4754
463d9108
JJ
4755 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
4756 rtx op1 = expand_normal (rhs1);
4757 rtx op2 = expand_normal (rhs2);
4758
4759 class expand_operand ops[3];
4760 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (lhs)));
4761 create_input_operand (&ops[1], op1, TYPE_MODE (type));
4762 create_input_operand (&ops[2], op2, TYPE_MODE (type));
4763 insn_code icode = optab_handler (spaceship_optab, TYPE_MODE (type));
4764 expand_insn (icode, 3, ops);
4765 if (!rtx_equal_p (target, ops[0].value))
4766 emit_move_insn (target, ops[0].value);
1ee62b92 4767}
f64eb636 4768
08b51bad
JJ
4769void
4770expand_ASSUME (internal_fn, gcall *)
4771{
08b51bad 4772}
3da77f21
AS
4773
4774void
4775expand_MASK_CALL (internal_fn, gcall *)
4776{
4777 /* This IFN should only exist between ifcvt and vect passes. */
4778 gcc_unreachable ();
4779}