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