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