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