diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 5269f0ac528e420d543eb4855719634aad71b5ba..c7c5222a169c39c6fabc0f0bc5d060432bbc43bc 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -1631,7 +1631,11 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, rtx target = NULL_RTX; signop sign; enum insn_code icode; + int save_flag_trapv = flag_trapv; + /* We don't want any __mulv?i3 etc. calls from the expansion of + these internal functions, so disable -ftrapv temporarily. */ + flag_trapv = 0; done_label = gen_label_rtx (); do_error = gen_label_rtx (); @@ -2479,6 +2483,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, else expand_arith_overflow_result_store (lhs, target, mode, res); } + flag_trapv = save_flag_trapv; } /* Expand UBSAN_CHECK_* internal function if it has vector operands. */ @@ -2499,7 +2504,11 @@ expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs, rtx resvr = NULL_RTX; unsigned HOST_WIDE_INT const_cnt = 0; bool use_loop_p = (!cnt.is_constant (&const_cnt) || const_cnt > 4); + int save_flag_trapv = flag_trapv; + /* We don't want any __mulv?i3 etc. calls from the expansion of + these internal functions, so disable -ftrapv temporarily. */ + flag_trapv = 0; if (lhs) { optab op; @@ -2629,6 +2638,7 @@ expand_vector_ubsan_overflow (location_t loc, enum tree_code code, tree lhs, } else if (resvr) emit_move_insn (lhsr, resvr); + flag_trapv = save_flag_trapv; } /* Expand UBSAN_CHECK_ADD call STMT. */ @@ -2707,7 +2717,11 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) prec0 = MIN (prec0, pr); pr = get_min_precision (arg1, uns1_p ? UNSIGNED : SIGNED); prec1 = MIN (prec1, pr); + int save_flag_trapv = flag_trapv; + /* We don't want any __mulv?i3 etc. calls from the expansion of + these internal functions, so disable -ftrapv temporarily. */ + flag_trapv = 0; /* If uns0_p && uns1_p, precop is minimum needed precision of unsigned type to hold the exact result, otherwise precop is minimum needed precision of signed type to @@ -2748,6 +2762,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) ops.location = loc; rtx tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); expand_arith_overflow_result_store (lhs, target, mode, tem); + flag_trapv = save_flag_trapv; return; } @@ -2771,6 +2786,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) if (integer_zerop (arg0) && !unsr_p) { expand_neg_overflow (loc, lhs, arg1, false, NULL); + flag_trapv = save_flag_trapv; return; } /* FALLTHRU */ @@ -2781,6 +2797,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) case MULT_EXPR: expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p, unsr_p, unsr_p, false, NULL); + flag_trapv = save_flag_trapv; return; default: gcc_unreachable (); @@ -2826,6 +2843,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt) else expand_mul_overflow (loc, lhs, arg0, arg1, unsr_p, uns0_p, uns1_p, false, NULL); + flag_trapv = save_flag_trapv; return; } diff --git a/gcc/testsuite/gcc.dg/pr114753.c b/gcc/testsuite/gcc.dg/pr114753.c new file mode 100644 index 0000000000000000000000000000000000000000..117f2c36d3ef0fec230a5d26d4db9e5f3c8e8c6d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114753.c @@ -0,0 +1,14 @@ +/* PR middle-end/114753 */ +/* { dg-do run } */ +/* { dg-options "-O2 -ftrapv" } */ + +int +main () +{ + volatile long long i = __LONG_LONG_MAX__; + volatile long long j = 2; + long long k; + if (!__builtin_mul_overflow (i, j, &k) || k != -2LL) + __builtin_abort (); + return 0; +}