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