https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79079
Bug ID: 79079 Summary: [6/7] Wrong code gen for __builtin_mul_overflow when TRULY_NOOP_TRUNCATION (32, 64) == false Product: gcc Version: 6.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: npickito at gmail dot com Target Milestone: --- Target: mips64-unknown-linux, riscv64-elf, riscv64-linux expand function on __builtin_mul_overflow is missing gen a truncdisi2 after muldi3 since it's just call gen_lowpart and it's not consider TRULY_NOOP_TRUNCATION == false GCC configure: --target=mips64-unknown-linux-gnu --with-abi=64 or --target=riscv64-unknown-linux-gnu (Review in progress) (https://gcc.gnu.org/ml/gcc-patches/2017-01/msg00776.html) Testcase: c-c++-common/torture/builtin-arith-overflow-12.c Reduced testcase (extract from builtin-arith-overflow-12.c): int v; __attribute__((noinline, noclone)) void bar (void) { v++; } __attribute__((noinline, noclone)) signed int t115_1mul (unsigned int x, signed int y) { signed int r; if (__builtin_mul_overflow (x, y, &r)) bar (); return r; } int main() { unsigned int x = ((unsigned int) 0x7fffffff + 1); signed int y = (-1); signed int r1, r2; v = 0; if (t115_1mul (x, y) != (signed int) ((-0x7fffffff - 1))) __builtin_abort (); return 0; } Patch: diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index c07b538..3c92183 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -1272,7 +1272,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec, NULL_RTX, uns); hipart = gen_lowpart (mode, hipart); - res = gen_lowpart (mode, res); + res = convert_modes (mode, wmode, res, uns); if (uns) /* For the unsigned multiplication, there was overflow if HIPART is non-zero. */ This patch already run gcc testsuite for mips64, x86-64 and riscv64/riscv32, fix mips64 and riscv64 for builtin-arith-overflow-12.c and no introduce new regression on x86-64 and riscv32