Re: [PATCH] Optimize (x * 8) | 5 and (x 3) ^ 3 to use lea (PR target/48688)

2011-06-04 Thread H.J. Lu
On Wed, Apr 20, 2011 at 9:09 AM, Jakub Jelinek ja...@redhat.com wrote:
 Hi!

 This splitter allows us to optimize (x {* {2,4,8}, {1,2,3}}) {|,^} y
 for constant integer y = {1ULL,3ULL,7ULL} using lea{l,q} (| or ^ in
 that case, when the low bits are known to be all 0, is like plus).

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

 2011-04-20  Jakub Jelinek  ja...@redhat.com

        PR target/48688
        * config/i386/i386.md (*lea_general_4): New define_insn_and_split.

        * gcc.target/i386/pr48688.c: New test.

 --- gcc/config/i386/i386.md.jj  2011-04-19 14:08:55.0 +0200
 +++ gcc/config/i386/i386.md     2011-04-20 14:34:50.0 +0200
 @@ -6646,6 +6646,40 @@ (define_insn_and_split *lea_general_3_z
  }
   [(set_attr type lea)
    (set_attr mode SI)])
 +
 +(define_insn_and_split *lea_general_4
 +  [(set (match_operand:SWI 0 register_operand =r)
 +       (any_or:SWI (ashift:SWI (match_operand:SWI 1 index_register_operand 
 l)
 +                               (match_operand:SWI 2 const_int_operand n))
 +                   (match_operand 3 const_int_operand n)))]
 +  (MODEmode == DImode
 +    || MODEmode == SImode
 +    || !TARGET_PARTIAL_REG_STALL
 +    || optimize_function_for_size_p (cfun))
 +    ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) - 1  3
 +    ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
 +       = ((unsigned HOST_WIDE_INT) 1  INTVAL (operands[2])))
 +  #
 +   reload_completed
 +  [(const_int 0)]
 +{
 +  rtx pat;
 +  if (MODEmode != DImode)
 +    operands[0] = gen_lowpart (SImode, operands[0]);
 +  operands[1] = gen_lowpart (Pmode, operands[1]);
 +  operands[2] = GEN_INT (1  INTVAL (operands[2]));
 +  pat = plus_constant (gen_rtx_MULT (Pmode, operands[1], operands[2]),
 +                      INTVAL (operands[3]));
 +  if (Pmode != SImode  MODEmode != DImode)
 +    pat = gen_rtx_SUBREG (SImode, pat, 0);
 +  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
 +  DONE;
 +}
 +  [(set_attr type lea)
 +   (set (attr mode)
 +      (if_then_else (eq (symbol_ref MODEmode == DImode) (const_int 0))
 +       (const_string SI)
 +       (const_string DI)))])

  ;; Subtract instructions

I don't think this pattern is correct.  See:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49281


H.J.


Re: [PATCH] Optimize (x * 8) | 5 and (x 3) ^ 3 to use lea (PR target/48688)

2011-04-21 Thread Jakub Jelinek
On Wed, Apr 20, 2011 at 10:27:36AM -0700, Richard Henderson wrote:
 On 04/20/2011 09:09 AM, Jakub Jelinek wrote:
  Hi!
  
  This splitter allows us to optimize (x {* {2,4,8}, {1,2,3}}) {|,^} y
  for constant integer y = {1ULL,3ULL,7ULL} using lea{l,q} (| or ^ in
  that case, when the low bits are known to be all 0, is like plus).
  
  Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
  
  2011-04-20  Jakub Jelinek  ja...@redhat.com
  
  PR target/48688
  * config/i386/i386.md (*lea_general_4): New define_insn_and_split.
 
 Any chance you could do this in combine instead?  Shift-and-add patterns
 are a fairly common architectural feature...

I've tried to do it in simplify-rtx.c, unfortunately combine.c does exactly
opposite canonicalization and thus it results in endless recursion:

  /* If we are adding two things that have no bits in common, convert
 the addition into an IOR.  This will often be further simplified,
 for example in cases like ((a  1) + (a  2)), which can
 become a  3.  */

  if (GET_MODE_BITSIZE (mode) = HOST_BITS_PER_WIDE_INT
   (nonzero_bits (XEXP (x, 0), mode)
   nonzero_bits (XEXP (x, 1), mode)) == 0)
{
  /* Try to simplify the expression further.  */
  rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
  temp = combine_simplify_rtx (tor, mode, in_dest, 0);

  /* If we could, great.  If not, do not go ahead with the IOR
 replacement, since PLUS appears in many special purpose
 address arithmetic instructions.  */
  if (GET_CODE (temp) != CLOBBER  temp != tor)
return temp;
}

