* [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688)
@ 2011-04-20 16:36 Jakub Jelinek
2011-04-20 17:51 ` Richard Henderson
2011-06-04 15:20 ` H.J. Lu
0 siblings, 2 replies; 5+ messages in thread
From: Jakub Jelinek @ 2011-04-20 16:36 UTC (permalink / raw)
To: Uros Bizjak; +Cc: gcc-patches
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 <jakub@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.000000000 +0200
+++ gcc/config/i386/i386.md 2011-04-20 14:34:50.000000000 +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")))]
+ "(<MODE>mode == DImode
+ || <MODE>mode == 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 (<MODE>mode != 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 && <MODE>mode != 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 "<MODE>mode == DImode") (const_int 0))
+ (const_string "SI")
+ (const_string "DI")))])
\f
;; Subtract instructions
--- gcc/testsuite/gcc.target/i386/pr48688.c.jj 2011-04-20 14:55:37.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/pr48688.c 2011-04-20 14:57:03.000000000 +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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688)
2011-04-20 16:36 [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688) Jakub Jelinek
@ 2011-04-20 17:51 ` Richard Henderson
2011-04-21 13:01 ` Jakub Jelinek
2011-06-04 15:20 ` H.J. Lu
1 sibling, 1 reply; 5+ messages in thread
From: Richard Henderson @ 2011-04-20 17:51 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Uros Bizjak, gcc-patches
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 <jakub@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...
r~
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688)
2011-04-20 17:51 ` Richard Henderson
@ 2011-04-21 13:01 ` Jakub Jelinek
0 siblings, 0 replies; 5+ messages in thread
From: Jakub Jelinek @ 2011-04-21 13:01 UTC (permalink / raw)
To: Richard Henderson; +Cc: Uros Bizjak, gcc-patches
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 <jakub@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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688)
2011-04-20 16:36 [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688) Jakub Jelinek
2011-04-20 17:51 ` Richard Henderson
@ 2011-06-04 15:20 ` H.J. Lu
2011-06-04 15:40 ` Jakub Jelinek
1 sibling, 1 reply; 5+ messages in thread
From: H.J. Lu @ 2011-06-04 15:20 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Uros Bizjak, gcc-patches
On Wed, Apr 20, 2011 at 9:09 AM, Jakub Jelinek <jakub@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 <jakub@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.000000000 +0200
> +++ gcc/config/i386/i386.md 2011-04-20 14:34:50.000000000 +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")))]
> + "(<MODE>mode == DImode
> + || <MODE>mode == 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 (<MODE>mode != 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 && <MODE>mode != 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 "<MODE>mode == 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.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688)
2011-06-04 15:20 ` H.J. Lu
@ 2011-06-04 15:40 ` Jakub Jelinek
0 siblings, 0 replies; 5+ messages in thread
From: Jakub Jelinek @ 2011-06-04 15:40 UTC (permalink / raw)
To: H.J. Lu; +Cc: Uros Bizjak, gcc-patches
On Sat, Jun 04, 2011 at 08:19:57AM -0700, H.J. Lu wrote:
> I don't think this pattern is correct. See:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49281
Fixed thusly, committed as obvious:
2011-06-04 Jakub Jelinek <jakub@redhat.com>
PR target/49281
* config/i386/i386.md (*lea_general_4): Require INTVAL (operands[3])
to be strictly smaller than 1 << shiftcount.
* gcc.c-torture/execute/pr49281.c: New test.
--- gcc/config/i386/i386.md.jj 2011-06-01 10:20:02.000000000 +0200
+++ gcc/config/i386/i386.md 2011-06-04 17:21:02.000000000 +0200
@@ -6425,7 +6425,7 @@ (define_insn_and_split "*lea_general_4"
|| 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])))"
+ < ((unsigned HOST_WIDE_INT) 1 << INTVAL (operands[2])))"
"#"
"&& reload_completed"
[(const_int 0)]
--- gcc/testsuite/gcc.c-torture/execute/pr49281.c.jj 2011-06-04 17:29:39.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr49281.c 2011-06-04 17:32:05.000000000 +0200
@@ -0,0 +1,25 @@
+/* PR target/49281 */
+
+extern void abort (void);
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+ return (x << 2) | 4;
+}
+
+__attribute__((noinline, noclone)) int
+bar (int x)
+{
+ return (x << 2) | 3;
+}
+
+int
+main ()
+{
+ if (foo (43) != 172 || foo (1) != 4 || foo (2) != 12)
+ abort ();
+ if (bar (43) != 175 || bar (1) != 7 || bar (2) != 11)
+ abort ();
+ return 0;
+}
Jakub
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-06-04 15:40 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-20 16:36 [PATCH] Optimize (x * 8) | 5 and (x << 3) ^ 3 to use lea (PR target/48688) Jakub Jelinek
2011-04-20 17:51 ` Richard Henderson
2011-04-21 13:01 ` Jakub Jelinek
2011-06-04 15:20 ` H.J. Lu
2011-06-04 15:40 ` Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).