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