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