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,

This patch has been run gcc testsuite for mips64, x86-64 and
riscv64/riscv32, fix mips64 and riscv64 for
builtin-arith-overflow-12.c/builtin-arith-overflow-p-12.c and no
introduce new regression on x86-64 and riscv32


gcc/ChangeLog:

2017-01-16  Kito Cheng <kito.ch...@gmail.com>
            Kuan-Lin Chen <kuanlinche...@gmail.com>

        PR target/PR79079
        * gcc/internal-fn.c (expand_mul_overflow): Use convert_modes instead of
        gen_lowpart.
From 7796f89dcfea0b583989a570d308ae5faf7213d1 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.ch...@gmail.com>
Date: Wed, 14 Sep 2016 15:06:28 +0800
Subject: [PATCH] Get the lowpart by convert_modes which checks
 TRULY_NOOP_TRUNCATION inside.

---
 gcc/internal-fn.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index c07b538..567cee4 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -1271,8 +1271,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
 	  res = expand_expr_real_2 (&ops, NULL_RTX, wmode, EXPAND_NORMAL);
 	  rtx hipart = expand_shift (RSHIFT_EXPR, wmode, res, prec,
 				     NULL_RTX, uns);
-	  hipart = gen_lowpart (mode, hipart);
-	  res = gen_lowpart (mode, res);
+	  hipart = convert_modes (mode, wmode, hipart, uns);
+	  res = convert_modes (mode, wmode, res, uns);
 	  if (uns)
 	    /* For the unsigned multiplication, there was overflow if
 	       HIPART is non-zero.  */
@@ -1305,16 +1305,16 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
 	  unsigned int hprec = GET_MODE_PRECISION (hmode);
 	  rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
 				      NULL_RTX, uns);
-	  hipart0 = gen_lowpart (hmode, hipart0);
-	  rtx lopart0 = gen_lowpart (hmode, op0);
+	  hipart0 = convert_modes (hmode, mode, hipart0, uns);
+	  rtx lopart0 = convert_modes (hmode, mode, op0, uns);
 	  rtx signbit0 = const0_rtx;
 	  if (!uns)
 	    signbit0 = expand_shift (RSHIFT_EXPR, hmode, lopart0, hprec - 1,
 				     NULL_RTX, 0);
 	  rtx hipart1 = expand_shift (RSHIFT_EXPR, mode, op1, hprec,
 				      NULL_RTX, uns);
-	  hipart1 = gen_lowpart (hmode, hipart1);
-	  rtx lopart1 = gen_lowpart (hmode, op1);
+	  hipart1 = convert_modes (hmode, mode, hipart1, uns);
+	  rtx lopart1 = convert_modes (hmode, mode, op1, uns);
 	  rtx signbit1 = const0_rtx;
 	  if (!uns)
 	    signbit1 = expand_shift (RSHIFT_EXPR, hmode, lopart1, hprec - 1,
@@ -1505,11 +1505,12 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
 	     if (loxhi >> (bitsize / 2) == 0		 (if uns).  */
 	  rtx hipartloxhi = expand_shift (RSHIFT_EXPR, mode, loxhi, hprec,
 					  NULL_RTX, 0);
-	  hipartloxhi = gen_lowpart (hmode, hipartloxhi);
+	  hipartloxhi = convert_modes (hmode, mode, hipartloxhi, uns);
 	  rtx signbitloxhi = const0_rtx;
 	  if (!uns)
 	    signbitloxhi = expand_shift (RSHIFT_EXPR, hmode,
-					 gen_lowpart (hmode, loxhi),
+					 convert_modes (hmode, mode,
+							loxhi, uns),
 					 hprec - 1, NULL_RTX, 0);
 
 	  do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
@@ -1519,7 +1520,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
 	  /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1;  */
 	  rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
 					   NULL_RTX, 1);
-	  tem = convert_modes (mode, hmode, gen_lowpart (hmode, lo0xlo1), 1);
+	  tem = convert_modes (mode, hmode,
+			       convert_modes (hmode, mode, lo0xlo1, uns), 1);
 
 	  tem = expand_simple_binop (mode, IOR, loxhishifted, tem, res,
 				     1, OPTAB_DIRECT);
-- 
2.7.4

Reply via email to