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