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