]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/internal-fn.c
libgo: redirect grep output in mkrsysinfo.sh to /dev/null
[thirdparty/gcc.git] / gcc / internal-fn.c
CommitLineData
25583c4f 1/* Internal functions.
818ab71a 2 Copyright (C) 2011-2016 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"
31e071ae 42#include "ubsan.h"
686ee971 43#include "recog.h"
adedd5c1 44#include "builtins.h"
25583c4f
RS
45
46/* The names of each internal function, indexed by function number. */
47const char *const internal_fn_name_array[] = {
b78475cf 48#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
25583c4f 49#include "internal-fn.def"
25583c4f
RS
50 "<invalid-fn>"
51};
52
53/* The ECF_* flags of each internal function, indexed by function number. */
54const int internal_fn_flags_array[] = {
b78475cf 55#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
25583c4f 56#include "internal-fn.def"
25583c4f
RS
57 0
58};
59
b78475cf
YG
60/* Fnspec of each internal function, indexed by function number. */
61const_tree internal_fn_fnspec_array[IFN_LAST + 1];
62
63void
64init_internal_fns ()
65{
66#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
67 if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
63a4184f 68 build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
b78475cf 69#include "internal-fn.def"
b78475cf
YG
70 internal_fn_fnspec_array[IFN_LAST] = 0;
71}
72
ab23f5d9
RS
73/* Create static initializers for the information returned by
74 direct_internal_fn. */
70439f0d
RS
75#define not_direct { -2, -2, false }
76#define mask_load_direct { -1, 2, false }
77#define load_lanes_direct { -1, -1, false }
78#define mask_store_direct { 3, 2, false }
79#define store_lanes_direct { 0, 0, false }
80#define unary_direct { 0, 0, true }
81#define binary_direct { 0, 0, true }
ab23f5d9
RS
82
83const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
84#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
85#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) TYPE##_direct,
86#include "internal-fn.def"
87 not_direct
88};
89
272c6793 90/* ARRAY_TYPE is an array of vector modes. Return the associated insn
ab23f5d9 91 for load-lanes-style optab OPTAB, or CODE_FOR_nothing if none. */
272c6793
RS
92
93static enum insn_code
94get_multi_vector_move (tree array_type, convert_optab optab)
95{
ef4bddc2
RS
96 machine_mode imode;
97 machine_mode vmode;
272c6793
RS
98
99 gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
100 imode = TYPE_MODE (array_type);
101 vmode = TYPE_MODE (TREE_TYPE (array_type));
102
ab23f5d9 103 return convert_optab_handler (optab, imode, vmode);
272c6793
RS
104}
105
ab23f5d9 106/* Expand LOAD_LANES call STMT using optab OPTAB. */
272c6793
RS
107
108static void
4cfe7a6c 109expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
272c6793
RS
110{
111 struct expand_operand ops[2];
112 tree type, lhs, rhs;
113 rtx target, mem;
114
115 lhs = gimple_call_lhs (stmt);
116 rhs = gimple_call_arg (stmt, 0);
117 type = TREE_TYPE (lhs);
118
119 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
120 mem = expand_normal (rhs);
121
122 gcc_assert (MEM_P (mem));
123 PUT_MODE (mem, TYPE_MODE (type));
124
125 create_output_operand (&ops[0], target, TYPE_MODE (type));
126 create_fixed_operand (&ops[1], mem);
ab23f5d9 127 expand_insn (get_multi_vector_move (type, optab), 2, ops);
272c6793
RS
128}
129
ab23f5d9 130/* Expand STORE_LANES call STMT using optab OPTAB. */
272c6793
RS
131
132static void
4cfe7a6c 133expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
272c6793
RS
134{
135 struct expand_operand ops[2];
136 tree type, lhs, rhs;
137 rtx target, reg;
138
139 lhs = gimple_call_lhs (stmt);
140 rhs = gimple_call_arg (stmt, 0);
141 type = TREE_TYPE (rhs);
142
143 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
144 reg = expand_normal (rhs);
145
146 gcc_assert (MEM_P (target));
147 PUT_MODE (target, TYPE_MODE (type));
148
149 create_fixed_operand (&ops[0], target);
150 create_input_operand (&ops[1], reg, TYPE_MODE (type));
ab23f5d9 151 expand_insn (get_multi_vector_move (type, optab), 2, ops);
272c6793
RS
152}
153
8170608b 154static void
4cfe7a6c 155expand_ANNOTATE (internal_fn, gcall *)
8170608b
TB
156{
157 gcc_unreachable ();
158}
159
74bf76ed
JJ
160/* This should get expanded in adjust_simduid_builtins. */
161
162static void
4cfe7a6c 163expand_GOMP_SIMD_LANE (internal_fn, gcall *)
74bf76ed
JJ
164{
165 gcc_unreachable ();
166}
167
168/* This should get expanded in adjust_simduid_builtins. */
169
170static void
4cfe7a6c 171expand_GOMP_SIMD_VF (internal_fn, gcall *)
74bf76ed
JJ
172{
173 gcc_unreachable ();
174}
175
176/* This should get expanded in adjust_simduid_builtins. */
177
178static void
4cfe7a6c 179expand_GOMP_SIMD_LAST_LANE (internal_fn, gcall *)
74bf76ed
JJ
180{
181 gcc_unreachable ();
182}
183
d9a6bd32
JJ
184/* This should get expanded in adjust_simduid_builtins. */
185
186static void
4cfe7a6c 187expand_GOMP_SIMD_ORDERED_START (internal_fn, gcall *)
d9a6bd32
JJ
188{
189 gcc_unreachable ();
190}
191
192/* This should get expanded in adjust_simduid_builtins. */
193
194static void
4cfe7a6c 195expand_GOMP_SIMD_ORDERED_END (internal_fn, gcall *)
d9a6bd32
JJ
196{
197 gcc_unreachable ();
198}
199
b9a55b13
MP
200/* This should get expanded in the sanopt pass. */
201
202static void
4cfe7a6c 203expand_UBSAN_NULL (internal_fn, gcall *)
b9a55b13
MP
204{
205 gcc_unreachable ();
206}
207
0e37a2f3
MP
208/* This should get expanded in the sanopt pass. */
209
210static void
4cfe7a6c 211expand_UBSAN_BOUNDS (internal_fn, gcall *)
0e82f089
MP
212{
213 gcc_unreachable ();
214}
215
216/* This should get expanded in the sanopt pass. */
217
218static void
4cfe7a6c 219expand_UBSAN_VPTR (internal_fn, gcall *)
0e37a2f3
MP
220{
221 gcc_unreachable ();
222}
223
c62ccb9a
YG
224/* This should get expanded in the sanopt pass. */
225
226static void
4cfe7a6c 227expand_UBSAN_OBJECT_SIZE (internal_fn, gcall *)
35228ac7
JJ
228{
229 gcc_unreachable ();
230}
231
232/* This should get expanded in the sanopt pass. */
233
234static void
4cfe7a6c 235expand_ASAN_CHECK (internal_fn, gcall *)
c62ccb9a
YG
236{
237 gcc_unreachable ();
238}
239
fca4adf2
JJ
240/* This should get expanded in the tsan pass. */
241
242static void
4cfe7a6c 243expand_TSAN_FUNC_EXIT (internal_fn, gcall *)
fca4adf2
JJ
244{
245 gcc_unreachable ();
246}
247
81fea426
MP
248/* This should get expanded in the lower pass. */
249
250static void
251expand_FALLTHROUGH (internal_fn, gcall *call)
252{
253 error_at (gimple_location (call),
254 "invalid use of attribute %<fallthrough%>");
255}
256
1304953e
JJ
257/* Helper function for expand_addsub_overflow. Return 1
258 if ARG interpreted as signed in its precision is known to be always
259 positive or 2 if ARG is known to be always negative, or 3 if ARG may
260 be positive or negative. */
261
262static int
263get_range_pos_neg (tree arg)
264{
265 if (arg == error_mark_node)
266 return 3;
267
268 int prec = TYPE_PRECISION (TREE_TYPE (arg));
269 int cnt = 0;
270 if (TREE_CODE (arg) == INTEGER_CST)
271 {
272 wide_int w = wi::sext (arg, prec);
273 if (wi::neg_p (w))
274 return 2;
275 else
276 return 1;
277 }
278 while (CONVERT_EXPR_P (arg)
279 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
280 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
281 {
282 arg = TREE_OPERAND (arg, 0);
283 /* Narrower value zero extended into wider type
284 will always result in positive values. */
285 if (TYPE_UNSIGNED (TREE_TYPE (arg))
286 && TYPE_PRECISION (TREE_TYPE (arg)) < prec)
287 return 1;
288 prec = TYPE_PRECISION (TREE_TYPE (arg));
289 if (++cnt > 30)
290 return 3;
291 }
292
293 if (TREE_CODE (arg) != SSA_NAME)
294 return 3;
295 wide_int arg_min, arg_max;
296 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
297 {
355fe088 298 gimple *g = SSA_NAME_DEF_STMT (arg);
1304953e
JJ
299 if (is_gimple_assign (g)
300 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
301 {
302 tree t = gimple_assign_rhs1 (g);
303 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
304 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
305 {
306 if (TYPE_UNSIGNED (TREE_TYPE (t))
307 && TYPE_PRECISION (TREE_TYPE (t)) < prec)
308 return 1;
309 prec = TYPE_PRECISION (TREE_TYPE (t));
310 arg = t;
311 if (++cnt > 30)
312 return 3;
313 continue;
314 }
315 }
316 return 3;
317 }
318 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
319 {
320 /* For unsigned values, the "positive" range comes
321 below the "negative" range. */
322 if (!wi::neg_p (wi::sext (arg_max, prec), SIGNED))
323 return 1;
324 if (wi::neg_p (wi::sext (arg_min, prec), SIGNED))
325 return 2;
326 }
327 else
328 {
329 if (!wi::neg_p (wi::sext (arg_min, prec), SIGNED))
330 return 1;
331 if (wi::neg_p (wi::sext (arg_max, prec), SIGNED))
332 return 2;
333 }
334 return 3;
335}
336
337/* Return minimum precision needed to represent all values
338 of ARG in SIGNed integral type. */
339
340static int
341get_min_precision (tree arg, signop sign)
342{
343 int prec = TYPE_PRECISION (TREE_TYPE (arg));
344 int cnt = 0;
345 signop orig_sign = sign;
346 if (TREE_CODE (arg) == INTEGER_CST)
347 {
348 int p;
349 if (TYPE_SIGN (TREE_TYPE (arg)) != sign)
350 {
351 widest_int w = wi::to_widest (arg);
352 w = wi::ext (w, prec, sign);
353 p = wi::min_precision (w, sign);
354 }
355 else
356 p = wi::min_precision (arg, sign);
357 return MIN (p, prec);
358 }
359 while (CONVERT_EXPR_P (arg)
360 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
361 && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) <= prec)
362 {
363 arg = TREE_OPERAND (arg, 0);
364 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
365 {
366 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
367 sign = UNSIGNED;
368 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
369 return prec + (orig_sign != sign);
370 prec = TYPE_PRECISION (TREE_TYPE (arg));
371 }
372 if (++cnt > 30)
373 return prec + (orig_sign != sign);
374 }
375 if (TREE_CODE (arg) != SSA_NAME)
376 return prec + (orig_sign != sign);
377 wide_int arg_min, arg_max;
378 while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
379 {
355fe088 380 gimple *g = SSA_NAME_DEF_STMT (arg);
1304953e
JJ
381 if (is_gimple_assign (g)
382 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (g)))
383 {
384 tree t = gimple_assign_rhs1 (g);
385 if (INTEGRAL_TYPE_P (TREE_TYPE (t))
386 && TYPE_PRECISION (TREE_TYPE (t)) <= prec)
387 {
388 arg = t;
389 if (TYPE_PRECISION (TREE_TYPE (arg)) < prec)
390 {
391 if (TYPE_UNSIGNED (TREE_TYPE (arg)))
392 sign = UNSIGNED;
393 else if (sign == UNSIGNED && get_range_pos_neg (arg) != 1)
394 return prec + (orig_sign != sign);
395 prec = TYPE_PRECISION (TREE_TYPE (arg));
396 }
397 if (++cnt > 30)
398 return prec + (orig_sign != sign);
399 continue;
400 }
401 }
402 return prec + (orig_sign != sign);
403 }
404 if (sign == TYPE_SIGN (TREE_TYPE (arg)))
405 {
406 int p1 = wi::min_precision (arg_min, sign);
407 int p2 = wi::min_precision (arg_max, sign);
408 p1 = MAX (p1, p2);
409 prec = MIN (prec, p1);
410 }
411 else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
412 {
c1ee2e62 413 int p = wi::min_precision (arg_max, UNSIGNED);
1304953e
JJ
414 prec = MIN (prec, p);
415 }
416 return prec + (orig_sign != sign);
417}
418
a86451b9
JJ
419/* Helper for expand_*_overflow. Set the __imag__ part to true
420 (1 except for signed:1 type, in which case store -1). */
421
422static void
423expand_arith_set_overflow (tree lhs, rtx target)
424{
425 if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
426 && !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
427 write_complex_part (target, constm1_rtx, true);
428 else
429 write_complex_part (target, const1_rtx, true);
430}
431
1304953e
JJ
432/* Helper for expand_*_overflow. Store RES into the __real__ part
433 of TARGET. If RES has larger MODE than __real__ part of TARGET,
a86451b9
JJ
434 set the __imag__ part to 1 if RES doesn't fit into it. Similarly
435 if LHS has smaller precision than its mode. */
1304953e
JJ
436
437static void
438expand_arith_overflow_result_store (tree lhs, rtx target,
439 machine_mode mode, rtx res)
440{
441 machine_mode tgtmode = GET_MODE_INNER (GET_MODE (target));
442 rtx lres = res;
443 if (tgtmode != mode)
444 {
445 rtx_code_label *done_label = gen_label_rtx ();
446 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
447 lres = convert_modes (tgtmode, mode, res, uns);
448 gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
92344ed0 449 do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
1476d1bd 450 EQ, true, mode, NULL_RTX, NULL, done_label,
1304953e 451 PROB_VERY_LIKELY);
a86451b9
JJ
452 expand_arith_set_overflow (lhs, target);
453 emit_label (done_label);
454 }
455 int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
456 int tgtprec = GET_MODE_PRECISION (tgtmode);
457 if (prec < tgtprec)
458 {
459 rtx_code_label *done_label = gen_label_rtx ();
460 int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
461 res = lres;
462 if (uns)
463 {
464 rtx mask
465 = immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
466 tgtmode);
467 lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
95ef39f4 468 true, OPTAB_LIB_WIDEN);
a86451b9
JJ
469 }
470 else
471 {
472 lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
473 NULL_RTX, 1);
474 lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
475 NULL_RTX, 0);
476 }
477 do_compare_rtx_and_jump (res, lres,
478 EQ, true, tgtmode, NULL_RTX, NULL, done_label,
479 PROB_VERY_LIKELY);
480 expand_arith_set_overflow (lhs, target);
1304953e
JJ
481 emit_label (done_label);
482 }
483 write_complex_part (target, lres, false);
484}
485
5620052d
JJ
486/* Helper for expand_*_overflow. Store RES into TARGET. */
487
488static void
489expand_ubsan_result_store (rtx target, rtx res)
490{
491 if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
492 /* If this is a scalar in a register that is stored in a wider mode
493 than the declared mode, compute the result into its declared mode
494 and then convert to the wider mode. Our value is the computed
495 expression. */
496 convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target));
497 else
498 emit_move_insn (target, res);
499}
500
31e071ae
MP
501/* Add sub/add overflow checking to the statement STMT.
502 CODE says whether the operation is +, or -. */
503
1304953e
JJ
504static void
505expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
506 tree arg0, tree arg1, bool unsr_p, bool uns0_p,
507 bool uns1_p, bool is_ubsan)
31e071ae 508{
1304953e
JJ
509 rtx res, target = NULL_RTX;
510 tree fn;
511 rtx_code_label *done_label = gen_label_rtx ();
512 rtx_code_label *do_error = gen_label_rtx ();
31e071ae 513 do_pending_stack_adjust ();
1304953e
JJ
514 rtx op0 = expand_normal (arg0);
515 rtx op1 = expand_normal (arg1);
ef4bddc2 516 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1304953e
JJ
517 int prec = GET_MODE_PRECISION (mode);
518 rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
519 bool do_xor = false;
520
521 if (is_ubsan)
522 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
523
31e071ae 524 if (lhs)
1304953e
JJ
525 {
526 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
527 if (!is_ubsan)
528 write_complex_part (target, const0_rtx, true);
529 }
530
531 /* We assume both operands and result have the same precision
532 here (GET_MODE_BITSIZE (mode)), S stands for signed type
533 with that precision, U for unsigned type with that precision,
534 sgn for unsigned most significant bit in that precision.
535 s1 is signed first operand, u1 is unsigned first operand,
536 s2 is signed second operand, u2 is unsigned second operand,
537 sr is signed result, ur is unsigned result and the following
538 rules say how to compute result (which is always result of
539 the operands as if both were unsigned, cast to the right
540 signedness) and how to compute whether operation overflowed.
541
542 s1 + s2 -> sr
543 res = (S) ((U) s1 + (U) s2)
544 ovf = s2 < 0 ? res > s1 : res < s1 (or jump on overflow)
545 s1 - s2 -> sr
546 res = (S) ((U) s1 - (U) s2)
547 ovf = s2 < 0 ? res < s1 : res > s2 (or jump on overflow)
548 u1 + u2 -> ur
549 res = u1 + u2
550 ovf = res < u1 (or jump on carry, but RTL opts will handle it)
551 u1 - u2 -> ur
552 res = u1 - u2
553 ovf = res > u1 (or jump on carry, but RTL opts will handle it)
554 s1 + u2 -> sr
555 res = (S) ((U) s1 + u2)
556 ovf = ((U) res ^ sgn) < u2
557 s1 + u2 -> ur
558 t1 = (S) (u2 ^ sgn)
559 t2 = s1 + t1
560 res = (U) t2 ^ sgn
561 ovf = t1 < 0 ? t2 > s1 : t2 < s1 (or jump on overflow)
562 s1 - u2 -> sr
563 res = (S) ((U) s1 - u2)
564 ovf = u2 > ((U) s1 ^ sgn)
565 s1 - u2 -> ur
566 res = (U) s1 - u2
567 ovf = s1 < 0 || u2 > (U) s1
568 u1 - s2 -> sr
569 res = u1 - (U) s2
570 ovf = u1 >= ((U) s2 ^ sgn)
571 u1 - s2 -> ur
572 t1 = u1 ^ sgn
573 t2 = t1 - (U) s2
574 res = t2 ^ sgn
575 ovf = s2 < 0 ? (S) t2 < (S) t1 : (S) t2 > (S) t1 (or jump on overflow)
576 s1 + s2 -> ur
577 res = (U) s1 + (U) s2
578 ovf = s2 < 0 ? (s1 | (S) res) < 0) : (s1 & (S) res) < 0)
579 u1 + u2 -> sr
580 res = (S) (u1 + u2)
581 ovf = (U) res < u2 || res < 0
582 u1 - u2 -> sr
583 res = (S) (u1 - u2)
584 ovf = u1 >= u2 ? res < 0 : res >= 0
585 s1 - s2 -> ur
586 res = (U) s1 - (U) s2
587 ovf = s2 >= 0 ? ((s1 | (S) res) < 0) : ((s1 & (S) res) < 0) */
588
589 if (code == PLUS_EXPR && uns0_p && !uns1_p)
590 {
591 /* PLUS_EXPR is commutative, if operand signedness differs,
592 canonicalize to the first operand being signed and second
593 unsigned to simplify following code. */
6b4db501
MM
594 std::swap (op0, op1);
595 std::swap (arg0, arg1);
596 uns0_p = false;
597 uns1_p = true;
1304953e
JJ
598 }
599
600 /* u1 +- u2 -> ur */
601 if (uns0_p && uns1_p && unsr_p)
602 {
cde9d596
RH
603 insn_code icode = optab_handler (code == PLUS_EXPR ? uaddv4_optab
604 : usubv4_optab, mode);
605 if (icode != CODE_FOR_nothing)
606 {
607 struct expand_operand ops[4];
608 rtx_insn *last = get_last_insn ();
609
610 res = gen_reg_rtx (mode);
611 create_output_operand (&ops[0], res, mode);
612 create_input_operand (&ops[1], op0, mode);
613 create_input_operand (&ops[2], op1, mode);
614 create_fixed_operand (&ops[3], do_error);
615 if (maybe_expand_insn (icode, 4, ops))
616 {
617 last = get_last_insn ();
618 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
619 && JUMP_P (last)
620 && any_condjump_p (last)
621 && !find_reg_note (last, REG_BR_PROB, 0))
622 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
623 emit_jump (done_label);
624 goto do_error_label;
625 }
626
627 delete_insns_since (last);
628 }
629
1304953e
JJ
630 /* Compute the operation. On RTL level, the addition is always
631 unsigned. */
632 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
633 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
634 rtx tem = op0;
635 /* For PLUS_EXPR, the operation is commutative, so we can pick
636 operand to compare against. For prec <= BITS_PER_WORD, I think
637 preferring REG operand is better over CONST_INT, because
638 the CONST_INT might enlarge the instruction or CSE would need
639 to figure out we'd already loaded it into a register before.
640 For prec > BITS_PER_WORD, I think CONST_INT might be more beneficial,
641 as then the multi-word comparison can be perhaps simplified. */
642 if (code == PLUS_EXPR
643 && (prec <= BITS_PER_WORD
644 ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
645 : CONST_SCALAR_INT_P (op1)))
646 tem = op1;
92344ed0 647 do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
1476d1bd 648 true, mode, NULL_RTX, NULL, done_label,
1304953e
JJ
649 PROB_VERY_LIKELY);
650 goto do_error_label;
651 }
652
653 /* s1 +- u2 -> sr */
654 if (!uns0_p && uns1_p && !unsr_p)
655 {
656 /* Compute the operation. On RTL level, the addition is always
657 unsigned. */
658 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
659 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
660 rtx tem = expand_binop (mode, add_optab,
661 code == PLUS_EXPR ? res : op0, sgn,
662 NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd 663 do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
664 done_label, PROB_VERY_LIKELY);
665 goto do_error_label;
666 }
667
668 /* s1 + u2 -> ur */
669 if (code == PLUS_EXPR && !uns0_p && uns1_p && unsr_p)
670 {
671 op1 = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
672 OPTAB_LIB_WIDEN);
673 /* As we've changed op1, we have to avoid using the value range
674 for the original argument. */
675 arg1 = error_mark_node;
676 do_xor = true;
677 goto do_signed;
678 }
679
680 /* u1 - s2 -> ur */
681 if (code == MINUS_EXPR && uns0_p && !uns1_p && unsr_p)
682 {
683 op0 = expand_binop (mode, add_optab, op0, sgn, NULL_RTX, false,
684 OPTAB_LIB_WIDEN);
685 /* As we've changed op0, we have to avoid using the value range
686 for the original argument. */
687 arg0 = error_mark_node;
688 do_xor = true;
689 goto do_signed;
690 }
691
692 /* s1 - u2 -> ur */
693 if (code == MINUS_EXPR && !uns0_p && uns1_p && unsr_p)
694 {
695 /* Compute the operation. On RTL level, the addition is always
696 unsigned. */
697 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
698 OPTAB_LIB_WIDEN);
699 int pos_neg = get_range_pos_neg (arg0);
700 if (pos_neg == 2)
701 /* If ARG0 is known to be always negative, this is always overflow. */
702 emit_jump (do_error);
703 else if (pos_neg == 3)
704 /* If ARG0 is not known to be always positive, check at runtime. */
92344ed0 705 do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd
MM
706 NULL, do_error, PROB_VERY_UNLIKELY);
707 do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
708 done_label, PROB_VERY_LIKELY);
709 goto do_error_label;
710 }
711
712 /* u1 - s2 -> sr */
713 if (code == MINUS_EXPR && uns0_p && !uns1_p && !unsr_p)
714 {
715 /* Compute the operation. On RTL level, the addition is always
716 unsigned. */
717 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
718 OPTAB_LIB_WIDEN);
719 rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
720 OPTAB_LIB_WIDEN);
1476d1bd 721 do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
1304953e
JJ
722 done_label, PROB_VERY_LIKELY);
723 goto do_error_label;
724 }
725
726 /* u1 + u2 -> sr */
727 if (code == PLUS_EXPR && uns0_p && uns1_p && !unsr_p)
728 {
729 /* Compute the operation. On RTL level, the addition is always
730 unsigned. */
731 res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
732 OPTAB_LIB_WIDEN);
92344ed0 733 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 734 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
735 rtx tem = op1;
736 /* The operation is commutative, so we can pick operand to compare
737 against. For prec <= BITS_PER_WORD, I think preferring REG operand
738 is better over CONST_INT, because the CONST_INT might enlarge the
739 instruction or CSE would need to figure out we'd already loaded it
740 into a register before. For prec > BITS_PER_WORD, I think CONST_INT
741 might be more beneficial, as then the multi-word comparison can be
742 perhaps simplified. */
743 if (prec <= BITS_PER_WORD
744 ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
745 : CONST_SCALAR_INT_P (op0))
746 tem = op0;
1476d1bd 747 do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
1304953e
JJ
748 done_label, PROB_VERY_LIKELY);
749 goto do_error_label;
750 }
751
752 /* s1 +- s2 -> ur */
753 if (!uns0_p && !uns1_p && unsr_p)
754 {
755 /* Compute the operation. On RTL level, the addition is always
756 unsigned. */
757 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
758 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
759 int pos_neg = get_range_pos_neg (arg1);
760 if (code == PLUS_EXPR)
761 {
762 int pos_neg0 = get_range_pos_neg (arg0);
763 if (pos_neg0 != 3 && pos_neg == 3)
764 {
6b4db501 765 std::swap (op0, op1);
1304953e
JJ
766 pos_neg = pos_neg0;
767 }
768 }
769 rtx tem;
770 if (pos_neg != 3)
771 {
772 tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
773 ? and_optab : ior_optab,
774 op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
1476d1bd
MM
775 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
776 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
777 }
778 else
779 {
780 rtx_code_label *do_ior_label = gen_label_rtx ();
92344ed0
JJ
781 do_compare_rtx_and_jump (op1, const0_rtx,
782 code == MINUS_EXPR ? GE : LT, false, mode,
1476d1bd 783 NULL_RTX, NULL, do_ior_label,
92344ed0 784 PROB_EVEN);
1304953e
JJ
785 tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
786 OPTAB_LIB_WIDEN);
92344ed0 787 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 788 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
789 emit_jump (do_error);
790 emit_label (do_ior_label);
791 tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
792 OPTAB_LIB_WIDEN);
92344ed0 793 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 794 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
795 }
796 goto do_error_label;
797 }
798
799 /* u1 - u2 -> sr */
800 if (code == MINUS_EXPR && uns0_p && uns1_p && !unsr_p)
801 {
802 /* Compute the operation. On RTL level, the addition is always
803 unsigned. */
804 res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
805 OPTAB_LIB_WIDEN);
806 rtx_code_label *op0_geu_op1 = gen_label_rtx ();
1476d1bd 807 do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
1304953e 808 op0_geu_op1, PROB_EVEN);
92344ed0 809 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
1476d1bd 810 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
811 emit_jump (do_error);
812 emit_label (op0_geu_op1);
92344ed0 813 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 814 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
815 goto do_error_label;
816 }
31e071ae 817
1304953e
JJ
818 gcc_assert (!uns0_p && !uns1_p && !unsr_p);
819
820 /* s1 +- s2 -> sr */
cde9d596
RH
821 do_signed:
822 {
823 insn_code icode = optab_handler (code == PLUS_EXPR ? addv4_optab
824 : subv4_optab, mode);
825 if (icode != CODE_FOR_nothing)
826 {
827 struct expand_operand ops[4];
828 rtx_insn *last = get_last_insn ();
829
830 res = gen_reg_rtx (mode);
831 create_output_operand (&ops[0], res, mode);
832 create_input_operand (&ops[1], op0, mode);
833 create_input_operand (&ops[2], op1, mode);
834 create_fixed_operand (&ops[3], do_error);
835 if (maybe_expand_insn (icode, 4, ops))
836 {
837 last = get_last_insn ();
838 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
839 && JUMP_P (last)
840 && any_condjump_p (last)
841 && !find_reg_note (last, REG_BR_PROB, 0))
842 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
843 emit_jump (done_label);
844 goto do_error_label;
845 }
846
847 delete_insns_since (last);
848 }
849
850 rtx_code_label *sub_check = gen_label_rtx ();
851 int pos_neg = 3;
852
853 /* Compute the operation. On RTL level, the addition is always
854 unsigned. */
855 res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
856 op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
857
858 /* If we can prove one of the arguments (for MINUS_EXPR only
859 the second operand, as subtraction is not commutative) is always
860 non-negative or always negative, we can do just one comparison
861 and conditional jump instead of 2 at runtime, 3 present in the
862 emitted code. If one of the arguments is CONST_INT, all we
863 need is to make sure it is op1, then the first
864 do_compare_rtx_and_jump will be just folded. Otherwise try
865 to use range info if available. */
866 if (code == PLUS_EXPR && CONST_INT_P (op0))
867 std::swap (op0, op1);
868 else if (CONST_INT_P (op1))
869 ;
870 else if (code == PLUS_EXPR && TREE_CODE (arg0) == SSA_NAME)
871 {
872 pos_neg = get_range_pos_neg (arg0);
873 if (pos_neg != 3)
874 std::swap (op0, op1);
875 }
876 if (pos_neg == 3 && !CONST_INT_P (op1) && TREE_CODE (arg1) == SSA_NAME)
877 pos_neg = get_range_pos_neg (arg1);
878
879 /* If the op1 is negative, we have to use a different check. */
880 if (pos_neg == 3)
881 do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
882 NULL, sub_check, PROB_EVEN);
883
884 /* Compare the result of the operation with one of the operands. */
885 if (pos_neg & 1)
886 do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
887 false, mode, NULL_RTX, NULL, done_label,
888 PROB_VERY_LIKELY);
97286431 889
cde9d596
RH
890 /* If we get here, we have to print the error. */
891 if (pos_neg == 3)
892 {
893 emit_jump (do_error);
894 emit_label (sub_check);
895 }
31e071ae 896
cde9d596
RH
897 /* We have k = a + b for b < 0 here. k <= a must hold. */
898 if (pos_neg & 2)
899 do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
900 false, mode, NULL_RTX, NULL, done_label,
901 PROB_VERY_LIKELY);
902 }
31e071ae 903
1304953e 904 do_error_label:
1769415d 905 emit_label (do_error);
1304953e
JJ
906 if (is_ubsan)
907 {
908 /* Expand the ubsan builtin call. */
909 push_temp_slots ();
910 fn = ubsan_build_overflow_builtin (code, loc, TREE_TYPE (arg0),
911 arg0, arg1);
912 expand_normal (fn);
913 pop_temp_slots ();
914 do_pending_stack_adjust ();
915 }
916 else if (lhs)
a86451b9 917 expand_arith_set_overflow (lhs, target);
31e071ae 918
1769415d
MP
919 /* We're done. */
920 emit_label (done_label);
31e071ae
MP
921
922 if (lhs)
1304953e
JJ
923 {
924 if (is_ubsan)
5620052d 925 expand_ubsan_result_store (target, res);
1304953e
JJ
926 else
927 {
928 if (do_xor)
929 res = expand_binop (mode, add_optab, res, sgn, NULL_RTX, false,
930 OPTAB_LIB_WIDEN);
931
932 expand_arith_overflow_result_store (lhs, target, mode, res);
933 }
934 }
31e071ae
MP
935}
936
937/* Add negate overflow checking to the statement STMT. */
938
1304953e
JJ
939static void
940expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan)
31e071ae
MP
941{
942 rtx res, op1;
1304953e 943 tree fn;
da664544
DM
944 rtx_code_label *done_label, *do_error;
945 rtx target = NULL_RTX;
31e071ae 946
31e071ae
MP
947 done_label = gen_label_rtx ();
948 do_error = gen_label_rtx ();
31e071ae
MP
949
950 do_pending_stack_adjust ();
951 op1 = expand_normal (arg1);
952
ef4bddc2 953 machine_mode mode = TYPE_MODE (TREE_TYPE (arg1));
31e071ae 954 if (lhs)
1304953e
JJ
955 {
956 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
957 if (!is_ubsan)
958 write_complex_part (target, const0_rtx, true);
959 }
31e071ae
MP
960
961 enum insn_code icode = optab_handler (negv3_optab, mode);
962 if (icode != CODE_FOR_nothing)
963 {
964 struct expand_operand ops[3];
da664544 965 rtx_insn *last = get_last_insn ();
31e071ae
MP
966
967 res = gen_reg_rtx (mode);
968 create_output_operand (&ops[0], res, mode);
969 create_input_operand (&ops[1], op1, mode);
970 create_fixed_operand (&ops[2], do_error);
971 if (maybe_expand_insn (icode, 3, ops))
972 {
973 last = get_last_insn ();
0a6a6ac9 974 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
975 && JUMP_P (last)
976 && any_condjump_p (last)
977 && !find_reg_note (last, REG_BR_PROB, 0))
978 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
979 emit_jump (done_label);
980 }
981 else
982 {
983 delete_insns_since (last);
984 icode = CODE_FOR_nothing;
985 }
986 }
987
988 if (icode == CODE_FOR_nothing)
989 {
990 /* Compute the operation. On RTL level, the addition is always
991 unsigned. */
992 res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
993
994 /* Compare the operand with the most negative value. */
995 rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
1476d1bd 996 do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
31e071ae
MP
997 done_label, PROB_VERY_LIKELY);
998 }
999
1000 emit_label (do_error);
1304953e
JJ
1001 if (is_ubsan)
1002 {
1003 /* Expand the ubsan builtin call. */
1004 push_temp_slots ();
1005 fn = ubsan_build_overflow_builtin (NEGATE_EXPR, loc, TREE_TYPE (arg1),
1006 arg1, NULL_TREE);
1007 expand_normal (fn);
1008 pop_temp_slots ();
1009 do_pending_stack_adjust ();
1010 }
1011 else if (lhs)
a86451b9 1012 expand_arith_set_overflow (lhs, target);
31e071ae
MP
1013
1014 /* We're done. */
1015 emit_label (done_label);
1016
1017 if (lhs)
1304953e
JJ
1018 {
1019 if (is_ubsan)
5620052d 1020 expand_ubsan_result_store (target, res);
1304953e
JJ
1021 else
1022 expand_arith_overflow_result_store (lhs, target, mode, res);
1023 }
31e071ae
MP
1024}
1025
1026/* Add mul overflow checking to the statement STMT. */
1027
1304953e
JJ
1028static void
1029expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
1030 bool unsr_p, bool uns0_p, bool uns1_p, bool is_ubsan)
31e071ae
MP
1031{
1032 rtx res, op0, op1;
1304953e 1033 tree fn, type;
da664544
DM
1034 rtx_code_label *done_label, *do_error;
1035 rtx target = NULL_RTX;
1304953e
JJ
1036 signop sign;
1037 enum insn_code icode;
31e071ae 1038
31e071ae
MP
1039 done_label = gen_label_rtx ();
1040 do_error = gen_label_rtx ();
31e071ae
MP
1041
1042 do_pending_stack_adjust ();
1043 op0 = expand_normal (arg0);
1044 op1 = expand_normal (arg1);
1045
ef4bddc2 1046 machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
1304953e 1047 bool uns = unsr_p;
31e071ae 1048 if (lhs)
1304953e
JJ
1049 {
1050 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1051 if (!is_ubsan)
1052 write_complex_part (target, const0_rtx, true);
1053 }
1054
1055 if (is_ubsan)
1056 gcc_assert (!unsr_p && !uns0_p && !uns1_p);
1057
1058 /* We assume both operands and result have the same precision
1059 here (GET_MODE_BITSIZE (mode)), S stands for signed type
1060 with that precision, U for unsigned type with that precision,
1061 sgn for unsigned most significant bit in that precision.
1062 s1 is signed first operand, u1 is unsigned first operand,
1063 s2 is signed second operand, u2 is unsigned second operand,
1064 sr is signed result, ur is unsigned result and the following
1065 rules say how to compute result (which is always result of
1066 the operands as if both were unsigned, cast to the right
1067 signedness) and how to compute whether operation overflowed.
1068 main_ovf (false) stands for jump on signed multiplication
1069 overflow or the main algorithm with uns == false.
1070 main_ovf (true) stands for jump on unsigned multiplication
1071 overflow or the main algorithm with uns == true.
1072
1073 s1 * s2 -> sr
1074 res = (S) ((U) s1 * (U) s2)
1075 ovf = main_ovf (false)
1076 u1 * u2 -> ur
1077 res = u1 * u2
1078 ovf = main_ovf (true)
1079 s1 * u2 -> ur
1080 res = (U) s1 * u2
1081 ovf = (s1 < 0 && u2) || main_ovf (true)
1082 u1 * u2 -> sr
1083 res = (S) (u1 * u2)
1084 ovf = res < 0 || main_ovf (true)
1085 s1 * u2 -> sr
1086 res = (S) ((U) s1 * u2)
1087 ovf = (S) u2 >= 0 ? main_ovf (false)
1088 : (s1 != 0 && (s1 != -1 || u2 != (U) res))
1089 s1 * s2 -> ur
1090 t1 = (s1 & s2) < 0 ? (-(U) s1) : ((U) s1)
1091 t2 = (s1 & s2) < 0 ? (-(U) s2) : ((U) s2)
1092 res = t1 * t2
1093 ovf = (s1 ^ s2) < 0 ? (s1 && s2) : main_ovf (true) */
1094
1095 if (uns0_p && !uns1_p)
1096 {
1097 /* Multiplication is commutative, if operand signedness differs,
1098 canonicalize to the first operand being signed and second
1099 unsigned to simplify following code. */
6b4db501
MM
1100 std::swap (op0, op1);
1101 std::swap (arg0, arg1);
1102 uns0_p = false;
1103 uns1_p = true;
1304953e
JJ
1104 }
1105
1106 int pos_neg0 = get_range_pos_neg (arg0);
1107 int pos_neg1 = get_range_pos_neg (arg1);
1108
1109 /* s1 * u2 -> ur */
1110 if (!uns0_p && uns1_p && unsr_p)
1111 {
1112 switch (pos_neg0)
1113 {
1114 case 1:
1115 /* If s1 is non-negative, just perform normal u1 * u2 -> ur. */
1116 goto do_main;
1117 case 2:
1118 /* If s1 is negative, avoid the main code, just multiply and
1119 signal overflow if op1 is not 0. */
1120 struct separate_ops ops;
1121 ops.code = MULT_EXPR;
1122 ops.type = TREE_TYPE (arg1);
1123 ops.op0 = make_tree (ops.type, op0);
1124 ops.op1 = make_tree (ops.type, op1);
1125 ops.op2 = NULL_TREE;
1126 ops.location = loc;
1127 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1128 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1129 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1130 goto do_error_label;
1131 case 3:
1132 rtx_code_label *do_main_label;
1133 do_main_label = gen_label_rtx ();
92344ed0 1134 do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1135 NULL, do_main_label, PROB_VERY_LIKELY);
92344ed0 1136 do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1137 NULL, do_main_label, PROB_VERY_LIKELY);
a86451b9 1138 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1139 emit_label (do_main_label);
1140 goto do_main;
1141 default:
1142 gcc_unreachable ();
1143 }
1144 }
1145
1146 /* u1 * u2 -> sr */
1147 if (uns0_p && uns1_p && !unsr_p)
1148 {
1149 uns = true;
1150 /* Rest of handling of this case after res is computed. */
1151 goto do_main;
1152 }
1153
1154 /* s1 * u2 -> sr */
1155 if (!uns0_p && uns1_p && !unsr_p)
1156 {
1157 switch (pos_neg1)
1158 {
1159 case 1:
1160 goto do_main;
1161 case 2:
1162 /* If (S) u2 is negative (i.e. u2 is larger than maximum of S,
1163 avoid the main code, just multiply and signal overflow
1164 unless 0 * u2 or -1 * ((U) Smin). */
1165 struct separate_ops ops;
1166 ops.code = MULT_EXPR;
1167 ops.type = TREE_TYPE (arg1);
1168 ops.op0 = make_tree (ops.type, op0);
1169 ops.op1 = make_tree (ops.type, op1);
1170 ops.op2 = NULL_TREE;
1171 ops.location = loc;
1172 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
92344ed0 1173 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1174 NULL, done_label, PROB_VERY_LIKELY);
92344ed0 1175 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd 1176 NULL, do_error, PROB_VERY_UNLIKELY);
1304953e
JJ
1177 int prec;
1178 prec = GET_MODE_PRECISION (mode);
1179 rtx sgn;
1180 sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
92344ed0 1181 do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
1476d1bd 1182 NULL, done_label, PROB_VERY_LIKELY);
1304953e
JJ
1183 goto do_error_label;
1184 case 3:
1185 /* Rest of handling of this case after res is computed. */
1186 goto do_main;
1187 default:
1188 gcc_unreachable ();
1189 }
1190 }
31e071ae 1191
1304953e
JJ
1192 /* s1 * s2 -> ur */
1193 if (!uns0_p && !uns1_p && unsr_p)
1194 {
1195 rtx tem, tem2;
1196 switch (pos_neg0 | pos_neg1)
1197 {
1198 case 1: /* Both operands known to be non-negative. */
1199 goto do_main;
1200 case 2: /* Both operands known to be negative. */
1201 op0 = expand_unop (mode, neg_optab, op0, NULL_RTX, false);
1202 op1 = expand_unop (mode, neg_optab, op1, NULL_RTX, false);
1203 /* Avoid looking at arg0/arg1 ranges, as we've changed
1204 the arguments. */
1205 arg0 = error_mark_node;
1206 arg1 = error_mark_node;
1207 goto do_main;
1208 case 3:
1209 if ((pos_neg0 ^ pos_neg1) == 3)
1210 {
1211 /* If one operand is known to be negative and the other
1212 non-negative, this overflows always, unless the non-negative
1213 one is 0. Just do normal multiply and set overflow
1214 unless one of the operands is 0. */
1215 struct separate_ops ops;
1216 ops.code = MULT_EXPR;
1217 ops.type
1218 = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
1219 1);
1220 ops.op0 = make_tree (ops.type, op0);
1221 ops.op1 = make_tree (ops.type, op1);
1222 ops.op2 = NULL_TREE;
1223 ops.location = loc;
1224 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1225 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1226 OPTAB_LIB_WIDEN);
92344ed0 1227 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
1476d1bd 1228 NULL_RTX, NULL, done_label,
92344ed0 1229 PROB_VERY_LIKELY);
1304953e
JJ
1230 goto do_error_label;
1231 }
1232 /* The general case, do all the needed comparisons at runtime. */
1233 rtx_code_label *do_main_label, *after_negate_label;
1234 rtx rop0, rop1;
1235 rop0 = gen_reg_rtx (mode);
1236 rop1 = gen_reg_rtx (mode);
1237 emit_move_insn (rop0, op0);
1238 emit_move_insn (rop1, op1);
1239 op0 = rop0;
1240 op1 = rop1;
1241 do_main_label = gen_label_rtx ();
1242 after_negate_label = gen_label_rtx ();
1243 tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
1244 OPTAB_LIB_WIDEN);
92344ed0 1245 do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1246 NULL, after_negate_label, PROB_VERY_LIKELY);
1304953e
JJ
1247 /* Both arguments negative here, negate them and continue with
1248 normal unsigned overflow checking multiplication. */
1249 emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
1250 NULL_RTX, false));
1251 emit_move_insn (op1, expand_unop (mode, neg_optab, op1,
1252 NULL_RTX, false));
1253 /* Avoid looking at arg0/arg1 ranges, as we might have changed
1254 the arguments. */
1255 arg0 = error_mark_node;
1256 arg1 = error_mark_node;
1257 emit_jump (do_main_label);
1258 emit_label (after_negate_label);
1259 tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
1260 OPTAB_LIB_WIDEN);
92344ed0 1261 do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1262 NULL, do_main_label, PROB_VERY_LIKELY);
1304953e
JJ
1263 /* One argument is negative here, the other positive. This
1264 overflows always, unless one of the arguments is 0. But
1265 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
1266 is, thus we can keep do_main code oring in overflow as is. */
92344ed0 1267 do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1268 NULL, do_main_label, PROB_VERY_LIKELY);
a86451b9 1269 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1270 emit_label (do_main_label);
1271 goto do_main;
1272 default:
1273 gcc_unreachable ();
1274 }
1275 }
1276
1277 do_main:
1278 type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode), uns);
1279 sign = uns ? UNSIGNED : SIGNED;
1280 icode = optab_handler (uns ? umulv4_optab : mulv4_optab, mode);
31e071ae
MP
1281 if (icode != CODE_FOR_nothing)
1282 {
1283 struct expand_operand ops[4];
da664544 1284 rtx_insn *last = get_last_insn ();
31e071ae
MP
1285
1286 res = gen_reg_rtx (mode);
1287 create_output_operand (&ops[0], res, mode);
1288 create_input_operand (&ops[1], op0, mode);
1289 create_input_operand (&ops[2], op1, mode);
1290 create_fixed_operand (&ops[3], do_error);
1291 if (maybe_expand_insn (icode, 4, ops))
1292 {
1293 last = get_last_insn ();
0a6a6ac9 1294 if (profile_status_for_fn (cfun) != PROFILE_ABSENT
31e071ae
MP
1295 && JUMP_P (last)
1296 && any_condjump_p (last)
1297 && !find_reg_note (last, REG_BR_PROB, 0))
1298 add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
1299 emit_jump (done_label);
1300 }
1301 else
1302 {
1303 delete_insns_since (last);
1304 icode = CODE_FOR_nothing;
1305 }
1306 }
1307
1308 if (icode == CODE_FOR_nothing)
1309 {
1310 struct separate_ops ops;
1304953e
JJ
1311 int prec = GET_MODE_PRECISION (mode);
1312 machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
1313 ops.op0 = make_tree (type, op0);
1314 ops.op1 = make_tree (type, op1);
31e071ae 1315 ops.op2 = NULL_TREE;
1304953e 1316 ops.location = loc;
31e071ae
MP
1317 if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode
1318 && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode)))
1319 {
ef4bddc2 1320 machine_mode wmode = GET_MODE_2XWIDER_MODE (mode);
31e071ae
MP
1321 ops.code = WIDEN_MULT_EXPR;
1322 ops.type
1304953e 1323 = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
31e071ae
MP
1324
1325 res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
1304953e
JJ
1326 rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
1327 NULL_RTX, uns);
31e071ae
MP
1328 hipart = gen_lowpart (mode, hipart);
1329 res = gen_lowpart (mode, res);
1304953e
JJ
1330 if (uns)
1331 /* For the unsigned multiplication, there was overflow if
1332 HIPART is non-zero. */
92344ed0 1333 do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
1476d1bd 1334 NULL_RTX, NULL, done_label,
92344ed0 1335 PROB_VERY_LIKELY);
1304953e
JJ
1336 else
1337 {
1338 rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
1339 NULL_RTX, 0);
1340 /* RES is low half of the double width result, HIPART
1341 the high half. There was overflow if
1342 HIPART is different from RES < 0 ? -1 : 0. */
92344ed0 1343 do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
1476d1bd 1344 NULL_RTX, NULL, done_label,
92344ed0 1345 PROB_VERY_LIKELY);
1304953e 1346 }
31e071ae 1347 }
1304953e 1348 else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
d5fa9cc9 1349 {
da664544
DM
1350 rtx_code_label *large_op0 = gen_label_rtx ();
1351 rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
1352 rtx_code_label *one_small_one_large = gen_label_rtx ();
1353 rtx_code_label *both_ops_large = gen_label_rtx ();
1304953e
JJ
1354 rtx_code_label *after_hipart_neg = uns ? NULL : gen_label_rtx ();
1355 rtx_code_label *after_lopart_neg = uns ? NULL : gen_label_rtx ();
da664544 1356 rtx_code_label *do_overflow = gen_label_rtx ();
1304953e 1357 rtx_code_label *hipart_different = uns ? NULL : gen_label_rtx ();
d5fa9cc9 1358
807e902e 1359 unsigned int hprec = GET_MODE_PRECISION (hmode);
d5fa9cc9 1360 rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
1304953e 1361 NULL_RTX, uns);
d5fa9cc9
JJ
1362 hipart0 = gen_lowpart (hmode, hipart0);
1363 rtx lopart0 = gen_lowpart (hmode, op0);
1304953e
JJ
1364 rtx signbit0 = const0_rtx;
1365 if (!uns)
1366 signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
1367 NULL_RTX, 0);
d5fa9cc9 1368 rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
1304953e 1369 NULL_RTX, uns);
d5fa9cc9
JJ
1370 hipart1 = gen_lowpart (hmode, hipart1);
1371 rtx lopart1 = gen_lowpart (hmode, op1);
1304953e
JJ
1372 rtx signbit1 = const0_rtx;
1373 if (!uns)
1374 signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
1375 NULL_RTX, 0);
d5fa9cc9
JJ
1376
1377 res = gen_reg_rtx (mode);
1378
1379 /* True if op0 resp. op1 are known to be in the range of
1380 halfstype. */
1381 bool op0_small_p = false;
1382 bool op1_small_p = false;
1383 /* True if op0 resp. op1 are known to have all zeros or all ones
1384 in the upper half of bits, but are not known to be
1385 op{0,1}_small_p. */
1386 bool op0_medium_p = false;
1387 bool op1_medium_p = false;
1388 /* -1 if op{0,1} is known to be negative, 0 if it is known to be
1389 nonnegative, 1 if unknown. */
1390 int op0_sign = 1;
1391 int op1_sign = 1;
1392
1304953e
JJ
1393 if (pos_neg0 == 1)
1394 op0_sign = 0;
1395 else if (pos_neg0 == 2)
1396 op0_sign = -1;
1397 if (pos_neg1 == 1)
1398 op1_sign = 0;
1399 else if (pos_neg1 == 2)
1400 op1_sign = -1;
1401
1402 unsigned int mprec0 = prec;
1403 if (arg0 != error_mark_node)
1404 mprec0 = get_min_precision (arg0, sign);
1405 if (mprec0 <= hprec)
1406 op0_small_p = true;
1407 else if (!uns && mprec0 <= hprec + 1)
1408 op0_medium_p = true;
1409 unsigned int mprec1 = prec;
1410 if (arg1 != error_mark_node)
1411 mprec1 = get_min_precision (arg1, sign);
1412 if (mprec1 <= hprec)
1413 op1_small_p = true;
1414 else if (!uns && mprec1 <= hprec + 1)
1415 op1_medium_p = true;
d5fa9cc9
JJ
1416
1417 int smaller_sign = 1;
1418 int larger_sign = 1;
1419 if (op0_small_p)
1420 {
1421 smaller_sign = op0_sign;
1422 larger_sign = op1_sign;
1423 }
1424 else if (op1_small_p)
1425 {
1426 smaller_sign = op1_sign;
1427 larger_sign = op0_sign;
1428 }
1429 else if (op0_sign == op1_sign)
1430 {
1431 smaller_sign = op0_sign;
1432 larger_sign = op0_sign;
1433 }
1434
1435 if (!op0_small_p)
92344ed0 1436 do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
1476d1bd 1437 NULL_RTX, NULL, large_op0,
92344ed0 1438 PROB_UNLIKELY);
d5fa9cc9
JJ
1439
1440 if (!op1_small_p)
92344ed0 1441 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1442 NULL_RTX, NULL, small_op0_large_op1,
d5fa9cc9
JJ
1443 PROB_UNLIKELY);
1444
1304953e
JJ
1445 /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
1446 hmode to mode, the multiplication will never overflow. We can
1447 do just one hmode x hmode => mode widening multiplication. */
1448 rtx lopart0s = lopart0, lopart1s = lopart1;
d5fa9cc9
JJ
1449 if (GET_CODE (lopart0) == SUBREG)
1450 {
1304953e
JJ
1451 lopart0s = shallow_copy_rtx (lopart0);
1452 SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
1453 SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9
JJ
1454 }
1455 if (GET_CODE (lopart1) == SUBREG)
1456 {
1304953e
JJ
1457 lopart1s = shallow_copy_rtx (lopart1);
1458 SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
1459 SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
d5fa9cc9 1460 }
1304953e
JJ
1461 tree halfstype = build_nonstandard_integer_type (hprec, uns);
1462 ops.op0 = make_tree (halfstype, lopart0s);
1463 ops.op1 = make_tree (halfstype, lopart1s);
d5fa9cc9 1464 ops.code = WIDEN_MULT_EXPR;
1304953e 1465 ops.type = type;
d5fa9cc9
JJ
1466 rtx thisres
1467 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1468 emit_move_insn (res, thisres);
1469 emit_jump (done_label);
1470
1471 emit_label (small_op0_large_op1);
1472
1304953e
JJ
1473 /* If op0 is sign (!uns) or zero (uns) extended from hmode to mode,
1474 but op1 is not, just swap the arguments and handle it as op1
1475 sign/zero extended, op0 not. */
d5fa9cc9
JJ
1476 rtx larger = gen_reg_rtx (mode);
1477 rtx hipart = gen_reg_rtx (hmode);
1478 rtx lopart = gen_reg_rtx (hmode);
1479 emit_move_insn (larger, op1);
1480 emit_move_insn (hipart, hipart1);
1481 emit_move_insn (lopart, lopart0);
1482 emit_jump (one_small_one_large);
1483
1484 emit_label (large_op0);
1485
1486 if (!op1_small_p)
92344ed0 1487 do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
1476d1bd 1488 NULL_RTX, NULL, both_ops_large,
92344ed0 1489 PROB_UNLIKELY);
d5fa9cc9 1490
1304953e
JJ
1491 /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
1492 but op0 is not, prepare larger, hipart and lopart pseudos and
1493 handle it together with small_op0_large_op1. */
d5fa9cc9
JJ
1494 emit_move_insn (larger, op0);
1495 emit_move_insn (hipart, hipart0);
1496 emit_move_insn (lopart, lopart1);
1497
1498 emit_label (one_small_one_large);
1499
1500 /* lopart is the low part of the operand that is sign extended
026c3cfd 1501 to mode, larger is the other operand, hipart is the
d5fa9cc9
JJ
1502 high part of larger and lopart0 and lopart1 are the low parts
1503 of both operands.
1504 We perform lopart0 * lopart1 and lopart * hipart widening
1505 multiplications. */
1506 tree halfutype = build_nonstandard_integer_type (hprec, 1);
1507 ops.op0 = make_tree (halfutype, lopart0);
1508 ops.op1 = make_tree (halfutype, lopart1);
1509 rtx lo0xlo1
1510 = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1511
1512 ops.op0 = make_tree (halfutype, lopart);
1513 ops.op1 = make_tree (halfutype, hipart);
1514 rtx loxhi = gen_reg_rtx (mode);
1515 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1516 emit_move_insn (loxhi, tem);
1517
1304953e
JJ
1518 if (!uns)
1519 {
1520 /* if (hipart < 0) loxhi -= lopart << (bitsize / 2); */
1521 if (larger_sign == 0)
1522 emit_jump (after_hipart_neg);
1523 else if (larger_sign != -1)
92344ed0 1524 do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
1476d1bd 1525 NULL_RTX, NULL, after_hipart_neg,
1304953e
JJ
1526 PROB_EVEN);
1527
1528 tem = convert_modes (mode, hmode, lopart, 1);
1529 tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
1530 tem = expand_simple_binop (mode, MINUS, loxhi, tem, NULL_RTX,
1531 1, OPTAB_DIRECT);
1532 emit_move_insn (loxhi, tem);
1533
1534 emit_label (after_hipart_neg);
1535
1536 /* if (lopart < 0) loxhi -= larger; */
1537 if (smaller_sign == 0)
1538 emit_jump (after_lopart_neg);
1539 else if (smaller_sign != -1)
92344ed0 1540 do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
1476d1bd 1541 NULL_RTX, NULL, after_lopart_neg,
1304953e
JJ
1542 PROB_EVEN);
1543
1544 tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1545 1, OPTAB_DIRECT);
1546 emit_move_insn (loxhi, tem);
1547
1548 emit_label (after_lopart_neg);
1549 }
d5fa9cc9
JJ
1550
1551 /* loxhi += (uns) lo0xlo1 >> (bitsize / 2); */
1552 tem = expand_shift (RSHIFT_EXPR, mode, lo0xlo1, hprec, NULL_RTX, 1);
1553 tem = expand_simple_binop (mode, PLUS, loxhi, tem, NULL_RTX,
1554 1, OPTAB_DIRECT);
1555 emit_move_insn (loxhi, tem);
1556
1557 /* if (loxhi >> (bitsize / 2)
1304953e
JJ
1558 == (hmode) loxhi >> (bitsize / 2 - 1)) (if !uns)
1559 if (loxhi >> (bitsize / 2) == 0 (if uns). */
d5fa9cc9
JJ
1560 rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
1561 NULL_RTX, 0);
1562 hipartloxhi = gen_lowpart (hmode, hipartloxhi);
1304953e
JJ
1563 rtx signbitloxhi = const0_rtx;
1564 if (!uns)
1565 signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
1566 gen_lowpart (hmode, loxhi),
1567 hprec - 1, NULL_RTX, 0);
d5fa9cc9 1568
92344ed0 1569 do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
1476d1bd 1570 NULL_RTX, NULL, do_overflow,
d5fa9cc9
JJ
1571 PROB_VERY_UNLIKELY);
1572
1573 /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
1574 rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
1575 NULL_RTX, 1);
1576 tem = convert_modes (mode, hmode, gen_lowpart (hmode, lo0xlo1), 1);
1577
1578 tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
1579 1, OPTAB_DIRECT);
1580 if (tem != res)
1581 emit_move_insn (res, tem);
1582 emit_jump (done_label);
1583
1584 emit_label (both_ops_large);
1585
1304953e
JJ
1586 /* If both operands are large (not sign (!uns) or zero (uns)
1587 extended from hmode), then perform the full multiplication
1588 which will be the result of the operation.
1589 The only cases which don't overflow are for signed multiplication
1590 some cases where both hipart0 and highpart1 are 0 or -1.
1591 For unsigned multiplication when high parts are both non-zero
1592 this overflows always. */
d5fa9cc9 1593 ops.code = MULT_EXPR;
1304953e
JJ
1594 ops.op0 = make_tree (type, op0);
1595 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1596 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1597 emit_move_insn (res, tem);
1598
1304953e 1599 if (!uns)
d5fa9cc9 1600 {
1304953e
JJ
1601 if (!op0_medium_p)
1602 {
1603 tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
1604 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1605 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1606 NULL_RTX, NULL, do_error,
1304953e
JJ
1607 PROB_VERY_UNLIKELY);
1608 }
d5fa9cc9 1609
1304953e
JJ
1610 if (!op1_medium_p)
1611 {
1612 tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
1613 NULL_RTX, 1, OPTAB_DIRECT);
92344ed0 1614 do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
1476d1bd 1615 NULL_RTX, NULL, do_error,
1304953e
JJ
1616 PROB_VERY_UNLIKELY);
1617 }
d5fa9cc9 1618
1304953e
JJ
1619 /* At this point hipart{0,1} are both in [-1, 0]. If they are
1620 the same, overflow happened if res is negative, if they are
1621 different, overflow happened if res is positive. */
1622 if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
1623 emit_jump (hipart_different);
1624 else if (op0_sign == 1 || op1_sign == 1)
92344ed0 1625 do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
1476d1bd 1626 NULL_RTX, NULL, hipart_different,
92344ed0 1627 PROB_EVEN);
d5fa9cc9 1628
92344ed0 1629 do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
1476d1bd 1630 NULL_RTX, NULL, do_error,
92344ed0 1631 PROB_VERY_UNLIKELY);
1304953e 1632 emit_jump (done_label);
d5fa9cc9 1633
1304953e
JJ
1634 emit_label (hipart_different);
1635
92344ed0 1636 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
1476d1bd 1637 NULL_RTX, NULL, do_error,
92344ed0 1638 PROB_VERY_UNLIKELY);
1304953e
JJ
1639 emit_jump (done_label);
1640 }
d5fa9cc9
JJ
1641
1642 emit_label (do_overflow);
1643
1644 /* Overflow, do full multiplication and fallthru into do_error. */
1304953e
JJ
1645 ops.op0 = make_tree (type, op0);
1646 ops.op1 = make_tree (type, op1);
d5fa9cc9
JJ
1647 tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1648 emit_move_insn (res, tem);
1649 }
31e071ae
MP
1650 else
1651 {
1304953e 1652 gcc_assert (!is_ubsan);
31e071ae 1653 ops.code = MULT_EXPR;
1304953e 1654 ops.type = type;
31e071ae
MP
1655 res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1656 emit_jump (done_label);
1657 }
1658 }
1659
1304953e 1660 do_error_label:
31e071ae 1661 emit_label (do_error);
1304953e
JJ
1662 if (is_ubsan)
1663 {
1664 /* Expand the ubsan builtin call. */
1665 push_temp_slots ();
1666 fn = ubsan_build_overflow_builtin (MULT_EXPR, loc, TREE_TYPE (arg0),
1667 arg0, arg1);
1668 expand_normal (fn);
1669 pop_temp_slots ();
1670 do_pending_stack_adjust ();
1671 }
1672 else if (lhs)
a86451b9 1673 expand_arith_set_overflow (lhs, target);
31e071ae
MP
1674
1675 /* We're done. */
1676 emit_label (done_label);
1677
1304953e
JJ
1678 /* u1 * u2 -> sr */
1679 if (uns0_p && uns1_p && !unsr_p)
1680 {
1681 rtx_code_label *all_done_label = gen_label_rtx ();
92344ed0 1682 do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1683 NULL, all_done_label, PROB_VERY_LIKELY);
a86451b9 1684 expand_arith_set_overflow (lhs, target);
1304953e
JJ
1685 emit_label (all_done_label);
1686 }
1687
1688 /* s1 * u2 -> sr */
1689 if (!uns0_p && uns1_p && !unsr_p && pos_neg1 == 3)
1690 {
1691 rtx_code_label *all_done_label = gen_label_rtx ();
1692 rtx_code_label *set_noovf = gen_label_rtx ();
92344ed0 1693 do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
1476d1bd 1694 NULL, all_done_label, PROB_VERY_LIKELY);
a86451b9 1695 expand_arith_set_overflow (lhs, target);
92344ed0 1696 do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
1476d1bd 1697 NULL, set_noovf, PROB_VERY_LIKELY);
92344ed0 1698 do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
1476d1bd
MM
1699 NULL, all_done_label, PROB_VERY_UNLIKELY);
1700 do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
92344ed0 1701 all_done_label, PROB_VERY_UNLIKELY);
1304953e
JJ
1702 emit_label (set_noovf);
1703 write_complex_part (target, const0_rtx, true);
1704 emit_label (all_done_label);
1705 }
1706
31e071ae 1707 if (lhs)
1304953e
JJ
1708 {
1709 if (is_ubsan)
5620052d 1710 expand_ubsan_result_store (target, res);
1304953e
JJ
1711 else
1712 expand_arith_overflow_result_store (lhs, target, mode, res);
1713 }
31e071ae
MP
1714}
1715
1716/* Expand UBSAN_CHECK_ADD call STMT. */
1717
1718static void
4cfe7a6c 1719expand_UBSAN_CHECK_ADD (internal_fn, gcall *stmt)
31e071ae 1720{
1304953e
JJ
1721 location_t loc = gimple_location (stmt);
1722 tree lhs = gimple_call_lhs (stmt);
1723 tree arg0 = gimple_call_arg (stmt, 0);
1724 tree arg1 = gimple_call_arg (stmt, 1);
1725 expand_addsub_overflow (loc, PLUS_EXPR, lhs, arg0, arg1,
1726 false, false, false, true);
31e071ae
MP
1727}
1728
1729/* Expand UBSAN_CHECK_SUB call STMT. */
1730
1731static void
4cfe7a6c 1732expand_UBSAN_CHECK_SUB (internal_fn, gcall *stmt)
31e071ae 1733{
1304953e
JJ
1734 location_t loc = gimple_location (stmt);
1735 tree lhs = gimple_call_lhs (stmt);
1736 tree arg0 = gimple_call_arg (stmt, 0);
1737 tree arg1 = gimple_call_arg (stmt, 1);
1738 if (integer_zerop (arg0))
1739 expand_neg_overflow (loc, lhs, arg1, true);
31e071ae 1740 else
1304953e
JJ
1741 expand_addsub_overflow (loc, MINUS_EXPR, lhs, arg0, arg1,
1742 false, false, false, true);
31e071ae
MP
1743}
1744
1745/* Expand UBSAN_CHECK_MUL call STMT. */
1746
1747static void
4cfe7a6c 1748expand_UBSAN_CHECK_MUL (internal_fn, gcall *stmt)
31e071ae 1749{
1304953e
JJ
1750 location_t loc = gimple_location (stmt);
1751 tree lhs = gimple_call_lhs (stmt);
1752 tree arg0 = gimple_call_arg (stmt, 0);
1753 tree arg1 = gimple_call_arg (stmt, 1);
1754 expand_mul_overflow (loc, lhs, arg0, arg1, false, false, false, true);
1755}
1756
1757/* Helper function for {ADD,SUB,MUL}_OVERFLOW call stmt expansion. */
1758
1759static void
355fe088 1760expand_arith_overflow (enum tree_code code, gimple *stmt)
1304953e
JJ
1761{
1762 tree lhs = gimple_call_lhs (stmt);
1763 if (lhs == NULL_TREE)
1764 return;
1765 tree arg0 = gimple_call_arg (stmt, 0);
1766 tree arg1 = gimple_call_arg (stmt, 1);
1767 tree type = TREE_TYPE (TREE_TYPE (lhs));
1768 int uns0_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
1769 int uns1_p = TYPE_UNSIGNED (TREE_TYPE (arg1));
1770 int unsr_p = TYPE_UNSIGNED (type);
1771 int prec0 = TYPE_PRECISION (TREE_TYPE (arg0));
1772 int prec1 = TYPE_PRECISION (TREE_TYPE (arg1));
1773 int precres = TYPE_PRECISION (type);
1774 location_t loc = gimple_location (stmt);
1775 if (!uns0_p && get_range_pos_neg (arg0) == 1)
1776 uns0_p = true;
1777 if (!uns1_p && get_range_pos_neg (arg1) == 1)
1778 uns1_p = true;
1779 int pr = get_min_precision (arg0, uns0_p ? UNSIGNED : SIGNED);
1780 prec0 = MIN (prec0, pr);
1781 pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED);
1782 prec1 = MIN (prec1, pr);
1783
1784 /* If uns0_p && uns1_p, precop is minimum needed precision
1785 of unsigned type to hold the exact result, otherwise
1786 precop is minimum needed precision of signed type to
1787 hold the exact result. */
1788 int precop;
1789 if (code == MULT_EXPR)
1790 precop = prec0 + prec1 + (uns0_p != uns1_p);
1791 else
1792 {
1793 if (uns0_p == uns1_p)
1794 precop = MAX (prec0, prec1) + 1;
1795 else if (uns0_p)
1796 precop = MAX (prec0 + 1, prec1) + 1;
1797 else
1798 precop = MAX (prec0, prec1 + 1) + 1;
1799 }
1800 int orig_precres = precres;
1801
1802 do
1803 {
1804 if ((uns0_p && uns1_p)
1805 ? ((precop + !unsr_p) <= precres
1806 /* u1 - u2 -> ur can overflow, no matter what precision
1807 the result has. */
1808 && (code != MINUS_EXPR || !unsr_p))
1809 : (!unsr_p && precop <= precres))
1810 {
1811 /* The infinity precision result will always fit into result. */
1812 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1813 write_complex_part (target, const0_rtx, true);
1814 enum machine_mode mode = TYPE_MODE (type);
1815 struct separate_ops ops;
1816 ops.code = code;
1817 ops.type = type;
1818 ops.op0 = fold_convert_loc (loc, type, arg0);
1819 ops.op1 = fold_convert_loc (loc, type, arg1);
1820 ops.op2 = NULL_TREE;
1821 ops.location = loc;
1822 rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
1823 expand_arith_overflow_result_store (lhs, target, mode, tem);
1824 return;
1825 }
1826
1304953e
JJ
1827 /* For sub-word operations, if target doesn't have them, start
1828 with precres widening right away, otherwise do it only
1829 if the most simple cases can't be used. */
9e11bfef
TS
1830 if (WORD_REGISTER_OPERATIONS
1831 && orig_precres == precres
1832 && precres < BITS_PER_WORD)
1304953e 1833 ;
9e11bfef
TS
1834 else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
1835 && prec1 <= precres)
1304953e
JJ
1836 || ((!uns0_p || !uns1_p) && !unsr_p
1837 && prec0 + uns0_p <= precres
1838 && prec1 + uns1_p <= precres))
1839 {
1840 arg0 = fold_convert_loc (loc, type, arg0);
1841 arg1 = fold_convert_loc (loc, type, arg1);
1842 switch (code)
1843 {
1844 case MINUS_EXPR:
1845 if (integer_zerop (arg0) && !unsr_p)
7d704548
JJ
1846 {
1847 expand_neg_overflow (loc, lhs, arg1, false);
1848 return;
1849 }
1304953e
JJ
1850 /* FALLTHRU */
1851 case PLUS_EXPR:
1852 expand_addsub_overflow (loc, code, lhs, arg0, arg1,
1853 unsr_p, unsr_p, unsr_p, false);
1854 return;
1855 case MULT_EXPR:
1856 expand_mul_overflow (loc, lhs, arg0, arg1,
1857 unsr_p, unsr_p, unsr_p, false);
1858 return;
1859 default:
1860 gcc_unreachable ();
1861 }
1862 }
1863
1864 /* For sub-word operations, retry with a wider type first. */
1865 if (orig_precres == precres && precop <= BITS_PER_WORD)
1866 {
208b85bb 1867 int p = WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : precop;
1304953e
JJ
1868 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
1869 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
1870 uns0_p && uns1_p
1871 && unsr_p);
1872 p = TYPE_PRECISION (optype);
1873 if (p > precres)
1874 {
1875 precres = p;
1876 unsr_p = TYPE_UNSIGNED (optype);
1877 type = optype;
1878 continue;
1879 }
1880 }
1881
1882 if (prec0 <= precres && prec1 <= precres)
1883 {
1884 tree types[2];
1885 if (unsr_p)
1886 {
1887 types[0] = build_nonstandard_integer_type (precres, 0);
1888 types[1] = type;
1889 }
1890 else
1891 {
1892 types[0] = type;
1893 types[1] = build_nonstandard_integer_type (precres, 1);
1894 }
1895 arg0 = fold_convert_loc (loc, types[uns0_p], arg0);
1896 arg1 = fold_convert_loc (loc, types[uns1_p], arg1);
1897 if (code != MULT_EXPR)
1898 expand_addsub_overflow (loc, code, lhs, arg0, arg1, unsr_p,
1899 uns0_p, uns1_p, false);
1900 else
1901 expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p,
1902 uns0_p, uns1_p, false);
1903 return;
1904 }
1905
1906 /* Retry with a wider type. */
1907 if (orig_precres == precres)
1908 {
1909 int p = MAX (prec0, prec1);
1910 enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
1911 tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
1912 uns0_p && uns1_p
1913 && unsr_p);
1914 p = TYPE_PRECISION (optype);
1915 if (p > precres)
1916 {
1917 precres = p;
1918 unsr_p = TYPE_UNSIGNED (optype);
1919 type = optype;
1920 continue;
1921 }
1922 }
1923
1924 gcc_unreachable ();
1925 }
1926 while (1);
1927}
1928
1929/* Expand ADD_OVERFLOW STMT. */
1930
1931static void
4cfe7a6c 1932expand_ADD_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
1933{
1934 expand_arith_overflow (PLUS_EXPR, stmt);
1935}
1936
1937/* Expand SUB_OVERFLOW STMT. */
1938
1939static void
4cfe7a6c 1940expand_SUB_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
1941{
1942 expand_arith_overflow (MINUS_EXPR, stmt);
1943}
1944
1945/* Expand MUL_OVERFLOW STMT. */
1946
1947static void
4cfe7a6c 1948expand_MUL_OVERFLOW (internal_fn, gcall *stmt)
1304953e
JJ
1949{
1950 expand_arith_overflow (MULT_EXPR, stmt);
31e071ae
MP
1951}
1952
5ce9450f
JJ
1953/* This should get folded in tree-vectorizer.c. */
1954
1955static void
4cfe7a6c 1956expand_LOOP_VECTORIZED (internal_fn, gcall *)
5ce9450f
JJ
1957{
1958 gcc_unreachable ();
1959}
1960
ab23f5d9
RS
1961/* Expand MASK_LOAD call STMT using optab OPTAB. */
1962
5ce9450f 1963static void
4cfe7a6c 1964expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
5ce9450f
JJ
1965{
1966 struct expand_operand ops[3];
08554c26 1967 tree type, lhs, rhs, maskt, ptr;
5ce9450f 1968 rtx mem, target, mask;
08554c26 1969 unsigned align;
5ce9450f
JJ
1970
1971 maskt = gimple_call_arg (stmt, 2);
1972 lhs = gimple_call_lhs (stmt);
8e91d222
JJ
1973 if (lhs == NULL_TREE)
1974 return;
5ce9450f 1975 type = TREE_TYPE (lhs);
08554c26
JJ
1976 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
1977 align = tree_to_shwi (gimple_call_arg (stmt, 1));
1978 if (TYPE_ALIGN (type) != align)
1979 type = build_aligned_type (type, align);
1980 rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
5ce9450f
JJ
1981
1982 mem = expand_expr (rhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1983 gcc_assert (MEM_P (mem));
1984 mask = expand_normal (maskt);
1985 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
1986 create_output_operand (&ops[0], target, TYPE_MODE (type));
1987 create_fixed_operand (&ops[1], mem);
1988 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
ab23f5d9 1989 expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
045c1278
IE
1990 TYPE_MODE (TREE_TYPE (maskt))),
1991 3, ops);
5ce9450f
JJ
1992}
1993
ab23f5d9
RS
1994/* Expand MASK_STORE call STMT using optab OPTAB. */
1995
5ce9450f 1996static void
4cfe7a6c 1997expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
5ce9450f
JJ
1998{
1999 struct expand_operand ops[3];
08554c26 2000 tree type, lhs, rhs, maskt, ptr;
5ce9450f 2001 rtx mem, reg, mask;
08554c26 2002 unsigned align;
5ce9450f
JJ
2003
2004 maskt = gimple_call_arg (stmt, 2);
2005 rhs = gimple_call_arg (stmt, 3);
2006 type = TREE_TYPE (rhs);
08554c26
JJ
2007 ptr = build_int_cst (TREE_TYPE (gimple_call_arg (stmt, 1)), 0);
2008 align = tree_to_shwi (gimple_call_arg (stmt, 1));
2009 if (TYPE_ALIGN (type) != align)
2010 type = build_aligned_type (type, align);
2011 lhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0), ptr);
5ce9450f
JJ
2012
2013 mem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2014 gcc_assert (MEM_P (mem));
2015 mask = expand_normal (maskt);
2016 reg = expand_normal (rhs);
2017 create_fixed_operand (&ops[0], mem);
2018 create_input_operand (&ops[1], reg, TYPE_MODE (type));
2019 create_input_operand (&ops[2], mask, TYPE_MODE (TREE_TYPE (maskt)));
ab23f5d9 2020 expand_insn (convert_optab_handler (optab, TYPE_MODE (type),
045c1278
IE
2021 TYPE_MODE (TREE_TYPE (maskt))),
2022 3, ops);
5ce9450f
JJ
2023}
2024
09b22f48 2025static void
4cfe7a6c 2026expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
09b22f48
JJ
2027{
2028}
2029
ed9c79e1 2030static void
4cfe7a6c 2031expand_BUILTIN_EXPECT (internal_fn, gcall *stmt)
ed9c79e1
JJ
2032{
2033 /* When guessing was done, the hints should be already stripped away. */
2034 gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());
2035
2036 rtx target;
2037 tree lhs = gimple_call_lhs (stmt);
2038 if (lhs)
2039 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2040 else
2041 target = const0_rtx;
2042 rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
2043 if (lhs && val != target)
2044 emit_move_insn (target, val);
2045}
2046
f8e89441
TV
2047/* IFN_VA_ARG is supposed to be expanded at pass_stdarg. So this dummy function
2048 should never be called. */
2049
2050static void
4cfe7a6c 2051expand_VA_ARG (internal_fn, gcall *)
f8e89441
TV
2052{
2053 gcc_unreachable ();
2054}
2055
8ab78162
NS
2056/* Expand the IFN_UNIQUE function according to its first argument. */
2057
2058static void
4cfe7a6c 2059expand_UNIQUE (internal_fn, gcall *stmt)
8ab78162
NS
2060{
2061 rtx pattern = NULL_RTX;
2062 enum ifn_unique_kind kind
2063 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
2064
2065 switch (kind)
2066 {
2067 default:
2068 gcc_unreachable ();
2069
2070 case IFN_UNIQUE_UNSPEC:
2071 if (targetm.have_unique ())
2072 pattern = targetm.gen_unique ();
2073 break;
9bd46bc9
NS
2074
2075 case IFN_UNIQUE_OACC_FORK:
2076 case IFN_UNIQUE_OACC_JOIN:
2077 if (targetm.have_oacc_fork () && targetm.have_oacc_join ())
2078 {
2079 tree lhs = gimple_call_lhs (stmt);
2080 rtx target = const0_rtx;
2081
2082 if (lhs)
2083 target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2084
2085 rtx data_dep = expand_normal (gimple_call_arg (stmt, 1));
2086 rtx axis = expand_normal (gimple_call_arg (stmt, 2));
2087
2088 if (kind == IFN_UNIQUE_OACC_FORK)
2089 pattern = targetm.gen_oacc_fork (target, data_dep, axis);
2090 else
2091 pattern = targetm.gen_oacc_join (target, data_dep, axis);
2092 }
2093 else
2094 gcc_unreachable ();
2095 break;
8ab78162
NS
2096 }
2097
2098 if (pattern)
2099 emit_insn (pattern);
2100}
2101
9bd46bc9
NS
2102/* The size of an OpenACC compute dimension. */
2103
2104static void
4cfe7a6c 2105expand_GOACC_DIM_SIZE (internal_fn, gcall *stmt)
9bd46bc9
NS
2106{
2107 tree lhs = gimple_call_lhs (stmt);
2108
2109 if (!lhs)
2110 return;
2111
2112 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2113 if (targetm.have_oacc_dim_size ())
2114 {
2115 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2116 VOIDmode, EXPAND_NORMAL);
2117 emit_insn (targetm.gen_oacc_dim_size (target, dim));
2118 }
2119 else
2120 emit_move_insn (target, GEN_INT (1));
2121}
2122
2123/* The position of an OpenACC execution engine along one compute axis. */
2124
2125static void
4cfe7a6c 2126expand_GOACC_DIM_POS (internal_fn, gcall *stmt)
9bd46bc9
NS
2127{
2128 tree lhs = gimple_call_lhs (stmt);
2129
2130 if (!lhs)
2131 return;
2132
2133 rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2134 if (targetm.have_oacc_dim_pos ())
2135 {
2136 rtx dim = expand_expr (gimple_call_arg (stmt, 0), NULL_RTX,
2137 VOIDmode, EXPAND_NORMAL);
2138 emit_insn (targetm.gen_oacc_dim_pos (target, dim));
2139 }
2140 else
2141 emit_move_insn (target, const0_rtx);
2142}
2143
2144/* This is expanded by oacc_device_lower pass. */
2145
2146static void
4cfe7a6c 2147expand_GOACC_LOOP (internal_fn, gcall *)
9bd46bc9
NS
2148{
2149 gcc_unreachable ();
2150}
2151
e5014671
NS
2152/* This is expanded by oacc_device_lower pass. */
2153
2154static void
4cfe7a6c 2155expand_GOACC_REDUCTION (internal_fn, gcall *)
e5014671
NS
2156{
2157 gcc_unreachable ();
2158}
2159
883cabde
RS
2160/* Set errno to EDOM. */
2161
2162static void
2163expand_SET_EDOM (internal_fn, gcall *)
2164{
2165#ifdef TARGET_EDOM
2166#ifdef GEN_ERRNO_RTX
2167 rtx errno_rtx = GEN_ERRNO_RTX;
2168#else
2169 rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
2170#endif
2171 emit_move_insn (errno_rtx,
2172 gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
2173#else
2174 gcc_unreachable ();
2175#endif
2176}
2177
adedd5c1
JJ
2178/* Expand atomic bit test and set. */
2179
2180static void
2181expand_ATOMIC_BIT_TEST_AND_SET (internal_fn, gcall *call)
2182{
2183 expand_ifn_atomic_bit_test_and (call);
2184}
2185
2186/* Expand atomic bit test and complement. */
2187
2188static void
2189expand_ATOMIC_BIT_TEST_AND_COMPLEMENT (internal_fn, gcall *call)
2190{
2191 expand_ifn_atomic_bit_test_and (call);
2192}
2193
2194/* Expand atomic bit test and reset. */
2195
2196static void
2197expand_ATOMIC_BIT_TEST_AND_RESET (internal_fn, gcall *call)
2198{
2199 expand_ifn_atomic_bit_test_and (call);
2200}
2201
849a76a5
JJ
2202/* Expand atomic bit test and set. */
2203
2204static void
2205expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
2206{
2207 expand_ifn_atomic_compare_exchange (call);
2208}
2209
e16f1cc7
JJ
2210/* Expand LAUNDER to assignment, lhs = arg0. */
2211
2212static void
2213expand_LAUNDER (internal_fn, gcall *call)
2214{
2215 tree lhs = gimple_call_lhs (call);
2216
2217 if (!lhs)
2218 return;
2219
2220 expand_assignment (lhs, gimple_call_arg (call, 0), false);
2221}
2222
4cfe7a6c
RS
2223/* Expand a call to FN using the operands in STMT. FN has a single
2224 output operand and NARGS input operands. */
686ee971
RS
2225
2226static void
4cfe7a6c
RS
2227expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
2228 unsigned int nargs)
686ee971
RS
2229{
2230 expand_operand *ops = XALLOCAVEC (expand_operand, nargs + 1);
2231
686ee971
RS
2232 tree_pair types = direct_internal_fn_types (fn, stmt);
2233 insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
2234
2235 tree lhs = gimple_call_lhs (stmt);
2236 tree lhs_type = TREE_TYPE (lhs);
2237 rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
2238 create_output_operand (&ops[0], lhs_rtx, insn_data[icode].operand[0].mode);
2239
2240 for (unsigned int i = 0; i < nargs; ++i)
2241 {
2242 tree rhs = gimple_call_arg (stmt, i);
2243 tree rhs_type = TREE_TYPE (rhs);
2244 rtx rhs_rtx = expand_normal (rhs);
2245 if (INTEGRAL_TYPE_P (rhs_type))
2246 create_convert_operand_from (&ops[i + 1], rhs_rtx,
2247 TYPE_MODE (rhs_type),
2248 TYPE_UNSIGNED (rhs_type));
2249 else
2250 create_input_operand (&ops[i + 1], rhs_rtx, TYPE_MODE (rhs_type));
2251 }
2252
2253 expand_insn (icode, nargs + 1, ops);
2254 if (!rtx_equal_p (lhs_rtx, ops[0].value))
2255 {
ee132692
RS
2256 /* If the return value has an integral type, convert the instruction
2257 result to that type. This is useful for things that return an
2258 int regardless of the size of the input. If the instruction result
2259 is smaller than required, assume that it is signed.
2260
2261 If the return value has a nonintegral type, its mode must match
2262 the instruction result. */
2263 if (GET_CODE (lhs_rtx) == SUBREG && SUBREG_PROMOTED_VAR_P (lhs_rtx))
2264 {
2265 /* If this is a scalar in a register that is stored in a wider
2266 mode than the declared mode, compute the result into its
2267 declared mode and then convert to the wider mode. */
2268 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2269 rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0);
2270 convert_move (SUBREG_REG (lhs_rtx), tmp,
2271 SUBREG_PROMOTED_SIGN (lhs_rtx));
2272 }
2273 else if (GET_MODE (lhs_rtx) == GET_MODE (ops[0].value))
686ee971 2274 emit_move_insn (lhs_rtx, ops[0].value);
ee132692
RS
2275 else
2276 {
2277 gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type));
2278 convert_move (lhs_rtx, ops[0].value, 0);
2279 }
686ee971
RS
2280 }
2281}
2282
2283/* Expanders for optabs that can use expand_direct_optab_fn. */
2284
4cfe7a6c
RS
2285#define expand_unary_optab_fn(FN, STMT, OPTAB) \
2286 expand_direct_optab_fn (FN, STMT, OPTAB, 1)
686ee971 2287
4cfe7a6c
RS
2288#define expand_binary_optab_fn(FN, STMT, OPTAB) \
2289 expand_direct_optab_fn (FN, STMT, OPTAB, 2)
686ee971 2290
ab23f5d9
RS
2291/* RETURN_TYPE and ARGS are a return type and argument list that are
2292 in principle compatible with FN (which satisfies direct_internal_fn_p).
2293 Return the types that should be used to determine whether the
2294 target supports FN. */
2295
2296tree_pair
2297direct_internal_fn_types (internal_fn fn, tree return_type, tree *args)
2298{
2299 const direct_internal_fn_info &info = direct_internal_fn (fn);
2300 tree type0 = (info.type0 < 0 ? return_type : TREE_TYPE (args[info.type0]));
2301 tree type1 = (info.type1 < 0 ? return_type : TREE_TYPE (args[info.type1]));
2302 return tree_pair (type0, type1);
2303}
2304
2305/* CALL is a call whose return type and arguments are in principle
2306 compatible with FN (which satisfies direct_internal_fn_p). Return the
2307 types that should be used to determine whether the target supports FN. */
2308
2309tree_pair
2310direct_internal_fn_types (internal_fn fn, gcall *call)
2311{
2312 const direct_internal_fn_info &info = direct_internal_fn (fn);
2313 tree op0 = (info.type0 < 0
2314 ? gimple_call_lhs (call)
2315 : gimple_call_arg (call, info.type0));
2316 tree op1 = (info.type1 < 0
2317 ? gimple_call_lhs (call)
2318 : gimple_call_arg (call, info.type1));
2319 return tree_pair (TREE_TYPE (op0), TREE_TYPE (op1));
2320}
2321
2322/* Return true if OPTAB is supported for TYPES (whose modes should be
d95ab70a
RS
2323 the same) when the optimization type is OPT_TYPE. Used for simple
2324 direct optabs. */
ab23f5d9
RS
2325
2326static bool
d95ab70a
RS
2327direct_optab_supported_p (direct_optab optab, tree_pair types,
2328 optimization_type opt_type)
ab23f5d9
RS
2329{
2330 machine_mode mode = TYPE_MODE (types.first);
2331 gcc_checking_assert (mode == TYPE_MODE (types.second));
d95ab70a 2332 return direct_optab_handler (optab, mode, opt_type) != CODE_FOR_nothing;
ab23f5d9
RS
2333}
2334
2335/* Return true if load/store lanes optab OPTAB is supported for
d95ab70a 2336 array type TYPES.first when the optimization type is OPT_TYPE. */
ab23f5d9
RS
2337
2338static bool
d95ab70a
RS
2339multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
2340 optimization_type opt_type)
ab23f5d9 2341{
d95ab70a
RS
2342 gcc_assert (TREE_CODE (types.first) == ARRAY_TYPE);
2343 machine_mode imode = TYPE_MODE (types.first);
2344 machine_mode vmode = TYPE_MODE (TREE_TYPE (types.first));
2345 return (convert_optab_handler (optab, imode, vmode, opt_type)
2346 != CODE_FOR_nothing);
ab23f5d9
RS
2347}
2348
686ee971
RS
2349#define direct_unary_optab_supported_p direct_optab_supported_p
2350#define direct_binary_optab_supported_p direct_optab_supported_p
ab23f5d9
RS
2351#define direct_mask_load_optab_supported_p direct_optab_supported_p
2352#define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
2353#define direct_mask_store_optab_supported_p direct_optab_supported_p
2354#define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
2355
d95ab70a
RS
2356/* Return true if FN is supported for the types in TYPES when the
2357 optimization type is OPT_TYPE. The types are those associated with
2358 the "type0" and "type1" fields of FN's direct_internal_fn_info
2359 structure. */
ab23f5d9
RS
2360
2361bool
d95ab70a
RS
2362direct_internal_fn_supported_p (internal_fn fn, tree_pair types,
2363 optimization_type opt_type)
ab23f5d9
RS
2364{
2365 switch (fn)
2366 {
2367#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
2368 case IFN_##CODE: break;
2369#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2370 case IFN_##CODE: \
d95ab70a
RS
2371 return direct_##TYPE##_optab_supported_p (OPTAB##_optab, types, \
2372 opt_type);
ab23f5d9
RS
2373#include "internal-fn.def"
2374
2375 case IFN_LAST:
2376 break;
2377 }
2378 gcc_unreachable ();
2379}
2380
d95ab70a
RS
2381/* Return true if FN is supported for type TYPE when the optimization
2382 type is OPT_TYPE. The caller knows that the "type0" and "type1"
2383 fields of FN's direct_internal_fn_info structure are the same. */
ab23f5d9
RS
2384
2385bool
d95ab70a
RS
2386direct_internal_fn_supported_p (internal_fn fn, tree type,
2387 optimization_type opt_type)
ab23f5d9
RS
2388{
2389 const direct_internal_fn_info &info = direct_internal_fn (fn);
2390 gcc_checking_assert (info.type0 == info.type1);
d95ab70a 2391 return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
ab23f5d9
RS
2392}
2393
883cabde
RS
2394/* Return true if IFN_SET_EDOM is supported. */
2395
2396bool
2397set_edom_supported_p (void)
2398{
2399#ifdef TARGET_EDOM
2400 return true;
2401#else
2402 return false;
2403#endif
2404}
2405
ab23f5d9
RS
2406#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
2407 static void \
4cfe7a6c 2408 expand_##CODE (internal_fn fn, gcall *stmt) \
ab23f5d9 2409 { \
4cfe7a6c 2410 expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \
ab23f5d9
RS
2411 }
2412#include "internal-fn.def"
2413
25583c4f
RS
2414/* Routines to expand each internal function, indexed by function number.
2415 Each routine has the prototype:
2416
538dd0b7 2417 expand_<NAME> (gcall *stmt)
25583c4f
RS
2418
2419 where STMT is the statement that performs the call. */
4cfe7a6c 2420static void (*const internal_fn_expanders[]) (internal_fn, gcall *) = {
b78475cf 2421#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
25583c4f 2422#include "internal-fn.def"
25583c4f
RS
2423 0
2424};
2425
4cfe7a6c
RS
2426/* Expand STMT as though it were a call to internal function FN. */
2427
2428void
2429expand_internal_call (internal_fn fn, gcall *stmt)
2430{
2431 internal_fn_expanders[fn] (fn, stmt);
2432}
2433
25583c4f
RS
2434/* Expand STMT, which is a call to internal function FN. */
2435
2436void
538dd0b7 2437expand_internal_call (gcall *stmt)
25583c4f 2438{
4cfe7a6c 2439 expand_internal_call (gimple_call_internal_fn (stmt), stmt);
25583c4f 2440}