Trunk expand_mult uses the following code to handle CONST_DOUBLEs:

          /* If we are multiplying in DImode, it may still be a win
             to try to work with shifts and adds.  */
          if (CONST_DOUBLE_HIGH (scalar_op1) == 0
              && (CONST_DOUBLE_LOW (scalar_op1) > 0
                  || (CONST_DOUBLE_LOW (scalar_op1) < 0
                      && EXACT_POWER_OF_2_OR_ZERO_P
                           (CONST_DOUBLE_LOW (scalar_op1)))))
            {
              coeff = CONST_DOUBLE_LOW (scalar_op1);
              is_neg = false;
            }
          else if (CONST_DOUBLE_LOW (scalar_op1) == 0)
            {
              coeff = CONST_DOUBLE_HIGH (scalar_op1);
              if (EXACT_POWER_OF_2_OR_ZERO_P (coeff))
                {
                  int shift = floor_log2 (coeff) + HOST_BITS_PER_WIDE_INT;
                  if (shift < HOST_BITS_PER_DOUBLE_INT - 1
                      || mode_bitsize <= HOST_BITS_PER_DOUBLE_INT)
                    return expand_shift (LSHIFT_EXPR, mode, op0,
                                         shift, target, unsignedp);
                }
              goto skip_synth;
            }
          else
            goto skip_synth;

So the only non-power-of-2 case that avoids the skip_synth treatment
is a CONST_DOUBLE whose high HWI is 0 and whose low HWI is positive.
I think that's outdated, because even on trunk such constants should be
CONST_INTs instead.  They definitely are on wide-int.  So we only need
to handle the power-of-2 case.

The shift handling for that case can be much simpler.  We're dealing
with a constant in a particular mode, so if exact_log2 returns >= 0,
it's a valid shift for that mode.  No truncation or boundary checks
are needed.  wide ints really clean this up.

The same reasoning applies to simplify_binary_operation_1, except there
we're just saving a redundant upper bound test.

Tested on powerpc64-linux-gnu and by rerunning the assembly comparison.
OK to install?

Thanks,
Richard


Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c        2013-11-09 10:50:12.836314443 +0000
+++ gcc/expmed.c        2013-11-09 10:50:37.333494113 +0000
@@ -3075,30 +3075,11 @@ expand_mult (enum machine_mode mode, rtx
       else if (CONST_DOUBLE_AS_INT_P (scalar_op1))
 #endif
        {
-         int p = GET_MODE_PRECISION (mode);
          int shift = wi::exact_log2 (std::make_pair (scalar_op1, mode));
-         /* Perfect power of 2.  */
-         is_neg = false;
+         /* Perfect power of 2 (other than 1, which is handled above).  */
          if (shift > 0)
-           {
-             /* Do the shift count trucation against the bitsize, not
-                the precision.  See the comment above
-                wide-int.c:trunc_shift for details.  */
-             if (SHIFT_COUNT_TRUNCATED)
-               shift &= GET_MODE_BITSIZE (mode) - 1;
-             /* We could consider adding just a move of 0 to target
-                if the shift >= p  */
-             if (shift < p)
-               return expand_shift (LSHIFT_EXPR, mode, op0, 
-                                    shift, target, unsignedp);
-             /* Any positive number that fits in a word.  */
-             coeff = CONST_WIDE_INT_ELT (scalar_op1, 0);
-           }
-         else if (wi::sign_mask (std::make_pair (scalar_op1, mode)) == 0)
-           {
-             /* Any positive number that fits in a word.  */
-             coeff = CONST_WIDE_INT_ELT (scalar_op1, 0);
-           }
+           return expand_shift (LSHIFT_EXPR, mode, op0,
+                                shift, target, unsignedp);
          else
            goto skip_synth;
        }
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c  2013-11-09 10:50:12.836314443 +0000
+++ gcc/simplify-rtx.c  2013-11-09 10:50:14.046323332 +0000
@@ -2399,7 +2399,7 @@ simplify_binary_operation_1 (enum rtx_co
       if (CONST_SCALAR_INT_P (trueop1))
        {
          val = wi::exact_log2 (std::make_pair (trueop1, mode));
-         if (val >= 0 && val < GET_MODE_BITSIZE (mode))
+         if (val >= 0)
            return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val));
        }
 

Reply via email to