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