simplify-rtx: Extend (truncate (*extract ...)) fold [PR87763]
authorRichard Sandiford <richard.sandiford@arm.com>
Sun, 26 Jan 2020 13:01:48 +0000 (13:01 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 28 Jan 2020 11:06:44 +0000 (11:06 +0000)
In the gcc.target/aarch64/lsl_asr_sbfiz.c part of this PR, we have:

Failed to match this instruction:
(set (reg:SI 95)
    (ashift:SI (subreg:SI (sign_extract:DI (subreg:DI (reg:SI 97) 0)
                (const_int 3 [0x3])
                (const_int 0 [0])) 0)
        (const_int 19 [0x13])))

If we perform the natural simplification to:

(set (reg:SI 95)
    (ashift:SI (sign_extract:SI (reg:SI 97)
                (const_int 3 [0x3])
                (const_int 0 [0])) 0)
        (const_int 19 [0x13])))

then the pattern matches.  And it turns out that we do have a
simplification like that already, but it would only kick in for
extractions from a reg, not a subreg.  E.g.:

(set (reg:SI 95)
    (ashift:SI (subreg:SI (sign_extract:DI (reg:DI X)
                (const_int 3 [0x3])
                (const_int 0 [0])) 0)
        (const_int 19 [0x13])))

would simplify to:

(set (reg:SI 95)
    (ashift:SI (sign_extract:SI (subreg:SI (reg:DI X) 0)
                (const_int 3 [0x3])
                (const_int 0 [0])) 0)
        (const_int 19 [0x13])))

IMO the subreg case is even more obviously a simplification
than the bare reg case, since the net effect is to remove
either one or two subregs, rather than simply change the
position of a subreg/truncation.

However, doing that regressed gcc.dg/tree-ssa/pr64910-2.c
for -m32 on x86_64-linux-gnu, because we could then simplify
a :HI zero_extract to a :QI one.  The associated *testqi_ext_3
pattern did already seem to want to handle QImode extractions:

  "ix86_match_ccmode (insn, CCNOmode)
   && ((TARGET_64BIT && GET_MODE (operands[2]) == DImode)
       || GET_MODE (operands[2]) == SImode
       || GET_MODE (operands[2]) == HImode
       || GET_MODE (operands[2]) == QImode)

but I'm not sure how often the QI case would trigger in practice,
since the zero_extract mode was restricted to HI and above.  I checked
the other x86 patterns and couldn't see any other instances of this.

2020-01-28  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
PR rtl-optimization/87763
* simplify-rtx.c (simplify_truncation): Extend sign/zero_extract
simplification to handle subregs as well as bare regs.
* config/i386/i386.md (*testqi_ext_3): Match QI extracts too.

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/simplify-rtx.c

index 4d6ceb69258fd03175dc2cc5bb9024d9efb780ae..9fc93c918f508911bd95f8654b9a1deee46690ba 100644 (file)
@@ -1,3 +1,10 @@
+2020-01-28  Richard Sandiford  <richard.sandiford@arm.com>
+
+       PR rtl-optimization/87763
+       * simplify-rtx.c (simplify_truncation): Extend sign/zero_extract
+       simplification to handle subregs as well as bare regs.
+       * config/i386/i386.md (*testqi_ext_3): Match QI extracts too.
+
 2020-01-28  Richard Sandiford  <richard.sandiford@arm.com>
 
        * tree-vect-loop.c (vectorizable_reduction): Fail gracefully
index 6e9c9bd2fb603e079806d9a30d9f2aee9917d6e6..a125ab350bb2698517cfe9744a13bc75c3470e98 100644 (file)
 (define_insn_and_split "*testqi_ext_3"
   [(set (match_operand 0 "flags_reg_operand")
         (match_operator 1 "compare_operator"
-         [(zero_extract:SWI248
+         [(zero_extract:SWI
             (match_operand 2 "nonimmediate_operand" "rm")
             (match_operand 3 "const_int_operand" "n")
             (match_operand 4 "const_int_operand" "n"))
index eff1d07a2533c7bda5f0529cd318f08e6d5209d6..db4f9339c157b1d032a25677d1af08aab9c15749 100644 (file)
@@ -736,7 +736,9 @@ simplify_truncation (machine_mode mode, rtx op,
      (*_extract:M1 (truncate:M1 (reg:M2)) (len) (pos')) if possible without
      changing len.  */
   if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT)
-      && REG_P (XEXP (op, 0))
+      && (REG_P (XEXP (op, 0))
+         || (SUBREG_P (XEXP (op, 0))
+             && REG_P (SUBREG_REG (XEXP (op, 0)))))
       && GET_MODE (XEXP (op, 0)) == GET_MODE (op)
       && CONST_INT_P (XEXP (op, 1))
       && CONST_INT_P (XEXP (op, 2)))