Hi!

In the PR57251 fixes, I've messed up the modes, convert_modes first argument
is the to mode and second argument is the from mode, i.e. mode the third
argument has or is assumed to have.

The following patch fixes that.  Additionally I've swapped two conditions
to avoid first convert_modes a CONST_INT to one mode and then convert_modes
it again from the old mode rather than new one.  With the two conditions
swapped it uses just one convert_modes for that case.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-12-21  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/88563
        * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: Swap innermode
        and mode arguments to convert_modes.  Likewise swap mode and word_mode
        arguments.  Handle both arguments with VOIDmode before convert_modes
        of one of them.  Formatting fixes.

        * gcc.dg/pr88563.c: New test.

--- gcc/expr.c.jj       2018-12-18 12:20:53.511482381 +0100
+++ gcc/expr.c  2018-12-21 11:57:25.523576071 +0100
@@ -8775,8 +8775,8 @@ expand_expr_real_2 (sepops ops, rtx targ
                 != INTEGER_CST check.  Handle it.  */
              if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
                {
-                 op0 = convert_modes (innermode, mode, op0, true);
-                 op1 = convert_modes (innermode, mode, op1, false);
+                 op0 = convert_modes (mode, innermode, op0, true);
+                 op1 = convert_modes (mode, innermode, op1, false);
                  return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1,
                                                        target, unsignedp));
                }
@@ -8798,7 +8798,7 @@ expand_expr_real_2 (sepops ops, rtx targ
          if (TREE_CODE (treeop0) != INTEGER_CST)
            {
              if (find_widening_optab_handler (this_optab, mode, innermode)
-                   != CODE_FOR_nothing)
+                 != CODE_FOR_nothing)
                {
                  expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
                                   EXPAND_NORMAL);
@@ -8807,9 +8807,9 @@ expand_expr_real_2 (sepops ops, rtx targ
                  if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
                    {
                     widen_mult_const:
-                     op0 = convert_modes (innermode, mode, op0, zextend_p);
+                     op0 = convert_modes (mode, innermode, op0, zextend_p);
                      op1
-                       = convert_modes (innermode, mode, op1,
+                       = convert_modes (mode, innermode, op1,
                                         TYPE_UNSIGNED (TREE_TYPE (treeop1)));
                      return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1,
                                                            target,
@@ -8820,21 +8820,19 @@ expand_expr_real_2 (sepops ops, rtx targ
                  return REDUCE_BIT_FIELD (temp);
                }
              if (find_widening_optab_handler (other_optab, mode, innermode)
-                   != CODE_FOR_nothing
+                 != CODE_FOR_nothing
                  && innermode == word_mode)
                {
                  rtx htem, hipart;
                  op0 = expand_normal (treeop0);
-                 if (TREE_CODE (treeop1) == INTEGER_CST)
-                   op1 = convert_modes (word_mode, mode,
-                                        expand_normal (treeop1),
-                                        TYPE_UNSIGNED (TREE_TYPE (treeop1)));
-                 else
-                   op1 = expand_normal (treeop1);
-                 /* op0 and op1 might still be constant, despite the above
+                 op1 = expand_normal (treeop1);
+                 /* op0 and op1 might be constants, despite the above
                     != INTEGER_CST check.  Handle it.  */
                  if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
                    goto widen_mult_const;
+                 if (TREE_CODE (treeop1) == INTEGER_CST)
+                   op1 = convert_modes (mode, word_mode, op1,
+                                        TYPE_UNSIGNED (TREE_TYPE (treeop1)));
                  temp = expand_binop (mode, other_optab, op0, op1, target,
                                       unsignedp, OPTAB_LIB_WIDEN);
                  hipart = gen_highpart (word_mode, temp);
--- gcc/testsuite/gcc.dg/pr88563.c.jj   2018-12-21 12:19:02.850681604 +0100
+++ gcc/testsuite/gcc.dg/pr88563.c      2018-12-21 12:18:52.891841942 +0100
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/88563 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O2 -fno-code-hoisting -fno-tree-ccp -fno-tree-dominator-opts 
-fno-tree-forwprop -fno-tree-fre -fno-tree-pre -fno-tree-vrp" } */
+
+int
+main ()
+{
+#if __SIZEOF_LONG_LONG__ == 8 && __SIZEOF_INT128__ == 16 && __CHAR_BIT__ == 8
+  unsigned __int128 a = 5;
+  __builtin_mul_overflow (0xffffffffffffffffULL, (unsigned long long) a, &a);
+  if (a != ((unsigned __int128)4 << 64 | 0xfffffffffffffffb))
+    __builtin_abort ();
+#endif
+  return 0;
+}

        Jakub

Reply via email to