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