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