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