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