So at least it can't be done in simplify_binary_operation_1.

Jakub


[PATCH] Optimize (x * 8) | 5 and (x 3) ^ 3 to use lea (PR target/48688)

2011-04-20 Thread Jakub Jelinek
Hi!

This splitter allows us to optimize (x {* {2,4,8}, {1,2,3}}) {|,^} y
for constant integer y = {1ULL,3ULL,7ULL} using lea{l,q} (| or ^ in
that case, when the low bits are known to be all 0, is like plus).

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

2011-04-20  Jakub Jelinek  ja...@redhat.com

PR target/48688
* config/i386/i386.md (*lea_general_4): New define_insn_and_split.

* gcc.target/i386/pr48688.c: New test.

--- gcc/config/i386/i386.md.jj  2011-04-19 14:08:55.0 +0200
+++ gcc/config/i386/i386.md 2011-04-20 14:34:50.0 +0200
@@ -6646,6 +6646,40 @@ (define_insn_and_split *lea_general_3_z
 }
   [(set_attr type lea)
(set_attr mode SI)])
+
+(define_insn_and_split *lea_general_4
+  [(set (match_operand:SWI 0 register_operand =r)
+   (any_or:SWI (ashift:SWI (match_operand:SWI 1 index_register_operand 
l)
+   (match_operand:SWI 2 const_int_operand n))
+   (match_operand 3 const_int_operand n)))]
+  (MODEmode == DImode
+|| MODEmode == SImode
+|| !TARGET_PARTIAL_REG_STALL
+|| optimize_function_for_size_p (cfun))
+((unsigned HOST_WIDE_INT) INTVAL (operands[2])) - 1  3
+((unsigned HOST_WIDE_INT) INTVAL (operands[3])
+   = ((unsigned HOST_WIDE_INT) 1  INTVAL (operands[2])))
+  #
+   reload_completed
+  [(const_int 0)]
+{
+  rtx pat;
+  if (MODEmode != DImode)
+operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (Pmode, operands[1]);
+  operands[2] = GEN_INT (1  INTVAL (operands[2]));
+  pat = plus_constant (gen_rtx_MULT (Pmode, operands[1], operands[2]),
+  INTVAL (operands[3]));
+  if (Pmode != SImode  MODEmode != DImode)
+pat = gen_rtx_SUBREG (SImode, pat, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+  DONE;
+}
+  [(set_attr type lea)
+   (set (attr mode)
+  (if_then_else (eq (symbol_ref MODEmode == DImode) (const_int 0))
+   (const_string SI)
+   (const_string DI)))])
 
 ;; Subtract instructions
 
--- gcc/testsuite/gcc.target/i386/pr48688.c.jj  2011-04-20 14:55:37.0 
+0200
+++ gcc/testsuite/gcc.target/i386/pr48688.c 2011-04-20 14:57:03.0 
+0200
@@ -0,0 +1,24 @@
+/* PR target/48688 */
+/* { dg-do compile } */
+/* { dg-options -O2 } */
+
+int fn1 (int x) { return (x  3) | 5; }
+int fn2 (int x) { return (x * 8) | 5; }
+int fn3 (int x) { return (x  3) + 5; }
+int fn4 (int x) { return (x * 8) + 5; }
+int fn5 (int x) { return (x  3) ^ 5; }
+int fn6 (int x) { return (x * 8) ^ 5; }
+long fn7 (long x) { return (x  3) | 5; }
+long fn8 (long x) { return (x * 8) | 5; }
+long fn9 (long x) { return (x  3) + 5; }
+long fn10 (long x) { return (x * 8) + 5; }
+long fn11 (long x) { return (x  3) ^ 5; }
+long fn12 (long x) { return (x * 8) ^ 5; }
+long fn13 (unsigned x) { return (x  3) | 5; }
+long fn14 (unsigned x) { return (x * 8) | 5; }
+long fn15 (unsigned x) { return (x  3) + 5; }
+long fn16 (unsigned x) { return (x * 8) + 5; }
+long fn17 (unsigned x) { return (x  3) ^ 5; }
+long fn18 (unsigned x) { return (x * 8) ^ 5; }
+
+/* { dg-final { scan-assembler-not \[ \t\]x?or\[bwlq\]\[ \t\] } } */

Jakub