Hi Kyrill,

On Mon, Nov 02, 2015 at 02:15:27PM +0000, Kyrill Tkachov wrote:
> This patch attempts to restrict combine from transforming ZERO_EXTEND and 
> SIGN_EXTEND operations into and-bitmask
> and weird SUBREG expressions when they appear inside MULT expressions. This 
> is because a MULT rtx containing these
> extend operations is usually a well understood widening multiply operation.

Right.  I have often wanted for combine to try plain substitution as well
as substitution and simplification: simplification (which uses nonzero_bits
etc.) often makes a mess of even moderately complex instructions.

But since we do not have that yet, and your 24% number is nicely impressive,
let's try to do no simplification for widening mults, as in your patch.

> With this patch on aarch64 I saw increased generation of smaddl and umaddl 
> instructions where
> before the combination of smull and add instructions were rejected because 
> the extend operands
> were being transformed into these weird equivalent expressions.
> 
> Overall, I see 24% more [su]maddl instructions being generated for SPEC2006 
> and with no performance regressions.
> 
> The testcase in the patch is the most minimal one I could get that 
> demonstrates the issue I'm trying to solve.
> 
> Does this approach look ok?

In broad lines it does.  Could you try this patch instead?  Not tested
etc. (other than building an aarch64 cross and your test case); I'll do
that tomorrow if you like the result.


Segher


diff --git a/gcc/combine.c b/gcc/combine.c
index c3db2e0..3bf7ffb 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -5284,6 +5284,15 @@ subst (rtx x, rtx from, rtx to, int in_dest, int 
in_cond, int unique_copy)
              || GET_CODE (SET_DEST (x)) == PC))
        fmt = "ie";
 
+      /* Substituting into the operands of a widening MULT is not likely
+        to create RTL matching a machine insn.  */
+      if (code == MULT
+         && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+             || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
+         && (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
+             || GET_CODE (XEXP (x, 1)) == SIGN_EXTEND))
+       return x;
+
       /* Get the mode of operand 0 in case X is now a SIGN_EXTEND of a
         constant.  */
       if (fmt[0] == 'e')
@@ -8455,6 +8464,15 @@ force_to_mode (rtx x, machine_mode mode, unsigned 
HOST_WIDE_INT mask,
       /* ... fall through ...  */
 
     case MULT:
+      /* Substituting into the operands of a widening MULT is not likely to
+        create RTL matching a machine insn.  */
+      if (code == MULT
+         && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+             || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
+         && (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
+             || GET_CODE (XEXP (x, 1)) == SIGN_EXTEND))
+       return gen_lowpart_or_truncate (mode, x);
+
       /* For PLUS, MINUS and MULT, we need any bits less significant than the
         most significant bit in MASK since carries from those bits will
         affect the bits we are interested in.  */
-- 
1.9.3

Reply via email to